diff --git a/packages/backend-openapi-utils/src/index.ts b/packages/backend-openapi-utils/src/index.ts index 57d9f755c2..320ad75e25 100644 --- a/packages/backend-openapi-utils/src/index.ts +++ b/packages/backend-openapi-utils/src/index.ts @@ -31,5 +31,10 @@ export type { PathParameters, } from './utility'; export type { ApiRouter } from './router'; +export type { + RequestMatcherByModelAndPath, + RequestMatcherByModelAndPathParams, +} from './types/express'; +export type { PathTemplate } from './types/common'; export { createValidatedOpenApiRouter, getOpenApiSpecRoute } from './stub'; export { wrapInOpenApiTestServer, wrapServer } from './testUtils'; diff --git a/packages/backend-openapi-utils/src/types/express.ts b/packages/backend-openapi-utils/src/types/express.ts index 127400099a..05266dade4 100644 --- a/packages/backend-openapi-utils/src/types/express.ts +++ b/packages/backend-openapi-utils/src/types/express.ts @@ -100,3 +100,29 @@ export interface DocRequestMatcher< > ): T; } + +export type RequestMatcherByModelAndPath< + PathParams, + QueryParams, + RequestBody, + ResponseBody, +> = core.RequestHandler< + PathParams, + ResponseBody, + RequestBody, + QueryParams, + Record +>; + +export type RequestMatcherByModelAndPathParams< + PathParams, + QueryParams, + RequestBody, + ResponseBody, +> = core.RequestHandlerParams< + PathParams, + ResponseBody, + RequestBody, + QueryParams, + Record +>; diff --git a/packages/catalog-client/src/index.ts b/packages/catalog-client/src/index.ts index 2e81942c2f..63748fa121 100644 --- a/packages/catalog-client/src/index.ts +++ b/packages/catalog-client/src/index.ts @@ -21,4 +21,6 @@ */ export { CatalogClient } from './CatalogClient'; -export * from './types'; +// export * from './types'; + +export * from './generated/models'; diff --git a/packages/repo-tools/plugins/catalog-backend/src/generated/.openapi-generator-ignore b/packages/repo-tools/plugins/catalog-backend/src/generated/.openapi-generator-ignore new file mode 100644 index 0000000000..1b59086ab7 --- /dev/null +++ b/packages/repo-tools/plugins/catalog-backend/src/generated/.openapi-generator-ignore @@ -0,0 +1,23 @@ +*.md +apis/baseapi.ts +apis/exception.ts +auth/* +http/* +middleware.ts +servers.ts +util.ts +configuration.ts +rxjsStub.ts +.gitignore +apis/*.ts +!apis/*.client.ts +models/*.ts +!models/*.model.ts +!index.ts +!**/index.ts +types/ObjectParamAPI.ts +types/ObservableAPI.ts +types/PromiseAPI.ts +git_push.sh +package.json +tsconfig.json \ No newline at end of file diff --git a/packages/repo-tools/src/commands/openapi/server/generate.ts b/packages/repo-tools/src/commands/openapi/server/generate.ts new file mode 100644 index 0000000000..380043efab --- /dev/null +++ b/packages/repo-tools/src/commands/openapi/server/generate.ts @@ -0,0 +1,101 @@ +/* + * 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. + */ + +import chalk from 'chalk'; +import { resolve } from 'path'; +import { OPENAPI_IGNORE_FILES, OUTPUT_PATH } from '../constants'; +import { paths as cliPaths } from '../../../lib/paths'; +import { mkdirpSync } from 'fs-extra'; +import fs from 'fs-extra'; +import { exec } from '../../../lib/exec'; +import { resolvePackagePath } from '@backstage/backend-common'; + +async function generate(spec: string, outputDirectory: string) { + const resolvedOpenapiPath = resolve(spec); + const resolvedOutputDirectory = resolve(outputDirectory, OUTPUT_PATH); + mkdirpSync(resolvedOutputDirectory); + + await fs.mkdirp(resolvedOutputDirectory); + + await fs.writeFile( + resolve(resolvedOutputDirectory, '.openapi-generator-ignore'), + OPENAPI_IGNORE_FILES.join('\n'), + ); + + await exec( + 'node', + [ + resolvePackagePath('@openapitools/openapi-generator-cli', 'main.js'), + 'generate', + '-i', + resolvedOpenapiPath, + '-o', + resolvedOutputDirectory, + '-g', + 'typescript', + '-c', + resolvePackagePath( + '@backstage/repo-tools', + 'templates/typescript-backstage.server.yaml', + ), + `--additional-properties=clientPackageName=@backstage/catalog-client`, + '--generator-key', + 'v3.0', + ], + { + maxBuffer: Number.MAX_VALUE, + cwd: resolvePackagePath('@backstage/repo-tools'), + env: { + ...process.env, + }, + }, + ); + + await exec( + `yarn backstage-cli package lint --fix ${resolvedOutputDirectory}`, + ); + + const prettier = cliPaths.resolveTargetRoot('node_modules/.bin/prettier'); + if (prettier) { + await exec(`${prettier} --write ${resolvedOutputDirectory}`); + } + + fs.removeSync(resolve(resolvedOutputDirectory, '.openapi-generator-ignore')); + + fs.rmSync(resolve(resolvedOutputDirectory, '.openapi-generator'), { + recursive: true, + force: true, + }); +} + +export async function singleCommand({ + inputSpec, + outputDirectory, +}: { + inputSpec: string; + outputDirectory: string; +}): Promise { + try { + await generate(inputSpec, outputDirectory); + console.log(chalk.green(`Generated client for ${inputSpec}`)); + } catch (err) { + console.log(); + console.log(chalk.red(`Client generation failed in ${outputDirectory}:`)); + console.log(err); + + process.exit(1); + } +} diff --git a/packages/repo-tools/src/commands/package/schema/openapi/generate/client.ts b/packages/repo-tools/src/commands/package/schema/openapi/generate/client.ts index 742f303f51..b9787a81d6 100644 --- a/packages/repo-tools/src/commands/package/schema/openapi/generate/client.ts +++ b/packages/repo-tools/src/commands/package/schema/openapi/generate/client.ts @@ -63,7 +63,7 @@ async function generate( '-c', resolvePackagePath( '@backstage/repo-tools', - 'templates/typescript-backstage.yaml', + 'templates/typescript-backstage.client.yaml', ), '--generator-key', 'v3.0', diff --git a/packages/repo-tools/templates/typescript-backstage.yaml b/packages/repo-tools/templates/typescript-backstage.client.yaml similarity index 59% rename from packages/repo-tools/templates/typescript-backstage.yaml rename to packages/repo-tools/templates/typescript-backstage.client.yaml index a2cb61c121..12f001654d 100644 --- a/packages/repo-tools/templates/typescript-backstage.yaml +++ b/packages/repo-tools/templates/typescript-backstage.client.yaml @@ -1,35 +1,35 @@ templateDir: templates/typescript-backstage files: - api.mustache: + client/api.mustache: templateType: API # For some reason, they check for destinationFilename differences. We have to change the ending to override the file. destinationFilename: .client.ts - model.mustache: + client/model.mustache: templateType: Model destinationFilename: .model.ts - modelGeneric.mustache: + client/models/modelGeneric.mustache: templateType: SupportingFiles - modelOneOf.mustache: + client/models/modelOneOf.mustache: templateType: SupportingFiles - modelGenericAdditionalProperties.mustache: + client/models/modelGenericAdditionalProperties.mustache: templateType: SupportingFiles - modelGenericEnums.mustache: + client/models/ modelGenericEnums.mustache: templateType: SupportingFiles - modelAlias.mustache: + client/models/modelAlias.mustache: templateType: SupportingFiles - modelEnum.mustache: + client/models/modelEnum.mustache: templateType: SupportingFiles - modelTaggedUnion.mustache: + client/models/modelTaggedUnion.mustache: templateType: SupportingFiles - models/models_all.mustache: + client/models/models_all.mustache: templateType: SupportingFiles destinationFilename: models/index.ts - types/fetch.ts: {} - types/discovery.ts: {} - apis/index.mustache: + client/types/fetch.ts: {} + client/types/discovery.ts: {} + client/apis/index.mustache: templateType: SupportingFiles destinationFilename: apis/index.ts - pluginId.mustache: + client/pluginId.mustache: templateType: SupportingFiles destinationFilename: pluginId.ts diff --git a/packages/repo-tools/templates/typescript-backstage.server.yaml b/packages/repo-tools/templates/typescript-backstage.server.yaml new file mode 100644 index 0000000000..546c3c181e --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage.server.yaml @@ -0,0 +1,10 @@ +templateDir: templates/typescript-backstage + +files: + server/api.mustache: + templateType: API + # For some reason, they check for destinationFilename differences. We have to change the ending to override the file. + destinationFilename: .client.ts + client/apis/index.mustache: + templateType: SupportingFiles + destinationFilename: apis/index.ts diff --git a/packages/repo-tools/templates/typescript-backstage/api.mustache b/packages/repo-tools/templates/typescript-backstage/client/api.mustache similarity index 100% rename from packages/repo-tools/templates/typescript-backstage/api.mustache rename to packages/repo-tools/templates/typescript-backstage/client/api.mustache diff --git a/packages/repo-tools/templates/typescript-backstage/apis/index.mustache b/packages/repo-tools/templates/typescript-backstage/client/apis/index.mustache similarity index 100% rename from packages/repo-tools/templates/typescript-backstage/apis/index.mustache rename to packages/repo-tools/templates/typescript-backstage/client/apis/index.mustache diff --git a/packages/repo-tools/templates/typescript-backstage/index.mustache b/packages/repo-tools/templates/typescript-backstage/client/index.mustache similarity index 100% rename from packages/repo-tools/templates/typescript-backstage/index.mustache rename to packages/repo-tools/templates/typescript-backstage/client/index.mustache diff --git a/packages/repo-tools/templates/typescript-backstage/model.mustache b/packages/repo-tools/templates/typescript-backstage/client/model.mustache similarity index 100% rename from packages/repo-tools/templates/typescript-backstage/model.mustache rename to packages/repo-tools/templates/typescript-backstage/client/model.mustache diff --git a/packages/repo-tools/templates/typescript-backstage/models/models_all.mustache b/packages/repo-tools/templates/typescript-backstage/client/models/models_all.mustache similarity index 100% rename from packages/repo-tools/templates/typescript-backstage/models/models_all.mustache rename to packages/repo-tools/templates/typescript-backstage/client/models/models_all.mustache diff --git a/packages/repo-tools/templates/typescript-backstage/pluginId.mustache b/packages/repo-tools/templates/typescript-backstage/client/pluginId.mustache similarity index 100% rename from packages/repo-tools/templates/typescript-backstage/pluginId.mustache rename to packages/repo-tools/templates/typescript-backstage/client/pluginId.mustache diff --git a/packages/repo-tools/templates/typescript-backstage/types/discovery.ts b/packages/repo-tools/templates/typescript-backstage/client/types/discovery.ts similarity index 100% rename from packages/repo-tools/templates/typescript-backstage/types/discovery.ts rename to packages/repo-tools/templates/typescript-backstage/client/types/discovery.ts diff --git a/packages/repo-tools/templates/typescript-backstage/types/fetch.ts b/packages/repo-tools/templates/typescript-backstage/client/types/fetch.ts similarity index 100% rename from packages/repo-tools/templates/typescript-backstage/types/fetch.ts rename to packages/repo-tools/templates/typescript-backstage/client/types/fetch.ts diff --git a/packages/repo-tools/templates/typescript-backstage/server/api.mustache b/packages/repo-tools/templates/typescript-backstage/server/api.mustache new file mode 100644 index 0000000000..7e1c82621c --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/server/api.mustache @@ -0,0 +1,45 @@ +{{>licenseInfo}} +import type { + PathTemplate,RequestMatcherByModelAndPath,RequestMatcherByModelAndPathParams +} from '@backstage/backend-openapi-utils'; +import type { +{{#imports}} + {{classname}}, +{{/imports}} +} from '{{clientPackageName}}'; +import {Router} from 'express'; + +type ExtendsString = Path; + + +{{#operations}} + +/** + * {{{description}}}{{^description}}no description{{/description}} + */ +{{! export interface TypedRouter extends Router { }} + + type InputOutput = { + {{#operation}} + + '#{{httpMethod}}|{{path}}': { + path: { + {{#pathParams}} + {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, + {{/pathParams}} + }, + query: { + {{#queryParams}} + {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, + {{/queryParams}} + }, + {{#bodyParam}} + body: {{{dataType}}}, + {{/bodyParam}} + response: {{{returnType}}}{{^returnType}}void{{/returnType}}, + }, + + {{/operation}} + } +{{! } }} +{{/operations}} diff --git a/packages/repo-tools/templates/typescript-backstage/server/content.mustache b/packages/repo-tools/templates/typescript-backstage/server/content.mustache new file mode 100644 index 0000000000..4ba5332132 --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/server/content.mustache @@ -0,0 +1,61 @@ +{{#lambda.lowercase}}{{httpMethod}}({{/lambda.lowercase}} + + path: ExtendsString>, + ...handlers: Array> + ): this; + + {{#lambda.lowercase}}{{httpMethod}}({{/lambda.lowercase}} + + path: ExtendsString>, + ...handlers: Array> + ): this; diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 12ca1a7be5..f3b55f929c 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -80,6 +80,7 @@ "@types/express": "^4.17.6", "codeowners-utils": "^1.0.2", "core-js": "^3.6.5", + "cross-fetch": "^4.0.0", "express": "^4.17.1", "fast-json-stable-stringify": "^2.1.0", "fs-extra": "^11.2.0", diff --git a/plugins/catalog-backend/src/generated/.openapi-generator-ignore b/plugins/catalog-backend/src/generated/.openapi-generator-ignore new file mode 100644 index 0000000000..1b59086ab7 --- /dev/null +++ b/plugins/catalog-backend/src/generated/.openapi-generator-ignore @@ -0,0 +1,23 @@ +*.md +apis/baseapi.ts +apis/exception.ts +auth/* +http/* +middleware.ts +servers.ts +util.ts +configuration.ts +rxjsStub.ts +.gitignore +apis/*.ts +!apis/*.client.ts +models/*.ts +!models/*.model.ts +!index.ts +!**/index.ts +types/ObjectParamAPI.ts +types/ObservableAPI.ts +types/PromiseAPI.ts +git_push.sh +package.json +tsconfig.json \ No newline at end of file diff --git a/plugins/catalog-backend/src/generated/.openapi-generator/FILES b/plugins/catalog-backend/src/generated/.openapi-generator/FILES new file mode 100644 index 0000000000..d8308a8aa6 --- /dev/null +++ b/plugins/catalog-backend/src/generated/.openapi-generator/FILES @@ -0,0 +1,3 @@ +apis/DefaultApi.client.ts +apis/index.ts +index.ts diff --git a/plugins/catalog-backend/src/generated/.openapi-generator/VERSION b/plugins/catalog-backend/src/generated/.openapi-generator/VERSION new file mode 100644 index 0000000000..4be2c727ad --- /dev/null +++ b/plugins/catalog-backend/src/generated/.openapi-generator/VERSION @@ -0,0 +1 @@ +6.5.0 \ No newline at end of file diff --git a/plugins/catalog-backend/src/generated/apis/DefaultApi.client.ts b/plugins/catalog-backend/src/generated/apis/DefaultApi.client.ts new file mode 100644 index 0000000000..43fff31806 --- /dev/null +++ b/plugins/catalog-backend/src/generated/apis/DefaultApi.client.ts @@ -0,0 +1,301 @@ +/* + * Copyright 2024 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. + */ + +import type core from 'express-serve-static-core'; + + +import type { + AnalyzeLocationRequest, + AnalyzeLocationResponse, + CreateLocation201Response, + CreateLocationRequest, + EntitiesBatchResponse, + EntitiesQueryResponse, + Entity, + EntityAncestryResponse, + EntityFacetsResponse, + GetEntitiesByRefsRequest, + GetLocations200ResponseInner, + Location, + RefreshEntityRequest, + ValidateEntityRequest, +} from '@backstage/catalog-client'; +import { Router } from 'express'; + + +/** + * no description + */ + + type InputOutput = { + + '#POST|/analyze-location': { + path: { + }, + query: { + }, + body: AnalyzeLocationRequest, + response: AnalyzeLocationResponse, + }, + + + '#POST|/locations': { + path: { + }, + query: { + dryRun?: string, + }, + body: CreateLocationRequest, + response: CreateLocation201Response, + }, + + + '#DELETE|/entities/by-uid/{uid}': { + path: { + uid: string, + }, + query: { + }, + response: void, + }, + + + '#DELETE|/locations/{id}': { + path: { + id: string, + }, + query: { + }, + response: void, + }, + + + '#GET|/entities': { + path: { + }, + query: { + fields?: Array, + limit?: number, + filter?: Array, + offset?: number, + after?: string, + order?: Array, + }, + response: Array, + }, + + + '#GET|/entities/by-query': { + path: { + }, + query: { + fields?: Array, + limit?: number, + orderField?: Array, + cursor?: string, + filter?: Array, + fullTextFilterTerm?: string, + fullTextFilterFields?: Array, + }, + response: EntitiesQueryResponse, + }, + + + '#POST|/entities/by-refs': { + path: { + }, + query: { + }, + body: GetEntitiesByRefsRequest, + response: EntitiesBatchResponse, + }, + + + '#GET|/entities/by-name/{kind}/{namespace}/{name}/ancestry': { + path: { + kind: string, + namespace: string, + name: string, + }, + query: { + }, + response: EntityAncestryResponse, + }, + + + '#GET|/entities/by-name/{kind}/{namespace}/{name}': { + path: { + kind: string, + namespace: string, + name: string, + }, + query: { + }, + response: Entity, + }, + + + '#GET|/entities/by-uid/{uid}': { + path: { + uid: string, + }, + query: { + }, + response: Entity, + }, + + + '#GET|/entity-facets': { + path: { + }, + query: { + facet: Array, + filter?: Array, + }, + response: EntityFacetsResponse, + }, + + + '#GET|/locations/{id}': { + path: { + id: string, + }, + query: { + }, + response: Location, + }, + + + '#GET|/locations': { + path: { + }, + query: { + }, + response: Array, + }, + + + '#POST|/refresh': { + path: { + }, + query: { + }, + body: RefreshEntityRequest, + response: void, + }, + + + '#POST|/validate-entity': { + path: { + }, + query: { + }, + body: ValidateEntityRequest, + response: void, + }, + + }; + +type ValueOf = T[keyof T]; + +type Filter = T extends K ? K : never; + +type ExtractDocPath = Path extends `#${string}|${infer OpenApiPath}` ? OpenApiPath : never; + +type ExtractDocMethod = Path extends `#${infer Method}|${string}` ? Method : never + +type DocPath = ExtractDocPath>; + +type DocPathMethod = ExtractDocMethod; + +/** + * Typed express request handler. + * @public + */ +export type DocRequestHandler< + Doc extends InputOutput, + Path extends DocPath, + Method extends DocPathMethod, +> = core.RequestHandler< + PathSchema, + ResponseBodyToJsonSchema, + RequestBodyToJsonSchema, + QuerySchema, + Record +>; + +/** + * Typed express error handler / request handler union type. + * @public + */ +export type DocRequestHandlerParams< + Doc extends RequiredDoc, + Path extends DocPath, + Method extends DocPathMethod, +> = core.RequestHandlerParams< + PathSchema, + ResponseBodyToJsonSchema, + RequestBodyToJsonSchema, + QuerySchema, + Record +>; + +/** + * Superset of the express router path matcher that enforces typed request and response bodies. + * @public + */ +export interface DocRequestMatcher< + Doc extends RequiredDoc, + T, + Method extends + | 'all' + | 'get' + | 'post' + | 'put' + | 'delete' + | 'patch' + | 'options' + | 'head', +> { + < + Path extends MethodAwareDocPath< + Doc, + PathTemplate>, + Method + >, + >( + path: Path, + ...handlers: Array< + DocRequestHandler, Method> + > + ): T; + < + Path extends MethodAwareDocPath< + Doc, + PathTemplate>, + Method + >, + >( + path: Path, + ...handlers: Array< + DocRequestHandlerParams, Method> + > + ): T; +} + +export interface TypedRouter extends Router { + get: +} diff --git a/plugins/catalog-backend/src/generated/apis/index.ts b/plugins/catalog-backend/src/generated/apis/index.ts new file mode 100644 index 0000000000..3f4657f6ca --- /dev/null +++ b/plugins/catalog-backend/src/generated/apis/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2024 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 * from './DefaultApi.client'; diff --git a/plugins/catalog-backend/src/generated/index.ts b/plugins/catalog-backend/src/generated/index.ts new file mode 100644 index 0000000000..ce0fac6ac4 --- /dev/null +++ b/plugins/catalog-backend/src/generated/index.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2024 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 * from "./http/http"; +export * from "./auth/auth"; +export * from "./models/all"; +export { createConfiguration } from "./configuration" +export { Configuration } from "./configuration" +export * from "./apis/exception"; +export * from "./servers"; +export { RequiredError } from "./apis/baseapi"; + +export { PromiseMiddleware as Middleware } from './middleware'; +export { PromiseDefaultApi as DefaultApi } from './types/PromiseAPI'; + diff --git a/plugins/catalog-backend/src/schema/openapi.generated.ts b/plugins/catalog-backend/src/schema/openapi.generated.ts index f3bd46c05c..ac3c93637a 100644 --- a/plugins/catalog-backend/src/schema/openapi.generated.ts +++ b/plugins/catalog-backend/src/schema/openapi.generated.ts @@ -18,6 +18,7 @@ // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** import { createValidatedOpenApiRouter } from '@backstage/backend-openapi-utils'; +import { TypedRouter } from '../generated/apis'; export const spec = { openapi: '3.0.3', diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index 4a89cfc6cb..d390fd4be5 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -57,6 +57,7 @@ import { } from '@backstage/backend-plugin-api'; import { LocationAnalyzer } from '@backstage/plugin-catalog-node'; import { AuthorizedValidationService } from './AuthorizedValidationService'; +import { TypedRouter } from '../generated/apis'; /** * Options used by {@link createRouter}. @@ -85,13 +86,13 @@ export interface RouterOptions { export async function createRouter( options: RouterOptions, ): Promise { - const router = await createOpenApiRouter({ + const router = (await createOpenApiRouter({ validatorOptions: { // We want the spec to be up to date with the expected value, but the return type needs // to be controlled by the router implementation not the request validator. ignorePaths: /^\/validate-entity\/?$/, }, - }); + })) as TypedRouter; const { entitiesCatalog, locationAnalyzer, diff --git a/yarn.lock b/yarn.lock index ba52ed11df..40eadc3977 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6038,6 +6038,7 @@ __metadata: better-sqlite3: ^11.0.0 codeowners-utils: ^1.0.2 core-js: ^3.6.5 + cross-fetch: ^4.0.0 express: ^4.17.1 fast-json-stable-stringify: ^2.1.0 fs-extra: ^11.2.0