Rename to package/backend-openapi-utils.

Signed-off-by: Aramis Sennyey <sennyeya@amazon.com>
This commit is contained in:
Aramis Sennyey
2023-03-20 10:31:46 -04:00
committed by Fredrik Adelöw
parent f14d03d08a
commit 1f5800ae6d
15 changed files with 2 additions and 2 deletions
@@ -0,0 +1,24 @@
/*
* 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.
*/
/**
* Common functionalities for the openapi-router plugin.
*
* @packageDocumentation
*/
export type { ApiRouter } from './router';
export * from './types';
@@ -0,0 +1,39 @@
/*
* 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 { Router } from 'express';
import { core } from './types';
/**
* Typed Express router based on an OpenAPI 3.1 spec.
* @public
*/
export interface ApiRouter<Doc extends core.Spec> extends Router {
get: core.RequestMatcher<Doc, this, 'get'>;
post: core.RequestMatcher<Doc, this, 'post'>;
all: core.RequestMatcher<Doc, this, 'all'>;
put: core.RequestMatcher<Doc, this, 'put'>;
delete: core.RequestMatcher<Doc, this, 'delete'>;
patch: core.RequestMatcher<Doc, this, 'patch'>;
options: core.RequestMatcher<Doc, this, 'options'>;
head: core.RequestMatcher<Doc, this, 'head'>;
}
@@ -0,0 +1,16 @@
/*
* 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 {};
@@ -0,0 +1,209 @@
/*
* 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.
*/
/**
* Pulled from https://github.com/varanauskas/oatx.
*/
import { FromSchema, JSONSchema7 } from 'json-schema-to-ts';
import {
ImmutableContentObject,
ImmutableOpenAPIObject,
ImmutableReferenceObject,
} from './immutable';
/**
* Basic OpenAPI spec with paths and components properties enforced.
*/
export type RequiredDoc = Pick<ImmutableOpenAPIObject, 'paths' | 'components'>;
export type PathDoc = Pick<ImmutableOpenAPIObject, 'paths'>;
/**
* Get value types of `T`.
*/
export type ValueOf<T> = T[keyof T];
/**
* Validate a string against OpenAPI path template, {@link https://spec.openapis.org/oas/v3.1.0#path-templating-matching}.
*
* @example
* ```ts
* const path: PathTemplate<"/posts/{postId}/comments/{commentId}"> = "/posts/:postId/comments/:commentId";
* const pathWithoutParams: PathTemplate<"/posts/comments"> = "/posts/comments";
* ```
*/
export type PathTemplate<Path extends string> =
Path extends `${infer Prefix}{${infer PathName}}${infer Suffix}`
? `${Prefix}:${PathName}${PathTemplate<Suffix>}`
: Path;
/**
* Extract path as specified in OpenAPI `Doc` based on request path
* @example
* ```ts
* const spec = {
* paths: {
* "/posts/{postId}/comments/{commentId}": {},
* "/posts/comments": {},
* }
* };
* const specPathWithParams: DocPath<typeof spec, "/posts/:postId/comments/:commentId"> = "/posts/{postId}/comments/{commentId}";
* const specPathWithoutParams: DocPath<typeof spec, "/posts/comments"> = "/posts/comments";
* ```
*/
export type DocPath<
Doc extends PathDoc,
Path extends PathTemplate<Extract<keyof Doc['paths'], string>>,
> = ValueOf<{
[Template in Extract<
keyof Doc['paths'],
string
>]: Path extends PathTemplate<Template> ? Template : never;
}>;
export type DocPathTemplate<Doc extends PathDoc> = PathTemplate<
Extract<keyof Doc['paths'], string>
>;
export type DocPathMethod<
Doc extends Pick<RequiredDoc, 'paths'>,
Path extends DocPathTemplate<Doc>,
> = keyof Doc['paths'][DocPath<Doc, Path>];
export type MethodAwareDocPath<
Doc extends PathDoc,
Path extends PathTemplate<Extract<keyof Doc['paths'], string>>,
Method extends keyof Doc['paths'][Path],
> = ValueOf<{
[Template in Extract<
keyof Doc['paths'],
string
>]: Path extends PathTemplate<Template>
? Method extends DocPathMethod<Doc, Path>
? PathTemplate<Template>
: never
: never;
}>;
export type DocOperation<
Doc extends RequiredDoc,
Path extends keyof Doc['paths'],
Method extends keyof Doc['paths'][Path],
> = Doc['paths'][Path][Method];
export type ComponentTypes<Doc extends RequiredDoc> = Extract<
keyof Doc['components'],
string
>;
export type ComponentRef<
Doc extends RequiredDoc,
Type extends ComponentTypes<Doc>,
Ref extends ImmutableReferenceObject,
> = Ref extends { $ref: `#/components/${Type}/${infer Name}` }
? Name extends keyof Doc['components'][Type]
? Doc['components'][Type][Name] extends ImmutableReferenceObject
? ComponentRef<Doc, Type, Doc['components'][Type][Name]>
: Doc['components'][Type][Name]
: never
: never;
export type SchemaRef<Doc extends RequiredDoc, Schema> = Schema extends {
$ref: `#/components/schemas/${infer Name}`;
}
? 'schemas' extends keyof Doc['components']
? Name extends keyof Doc['components']['schemas']
? SchemaRef<Doc, Doc['components']['schemas'][Name]>
: never
: never
: { [Key in keyof Schema]: SchemaRef<Doc, Schema[Key]> };
export type ObjectWithContentSchema<
Doc extends RequiredDoc,
Object extends { content?: ImmutableContentObject },
> = Object['content'] extends ImmutableContentObject
? SchemaRef<Doc, Object['content']['application/json']['schema']>
: never;
/**
* From {@link https://stackoverflow.com/questions/71393738/typescript-intersection-not-union-type-from-json-schema}
*
* StackOverflow says not to do this, but union types aren't possible any other way.
*/
export type UnionToIntersection<U> = (
U extends any ? (k: U) => void : never
) extends (k: infer I) => void
? I
: never;
export type LastOf<T> = UnionToIntersection<
T extends any ? () => T : never
> extends () => infer R
? R
: never;
export type Push<T extends any[], V> = [...T, V];
export type TuplifyUnion<
T,
L = LastOf<T>,
N = [T] extends [never] ? true : false,
> = true extends N ? [] : Push<TuplifyUnion<Exclude<T, L>>, L>;
export type ConvertAll<T, R extends ReadonlyArray<unknown> = []> = T extends [
infer First extends JSONSchema7,
...infer Rest,
]
? ConvertAll<Rest, [...R, FromSchema<First>]>
: R;
export type UnknownIfNever<P> = [P] extends [never] ? unknown : P;
export type ToTypeSafe<T> = UnknownIfNever<ConvertAll<TuplifyUnion<T>>[number]>;
export type DiscriminateUnion<T, K extends keyof T, V extends T[K]> = Extract<
T,
Record<K, V>
>;
export type MapDiscriminatedUnion<
T extends Record<K, string>,
K extends keyof T,
> = {
[V in T[K]]: DiscriminateUnion<T, K, V>;
};
export type PickOptionalKeys<T extends { [key: string]: any }> = {
[K in keyof T]: true extends T[K]['required'] ? never : K;
}[keyof T];
export type PickRequiredKeys<T extends { [key: string]: any }> = {
[K in keyof T]: true extends T[K]['required'] ? K : never;
}[keyof T];
export type OptionalMap<T extends { [key: string]: any }> = {
[P in Exclude<PickOptionalKeys<T>, undefined>]?: NonNullable<T[P]>;
};
export type RequiredMap<T extends { [key: string]: any }> = {
[P in Exclude<PickRequiredKeys<T>, undefined>]: NonNullable<T[P]>;
};
export type FullMap<T extends { [key: string]: any }> = RequiredMap<T> &
OptionalMap<T>;
export type Filter<T, U> = T extends U ? T : never;
@@ -0,0 +1,76 @@
/*
* 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 core from 'express-serve-static-core';
import { DocPathTemplate, MethodAwareDocPath, RequiredDoc } from './common';
import { PathSchema, QuerySchema } from './params';
import { RequestBodyToJsonSchema } from './requests';
import { ResponseBodyToJsonSchema } from './responses';
/**
* Typed express request handler.
*/
type DocRequestHandler<
Doc extends RequiredDoc,
Path extends DocPathTemplate<Doc>,
Method extends keyof Doc['paths'][Path],
> = core.RequestHandler<
PathSchema<Doc, Path, Method>,
ResponseBodyToJsonSchema<Doc, Path, Method>,
RequestBodyToJsonSchema<Doc, Path, Method>,
QuerySchema<Doc, Path, Method>,
Record<string, string>
>;
/**
* Typed express error handler / request handler union type.
*/
type DocRequestHandlerParams<
Doc extends RequiredDoc,
Path extends DocPathTemplate<Doc>,
Method extends keyof Doc['paths'][Path],
> = core.RequestHandlerParams<
PathSchema<Doc, Path, Method>,
ResponseBodyToJsonSchema<Doc, Path, Method>,
RequestBodyToJsonSchema<Doc, Path, Method>,
QuerySchema<Doc, Path, Method>,
Record<string, string>
>;
/**
* Superset of the express router path matcher that enforces typed request and response bodies.
*/
export interface DocRequestMatcher<
Doc extends RequiredDoc,
T,
Method extends
| 'all'
| 'get'
| 'post'
| 'put'
| 'delete'
| 'patch'
| 'options'
| 'head',
> {
<Path extends MethodAwareDocPath<Doc, DocPathTemplate<Doc>, Method>>(
path: Path,
...handlers: Array<DocRequestHandler<Doc, Path, Method>>
): T;
<Path extends MethodAwareDocPath<Doc, DocPathTemplate<Doc>, Method>>(
path: Path,
...handlers: Array<DocRequestHandlerParams<Doc, Path, Method>>
): T;
}
@@ -0,0 +1,91 @@
/*
* 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 type {
ContentObject,
OpenAPIObject,
ReferenceObject,
RequestBodyObject,
ParameterObject,
SchemaObject,
ResponseObject,
} from 'openapi3-ts';
/**
* This file is meant to hold Immutable overwrites of the values provided by the `openapi3-ts`
* package due to issues with `as const` supporting only readonly values.
*/
/**
* From {@link https://github.com/microsoft/TypeScript/issues/13923#issuecomment-653675557}, allows
* us to convert from `as const` to the various OpenAPI types documented in `openapi3-ts`.
*/
export type Immutable<T> = T extends
| Function
| boolean
| number
| string
| null
| undefined
? T
: T extends Map<infer K, infer V>
? ReadonlyMap<Immutable<K>, Immutable<V>>
: T extends Set<infer S>
? ReadonlySet<Immutable<S>>
: { readonly [P in keyof T]: Immutable<T[P]> };
export type ImmutableObject<T> = { readonly [K in keyof T]: Immutable<T[K]> };
export type ImmutableReferenceObject = ImmutableObject<ReferenceObject>;
export type ImmutableOpenAPIObject = ImmutableObject<OpenAPIObject>;
export type ImmutableContentObject = ImmutableObject<ContentObject>;
export type ImmutableRequestBodyObject = ImmutableObject<RequestBodyObject>;
export type ImmutableResponseObject = ImmutableObject<ResponseObject>;
export type ImmutableParameterObject = ImmutableObject<ParameterObject>;
interface HeaderObject extends ParameterObject {
in: 'header';
style: 'simple';
}
export type ImmutableHeaderObject = ImmutableObject<HeaderObject>;
interface CookieObject extends ParameterObject {
in: 'cookie';
style?: 'form';
}
export type ImmutableCookieObject = ImmutableObject<CookieObject>;
interface QueryObject extends ParameterObject {
in: 'query';
style?: 'form' | 'deepObject' | 'pipeDelimited' | 'spaceDelimited';
}
export type ImmutableQueryObject = ImmutableObject<QueryObject>;
interface PathObject extends ParameterObject {
in: 'path';
style?: 'simple' | 'label' | 'matrix';
}
export type ImmutablePathObject = ImmutableObject<PathObject>;
export type ImmutableSchemaObject = ImmutableObject<SchemaObject>;
@@ -0,0 +1,45 @@
/*
* 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 type { RequiredDoc } from './common';
import type { DocRequestMatcher } from './express';
/**
* @public
*/
export namespace core {
/**
* @internal
*/
export type Spec = RequiredDoc;
/**
* @internal
*/
export type RequestMatcher<
Doc extends RequiredDoc,
T,
Method extends
| 'all'
| 'get'
| 'post'
| 'put'
| 'delete'
| 'patch'
| 'options'
| 'head',
> = DocRequestMatcher<Doc, T, Method>;
}
@@ -0,0 +1,141 @@
/*
* 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 {
ImmutableCookieObject,
ImmutableHeaderObject,
ImmutableParameterObject,
ImmutablePathObject,
ImmutableQueryObject,
ImmutableReferenceObject,
ImmutableSchemaObject,
} from './immutable';
import {
ComponentRef,
ComponentTypes,
DocOperation,
DocPath,
DocPathMethod,
Filter,
FullMap,
MapDiscriminatedUnion,
PathTemplate,
RequiredDoc,
} from './common';
import { FromSchema, JSONSchema7 } from 'json-schema-to-ts';
type DocParameter<
Doc extends RequiredDoc,
Path extends Extract<keyof Doc['paths'], string>,
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<Doc>
? ComponentRef<
Doc,
'parameters',
DocOperation<Doc, Path, Method>['parameters'][Parameter]
>
: never
: DocOperation<Doc, Path, Method>['parameters'][Parameter];
type DocParameters<
Doc extends RequiredDoc,
Path extends Extract<keyof Doc['paths'], string>,
Method extends keyof Doc['paths'][Path],
> = DocOperation<Doc, Path, Method>['parameters'] extends ReadonlyArray<any>
? {
[Index in keyof DocOperation<
Doc,
Path,
Method
>['parameters']]: DocParameter<Doc, Path, Method, Index>;
}
: never;
type ResolveDocParameterSchema<
Doc extends RequiredDoc,
Schema extends ImmutableParameterObject['schema'],
> = Schema extends ImmutableReferenceObject
? 'parameters' extends ComponentTypes<Doc>
? ComponentRef<Doc, 'parameters', Schema>
: never
: Schema;
type ParameterSchema<
Doc extends RequiredDoc,
Schema extends ImmutableParameterObject['schema'],
> = ResolveDocParameterSchema<Doc, Schema> extends infer R
? R extends ImmutableSchemaObject
? R extends JSONSchema7
? FromSchema<R>
: never
: never
: never;
type MapToSchema<
Doc extends RequiredDoc,
T extends Record<string, ImmutableParameterObject>,
> = {
[V in keyof T]: NonNullable<T[V]> extends ImmutableParameterObject
? ParameterSchema<Doc, NonNullable<T[V]>['schema']>
: never;
};
type ParametersSchema<
Doc extends RequiredDoc,
Path extends Extract<keyof Doc['paths'], string>,
Method extends keyof Doc['paths'][Path],
FilterType extends ImmutableParameterObject,
> = number extends keyof DocParameters<Doc, Path, Method>
? MapToSchema<
Doc,
FullMap<
MapDiscriminatedUnion<
Filter<DocParameters<Doc, Path, Method>[number], FilterType>,
'name'
>
>
>
: never;
export type HeaderSchema<
Doc extends RequiredDoc,
Path extends PathTemplate<Extract<keyof Doc['paths'], string>>,
Method extends DocPathMethod<Doc, Path>,
> = ParametersSchema<Doc, DocPath<Doc, Path>, Method, ImmutableHeaderObject>;
export type CookieSchema<
Doc extends RequiredDoc,
Path extends PathTemplate<Extract<keyof Doc['paths'], string>>,
Method extends DocPathMethod<Doc, Path>,
> = ParametersSchema<Doc, DocPath<Doc, Path>, Method, ImmutableCookieObject>;
export type PathSchema<
Doc extends RequiredDoc,
Path extends PathTemplate<Extract<keyof Doc['paths'], string>>,
Method extends DocPathMethod<Doc, Path>,
> = ParametersSchema<Doc, DocPath<Doc, Path>, Method, ImmutablePathObject>;
export type QuerySchema<
Doc extends RequiredDoc,
Path extends PathTemplate<Extract<keyof Doc['paths'], string>>,
Method extends DocPathMethod<Doc, Path>,
> = ParametersSchema<Doc, DocPath<Doc, Path>, Method, ImmutableQueryObject>;
@@ -0,0 +1,75 @@
/*
* 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.
*/
/**
* Pulled from https://github.com/varanauskas/oatx.
*/
import type {
ComponentRef,
ComponentTypes,
ObjectWithContentSchema,
RequiredDoc,
DocOperation,
DocPath,
DocPathMethod,
DocPathTemplate,
PathTemplate,
ToTypeSafe,
} from './common';
import {
ImmutableReferenceObject,
ImmutableRequestBodyObject,
} from './immutable';
type RequestBody<
Doc extends RequiredDoc,
Path extends Extract<keyof Doc['paths'], string>,
Method extends keyof Doc['paths'][Path],
> = DocOperation<
Doc,
Path,
Method
>['requestBody'] extends ImmutableReferenceObject
? 'requestBodies' extends ComponentTypes<Doc>
? ComponentRef<
Doc,
'requestBodies',
DocOperation<Doc, Path, Method>['requestBody']
>
: never
: DocOperation<Doc, Path, Method>['requestBody'];
type RequestBodySchema<
Doc extends RequiredDoc,
Path extends DocPathTemplate<Doc>,
Method extends DocPathMethod<Doc, Path>,
> = RequestBody<
Doc,
DocPath<Doc, Path>,
Method
> extends ImmutableRequestBodyObject
? ObjectWithContentSchema<Doc, RequestBody<Doc, DocPath<Doc, Path>, Method>>
: never;
/**
* Transform the OpenAPI request body schema to a typesafe JSON schema.
*/
export type RequestBodyToJsonSchema<
Doc extends RequiredDoc,
Path extends PathTemplate<Extract<keyof Doc['paths'], string>>,
Method extends DocPathMethod<Doc, Path>,
> = ToTypeSafe<RequestBodySchema<Doc, Path, Method>>;
@@ -0,0 +1,97 @@
/*
* 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.
*/
/**
* Pulled from https://github.com/varanauskas/oatx.
*/
import type {
ComponentRef,
ComponentTypes,
ObjectWithContentSchema,
RequiredDoc,
DocOperation,
DocPath,
DocPathMethod,
DocPathTemplate,
PathTemplate,
ToTypeSafe,
ValueOf,
} from './common';
import { ImmutableReferenceObject, ImmutableResponseObject } from './immutable';
type Response<
Doc extends RequiredDoc,
Path extends keyof Doc['paths'],
Method extends keyof Doc['paths'][Path],
StatusCode extends keyof Doc['paths'][Path]['responses'],
> = DocOperation<
Doc,
Path,
Method
>['responses'][StatusCode] extends ImmutableReferenceObject
? 'responses' extends ComponentTypes<Doc>
? ComponentRef<
Doc,
'responses',
DocOperation<Doc, Path, Method>['responses'][StatusCode]
>
: never
: DocOperation<Doc, Path, Method>['responses'][StatusCode];
type Responses<
Doc extends RequiredDoc,
Path extends keyof Doc['paths'],
Method extends keyof Doc['paths'][Path],
> = {
[StatusCode in keyof DocOperation<Doc, Path, Method>['responses']]: Response<
Doc,
Path,
Method,
StatusCode
>;
};
type ResponseSchema<
Doc extends RequiredDoc,
Object extends ImmutableResponseObject,
> = ObjectWithContentSchema<Doc, Object>;
type ResponseSchemas<
Doc extends RequiredDoc,
Path extends DocPathTemplate<Doc>,
Method extends DocPathMethod<Doc, Path>,
> = {
[StatusCode in keyof Responses<Doc, DocPath<Doc, Path>, Method>]: Responses<
Doc,
DocPath<Doc, Path>,
Method
>[StatusCode] extends ImmutableResponseObject
? ResponseSchema<
Doc,
Responses<Doc, DocPath<Doc, Path>, Method>[StatusCode]
>
: never;
};
/**
* Transform the OpenAPI request body schema to a typesafe JSON schema.
*/
export type ResponseBodyToJsonSchema<
Doc extends RequiredDoc,
Path extends PathTemplate<Extract<keyof Doc['paths'], string>>,
Method extends DocPathMethod<Doc, Path>,
> = ToTypeSafe<ValueOf<ResponseSchemas<Doc, Path, Method>>>;