Lint on generate success. Move YAML file to src/schema/

Signed-off-by: Aramis Sennyey <sennyeya@amazon.com>
This commit is contained in:
Aramis Sennyey
2023-04-03 12:22:50 -04:00
committed by Fredrik Adelöw
parent 1f5800ae6d
commit ef770923df
11 changed files with 48 additions and 24 deletions
+1 -1
View File
@@ -2,4 +2,4 @@
'@backstage/plugin-catalog-backend': patch
---
Update `openapi.yaml` and use `ApiRouter` type from `@backstage/backend-openapi-utils` to handle automatic types from the OpenAPI spec file.
Updates and moves OpenAPI spec to `src/schema/openapi.yaml` and uses `ApiRouter` type from `@backstage/backend-openapi-utils` to handle automatic types from the OpenAPI spec file.
+1 -1
View File
@@ -2,4 +2,4 @@
'@backstage/repo-tools': minor
---
Adding two new commands to support OpenAPI spec writing, `schema:openapi:generate` to generate the Typescript file that `@backstage/backend-openapi-utils` needs for typing and `schema:openapi:verify` to verify that this file exists and matches your `openapi.yaml` file.
Adding two new commands to support OpenAPI spec writing, `schema:openapi:generate` to generate the Typescript file that `@backstage/backend-openapi-utils` needs for typing and `schema:openapi:verify` to verify that this file exists and matches your `src/schema/openapi.yaml` file.
+1 -1
View File
@@ -92,7 +92,7 @@ jobs:
- name: verify api reference
run: node scripts/verify-api-reference.js
- name: verify openapi.yaml matches schema/openapi.ts files
- name: verify openapi yaml file matches generated ts file
run: yarn backstage-repo-tools schema:openapi:verify
- name: verify doc links
+2 -2
View File
@@ -8,13 +8,13 @@ This package is meant to provide a typed Express router for an OpenAPI spec. Bas
### Configuration
1. Run `yarn --cwd <package-dir> backstage-cli package schema:openapi:generate` to translate your `openapi.yaml` to a new Typescript file in `schema/openapi.ts`. In the case of projects that require linting + a license header, you will need to do this manually.
1. Run `yarn --cwd <package-dir> backstage-cli package schema:openapi:generate` to translate your `src/schema/openapi.yaml` to a new Typescript file in `src/schema/openapi.ts`. In the case of projects that require linting + a license header, you will need to do this manually.
2. In your plugin's `src/service/createRouter.ts`,
```ts
import {ApiRouter} from `@backstage/backend-openapi-utils`;
import spec from '../../schema/openapi'
import spec from '../schema/openapi'
...
export function createRouter(){
@@ -0,0 +1,18 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const YAML_SCHEMA_PATH = 'src/schema/openapi.yaml';
export const TS_MODULE = 'src/schema/openapi';
export const TS_SCHEMA_PATH = `${TS_MODULE}.ts`;
@@ -19,26 +19,34 @@ import YAML from 'js-yaml';
import chalk from 'chalk';
import { resolve } from 'path';
import { runner } from './runner';
import { TS_SCHEMA_PATH, YAML_SCHEMA_PATH } from './constants';
import { promisify } from 'util';
import { exec as execCb } from 'child_process';
const exec = promisify(execCb);
async function generate(
directoryPath: string,
config?: { skipMissingYamlFile: boolean },
) {
const { skipMissingYamlFile } = config ?? {};
const openapiPath = resolve(directoryPath, 'openapi.yaml');
const openapiPath = resolve(directoryPath, YAML_SCHEMA_PATH);
if (!(await fs.pathExists(openapiPath))) {
if (skipMissingYamlFile) {
return;
}
throw new Error('Could not find openapi.yaml in root of directory.');
throw new Error(`Could not find ${YAML_SCHEMA_PATH} in root of directory.`);
}
const yaml = YAML.load(await fs.readFile(openapiPath, 'utf8'));
// For now, we're not adding a header or linting after pasting.
const tsPath = resolve(directoryPath, TS_SCHEMA_PATH);
await fs.writeFile(
resolve(directoryPath, 'schema/openapi.ts'),
tsPath,
`export default ${JSON.stringify(yaml, null, 2)} as const`,
);
await exec(`yarn backstage-cli package lint --fix ${tsPath}`);
}
export async function bulkCommand(paths: string[] = []): Promise<void> {
@@ -23,9 +23,10 @@ import { relative as relativePath, resolve as resolvePath } from 'path';
import Parser from '@apidevtools/swagger-parser';
import { runner } from './runner';
import { paths as cliPaths } from '../../lib/paths';
import { TS_MODULE, TS_SCHEMA_PATH, YAML_SCHEMA_PATH } from './constants';
async function verify(directoryPath: string) {
const openapiPath = join(directoryPath, 'openapi.yaml');
const openapiPath = join(directoryPath, YAML_SCHEMA_PATH);
if (!(await fs.pathExists(openapiPath))) {
return;
}
@@ -33,30 +34,27 @@ async function verify(directoryPath: string) {
const yaml = YAML.load(await fs.readFile(openapiPath, 'utf8'));
await Parser.validate(cloneDeep(yaml) as any);
const schemaPath = join(directoryPath, 'schema/openapi.ts');
const schemaPath = join(directoryPath, TS_SCHEMA_PATH);
if (!(await fs.pathExists(schemaPath))) {
throw new Error('No `schema/openapi.ts` file found.');
throw new Error(`No \`${TS_SCHEMA_PATH}\` file found.`);
}
const schema = await import(
resolvePath(join(directoryPath, 'schema/openapi'))
);
const schema = await import(resolvePath(join(directoryPath, TS_MODULE)));
if (!schema.default) {
throw new Error('`schemas/openapi.ts` needs to have a default export.');
throw new Error(`\`${TS_SCHEMA_PATH}\` needs to have a default export.`);
}
if (!isEqual(schema.default, yaml)) {
throw new Error(
`\`openapi.yaml\` and \`schema/openapi.ts\` do not match. Please run \`yarn --cwd ${relativePath(
`\`${YAML_SCHEMA_PATH}\` and \`${TS_SCHEMA_PATH}\` do not match. Please run \`yarn --cwd ${relativePath(
cliPaths.targetRoot,
directoryPath,
)} schema:openapi:generate\` to regenerate \`schema/openapi.ts\`.`,
)} schema:openapi:generate\` to regenerate \`${TS_SCHEMA_PATH}\`.`,
);
}
}
export async function bulkCommand(paths: string[] = []): Promise<void> {
console.log(paths);
const resultsList = await runner(paths, dir => verify(dir));
let failed = false;
+4 -4
View File
@@ -90,10 +90,10 @@ export async function getWorkspacePackagePathPatterns(): Promise<
}
/**
* Given a list of paths from the user or none and return the listing package directories from the
* workspace.
* @param cliPaths
* @returns
* Given a list of paths from the user, returns the listing package directories from the
* workspace. Returns all directories if no paths are given.
* @param cliPaths User given paths from CLI.
* @returns Matching package directories or all if no cli paths passed in.
*/
export async function getMatchingWorkspacePaths(cliPaths: string[]) {
const isAllPackages = !cliPaths?.length;
@@ -51,7 +51,7 @@ import {
validateRequestBody,
} from './util';
import type { ApiRouter } from '@backstage/backend-openapi-utils';
import spec from '../../schema/openapi';
import spec from '../schema/openapi';
/**
* Options used by {@link createRouter}.