mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-04-08 02:52:39 -05:00
Switched URL calls to use Content API SDK
refs https://github.com/TryGhost/Team/issues/1665 - The Content API SDK is the recommended way to interact with the API
This commit is contained in:
parent
2ef8eb0586
commit
44c8969192
7 changed files with 84 additions and 46 deletions
|
@ -21,6 +21,7 @@
|
|||
"@testing-library/jest-dom": "5.16.2",
|
||||
"@testing-library/react": "12.1.2",
|
||||
"@testing-library/user-event": "14.0.0",
|
||||
"@tryghost/content-api": "^1.11.0",
|
||||
"elasticlunr": "0.9.5",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
|
|
|
@ -9,7 +9,7 @@ export default class App extends React.Component {
|
|||
super(props);
|
||||
|
||||
const searchIndex = new SearchIndex({
|
||||
apiUrl: props.apiUrl,
|
||||
siteURL: props.siteURL,
|
||||
apiKey: props.apiKey
|
||||
});
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import React from 'react';
|
|||
|
||||
test('renders Sodo Search app component', () => {
|
||||
window.location.hash = '#/search';
|
||||
render(<App />);
|
||||
render(<App siteURL="http://localhost" apiKey="69010382388f9de5869ad6e558" />);
|
||||
// const containerElement = screen.getElementsByClassName('gh-portal-popup-container');
|
||||
const containerElement = document.querySelector('.gh-root-frame');
|
||||
expect(containerElement).toBeInTheDocument();
|
||||
|
|
|
@ -19,9 +19,8 @@ function getSiteData() {
|
|||
if (scriptTag) {
|
||||
const siteUrl = scriptTag.dataset.sodoSearch;
|
||||
const apiKey = scriptTag.dataset.key;
|
||||
const apiUrl = scriptTag.dataset.api;
|
||||
const appVersion = scriptTag.dataset.version;
|
||||
return {siteUrl, apiKey, apiUrl, appVersion};
|
||||
return {siteUrl, apiKey, appVersion};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import elasticlunr from 'elasticlunr';
|
||||
import GhostContentAPI from '@tryghost/content-api';
|
||||
|
||||
export default class SearchIndex {
|
||||
constructor({apiUrl, apiKey}) {
|
||||
this.apiUrl = apiUrl;
|
||||
this.apiKey = apiKey;
|
||||
constructor({siteURL, apiKey}) {
|
||||
this.api = new GhostContentAPI({
|
||||
url: siteURL,
|
||||
key: apiKey,
|
||||
version: 'v5.0'
|
||||
});
|
||||
|
||||
this.postsIndex = null;
|
||||
this.authorsIndex = null;
|
||||
|
@ -12,8 +16,8 @@ export default class SearchIndex {
|
|||
this.search = this.search.bind(this);
|
||||
}
|
||||
|
||||
#updatePostIndex(data) {
|
||||
data.posts.forEach((post) => {
|
||||
#updatePostIndex(posts) {
|
||||
posts.forEach((post) => {
|
||||
this.postsIndex.addDoc({
|
||||
id: post.id,
|
||||
title: post.title,
|
||||
|
@ -24,8 +28,8 @@ export default class SearchIndex {
|
|||
});
|
||||
}
|
||||
|
||||
#updateAuthorsIndex(data) {
|
||||
data.authors.forEach((author) => {
|
||||
#updateAuthorsIndex(authors) {
|
||||
authors.forEach((author) => {
|
||||
this.authorsIndex.addDoc({
|
||||
id: author.id,
|
||||
name: author.name,
|
||||
|
@ -35,8 +39,8 @@ export default class SearchIndex {
|
|||
});
|
||||
}
|
||||
|
||||
#updateTagsIndex(data) {
|
||||
data.tags.forEach((tag) => {
|
||||
#updateTagsIndex(tags) {
|
||||
tags.forEach((tag) => {
|
||||
this.tagsIndex.addDoc({
|
||||
id: tag.id,
|
||||
name: tag.name,
|
||||
|
@ -49,12 +53,12 @@ export default class SearchIndex {
|
|||
// remove default stop words to search of *any* word
|
||||
elasticlunr.clearStopWords();
|
||||
|
||||
const postsAPIUrl = `${this.apiUrl}/posts/?key=${this.apiKey}&limit=all&fields=id,slug,title,excerpt,url,updated_at,visibility&order=updated_at%20desc&formats=plaintext`;
|
||||
const authorsAPIUrl = `${this.apiUrl}/authors/?key=${this.apiKey}&limit=all&fields=id,slug,name,url,profile_image`;
|
||||
const tagsAPIUrl = `${this.apiUrl}/tags/?key=${this.apiKey}&limit=all&fields=id,slug,name,url`;
|
||||
|
||||
const postsResponse = await fetch(postsAPIUrl);
|
||||
const posts = await postsResponse.json();
|
||||
let posts = await this.api.posts.browse({
|
||||
limit: 'all',
|
||||
fields: 'id,slug,title,excerpt,url,updated_at,visibility',
|
||||
order: 'updated_at DESC',
|
||||
formats: 'plaintext'
|
||||
});
|
||||
|
||||
this.postsIndex = elasticlunr();
|
||||
this.postsIndex.addField('title');
|
||||
|
@ -62,12 +66,17 @@ export default class SearchIndex {
|
|||
this.postsIndex.addField('excerpt');
|
||||
this.postsIndex.setRef('id');
|
||||
|
||||
if (posts.posts.length > 0) {
|
||||
if (posts || posts.length > 0) {
|
||||
if (!posts.length) {
|
||||
posts = [posts];
|
||||
}
|
||||
this.#updatePostIndex(posts);
|
||||
}
|
||||
|
||||
const authorsResponse = await fetch(authorsAPIUrl);
|
||||
const authors = await authorsResponse.json();
|
||||
let authors = await this.api.authors.browse({
|
||||
limit: 'all',
|
||||
fields: 'id,slug,name,url,profile_image'
|
||||
});
|
||||
|
||||
this.authorsIndex = elasticlunr();
|
||||
this.authorsIndex.addField('name');
|
||||
|
@ -75,19 +84,28 @@ export default class SearchIndex {
|
|||
this.authorsIndex.addField('profile_image');
|
||||
this.authorsIndex.setRef('id');
|
||||
|
||||
if (authors.authors.length > 0) {
|
||||
if (authors || authors.length > 0) {
|
||||
if (!authors.length) {
|
||||
authors = [authors];
|
||||
}
|
||||
|
||||
this.#updateAuthorsIndex(authors);
|
||||
}
|
||||
|
||||
const tagsResponse = await fetch(tagsAPIUrl);
|
||||
const tags = await tagsResponse.json();
|
||||
|
||||
let tags = await this.api.tags.browse({
|
||||
limit: 'all',
|
||||
fields: 'id,slug,name,url'
|
||||
});
|
||||
this.tagsIndex = elasticlunr();
|
||||
this.tagsIndex.addField('name');
|
||||
this.tagsIndex.addField('url');
|
||||
this.tagsIndex.setRef('id');
|
||||
|
||||
if (tags.tags.length > 0) {
|
||||
if (tags || tags.length > 0) {
|
||||
if (!tags.length) {
|
||||
tags = [tags];
|
||||
}
|
||||
|
||||
this.#updateTagsIndex(tags);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,30 +2,26 @@ import SearchIndex from './search-index';
|
|||
import nock from 'nock';
|
||||
|
||||
describe('search index', function () {
|
||||
afterEach(function () {
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
test('initializes search index', async () => {
|
||||
const apiUrl = 'http://localhost/ghost/api/content';
|
||||
const apiKey = 'secret_key';
|
||||
const searchIndex = new SearchIndex({apiUrl, apiKey, storage: localStorage});
|
||||
const siteURL = 'http://localhost';
|
||||
const apiKey = '69010382388f9de5869ad6e558';
|
||||
const searchIndex = new SearchIndex({siteURL, apiKey, storage: localStorage});
|
||||
|
||||
const scope = nock('http://localhost/ghost/api/content')
|
||||
.get('/posts/?key=secret_key&limit=all&fields=id,slug,title,excerpt,url,updated_at,visibility&order=updated_at%20desc&formats=plaintext')
|
||||
.get('/posts/?key=69010382388f9de5869ad6e558&limit=all&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC&formats=plaintext')
|
||||
.reply(200, {
|
||||
posts: []
|
||||
})
|
||||
.get('/authors/?key=secret_key&limit=all&fields=id,slug,name,url,profile_image')
|
||||
.get('/authors/?key=69010382388f9de5869ad6e558&limit=all&fields=id,slug,name,url,profile_image')
|
||||
.reply(200, {
|
||||
authors: []
|
||||
})
|
||||
.get('/tags/?key=secret_key&&limit=all&fields=id,slug,name,url')
|
||||
.get('/tags/?key=69010382388f9de5869ad6e558&&limit=all&fields=id,slug,name,url')
|
||||
.reply(200, {
|
||||
tags: []
|
||||
});
|
||||
|
||||
await searchIndex.init({apiUrl, apiKey});
|
||||
await searchIndex.init({siteURL, apiKey});
|
||||
|
||||
expect(scope.isDone()).toBeTruthy();
|
||||
|
||||
|
@ -37,12 +33,12 @@ describe('search index', function () {
|
|||
});
|
||||
|
||||
test('allows to search for indexed posts and authors', async () => {
|
||||
const apiUrl = 'http://localhost/ghost/api/content';
|
||||
const apiKey = 'secret_key';
|
||||
const searchIndex = new SearchIndex({apiUrl, apiKey, storage: localStorage});
|
||||
const siteURL = 'http://localhost';
|
||||
const apiKey = '69010382388f9de5869ad6e558';
|
||||
const searchIndex = new SearchIndex({siteURL, apiKey, storage: localStorage});
|
||||
|
||||
nock('http://localhost/ghost/api/content')
|
||||
.get('/posts/?key=secret_key&limit=all&fields=id,slug,title,excerpt,url,updated_at,visibility&order=updated_at%20desc&formats=plaintext')
|
||||
.get('/posts/?key=69010382388f9de5869ad6e558&limit=all&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC&formats=plaintext')
|
||||
.reply(200, {
|
||||
posts: [{
|
||||
id: 'sounique',
|
||||
|
@ -51,7 +47,7 @@ describe('search index', function () {
|
|||
url: 'http://localhost/ghost/awesome-barcelona-life/'
|
||||
}]
|
||||
})
|
||||
.get('/authors/?key=secret_key&limit=all&fields=id,slug,name,url,profile_image')
|
||||
.get('/authors/?key=69010382388f9de5869ad6e558&limit=all&fields=id,slug,name,url,profile_image')
|
||||
.reply(200, {
|
||||
authors: [{
|
||||
id: 'different_uniq',
|
||||
|
@ -67,7 +63,7 @@ describe('search index', function () {
|
|||
url: 'http://localhost/ghost/authors/bob/'
|
||||
}]
|
||||
})
|
||||
.get('/tags/?key=secret_key&&limit=all&fields=id,slug,name,url')
|
||||
.get('/tags/?key=69010382388f9de5869ad6e558&&limit=all&fields=id,slug,name,url')
|
||||
.reply(200, {
|
||||
tags: [{
|
||||
id: 'uniq_tag',
|
||||
|
@ -77,7 +73,7 @@ describe('search index', function () {
|
|||
}]
|
||||
});
|
||||
|
||||
await searchIndex.init({apiUrl, apiKey});
|
||||
await searchIndex.init({siteURL, apiKey});
|
||||
|
||||
let searchResults = searchIndex.search('Barcelona');
|
||||
expect(searchResults.posts.length).toEqual(1);
|
||||
|
|
|
@ -1680,6 +1680,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
||||
|
||||
"@tryghost/content-api@^1.11.0":
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/content-api/-/content-api-1.11.0.tgz#25ab0e2c5618f4ae190d5ad739611a07a551b245"
|
||||
integrity sha512-0JTlp5Ln4BfCJzCYuT2X3MC9ZupIkRtzZaHpf9KZw7O8uOsRnO9RwjItN+lwvkoLIesMzfgrZd/tBJ4BAzeBrg==
|
||||
dependencies:
|
||||
axios "^0.27.0"
|
||||
|
||||
"@types/aria-query@^4.2.0":
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
|
||||
|
@ -2583,6 +2590,14 @@ axe-core@^4.4.2:
|
|||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.2.tgz#dcf7fb6dea866166c3eab33d68208afe4d5f670c"
|
||||
integrity sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA==
|
||||
|
||||
axios@^0.27.0:
|
||||
version "0.27.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
|
||||
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.9"
|
||||
form-data "^4.0.0"
|
||||
|
||||
axobject-query@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
||||
|
@ -5382,7 +5397,7 @@ flush-write-stream@^1.0.0:
|
|||
inherits "^2.0.3"
|
||||
readable-stream "^2.3.6"
|
||||
|
||||
follow-redirects@^1.0.0:
|
||||
follow-redirects@^1.0.0, follow-redirects@^1.14.9:
|
||||
version "1.15.1"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
|
||||
integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
|
||||
|
@ -5414,6 +5429,15 @@ form-data@^3.0.0:
|
|||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
|
|
Loading…
Add table
Reference in a new issue