From abd4ff4cee71798534c3fac47a2fc6e7dada4252 Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Thu, 16 Mar 2023 12:13:17 -0400 Subject: [PATCH] Update api report and shift openapi-utils to a devDependency. Signed-off-by: Aramis Sennyey --- plugins/catalog-backend/openapi.yaml | 2 +- plugins/catalog-backend/package.json | 2 +- .../src/service/createRouter.ts | 2 +- plugins/openapi-utils/README.md | 46 +- plugins/openapi-utils/api-report.md | 591 +----------------- plugins/openapi-utils/package.json | 2 +- plugins/openapi-utils/src/example.ts | 50 -- plugins/openapi-utils/src/router.ts | 20 +- plugins/openapi-utils/src/schema/petstore.ts | 183 ------ plugins/openapi-utils/src/types/common.ts | 86 +-- plugins/openapi-utils/src/types/express.ts | 15 +- plugins/openapi-utils/src/types/immutable.ts | 57 +- plugins/openapi-utils/src/types/index.ts | 36 +- plugins/openapi-utils/src/types/params.ts | 42 +- plugins/openapi-utils/src/types/requests.ts | 11 +- plugins/openapi-utils/src/types/responses.ts | 21 +- yarn.lock | 46 +- 17 files changed, 94 insertions(+), 1118 deletions(-) delete mode 100644 plugins/openapi-utils/src/example.ts delete mode 100644 plugins/openapi-utils/src/schema/petstore.ts diff --git a/plugins/catalog-backend/openapi.yaml b/plugins/catalog-backend/openapi.yaml index a52cc9235f..d2dd74fb33 100644 --- a/plugins/catalog-backend/openapi.yaml +++ b/plugins/catalog-backend/openapi.yaml @@ -77,7 +77,7 @@ components: required: false schema: type: integer - minimum: 1 + minimum: 0 limit: name: limit in: query diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 2d77c724c5..bdbf242590 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -46,7 +46,6 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", - "@backstage/backend-openapi-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", @@ -85,6 +84,7 @@ "zod": "^3.21.4" }, "devDependencies": { + "@backstage/backend-openapi-utils": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index 77fe4a24e8..3aff802660 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -50,7 +50,7 @@ import { locationInput, validateRequestBody, } from './util'; -import { ApiRouter } from '@backstage/backend-openapi-utils'; +import type { ApiRouter } from '@backstage/backend-openapi-utils'; import spec from '../../schema/openapi'; /** diff --git a/plugins/openapi-utils/README.md b/plugins/openapi-utils/README.md index 882b99b698..04344baa9d 100644 --- a/plugins/openapi-utils/README.md +++ b/plugins/openapi-utils/README.md @@ -1,55 +1,45 @@ -# @backstage/plugin-openapi-router +# @backstage/openapi-utils -## Purpose +## Summary -This package is meant to provide a typed Express router for an OpenAPI spec. Specs must be converted to JSON and then copied to a Typescript file. +This package is meant to provide a typed Express router for an OpenAPI spec. Based on the [oatx](https://github.com/varanauskas/oatx) library and adapted to override Express values. ## Getting Started ### Configuration -In your plugin's `schema/openapi.ts`, +1. Run `yarn --cwd 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. + +2. In your plugin's `src/service/createRouter.ts`, ```ts -export default { - // If your spec is in YAML, convert it to JSON, then paste it here. - // If your spec is in JSON, just paste it here. -} as const; -``` - -In your plugin's `service/createRouter.ts`, - -```ts -import {ApiRouter} from `@backstage/plugin-openapi-router`; -import spec from './schema/openapi' +import {ApiRouter} from `@backstage/backend-openapi-utils`; +import spec from '../../schema/openapi' ... export function createRouter(){ - const router = Router() as ApiRouter + const router = Router() as ApiRouter; + ... } ``` ### Limitations -1. OpenAPI definitions must be converted to Typescript files - From [#32063](https://github.com/microsoft/TypeScript/issues/32063), we cannot import JSON `as const`. If we could, this would allow us to force all specs to be JSON and then just import from a spec. -2. `as const` makes all fields `readonly` - To ensure a good DX of using a simple imported JSON spec, we want to remove any type issues between `readonly` arrays and mutable arrays. Typescript does not allow them to be compared, so converting all imports from the `openapi3-ts` library to `readonly` is important. +1. `as const` makes all fields `readonly` + To ensure a good DX of using a simple imported JSON spec, we want to remove any type issues between `readonly` arrays and mutable arrays. Typescript does not allow them to be compared, so converting all imports from the `openapi3-ts` library to `readonly` is important. This is achieved through the `ImmutableObject` type in `types/immutable.ts`. -```tsx +```ts ... +// We want an interface like this, Router() as ApiRouter + +// Not an interface like this, +Router() as ApiRouter> ... ``` -we need to type all internals of this package as `Immutable`. - ## Future Work ### Runtime validation -Using a package like [`express-openapi-validator`](https://www.npmjs.com/package/express-openapi-validator), would allow us to remove [validation of request bodies with `AJV`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/service/util.ts#L58). - -### PR-time verification. - -1. Verify that spec file matches the router input/output. +Using a package like [`express-openapi-validator`](https://www.npmjs.com/package/express-openapi-validator), would allow us to remove [validation of request bodies with `AJV`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/service/util.ts#L58). However, `AJV` currently doesn't have support for OpenAPI 3.1 and `express-openapi-validator` enforces full URL matching for paths, meaning it cannot be mounted at the router level. diff --git a/plugins/openapi-utils/api-report.md b/plugins/openapi-utils/api-report.md index a51fd8e4f7..7e5024b15b 100644 --- a/plugins/openapi-utils/api-report.md +++ b/plugins/openapi-utils/api-report.md @@ -3,599 +3,28 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import type { ContentObject } from 'openapi3-ts'; -import core from 'express-serve-static-core'; -import { FromSchema } from 'json-schema-to-ts'; -import { JSONSchema7 } from 'json-schema-to-ts'; -import type { OpenAPIObject } from 'openapi3-ts'; -import type { ParameterObject } from 'openapi3-ts'; -import type { ReferenceObject } from 'openapi3-ts'; -import type { RequestBodyObject } from 'openapi3-ts'; -import type { ResponseObject } from 'openapi3-ts'; import { Router } from 'express'; -import type { SchemaObject } from 'openapi3-ts'; // @public -export interface ApiRouter extends Router { +export interface ApiRouter extends Router { // (undocumented) - all: DocRequestMatcher; + all: core.RequestMatcher; // (undocumented) - delete: DocRequestMatcher; + delete: core.RequestMatcher; // (undocumented) - get: DocRequestMatcher; + get: core.RequestMatcher; // (undocumented) - head: DocRequestMatcher; + head: core.RequestMatcher; // (undocumented) - options: DocRequestMatcher; + options: core.RequestMatcher; // (undocumented) - patch: DocRequestMatcher; + patch: core.RequestMatcher; // (undocumented) - post: DocRequestMatcher; + post: core.RequestMatcher; // (undocumented) - put: DocRequestMatcher; + put: core.RequestMatcher; } // @public (undocumented) -export type ComponentRef< - Doc extends RequiredDoc, - Type extends ComponentTypes, - Ref extends ImmutableReferenceObject, -> = Ref extends { - $ref: `#/components/${Type}/${infer Name}`; -} - ? Name extends keyof Doc['components'][Type] - ? Doc['components'][Type][Name] extends ImmutableReferenceObject - ? ComponentRef - : Doc['components'][Type][Name] - : never - : never; - -// @public (undocumented) -export type ComponentTypes = Extract< - keyof Doc['components'], - string ->; - -// @public (undocumented) -export type ConvertAll = []> = T extends [ - infer First extends JSONSchema7, - ...infer Rest, -] - ? ConvertAll]> - : R; - -// @public (undocumented) -export interface CookieObject extends ParameterObject { - // (undocumented) - in: 'cookie'; - // (undocumented) - style?: 'form'; -} - -// @public (undocumented) -export type CookieSchema< - Doc extends RequiredDoc, - Path extends PathTemplate>, - Method extends DocPathMethod, -> = ParametersSchema, Method, ImmutableCookieObject>; - -// @public (undocumented) -export type DiscriminateUnion = Extract< - T, - Record ->; - -// @public (undocumented) -export type DocOperation< - Doc extends RequiredDoc, - Path extends keyof Doc['paths'], - Method extends keyof Doc['paths'][Path], -> = Doc['paths'][Path][Method]; - -// @public (undocumented) -export type DocParameter< - Doc extends RequiredDoc, - Path extends Extract, - Method extends keyof Doc['paths'][Path], - Parameter extends keyof Doc['paths'][Path][Method]['parameters'], -> = DocOperation< - Doc, - Path, - Method ->['parameters'][Parameter] extends ImmutableReferenceObject - ? 'parameters' extends ComponentTypes - ? ComponentRef< - Doc, - 'parameters', - DocOperation['parameters'][Parameter] - > - : never - : DocOperation['parameters'][Parameter]; - -// @public (undocumented) -export type DocParameters< - Doc extends RequiredDoc, - Path extends Extract, - Method extends keyof Doc['paths'][Path], -> = DocOperation['parameters'] extends ReadonlyArray - ? { - [Index in keyof DocOperation< - Doc, - Path, - Method - >['parameters']]: DocParameter; - } - : never; - -// @public -export type DocPath< - Doc extends PathDoc, - Path extends PathTemplate>, -> = ValueOf<{ - [Template in Extract< - keyof Doc['paths'], - string - >]: Path extends PathTemplate