Remove use of DeepWriteable. Support as const fully.

Signed-off-by: Aramis Sennyey <sennyeya@amazon.com>
This commit is contained in:
Aramis Sennyey
2023-02-28 13:57:35 -05:00
committed by Fredrik Adelöw
parent 6643f4fa68
commit 68c4160011
10 changed files with 146 additions and 1293 deletions
-1
View File
@@ -328,7 +328,6 @@ components:
- $ref: '#/components/schemas/JsonObject'
- type: object
properties:
properties:
links:
type: array
items:
@@ -50,7 +50,7 @@ import {
locationInput,
validateRequestBody,
} from './util';
import { ApiRouter, DeepWriteable } from '@backstage/plugin-openapi-router';
import { ApiRouter } from '@backstage/plugin-openapi-router';
import spec from './schema/openapi';
/**
@@ -87,7 +87,7 @@ export async function createRouter(
logger,
permissionIntegrationRouter,
} = options;
const router = Router() as ApiRouter<DeepWriteable<typeof spec>>;
const router = Router() as ApiRouter<typeof spec>;
router.use(express.json());
const readonlyEnabled =
@@ -34,7 +34,54 @@ export default {
components: {
examples: {},
headers: {},
parameters: {},
parameters: {
cursor: {
name: 'cursor',
in: 'query',
description: 'Cursor to a set page of results.',
required: false,
schema: {
type: 'string',
},
},
fields: {
name: 'fields',
in: 'query',
description: 'Restrict to just these fields in the response.',
required: false,
schema: {
type: 'string',
},
},
limit: {
name: 'limit',
in: 'query',
description: 'Number of records to return in the response.',
required: false,
schema: {
type: 'integer',
minimum: 1,
},
},
sortField: {
name: 'sortField',
in: 'query',
description: 'The fields to sort returned results by.',
required: false,
schema: {
type: 'array',
items: {
type: 'array',
items: {
type: 'string',
},
description: 'A two-item tuple of [field, order].',
},
},
explode: true,
style: 'form',
},
},
requestBodies: {},
responses: {},
schemas: {
@@ -253,19 +300,16 @@ export default {
},
additionalProperties: false,
},
EntityFacets: {
type: 'array',
items: {
$ref: '#/components/schemas/EntityFacet',
},
},
EntityFacetsResponse: {
type: 'object',
properties: {
facets: {
type: 'object',
additionalProperties: {
$ref: '#/components/schemas/EntityFacets',
type: 'array',
items: {
$ref: '#/components/schemas/EntityFacet',
},
},
},
},
@@ -349,7 +393,6 @@ export default {
{
type: 'object',
properties: {
properties: null,
links: {
type: 'array',
items: {
@@ -408,7 +451,7 @@ export default {
],
additionalProperties: false,
},
RecursivePartial_Entity_: {
RecursivePartialEntity: {
type: 'object',
properties: {
apiVersion: {
@@ -444,7 +487,7 @@ export default {
description: {
type: 'string',
description:
'A text to show to the user to inform about the choices made. Like, it could say\n"Found a CODEOWNERS file that covers this target, so we suggest leaving this \nfield empty; which would currently make it owned by X" where X is taken from the\ncodeowners file.',
'A text to show to the user to inform about the choices made. Like, it could say\n"Found a CODEOWNERS file that covers this target, so we suggest leaving this\nfield empty; which would currently make it owned by X" where X is taken from the\ncodeowners file.',
},
value: {
type: 'string',
@@ -479,7 +522,7 @@ export default {
},
},
entity: {
$ref: '#/components/schemas/RecursivePartial_Entity_',
$ref: '#/components/schemas/RecursivePartialEntity',
},
},
required: ['fields', 'entity'],
@@ -573,12 +616,11 @@ export default {
properties: {
nextCursor: {
type: 'string',
description: 'Base64 encoded database query for the next page.',
description: 'The cursor for the next batch of entities.',
},
prevCursor: {
type: 'string',
description:
'Base64 encoded database query for the previous page.',
description: 'The cursor for the previous batch of entities.',
},
},
},
@@ -928,13 +970,41 @@ export default {
],
parameters: [
{
$ref: '#/components/parameters/fields',
},
{
$ref: '#/components/parameters/limit',
},
{
$ref: '#/components/parameters/sortField',
},
{
$ref: '#/components/parameters/cursor',
},
{
name: 'fullTextFilterTerm',
in: 'query',
name: 'fields',
description: 'Text search term.',
required: false,
schema: {
type: 'string',
},
},
{
name: 'fullTextFilterFields',
in: 'query',
description:
'A comma separated list of fields to sort returned results by.',
required: false,
schema: {
type: 'array',
items: {
type: 'string',
},
},
explode: false,
style: 'form',
},
],
requestBody: {
required: true,
+2 -2
View File
@@ -15,7 +15,7 @@
*/
import express from 'express';
import Router from 'express-promise-router';
import { ApiRouter, DeepWriteable } from './router';
import { ApiRouter } from './router';
import doc from './schema/petstore';
interface RouterOptions {}
@@ -24,7 +24,7 @@ export async function createRouter(
options: RouterOptions,
): Promise<express.Router> {
console.log(options);
const router = Router() as ApiRouter<DeepWriteable<typeof doc>>;
const router = Router() as ApiRouter<typeof doc>;
router.get('/pets/:uid', (_, res) => {
res.json({
+1 -1
View File
@@ -20,5 +20,5 @@
* @packageDocumentation
*/
export type { ApiRouter, DeepWriteable } from './router';
export type { ApiRouter } from './router';
export * from './types';
+2 -2
View File
@@ -20,8 +20,8 @@ import { RequiredDoc, DocRequestMatcher } from './types';
* Helper to transform readonly `as const` API specs for the ApiRouter.
* @public
*/
export type DeepWriteable<T> = {
-readonly [P in keyof T]: DeepWriteable<T[P]>;
export type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
/**
File diff suppressed because it is too large Load Diff
@@ -19,11 +19,7 @@
*/
import { FromSchema, JSONSchema7 } from 'json-schema-to-ts';
import type {
ContentObject,
OpenAPIObject,
ReferenceObject,
} from 'openapi3-ts';
import { ContentObject, OpenAPIObject, ReferenceObject } from './immutable';
/**
* Basic OpenAPI spec with paths and components properties enforced.
@@ -0,0 +1,51 @@
/*
* 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 as MutableContentObject,
OpenAPIObject as MutableOpenApiObject,
ReferenceObject as MutableReferenceObject,
RequestBodyObject as MutableRequestBodyObject,
} 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.
*/
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]> };
// This works for objects, arrays and tuples:
export type ImmutableObject<T> = { readonly [K in keyof T]: Immutable<T[K]> };
export type ReferenceObject = ImmutableObject<MutableReferenceObject>;
export type OpenAPIObject = ImmutableObject<MutableOpenApiObject>;
export type ContentObject = ImmutableObject<MutableContentObject>;
export type RequestBodyObject = ImmutableObject<MutableRequestBodyObject>;
@@ -18,7 +18,6 @@
* Pulled from https://github.com/varanauskas/oatx.
*/
import type { ReferenceObject, RequestBodyObject } from 'openapi3-ts';
import type {
ComponentRef,
ComponentTypes,
@@ -31,6 +30,7 @@ import type {
PathTemplate,
ToTypeSafe,
} from './common';
import { ReferenceObject, RequestBodyObject } from './immutable';
/**
* @public