Skip to content

Commit fe375cc

Browse files
Add search endpoint to site-server (#1417)
1 parent 3de0eec commit fe375cc

File tree

10 files changed

+138
-71
lines changed

10 files changed

+138
-71
lines changed

package-lock.json

+1-34
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/catalog-server/package.json

+10-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@
4949
},
5050
"start:dev": {
5151
"command": "FIRESTORE_EMULATOR_HOST=localhost:7450 npm start",
52-
"service": true,
52+
"service": {
53+
"readyWhen": {
54+
"lineMatches": "Server started"
55+
}
56+
},
5357
"dependencies": [
5458
"build",
5559
"emulators:start"
@@ -66,7 +70,11 @@
6670
},
6771
"emulators:start": {
6872
"command": "firebase emulators:start --project wc-catalog --import firebase-data",
69-
"service": true,
73+
"service": {
74+
"readyWhen": {
75+
"lineMatches": "All emulators ready"
76+
}
77+
},
7078
"files": [
7179
"firebase.json",
7280
"firestore.indexes.json",

packages/site-client/package.json

-2
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@
8686
}
8787
},
8888
"dependencies": {
89-
"@urql/core": "^3.0.4",
9089
"@webcomponents/catalog-api": "^0.0.0",
91-
"graphql": "^16.6.0",
9290
"lit": "^2.6.0",
9391
"lit-analyzer": "^1.2.1"
9492
}

packages/site-client/src/components/wco-catalog-search.ts

+3-22
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,10 @@
66

77
import {html, css, LitElement} from 'lit';
88
import {customElement, query, state} from 'lit/decorators.js';
9-
import {gql, createClient, defaultExchanges} from '@urql/core';
109
import type {CustomElement} from '@webcomponents/catalog-api/lib/schema.js';
1110

1211
import './wco-element-card.js';
1312

14-
const client = createClient({
15-
// TODO (justinfagnani): get this URL from server
16-
url: 'http://localhost:6451/graphql',
17-
exchanges: defaultExchanges,
18-
});
19-
20-
const elementsQuery = gql`
21-
query Elements($query: String) {
22-
elements(query: $query, limit: 16) {
23-
tagName
24-
package
25-
version
26-
className
27-
}
28-
}
29-
`;
30-
3113
@customElement('wco-catalog-search')
3214
export class WCOCatalogSearch extends LitElement {
3315
static styles = css`
@@ -78,10 +60,9 @@ export class WCOCatalogSearch extends LitElement {
7860

7961
async _onChange() {
8062
const searchText = this._search.value;
81-
const result = await client
82-
.query(elementsQuery, {query: searchText})
83-
.toPromise();
84-
this._elements = result.data?.elements;
63+
const response = await fetch(`/catalog/search?query=${searchText}`);
64+
const result = await response.json();
65+
this._elements = result.elements;
8566
}
8667
}
8768

packages/site-server/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@
9898
"test": {
9999
"command": "NODE_OPTIONS=--enable-source-maps uvu test \"_test\\.js$\"",
100100
"dependencies": [
101-
"start:dev"
101+
"start:dev",
102+
"../catalog-server:start:dev"
102103
]
103104
}
104105
},

packages/site-server/src/lib/catalog/router.ts

+6
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@
66

77
import Router from '@koa/router';
88
import {handleCatalogRoute} from './routes/catalog/catalog-route.js';
9+
import {handleCatalogSearchRoute} from './routes/catalog/search-route.js';
910
import {handleElementRoute} from './routes/element/element-route.js';
11+
// import cors from '@koa/cors';
1012

1113
export const catalogRouter = new Router();
1214

15+
// catalogRouter.use(cors());
16+
1317
catalogRouter.get('/', handleCatalogRoute);
1418

19+
catalogRouter.get('/search', handleCatalogSearchRoute);
20+
1521
catalogRouter.get('/element/:path+', handleElementRoute);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* @license
3+
* Copyright 2023 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {DefaultContext, DefaultState, ParameterizedContext} from 'koa';
8+
import Router from '@koa/router';
9+
import {client} from '../../graphql.js';
10+
import {gql} from '@apollo/client/core/index.js';
11+
12+
import '@webcomponents/internal-site-client/lib/entrypoints/catalog.js';
13+
14+
const elementsQuery = gql`
15+
query Elements($query: String) {
16+
elements(query: $query, limit: 16) {
17+
tagName
18+
package
19+
version
20+
className
21+
}
22+
}
23+
`;
24+
25+
export const handleCatalogSearchRoute = async (
26+
context: ParameterizedContext<
27+
DefaultState,
28+
DefaultContext & Router.RouterParamContext<DefaultState, DefaultContext>,
29+
unknown
30+
>
31+
) => {
32+
const searchText = context.query['query'];
33+
context.type = 'json';
34+
35+
if (typeof searchText !== 'string') {
36+
context.status = 400;
37+
context.body = {
38+
message: 'Query parmeter `query` must be a string',
39+
};
40+
return;
41+
}
42+
43+
const result = await client.query({
44+
query: elementsQuery,
45+
variables: {query: searchText},
46+
});
47+
48+
if (result.error) {
49+
context.status = 500;
50+
context.body = {
51+
message: result.error,
52+
};
53+
return;
54+
}
55+
56+
context.status = 200;
57+
context.body = {
58+
elements: result.data?.elements,
59+
};
60+
};

packages/site-server/src/test/catalog/routes_test.ts

+14-5
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,28 @@ const request = async (path: string) => fetch(`http://127.0.0.1:5450${path}`);
1414

1515
test('Returns 404 for malformed element page URL', async () => {
1616
// Missing package and element:
17-
assert.equal((await request('/element/')).status, 404);
17+
assert.equal((await request('/catalog/element/')).status, 404);
1818

1919
// Missing element name on scoped package:
20-
assert.equal((await request('/element/@lion/button')).status, 404);
20+
assert.equal((await request('/catalog/element/@lion/button')).status, 404);
2121

2222
// Missing element name on non-scoped package:
23-
assert.equal((await request('/element/chessboard-element')).status, 404);
23+
assert.equal(
24+
(await request('/catalog/element/chessboard-element')).status,
25+
404
26+
);
2427

2528
// Extra path segments on scoped package:
26-
assert.equal((await request('/element/@lion/button/a/b')).status, 404);
29+
assert.equal(
30+
(await request('/catalog/element/@lion/button/a/b')).status,
31+
404
32+
);
2733

2834
// Extra path segments on non-scoped package:
29-
assert.equal((await request('/element/chessboard-element/a/b')).status, 404);
35+
assert.equal(
36+
(await request('/catalog/element/chessboard-element/a/b')).status,
37+
404
38+
);
3039
});
3140

3241
test.run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* @license
3+
* Copyright 2023 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {suite} from 'uvu';
8+
// eslint-disable-next-line import/extensions
9+
import * as assert from 'uvu/assert';
10+
11+
const test = suite('Route tests');
12+
13+
const request = async (path: string) => fetch(`http://127.0.0.1:5450${path}`);
14+
15+
test('Finds a button', async () => {
16+
// Import lion-button
17+
assert.equal(
18+
(await request('/catalog/element/@lion/button/lion-button')).status,
19+
200
20+
);
21+
22+
// Import sl-button
23+
assert.equal(
24+
(await request('/catalog/element/@shoelace-style/shoelace/sl-button'))
25+
.status,
26+
200
27+
);
28+
29+
const response = await request('/catalog/search?query=button');
30+
assert.equal(response.status, 200);
31+
const result = await response.json();
32+
33+
// Shoelace has a few buttons that all get imported
34+
assert.ok(result.elements.length > 2);
35+
});
36+
37+
test.run();

packages/site-server/test/catalog/routes_test.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import * as assert from "uvu/assert";
88
const test = suite("Route tests");
99
const request = async (path) => fetch(`http://127.0.0.1:5450${path}`);
1010
test("Returns 404 for malformed element page URL", async () => {
11-
assert.equal((await request("/element/")).status, 404);
12-
assert.equal((await request("/element/@lion/button")).status, 404);
13-
assert.equal((await request("/element/chessboard-element")).status, 404);
14-
assert.equal((await request("/element/@lion/button/a/b")).status, 404);
15-
assert.equal((await request("/element/chessboard-element/a/b")).status, 404);
11+
assert.equal((await request("/catalog/element/")).status, 404);
12+
assert.equal((await request("/catalog/element/@lion/button")).status, 404);
13+
assert.equal((await request("/catalog/element/chessboard-element")).status, 404);
14+
assert.equal((await request("/catalog/element/@lion/button/a/b")).status, 404);
15+
assert.equal((await request("/catalog/element/chessboard-element/a/b")).status, 404);
1616
});
1717
test.run();

0 commit comments

Comments
 (0)