From 4ddb0d49123606feeffa55f252bbf279694ce730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Duliscou=C3=ABt?= Date: Thu, 19 Dec 2024 16:55:14 +0100 Subject: [PATCH 1/2] fix(openapi-typescript): handle nullable schemas --- .changeset/strange-cherries-collect.md | 5 + .../src/transform/schema-object.ts | 24 ++-- .../openapi-typescript/test/index.test.ts | 113 ++++++++++++++++++ 3 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 .changeset/strange-cherries-collect.md diff --git a/.changeset/strange-cherries-collect.md b/.changeset/strange-cherries-collect.md new file mode 100644 index 000000000..fed71ab05 --- /dev/null +++ b/.changeset/strange-cherries-collect.md @@ -0,0 +1,5 @@ +--- +"openapi-typescript": minor +--- + +Allow all types except UNKNOWN to be nullable diff --git a/packages/openapi-typescript/src/transform/schema-object.ts b/packages/openapi-typescript/src/transform/schema-object.ts index 80ec56b51..a41ce0e69 100644 --- a/packages/openapi-typescript/src/transform/schema-object.ts +++ b/packages/openapi-typescript/src/transform/schema-object.ts @@ -257,24 +257,20 @@ export function transformSchemaObjectWithComposition( } } - // if final type could be generated, return intersection of all members - if (finalType) { - // deprecated nullable - if (schemaObject.nullable && !schemaObject.default) { - return tsNullable([finalType]); + // When no final type can be generated, fall back to unknown type (or related variants) + if (!finalType) { + if ("type" in schemaObject) { + finalType = tsRecord(STRING, options.ctx.emptyObjectsUnknown ? UNKNOWN : NEVER); + } else { + finalType = UNKNOWN; } - return finalType; } - // otherwise fall back to unknown type (or related variants) - else { - // fallback: unknown - if (!("type" in schemaObject)) { - return UNKNOWN; - } - // if no type could be generated, fall back to “empty object” type - return tsRecord(STRING, options.ctx.emptyObjectsUnknown ? UNKNOWN : NEVER); + if (finalType !== UNKNOWN && schemaObject.nullable && !schemaObject.default) { + finalType = tsNullable([finalType]); } + + return finalType; } /** diff --git a/packages/openapi-typescript/test/index.test.ts b/packages/openapi-typescript/test/index.test.ts index 3b81ead07..0789d6757 100644 --- a/packages/openapi-typescript/test/index.test.ts +++ b/packages/openapi-typescript/test/index.test.ts @@ -759,6 +759,119 @@ export enum ApiPaths { }, }, ], + [ + "nullable > 3.0 syntax", + { + given: { + openapi: "3.0.3", + info: { + title: "Test", + version: "0", + }, + paths: {}, + components: { + schemas: { + obj1: { + title: "Nullable object", + type: "object", + properties: { + id: { + type: "string", + }, + }, + nullable: true, + }, + obj2: { + title: "Nullable empty object", + type: "object", + nullable: true, + }, + str: { + title: "Nullable string", + type: "string", + nullable: true, + }, + }, + }, + }, + want: `export type paths = Record; +export type webhooks = Record; +export interface components { + schemas: { + /** Nullable object */ + obj1: { + id?: string; + } | null; + /** Nullable empty object */ + obj2: Record | null; + /** Nullable string */ + str: string | null; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export type operations = Record;`, + }, + ], + [ + "nullable > 3.1 syntax", + { + given: { + openapi: "3.1.0", + info: { + title: "Test", + version: "0", + }, + paths: {}, + components: { + schemas: { + obj1: { + title: "Nullable object", + type: ["object", "null"], + properties: { + id: { + type: "string", + }, + }, + }, + obj2: { + title: "Nullable empty object", + type: ["object", "null"], + }, + str: { + title: "Nullable string", + type: ["string", "null"], + }, + }, + }, + }, + want: `export type paths = Record; +export type webhooks = Record; +export interface components { + schemas: { + /** Nullable object */ + obj1: { + id?: string; + } | null; + /** Nullable empty object */ + obj2: Record | null; + /** Nullable string */ + str: string | null; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export type operations = Record;`, + }, + ], ]; for (const [testName, { given, want, options, ci }] of tests) { From 234bcebb1f5070f93660ba0a7417436dc4523ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Duliscou=C3=ABt?= Date: Fri, 3 Jan 2025 09:22:37 +0100 Subject: [PATCH 2/2] chore(examples): regenerate after nullable handling fix --- .../examples/digital-ocean-api.ts | 6 +- .../github-api-export-type-immutable.ts | 60 +++++++++---------- .../examples/github-api-immutable.ts | 60 +++++++++---------- .../examples/github-api-required.ts | 60 +++++++++---------- .../examples/github-api-root-types.ts | 60 +++++++++---------- .../openapi-typescript/examples/github-api.ts | 60 +++++++++---------- 6 files changed, 153 insertions(+), 153 deletions(-) diff --git a/packages/openapi-typescript/examples/digital-ocean-api.ts b/packages/openapi-typescript/examples/digital-ocean-api.ts index 1ae505549..85f6ac19a 100644 --- a/packages/openapi-typescript/examples/digital-ocean-api.ts +++ b/packages/openapi-typescript/examples/digital-ocean-api.ts @@ -12439,7 +12439,7 @@ export interface components { * @description The Droplet that the floating IP has been assigned to. When you query a floating IP, if it is assigned to a Droplet, the entire Droplet object will be returned. If it is not assigned, the value will be null. * @example null */ - droplet?: Record | components["schemas"]["droplet"]; + droplet?: (Record | null) | components["schemas"]["droplet"]; /** * @description A boolean value indicating whether or not the floating IP has pending actions preventing new ones from being submitted. * @example true @@ -12780,7 +12780,7 @@ export interface components { * @description An object of key/value mappings specifying labels to apply to all nodes in a pool. Labels will automatically be applied to all existing nodes and any subsequent nodes added to the pool. Note that when a label is removed, it is not deleted from the nodes in the pool. * @example null */ - labels?: Record; + labels?: Record | null; /** @description An array of taints to apply to all nodes in a pool. Taints will automatically be applied to all existing nodes and any subsequent nodes added to the pool. When a taint is removed, it is deleted from all nodes in the pool. */ taints?: components["schemas"]["kubernetes_node_pool_taint"][]; /** @@ -14339,7 +14339,7 @@ export interface components { * @description The Droplet that the reserved IP has been assigned to. When you query a reserved IP, if it is assigned to a Droplet, the entire Droplet object will be returned. If it is not assigned, the value will be null. * @example null */ - droplet?: Record | components["schemas"]["droplet"]; + droplet?: (Record | null) | components["schemas"]["droplet"]; /** * @description A boolean value indicating whether or not the reserved IP has pending actions preventing new ones from being submitted. * @example true diff --git a/packages/openapi-typescript/examples/github-api-export-type-immutable.ts b/packages/openapi-typescript/examples/github-api-export-type-immutable.ts index a155755c4..ef5a93651 100644 --- a/packages/openapi-typescript/examples/github-api-export-type-immutable.ts +++ b/packages/openapi-typescript/examples/github-api-export-type-immutable.ts @@ -41164,7 +41164,7 @@ export type components = { readonly created_at: string; /** @description The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. */ readonly dismissed_at: string | null; - readonly dismissed_by: Record; + readonly dismissed_by: Record | null; /** @description The reason for dismissing or closing the alert. Can be one of: `false positive`, `won't fix`, and `used in tests`. */ readonly dismissed_reason: string | null; /** @@ -42189,7 +42189,7 @@ export type components = { readonly display_title: string; readonly event: string; readonly head_branch: string; - readonly head_commit?: Record; + readonly head_commit?: Record | null; readonly head_repository?: { readonly archive_url?: string; readonly assignees_url?: string; @@ -42496,7 +42496,7 @@ export type components = { readonly created_at: string; readonly event: string; readonly head_branch: string; - readonly head_commit?: Record; + readonly head_commit?: Record | null; readonly head_repository?: { readonly archive_url?: string; readonly assignees_url?: string; @@ -42844,7 +42844,7 @@ export type components = { readonly created_at: string; readonly event: string; readonly head_branch: string; - readonly head_commit?: Record; + readonly head_commit?: Record | null; readonly head_repository?: { readonly archive_url?: string; readonly assignees_url?: string; @@ -44324,7 +44324,7 @@ export type components = { readonly labels_url?: string; readonly language?: unknown; readonly languages_url?: string; - readonly license?: Record; + readonly license?: Record | null; readonly merges_url?: string; readonly milestones_url?: string; readonly mirror_url?: unknown; @@ -45131,7 +45131,7 @@ export type components = { readonly url?: string; readonly user_view_type?: string; } | null; - readonly assignees?: readonly Record[]; + readonly assignees?: readonly (Record | null)[]; readonly author_association?: string; readonly body?: string | null; readonly closed_at?: string | null; @@ -45158,10 +45158,10 @@ export type components = { }[]; readonly labels_url?: string; readonly locked: boolean; - readonly milestone?: Record; + readonly milestone?: Record | null; readonly node_id?: string; readonly number?: number; - readonly performed_via_github_app?: Record; + readonly performed_via_github_app?: Record | null; readonly reactions?: { readonly "+1"?: number; readonly "-1"?: number; @@ -45675,7 +45675,7 @@ export type components = { readonly url?: string; readonly user_view_type?: string; } | null; - readonly assignees?: readonly Record[]; + readonly assignees?: readonly (Record | null)[]; readonly author_association?: string; readonly body?: string | null; readonly closed_at?: string | null; @@ -45702,10 +45702,10 @@ export type components = { }[]; readonly labels_url?: string; readonly locked: boolean; - readonly milestone?: Record; + readonly milestone?: Record | null; readonly node_id?: string; readonly number?: number; - readonly performed_via_github_app?: Record; + readonly performed_via_github_app?: Record | null; readonly reactions?: { readonly "+1"?: number; readonly "-1"?: number; @@ -46221,7 +46221,7 @@ export type components = { readonly url?: string; readonly user_view_type?: string; } | null; - readonly assignees?: readonly Record[]; + readonly assignees?: readonly (Record | null)[]; readonly author_association?: string; readonly body?: string | null; readonly closed_at?: string | null; @@ -46248,10 +46248,10 @@ export type components = { }[]; readonly labels_url?: string; readonly locked: boolean; - readonly milestone?: Record; + readonly milestone?: Record | null; readonly node_id?: string; readonly number?: number; - readonly performed_via_github_app?: Record; + readonly performed_via_github_app?: Record | null; readonly reactions?: { readonly "+1"?: number; readonly "-1"?: number; @@ -46744,8 +46744,8 @@ export type components = { } | null; } & { readonly active_lock_reason?: string | null; - readonly assignee?: Record; - readonly assignees?: readonly Record[]; + readonly assignee?: Record | null; + readonly assignees?: readonly (Record | null)[]; readonly author_association?: string; readonly body?: string | null; readonly closed_at: string | null; @@ -46755,13 +46755,13 @@ export type components = { readonly events_url?: string; readonly html_url?: string; readonly id?: number; - readonly labels?: readonly Record[]; + readonly labels?: readonly (Record | null)[]; readonly labels_url?: string; readonly locked?: boolean; - readonly milestone?: Record; + readonly milestone?: Record | null; readonly node_id?: string; readonly number?: number; - readonly performed_via_github_app?: Record; + readonly performed_via_github_app?: Record | null; readonly reactions?: { readonly "+1"?: number; readonly "-1"?: number; @@ -52843,8 +52843,8 @@ export type components = { readonly body?: string | Record; readonly body_html?: string; readonly container_metadata?: { - readonly labels?: Record; - readonly manifest?: Record; + readonly labels?: Record | null; + readonly manifest?: Record | null; readonly tag?: { readonly digest?: string; readonly name?: string; @@ -52869,19 +52869,19 @@ export type components = { readonly name?: string; readonly version?: string; readonly npm_user?: string; - readonly author?: Record; - readonly bugs?: Record; + readonly author?: Record | null; + readonly bugs?: Record | null; readonly dependencies?: Record; readonly dev_dependencies?: Record; readonly peer_dependencies?: Record; readonly optional_dependencies?: Record; readonly description?: string; - readonly dist?: Record; + readonly dist?: Record | null; readonly git_head?: string; readonly homepage?: string; readonly license?: string; readonly main?: string; - readonly repository?: Record; + readonly repository?: Record | null; readonly scripts?: Record; readonly id?: string; readonly node_version?: string; @@ -52894,7 +52894,7 @@ export type components = { readonly files?: readonly string[]; readonly bin?: Record; readonly man?: Record; - readonly directories?: Record; + readonly directories?: Record | null; readonly os?: readonly string[]; readonly cpu?: readonly string[]; readonly readme?: string; @@ -82202,8 +82202,8 @@ export type components = { readonly body?: string | Record; readonly body_html?: string; readonly container_metadata?: { - readonly labels?: Record; - readonly manifest?: Record; + readonly labels?: Record | null; + readonly manifest?: Record | null; readonly tag?: { readonly digest?: string; readonly name?: string; @@ -82470,7 +82470,7 @@ export type components = { readonly updated_at: string; readonly version: string; }; - readonly registry: Record; + readonly registry: Record | null; readonly updated_at: string; }; readonly repository?: components["schemas"]["repository-webhooks"]; @@ -85136,7 +85136,7 @@ export type components = { readonly head_branch?: string | null; /** @description The name of the workflow. */ readonly workflow_name?: string | null; - readonly steps?: readonly Record[]; + readonly steps?: readonly (Record | null)[]; readonly url?: string; }; readonly deployment?: components["schemas"]["deployment"]; diff --git a/packages/openapi-typescript/examples/github-api-immutable.ts b/packages/openapi-typescript/examples/github-api-immutable.ts index 7591232fb..966d6b87c 100644 --- a/packages/openapi-typescript/examples/github-api-immutable.ts +++ b/packages/openapi-typescript/examples/github-api-immutable.ts @@ -41164,7 +41164,7 @@ export interface components { readonly created_at: string; /** @description The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. */ readonly dismissed_at: string | null; - readonly dismissed_by: Record; + readonly dismissed_by: Record | null; /** @description The reason for dismissing or closing the alert. Can be one of: `false positive`, `won't fix`, and `used in tests`. */ readonly dismissed_reason: string | null; /** @@ -42189,7 +42189,7 @@ export interface components { readonly display_title: string; readonly event: string; readonly head_branch: string; - readonly head_commit?: Record; + readonly head_commit?: Record | null; readonly head_repository?: { readonly archive_url?: string; readonly assignees_url?: string; @@ -42496,7 +42496,7 @@ export interface components { readonly created_at: string; readonly event: string; readonly head_branch: string; - readonly head_commit?: Record; + readonly head_commit?: Record | null; readonly head_repository?: { readonly archive_url?: string; readonly assignees_url?: string; @@ -42844,7 +42844,7 @@ export interface components { readonly created_at: string; readonly event: string; readonly head_branch: string; - readonly head_commit?: Record; + readonly head_commit?: Record | null; readonly head_repository?: { readonly archive_url?: string; readonly assignees_url?: string; @@ -44324,7 +44324,7 @@ export interface components { readonly labels_url?: string; readonly language?: unknown; readonly languages_url?: string; - readonly license?: Record; + readonly license?: Record | null; readonly merges_url?: string; readonly milestones_url?: string; readonly mirror_url?: unknown; @@ -45131,7 +45131,7 @@ export interface components { readonly url?: string; readonly user_view_type?: string; } | null; - readonly assignees?: readonly Record[]; + readonly assignees?: readonly (Record | null)[]; readonly author_association?: string; readonly body?: string | null; readonly closed_at?: string | null; @@ -45158,10 +45158,10 @@ export interface components { }[]; readonly labels_url?: string; readonly locked: boolean; - readonly milestone?: Record; + readonly milestone?: Record | null; readonly node_id?: string; readonly number?: number; - readonly performed_via_github_app?: Record; + readonly performed_via_github_app?: Record | null; readonly reactions?: { readonly "+1"?: number; readonly "-1"?: number; @@ -45675,7 +45675,7 @@ export interface components { readonly url?: string; readonly user_view_type?: string; } | null; - readonly assignees?: readonly Record[]; + readonly assignees?: readonly (Record | null)[]; readonly author_association?: string; readonly body?: string | null; readonly closed_at?: string | null; @@ -45702,10 +45702,10 @@ export interface components { }[]; readonly labels_url?: string; readonly locked: boolean; - readonly milestone?: Record; + readonly milestone?: Record | null; readonly node_id?: string; readonly number?: number; - readonly performed_via_github_app?: Record; + readonly performed_via_github_app?: Record | null; readonly reactions?: { readonly "+1"?: number; readonly "-1"?: number; @@ -46221,7 +46221,7 @@ export interface components { readonly url?: string; readonly user_view_type?: string; } | null; - readonly assignees?: readonly Record[]; + readonly assignees?: readonly (Record | null)[]; readonly author_association?: string; readonly body?: string | null; readonly closed_at?: string | null; @@ -46248,10 +46248,10 @@ export interface components { }[]; readonly labels_url?: string; readonly locked: boolean; - readonly milestone?: Record; + readonly milestone?: Record | null; readonly node_id?: string; readonly number?: number; - readonly performed_via_github_app?: Record; + readonly performed_via_github_app?: Record | null; readonly reactions?: { readonly "+1"?: number; readonly "-1"?: number; @@ -46744,8 +46744,8 @@ export interface components { } | null; } & { readonly active_lock_reason?: string | null; - readonly assignee?: Record; - readonly assignees?: readonly Record[]; + readonly assignee?: Record | null; + readonly assignees?: readonly (Record | null)[]; readonly author_association?: string; readonly body?: string | null; readonly closed_at: string | null; @@ -46755,13 +46755,13 @@ export interface components { readonly events_url?: string; readonly html_url?: string; readonly id?: number; - readonly labels?: readonly Record[]; + readonly labels?: readonly (Record | null)[]; readonly labels_url?: string; readonly locked?: boolean; - readonly milestone?: Record; + readonly milestone?: Record | null; readonly node_id?: string; readonly number?: number; - readonly performed_via_github_app?: Record; + readonly performed_via_github_app?: Record | null; readonly reactions?: { readonly "+1"?: number; readonly "-1"?: number; @@ -52843,8 +52843,8 @@ export interface components { readonly body?: string | Record; readonly body_html?: string; readonly container_metadata?: { - readonly labels?: Record; - readonly manifest?: Record; + readonly labels?: Record | null; + readonly manifest?: Record | null; readonly tag?: { readonly digest?: string; readonly name?: string; @@ -52869,19 +52869,19 @@ export interface components { readonly name?: string; readonly version?: string; readonly npm_user?: string; - readonly author?: Record; - readonly bugs?: Record; + readonly author?: Record | null; + readonly bugs?: Record | null; readonly dependencies?: Record; readonly dev_dependencies?: Record; readonly peer_dependencies?: Record; readonly optional_dependencies?: Record; readonly description?: string; - readonly dist?: Record; + readonly dist?: Record | null; readonly git_head?: string; readonly homepage?: string; readonly license?: string; readonly main?: string; - readonly repository?: Record; + readonly repository?: Record | null; readonly scripts?: Record; readonly id?: string; readonly node_version?: string; @@ -52894,7 +52894,7 @@ export interface components { readonly files?: readonly string[]; readonly bin?: Record; readonly man?: Record; - readonly directories?: Record; + readonly directories?: Record | null; readonly os?: readonly string[]; readonly cpu?: readonly string[]; readonly readme?: string; @@ -82202,8 +82202,8 @@ export interface components { readonly body?: string | Record; readonly body_html?: string; readonly container_metadata?: { - readonly labels?: Record; - readonly manifest?: Record; + readonly labels?: Record | null; + readonly manifest?: Record | null; readonly tag?: { readonly digest?: string; readonly name?: string; @@ -82470,7 +82470,7 @@ export interface components { readonly updated_at: string; readonly version: string; }; - readonly registry: Record; + readonly registry: Record | null; readonly updated_at: string; }; readonly repository?: components["schemas"]["repository-webhooks"]; @@ -85136,7 +85136,7 @@ export interface components { readonly head_branch?: string | null; /** @description The name of the workflow. */ readonly workflow_name?: string | null; - readonly steps?: readonly Record[]; + readonly steps?: readonly (Record | null)[]; readonly url?: string; }; readonly deployment?: components["schemas"]["deployment"]; diff --git a/packages/openapi-typescript/examples/github-api-required.ts b/packages/openapi-typescript/examples/github-api-required.ts index f562f0873..5b6e4ba00 100644 --- a/packages/openapi-typescript/examples/github-api-required.ts +++ b/packages/openapi-typescript/examples/github-api-required.ts @@ -41164,7 +41164,7 @@ export interface components { created_at: string; /** @description The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. */ dismissed_at: string | null; - dismissed_by: Record; + dismissed_by: Record | null; /** @description The reason for dismissing or closing the alert. Can be one of: `false positive`, `won't fix`, and `used in tests`. */ dismissed_reason: string | null; /** @@ -42189,7 +42189,7 @@ export interface components { display_title: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url: string; assignees_url: string; @@ -42496,7 +42496,7 @@ export interface components { created_at: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url: string; assignees_url: string; @@ -42844,7 +42844,7 @@ export interface components { created_at: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url: string; assignees_url: string; @@ -44324,7 +44324,7 @@ export interface components { labels_url?: string; language?: unknown; languages_url?: string; - license?: Record; + license?: Record | null; merges_url?: string; milestones_url?: string; mirror_url?: unknown; @@ -45131,7 +45131,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -45158,10 +45158,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1": number; "-1": number; @@ -45675,7 +45675,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -45702,10 +45702,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1": number; "-1": number; @@ -46221,7 +46221,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -46248,10 +46248,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1": number; "-1": number; @@ -46744,8 +46744,8 @@ export interface components { } | null; } & { active_lock_reason?: string | null; - assignee?: Record; - assignees?: Record[]; + assignee?: Record | null; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at: string | null; @@ -46755,13 +46755,13 @@ export interface components { events_url?: string; html_url?: string; id?: number; - labels?: Record[]; + labels?: (Record | null)[]; labels_url?: string; locked?: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1": number; "-1": number; @@ -52843,8 +52843,8 @@ export interface components { body?: string | Record; body_html?: string; container_metadata?: { - labels: Record; - manifest: Record; + labels: Record | null; + manifest: Record | null; tag: { digest: string; name: string; @@ -52869,19 +52869,19 @@ export interface components { name: string; version: string; npm_user: string; - author: Record; - bugs: Record; + author: Record | null; + bugs: Record | null; dependencies: Record; dev_dependencies: Record; peer_dependencies: Record; optional_dependencies: Record; description: string; - dist: Record; + dist: Record | null; git_head: string; homepage: string; license: string; main: string; - repository: Record; + repository: Record | null; scripts: Record; id: string; node_version: string; @@ -52894,7 +52894,7 @@ export interface components { files: string[]; bin: Record; man: Record; - directories: Record; + directories: Record | null; os: string[]; cpu: string[]; readme: string; @@ -82202,8 +82202,8 @@ export interface components { body?: string | Record; body_html?: string; container_metadata?: { - labels: Record; - manifest: Record; + labels: Record | null; + manifest: Record | null; tag: { digest: string; name: string; @@ -82470,7 +82470,7 @@ export interface components { updated_at: string; version: string; }; - registry: Record; + registry: Record | null; updated_at: string; }; repository?: components["schemas"]["repository-webhooks"]; @@ -85136,7 +85136,7 @@ export interface components { head_branch?: string | null; /** @description The name of the workflow. */ workflow_name?: string | null; - steps?: Record[]; + steps?: (Record | null)[]; url?: string; }; deployment?: components["schemas"]["deployment"]; diff --git a/packages/openapi-typescript/examples/github-api-root-types.ts b/packages/openapi-typescript/examples/github-api-root-types.ts index c08439d82..19bfd78c3 100644 --- a/packages/openapi-typescript/examples/github-api-root-types.ts +++ b/packages/openapi-typescript/examples/github-api-root-types.ts @@ -41164,7 +41164,7 @@ export interface components { created_at: string; /** @description The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. */ dismissed_at: string | null; - dismissed_by: Record; + dismissed_by: Record | null; /** @description The reason for dismissing or closing the alert. Can be one of: `false positive`, `won't fix`, and `used in tests`. */ dismissed_reason: string | null; /** @@ -42189,7 +42189,7 @@ export interface components { display_title: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url?: string; assignees_url?: string; @@ -42496,7 +42496,7 @@ export interface components { created_at: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url?: string; assignees_url?: string; @@ -42844,7 +42844,7 @@ export interface components { created_at: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url?: string; assignees_url?: string; @@ -44324,7 +44324,7 @@ export interface components { labels_url?: string; language?: unknown; languages_url?: string; - license?: Record; + license?: Record | null; merges_url?: string; milestones_url?: string; mirror_url?: unknown; @@ -45131,7 +45131,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -45158,10 +45158,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1"?: number; "-1"?: number; @@ -45675,7 +45675,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -45702,10 +45702,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1"?: number; "-1"?: number; @@ -46221,7 +46221,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -46248,10 +46248,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1"?: number; "-1"?: number; @@ -46744,8 +46744,8 @@ export interface components { } | null; } & { active_lock_reason?: string | null; - assignee?: Record; - assignees?: Record[]; + assignee?: Record | null; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at: string | null; @@ -46755,13 +46755,13 @@ export interface components { events_url?: string; html_url?: string; id?: number; - labels?: Record[]; + labels?: (Record | null)[]; labels_url?: string; locked?: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1"?: number; "-1"?: number; @@ -52843,8 +52843,8 @@ export interface components { body?: string | Record; body_html?: string; container_metadata?: { - labels?: Record; - manifest?: Record; + labels?: Record | null; + manifest?: Record | null; tag?: { digest?: string; name?: string; @@ -52869,19 +52869,19 @@ export interface components { name?: string; version?: string; npm_user?: string; - author?: Record; - bugs?: Record; + author?: Record | null; + bugs?: Record | null; dependencies?: Record; dev_dependencies?: Record; peer_dependencies?: Record; optional_dependencies?: Record; description?: string; - dist?: Record; + dist?: Record | null; git_head?: string; homepage?: string; license?: string; main?: string; - repository?: Record; + repository?: Record | null; scripts?: Record; id?: string; node_version?: string; @@ -52894,7 +52894,7 @@ export interface components { files?: string[]; bin?: Record; man?: Record; - directories?: Record; + directories?: Record | null; os?: string[]; cpu?: string[]; readme?: string; @@ -82202,8 +82202,8 @@ export interface components { body?: string | Record; body_html?: string; container_metadata?: { - labels?: Record; - manifest?: Record; + labels?: Record | null; + manifest?: Record | null; tag?: { digest?: string; name?: string; @@ -82470,7 +82470,7 @@ export interface components { updated_at: string; version: string; }; - registry: Record; + registry: Record | null; updated_at: string; }; repository?: components["schemas"]["repository-webhooks"]; @@ -85136,7 +85136,7 @@ export interface components { head_branch?: string | null; /** @description The name of the workflow. */ workflow_name?: string | null; - steps?: Record[]; + steps?: (Record | null)[]; url?: string; }; deployment?: components["schemas"]["deployment"]; diff --git a/packages/openapi-typescript/examples/github-api.ts b/packages/openapi-typescript/examples/github-api.ts index b4eb2bae5..20a0d85ff 100644 --- a/packages/openapi-typescript/examples/github-api.ts +++ b/packages/openapi-typescript/examples/github-api.ts @@ -41164,7 +41164,7 @@ export interface components { created_at: string; /** @description The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. */ dismissed_at: string | null; - dismissed_by: Record; + dismissed_by: Record | null; /** @description The reason for dismissing or closing the alert. Can be one of: `false positive`, `won't fix`, and `used in tests`. */ dismissed_reason: string | null; /** @@ -42189,7 +42189,7 @@ export interface components { display_title: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url?: string; assignees_url?: string; @@ -42496,7 +42496,7 @@ export interface components { created_at: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url?: string; assignees_url?: string; @@ -42844,7 +42844,7 @@ export interface components { created_at: string; event: string; head_branch: string; - head_commit?: Record; + head_commit?: Record | null; head_repository?: { archive_url?: string; assignees_url?: string; @@ -44324,7 +44324,7 @@ export interface components { labels_url?: string; language?: unknown; languages_url?: string; - license?: Record; + license?: Record | null; merges_url?: string; milestones_url?: string; mirror_url?: unknown; @@ -45131,7 +45131,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -45158,10 +45158,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1"?: number; "-1"?: number; @@ -45675,7 +45675,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -45702,10 +45702,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1"?: number; "-1"?: number; @@ -46221,7 +46221,7 @@ export interface components { url?: string; user_view_type?: string; } | null; - assignees?: Record[]; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at?: string | null; @@ -46248,10 +46248,10 @@ export interface components { }[]; labels_url?: string; locked: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1"?: number; "-1"?: number; @@ -46744,8 +46744,8 @@ export interface components { } | null; } & { active_lock_reason?: string | null; - assignee?: Record; - assignees?: Record[]; + assignee?: Record | null; + assignees?: (Record | null)[]; author_association?: string; body?: string | null; closed_at: string | null; @@ -46755,13 +46755,13 @@ export interface components { events_url?: string; html_url?: string; id?: number; - labels?: Record[]; + labels?: (Record | null)[]; labels_url?: string; locked?: boolean; - milestone?: Record; + milestone?: Record | null; node_id?: string; number?: number; - performed_via_github_app?: Record; + performed_via_github_app?: Record | null; reactions?: { "+1"?: number; "-1"?: number; @@ -52843,8 +52843,8 @@ export interface components { body?: string | Record; body_html?: string; container_metadata?: { - labels?: Record; - manifest?: Record; + labels?: Record | null; + manifest?: Record | null; tag?: { digest?: string; name?: string; @@ -52869,19 +52869,19 @@ export interface components { name?: string; version?: string; npm_user?: string; - author?: Record; - bugs?: Record; + author?: Record | null; + bugs?: Record | null; dependencies?: Record; dev_dependencies?: Record; peer_dependencies?: Record; optional_dependencies?: Record; description?: string; - dist?: Record; + dist?: Record | null; git_head?: string; homepage?: string; license?: string; main?: string; - repository?: Record; + repository?: Record | null; scripts?: Record; id?: string; node_version?: string; @@ -52894,7 +52894,7 @@ export interface components { files?: string[]; bin?: Record; man?: Record; - directories?: Record; + directories?: Record | null; os?: string[]; cpu?: string[]; readme?: string; @@ -82202,8 +82202,8 @@ export interface components { body?: string | Record; body_html?: string; container_metadata?: { - labels?: Record; - manifest?: Record; + labels?: Record | null; + manifest?: Record | null; tag?: { digest?: string; name?: string; @@ -82470,7 +82470,7 @@ export interface components { updated_at: string; version: string; }; - registry: Record; + registry: Record | null; updated_at: string; }; repository?: components["schemas"]["repository-webhooks"]; @@ -85136,7 +85136,7 @@ export interface components { head_branch?: string | null; /** @description The name of the workflow. */ workflow_name?: string | null; - steps?: Record[]; + steps?: (Record | null)[]; url?: string; }; deployment?: components["schemas"]["deployment"];