Skip to content

Commit e8fc5f0

Browse files
Refactor catalog router to use separate modules (#1368)
1 parent 1ba834e commit e8fc5f0

File tree

5 files changed

+136
-82
lines changed

5 files changed

+136
-82
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* @license
3+
* Copyright 2022 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {ApolloClient, InMemoryCache} from '@apollo/client/core/index.js';
8+
9+
const CATALOG_GRAPHQL_URL =
10+
process.env['CATALOG_GRAPHQL_URL'] || `http://localhost:6451/graphql`;
11+
12+
export const client = new ApolloClient({
13+
uri: CATALOG_GRAPHQL_URL,
14+
cache: new InMemoryCache(),
15+
});

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

Lines changed: 4 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -5,88 +5,11 @@
55
*/
66

77
import Router from '@koa/router';
8-
import {ApolloClient, InMemoryCache, gql} from '@apollo/client/core/index.js';
9-
import {renderPage} from '../templates/base.js';
10-
import {renderElement} from './element-template.js';
11-
12-
const CATALOG_GRAPHQL_URL =
13-
process.env['CATALOG_GRAPHQL_URL'] || `http://localhost:6451/graphql`;
14-
15-
const client = new ApolloClient({
16-
uri: CATALOG_GRAPHQL_URL,
17-
cache: new InMemoryCache(),
18-
});
8+
import {handleCatalogRoute} from './routes/catalog/catalog-route.js';
9+
import {handleElementRoute} from './routes/element/element-route.js';
1910

2011
export const catalogRouter = new Router();
2112

22-
catalogRouter.get('/element/:path+', async (context) => {
23-
const {params} = context;
24-
25-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
26-
const elementPath = params['path']!;
27-
const elementPathSegments = elementPath.split('/');
28-
const isScoped = elementPathSegments[0]?.startsWith('@');
29-
const packageName = isScoped
30-
? elementPathSegments[0] + '/' + elementPathSegments[1]
31-
: elementPathSegments[0]!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
32-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
33-
const elementName = elementPathSegments[isScoped ? 2 : 1]!;
34-
35-
// TODO (justinfagnani): To make this type-safe, we need to write
36-
// a query .graphql document and generate a TypedDocumentNode from it.
37-
const result = await client.query({
38-
query: gql`
39-
{
40-
package(packageName: "${packageName}") {
41-
... on ReadablePackageInfo {
42-
name
43-
description
44-
version {
45-
... on ReadablePackageVersion {
46-
version
47-
description
48-
customElements(tagName: "${elementName}") {
49-
tagName
50-
declaration
51-
customElementExport
52-
declaration
53-
}
54-
customElementsManifest
55-
}
56-
}
57-
}
58-
}
59-
}
60-
`,
61-
});
62-
63-
if (result.errors !== undefined && result.errors.length > 0) {
64-
throw new Error(result.errors.map((e) => e.message).join('\n'));
65-
}
66-
const {data} = result;
67-
const packageVersion = data.package?.version;
68-
if (packageVersion === undefined) {
69-
throw new Error(`No such package version: ${packageName}`);
70-
}
71-
const customElementsManifest =
72-
packageVersion.customElementsManifest !== undefined &&
73-
JSON.parse(packageVersion.customElementsManifest);
74-
75-
const customElement = packageVersion.customElements?.[0];
76-
77-
if (customElement === undefined || customElement.tagName !== elementName) {
78-
throw new Error('Internal error');
79-
}
80-
81-
const content = renderElement({
82-
packageName: packageName,
83-
elementName: elementName,
84-
declarationReference: customElement.declaration,
85-
customElementExport: customElement.export,
86-
manifest: customElementsManifest,
87-
});
13+
catalogRouter.get('/', handleCatalogRoute);
8814

89-
context.body = renderPage({title: `${packageName}/${elementName}`, content});
90-
context.type = 'html';
91-
context.status = 200;
92-
});
15+
catalogRouter.get('/element/:path+', handleElementRoute);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @license
3+
* Copyright 2022 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import Router from '@koa/router';
8+
import {renderPage} from '../../../templates/base.js';
9+
import {DefaultContext, DefaultState, ParameterizedContext} from 'koa';
10+
11+
export const handleCatalogRoute = async (
12+
context: ParameterizedContext<
13+
DefaultState,
14+
DefaultContext & Router.RouterParamContext<DefaultState, DefaultContext>,
15+
unknown
16+
>
17+
) => {
18+
context.body = renderPage({
19+
title: `Web Components Catalog`,
20+
content: `
21+
<h1>Catalog</h1>
22+
`,
23+
});
24+
context.type = 'html';
25+
context.status = 200;
26+
};
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* @license
3+
* Copyright 2022 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import Router from '@koa/router';
8+
import {gql} from '@apollo/client/core/index.js';
9+
import {renderPage} from '../../../templates/base.js';
10+
import {renderElement} from './element-template.js';
11+
import {DefaultContext, DefaultState, ParameterizedContext} from 'koa';
12+
import { client } from '../../graphql.js';
13+
14+
export const handleElementRoute = async (
15+
context: ParameterizedContext<
16+
DefaultState,
17+
DefaultContext & Router.RouterParamContext<DefaultState, DefaultContext>,
18+
unknown
19+
>
20+
) => {
21+
const {params} = context;
22+
23+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
24+
const elementPath = params['path']!;
25+
const elementPathSegments = elementPath.split('/');
26+
const isScoped = elementPathSegments[0]?.startsWith('@');
27+
const packageName = isScoped
28+
? elementPathSegments[0] + '/' + elementPathSegments[1]
29+
: elementPathSegments[0]!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
30+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
31+
const elementName = elementPathSegments[isScoped ? 2 : 1]!;
32+
33+
// TODO (justinfagnani): To make this type-safe, we need to write
34+
// a query .graphql document and generate a TypedDocumentNode from it.
35+
const result = await client.query({
36+
query: gql`
37+
{
38+
package(packageName: "${packageName}") {
39+
... on ReadablePackageInfo {
40+
name
41+
description
42+
version {
43+
... on ReadablePackageVersion {
44+
version
45+
description
46+
customElements(tagName: "${elementName}") {
47+
tagName
48+
declaration
49+
customElementExport
50+
declaration
51+
}
52+
customElementsManifest
53+
}
54+
}
55+
}
56+
}
57+
}
58+
`,
59+
});
60+
61+
if (result.errors !== undefined && result.errors.length > 0) {
62+
throw new Error(result.errors.map((e) => e.message).join('\n'));
63+
}
64+
const {data} = result;
65+
const packageVersion = data.package?.version;
66+
if (packageVersion === undefined) {
67+
throw new Error(`No such package version: ${packageName}`);
68+
}
69+
const customElementsManifest =
70+
packageVersion.customElementsManifest !== undefined &&
71+
JSON.parse(packageVersion.customElementsManifest);
72+
73+
const customElement = packageVersion.customElements?.[0];
74+
75+
if (customElement === undefined || customElement.tagName !== elementName) {
76+
throw new Error('Internal error');
77+
}
78+
79+
const content = renderElement({
80+
packageName: packageName,
81+
elementName: elementName,
82+
declarationReference: customElement.declaration,
83+
customElementExport: customElement.export,
84+
manifest: customElementsManifest,
85+
});
86+
87+
context.body = renderPage({title: `${packageName}/${elementName}`, content});
88+
context.type = 'html';
89+
context.status = 200;
90+
};

packages/site-server/src/catalog/element-template.ts renamed to packages/site-server/src/catalog/routes/element/element-template.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
resolveReference,
1212
normalizeModulePath,
1313
} from '@webcomponents/custom-elements-manifest-tools';
14-
import {escapeHTML} from './escape-html.js';
14+
import {escapeHTML} from '../../escape-html.js';
1515

1616
export const renderElement = ({
1717
packageName,

0 commit comments

Comments
 (0)