Skip to content

Commit

Permalink
Refactor catalog router to use separate modules (#1368)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinfagnani authored Oct 15, 2022
1 parent 1ba834e commit e8fc5f0
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 82 deletions.
15 changes: 15 additions & 0 deletions packages/site-server/src/catalog/graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import {ApolloClient, InMemoryCache} from '@apollo/client/core/index.js';

const CATALOG_GRAPHQL_URL =
process.env['CATALOG_GRAPHQL_URL'] || `http://localhost:6451/graphql`;

export const client = new ApolloClient({
uri: CATALOG_GRAPHQL_URL,
cache: new InMemoryCache(),
});
85 changes: 4 additions & 81 deletions packages/site-server/src/catalog/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,88 +5,11 @@
*/

import Router from '@koa/router';
import {ApolloClient, InMemoryCache, gql} from '@apollo/client/core/index.js';
import {renderPage} from '../templates/base.js';
import {renderElement} from './element-template.js';

const CATALOG_GRAPHQL_URL =
process.env['CATALOG_GRAPHQL_URL'] || `http://localhost:6451/graphql`;

const client = new ApolloClient({
uri: CATALOG_GRAPHQL_URL,
cache: new InMemoryCache(),
});
import {handleCatalogRoute} from './routes/catalog/catalog-route.js';
import {handleElementRoute} from './routes/element/element-route.js';

export const catalogRouter = new Router();

catalogRouter.get('/element/:path+', async (context) => {
const {params} = context;

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const elementPath = params['path']!;
const elementPathSegments = elementPath.split('/');
const isScoped = elementPathSegments[0]?.startsWith('@');
const packageName = isScoped
? elementPathSegments[0] + '/' + elementPathSegments[1]
: elementPathSegments[0]!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const elementName = elementPathSegments[isScoped ? 2 : 1]!;

// TODO (justinfagnani): To make this type-safe, we need to write
// a query .graphql document and generate a TypedDocumentNode from it.
const result = await client.query({
query: gql`
{
package(packageName: "${packageName}") {
... on ReadablePackageInfo {
name
description
version {
... on ReadablePackageVersion {
version
description
customElements(tagName: "${elementName}") {
tagName
declaration
customElementExport
declaration
}
customElementsManifest
}
}
}
}
}
`,
});

if (result.errors !== undefined && result.errors.length > 0) {
throw new Error(result.errors.map((e) => e.message).join('\n'));
}
const {data} = result;
const packageVersion = data.package?.version;
if (packageVersion === undefined) {
throw new Error(`No such package version: ${packageName}`);
}
const customElementsManifest =
packageVersion.customElementsManifest !== undefined &&
JSON.parse(packageVersion.customElementsManifest);

const customElement = packageVersion.customElements?.[0];

if (customElement === undefined || customElement.tagName !== elementName) {
throw new Error('Internal error');
}

const content = renderElement({
packageName: packageName,
elementName: elementName,
declarationReference: customElement.declaration,
customElementExport: customElement.export,
manifest: customElementsManifest,
});
catalogRouter.get('/', handleCatalogRoute);

context.body = renderPage({title: `${packageName}/${elementName}`, content});
context.type = 'html';
context.status = 200;
});
catalogRouter.get('/element/:path+', handleElementRoute);
26 changes: 26 additions & 0 deletions packages/site-server/src/catalog/routes/catalog/catalog-route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import Router from '@koa/router';
import {renderPage} from '../../../templates/base.js';
import {DefaultContext, DefaultState, ParameterizedContext} from 'koa';

export const handleCatalogRoute = async (
context: ParameterizedContext<
DefaultState,
DefaultContext & Router.RouterParamContext<DefaultState, DefaultContext>,
unknown
>
) => {
context.body = renderPage({
title: `Web Components Catalog`,
content: `
<h1>Catalog</h1>
`,
});
context.type = 'html';
context.status = 200;
};
90 changes: 90 additions & 0 deletions packages/site-server/src/catalog/routes/element/element-route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import Router from '@koa/router';
import {gql} from '@apollo/client/core/index.js';
import {renderPage} from '../../../templates/base.js';
import {renderElement} from './element-template.js';
import {DefaultContext, DefaultState, ParameterizedContext} from 'koa';
import { client } from '../../graphql.js';

export const handleElementRoute = async (
context: ParameterizedContext<
DefaultState,
DefaultContext & Router.RouterParamContext<DefaultState, DefaultContext>,
unknown
>
) => {
const {params} = context;

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const elementPath = params['path']!;
const elementPathSegments = elementPath.split('/');
const isScoped = elementPathSegments[0]?.startsWith('@');
const packageName = isScoped
? elementPathSegments[0] + '/' + elementPathSegments[1]
: elementPathSegments[0]!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const elementName = elementPathSegments[isScoped ? 2 : 1]!;

// TODO (justinfagnani): To make this type-safe, we need to write
// a query .graphql document and generate a TypedDocumentNode from it.
const result = await client.query({
query: gql`
{
package(packageName: "${packageName}") {
... on ReadablePackageInfo {
name
description
version {
... on ReadablePackageVersion {
version
description
customElements(tagName: "${elementName}") {
tagName
declaration
customElementExport
declaration
}
customElementsManifest
}
}
}
}
}
`,
});

if (result.errors !== undefined && result.errors.length > 0) {
throw new Error(result.errors.map((e) => e.message).join('\n'));
}
const {data} = result;
const packageVersion = data.package?.version;
if (packageVersion === undefined) {
throw new Error(`No such package version: ${packageName}`);
}
const customElementsManifest =
packageVersion.customElementsManifest !== undefined &&
JSON.parse(packageVersion.customElementsManifest);

const customElement = packageVersion.customElements?.[0];

if (customElement === undefined || customElement.tagName !== elementName) {
throw new Error('Internal error');
}

const content = renderElement({
packageName: packageName,
elementName: elementName,
declarationReference: customElement.declaration,
customElementExport: customElement.export,
manifest: customElementsManifest,
});

context.body = renderPage({title: `${packageName}/${elementName}`, content});
context.type = 'html';
context.status = 200;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
resolveReference,
normalizeModulePath,
} from '@webcomponents/custom-elements-manifest-tools';
import {escapeHTML} from './escape-html.js';
import {escapeHTML} from '../../escape-html.js';

export const renderElement = ({
packageName,
Expand Down

0 comments on commit e8fc5f0

Please sign in to comment.