openapi-typesafe 1.0.0-rc.1 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -5
- package/dist/adapters/redocly-loader/configured-headers.cjs +32 -0
- package/dist/adapters/redocly-loader/configured-headers.cjs.map +1 -0
- package/dist/adapters/redocly-loader/configured-headers.mjs +30 -0
- package/dist/adapters/redocly-loader/configured-headers.mjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +19 -6
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +18 -5
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.cjs +37 -4
- package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.mjs +37 -4
- package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-resolution-check.cjs +191 -0
- package/dist/adapters/redocly-loader/ref-resolution-check.cjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-resolution-check.mjs +189 -0
- package/dist/adapters/redocly-loader/ref-resolution-check.mjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-resolution-steps.cjs +73 -0
- package/dist/adapters/redocly-loader/ref-resolution-steps.cjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-resolution-steps.mjs +60 -0
- package/dist/adapters/redocly-loader/ref-resolution-steps.mjs.map +1 -0
- package/dist/adapters/redocly-loader/remote-fetch.cjs +41 -14
- package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-fetch.mjs +40 -14
- package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-load-errors.cjs +23 -5
- package/dist/adapters/redocly-loader/schema-load-errors.cjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-load-errors.mjs +23 -5
- package/dist/adapters/redocly-loader/schema-load-errors.mjs.map +1 -1
- package/dist/adapters/redocly-loader/unsupported-keys.cjs +9 -1
- package/dist/adapters/redocly-loader/unsupported-keys.cjs.map +1 -1
- package/dist/adapters/redocly-loader/unsupported-keys.mjs +9 -1
- package/dist/adapters/redocly-loader/unsupported-keys.mjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.cjs +6 -4
- package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.mjs +6 -4
- package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs +2 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs.map +1 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs +2 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs.map +1 -1
- package/dist/adapters/type-ast-bridge/print-typescript.cjs.map +1 -1
- package/dist/adapters/type-ast-bridge/print-typescript.mjs.map +1 -1
- package/dist/api/default-ports.cjs +9 -0
- package/dist/api/default-ports.cjs.map +1 -1
- package/dist/api/default-ports.mjs +8 -1
- package/dist/api/default-ports.mjs.map +1 -1
- package/dist/api/discriminator-patch.cjs +5 -1
- package/dist/api/discriminator-patch.cjs.map +1 -1
- package/dist/api/discriminator-patch.mjs +5 -1
- package/dist/api/discriminator-patch.mjs.map +1 -1
- package/dist/api/document-refs.cjs +15 -12
- package/dist/api/document-refs.cjs.map +1 -1
- package/dist/api/document-refs.mjs +15 -12
- package/dist/api/document-refs.mjs.map +1 -1
- package/dist/api/document-run.cjs +4 -2
- package/dist/api/document-run.cjs.map +1 -1
- package/dist/api/document-run.mjs +4 -2
- package/dist/api/document-run.mjs.map +1 -1
- package/dist/api/footer-sink.cjs +25 -2
- package/dist/api/footer-sink.cjs.map +1 -1
- package/dist/api/footer-sink.mjs +25 -2
- package/dist/api/footer-sink.mjs.map +1 -1
- package/dist/api/legacy-callback-warning.cjs +4 -1
- package/dist/api/legacy-callback-warning.cjs.map +1 -1
- package/dist/api/legacy-callback-warning.mjs +4 -1
- package/dist/api/legacy-callback-warning.mjs.map +1 -1
- package/dist/api/legacy-ts-helpers.cjs.map +1 -1
- package/dist/api/legacy-ts-helpers.mjs.map +1 -1
- package/dist/api/legacy-utils.cjs.map +1 -1
- package/dist/api/legacy-utils.mjs.map +1 -1
- package/dist/api/openapi-ts.cjs +2 -1
- package/dist/api/openapi-ts.cjs.map +1 -1
- package/dist/api/openapi-ts.mjs +3 -2
- package/dist/api/openapi-ts.mjs.map +1 -1
- package/dist/api/transform-context.cjs +1 -1
- package/dist/api/transform-context.cjs.map +1 -1
- package/dist/api/transform-context.mjs +1 -1
- package/dist/api/transform-context.mjs.map +1 -1
- package/dist/api/transform-schema.cjs.map +1 -1
- package/dist/api/transform-schema.mjs.map +1 -1
- package/dist/application/print/type-printer.cjs +2 -1
- package/dist/application/print/type-printer.cjs.map +1 -1
- package/dist/application/print/type-printer.mjs +2 -1
- package/dist/application/print/type-printer.mjs.map +1 -1
- package/dist/application/transform/document/parameters.cjs +1 -1
- package/dist/application/transform/document/parameters.cjs.map +1 -1
- package/dist/application/transform/document/parameters.mjs +1 -1
- package/dist/application/transform/document/parameters.mjs.map +1 -1
- package/dist/application/transform/document/paths.cjs +1 -1
- package/dist/application/transform/document/paths.cjs.map +1 -1
- package/dist/application/transform/document/paths.mjs +1 -1
- package/dist/application/transform/document/paths.mjs.map +1 -1
- package/dist/application/transform/footer/evaluation.cjs +9 -0
- package/dist/application/transform/footer/evaluation.cjs.map +1 -1
- package/dist/application/transform/footer/evaluation.mjs +8 -1
- package/dist/application/transform/footer/evaluation.mjs.map +1 -1
- package/dist/application/transform/footer/type-evaluation.cjs +4 -112
- package/dist/application/transform/footer/type-evaluation.cjs.map +1 -1
- package/dist/application/transform/footer/type-evaluation.mjs +4 -112
- package/dist/application/transform/footer/type-evaluation.mjs.map +1 -1
- package/dist/application/transform/footer/type-indexing.cjs +107 -0
- package/dist/application/transform/footer/type-indexing.cjs.map +1 -0
- package/dist/application/transform/footer/type-indexing.mjs +105 -0
- package/dist/application/transform/footer/type-indexing.mjs.map +1 -0
- package/dist/cli/api-settings.cjs +78 -0
- package/dist/cli/api-settings.cjs.map +1 -0
- package/dist/cli/api-settings.mjs +73 -0
- package/dist/cli/api-settings.mjs.map +1 -0
- package/dist/cli/cli-arguments.cjs +1 -0
- package/dist/cli/cli-arguments.cjs.map +1 -1
- package/dist/cli/cli-arguments.mjs +1 -1
- package/dist/cli/cli-arguments.mjs.map +1 -1
- package/dist/cli/help-text.cjs +3 -3
- package/dist/cli/help-text.cjs.map +1 -1
- package/dist/cli/help-text.mjs +3 -3
- package/dist/cli/help-text.mjs.map +1 -1
- package/dist/cli/redocly-apis.cjs +8 -4
- package/dist/cli/redocly-apis.cjs.map +1 -1
- package/dist/cli/redocly-apis.mjs +7 -3
- package/dist/cli/redocly-apis.mjs.map +1 -1
- package/dist/cli/run-cli.cjs +5 -1
- package/dist/cli/run-cli.cjs.map +1 -1
- package/dist/cli/run-cli.mjs +5 -1
- package/dist/cli/run-cli.mjs.map +1 -1
- package/dist/domain/errors.cjs +4 -1
- package/dist/domain/errors.cjs.map +1 -1
- package/dist/domain/errors.mjs +4 -1
- package/dist/domain/errors.mjs.map +1 -1
- package/dist/domain/ir/constructors.cjs +2 -0
- package/dist/domain/ir/constructors.cjs.map +1 -1
- package/dist/domain/ir/constructors.mjs +2 -1
- package/dist/domain/ir/constructors.mjs.map +1 -1
- package/dist/domain/openapi/path-templates.cjs +1 -1
- package/dist/domain/openapi/path-templates.cjs.map +1 -1
- package/dist/domain/openapi/path-templates.mjs +1 -1
- package/dist/domain/openapi/path-templates.mjs.map +1 -1
- package/dist/domain/url-credentials.cjs +10 -0
- package/dist/domain/url-credentials.cjs.map +1 -0
- package/dist/domain/url-credentials.mjs +8 -0
- package/dist/domain/url-credentials.mjs.map +1 -0
- package/dist/domain/warnings.cjs +9 -1
- package/dist/domain/warnings.cjs.map +1 -1
- package/dist/domain/warnings.mjs +9 -1
- package/dist/domain/warnings.mjs.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1160 -53
- package/dist/index.d.mts +1160 -53
- package/dist/index.d.ts +1160 -53
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/transform/path-item-object.cjs.map +1 -1
- package/dist/transform/path-item-object.mjs.map +1 -1
- package/package.json +6 -5
- package/src/adapters/redocly-loader/configured-headers.ts +65 -0
- package/src/adapters/redocly-loader/redocly-schema-loader.ts +22 -7
- package/src/adapters/redocly-loader/ref-access.ts +60 -5
- package/src/adapters/redocly-loader/ref-resolution-check.ts +257 -0
- package/src/adapters/redocly-loader/ref-resolution-steps.ts +113 -0
- package/src/adapters/redocly-loader/remote-fetch.ts +77 -21
- package/src/adapters/redocly-loader/schema-load-errors.ts +33 -11
- package/src/adapters/redocly-loader/unsupported-keys.ts +17 -2
- package/src/adapters/terminal-logger/terminal-logger.ts +9 -5
- package/src/adapters/type-ast-bridge/ir-to-typescript.ts +2 -1
- package/src/adapters/type-ast-bridge/print-typescript.ts +3 -1
- package/src/adapters/type-ast-bridge/typescript-types.ts +57 -5
- package/src/api/default-ports.ts +16 -0
- package/src/api/discriminator-patch.ts +7 -2
- package/src/api/document-refs.ts +19 -15
- package/src/api/document-run.ts +9 -6
- package/src/api/footer-sink.ts +34 -2
- package/src/api/legacy-callback-warning.ts +7 -3
- package/src/api/legacy-ts-helpers.ts +7 -5
- package/src/api/legacy-utils.ts +1 -1
- package/src/api/openapi-ts.ts +2 -0
- package/src/api/run-context.ts +34 -0
- package/src/api/transform-context.ts +10 -8
- package/src/api/transform-schema.ts +6 -5
- package/src/application/print/type-printer.ts +2 -1
- package/src/application/transform/document/parameters.ts +2 -1
- package/src/application/transform/document/paths.ts +2 -1
- package/src/application/transform/footer/evaluation.ts +10 -0
- package/src/application/transform/footer/type-evaluation.ts +6 -133
- package/src/application/transform/footer/type-indexing.ts +152 -0
- package/src/cli/api-settings.ts +109 -0
- package/src/cli/cli-arguments.ts +5 -2
- package/src/cli/help-text.ts +4 -4
- package/src/cli/redocly-apis.ts +13 -7
- package/src/cli/run-cli.ts +5 -1
- package/src/domain/errors.ts +8 -2
- package/src/domain/ir/constructors.ts +3 -0
- package/src/domain/ir/nodes.ts +9 -6
- package/src/domain/openapi/path-templates.ts +2 -1
- package/src/domain/url-credentials.ts +18 -0
- package/src/domain/warnings.ts +8 -0
- package/src/index.ts +1 -0
- package/src/transform/path-item-object.ts +6 -2
- package/src/types/generator-options.ts +12 -32
- package/src/types/openapi-common.ts +1 -0
- package/src/types/openapi-request.ts +3 -0
- package/src/types/openapi-schema.ts +2 -0
- package/src/types/openapi-security.ts +1 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { IrMember, IrType } from "../../../domain/ir/nodes.js";
|
|
2
|
+
import {
|
|
3
|
+
type Evaluated,
|
|
4
|
+
type Evaluation,
|
|
5
|
+
intersectionType,
|
|
6
|
+
isNullish,
|
|
7
|
+
MISSING,
|
|
8
|
+
NEVER,
|
|
9
|
+
OPAQUE,
|
|
10
|
+
propertyKey,
|
|
11
|
+
unionType,
|
|
12
|
+
} from "./evaluation.js";
|
|
13
|
+
import { declaredFirst, isNeverIntersection, type TypeExpansion } from "./type-rules.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Indexed access (`T["key"]`, `T[number]`) on the generated types, as TypeScript reads it, for
|
|
17
|
+
* the evaluator of the `--enum-values` check (ADR-027).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** The part of the evaluator that indexed access uses. */
|
|
21
|
+
export interface IndexedTypes extends TypeExpansion {
|
|
22
|
+
expand(value: Evaluated): Evaluation;
|
|
23
|
+
index(value: Evaluated, index: IrType): Evaluation;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** `value[index]` for a string literal, `string` or `number` index. */
|
|
27
|
+
export function indexType(types: IndexedTypes, value: Evaluated, index: IrType): Evaluation {
|
|
28
|
+
const owner = types.expand(value);
|
|
29
|
+
if (owner.kind !== "type") {
|
|
30
|
+
return owner;
|
|
31
|
+
}
|
|
32
|
+
if (types.membersOf(owner).length > 1) {
|
|
33
|
+
return unionIndex(types, owner, index);
|
|
34
|
+
}
|
|
35
|
+
const { type } = owner;
|
|
36
|
+
switch (type.kind) {
|
|
37
|
+
case "object":
|
|
38
|
+
return memberType(types, owner, type.members, index);
|
|
39
|
+
case "intersection":
|
|
40
|
+
return partsIndex(types, owner, type.types, index);
|
|
41
|
+
case "union":
|
|
42
|
+
return unionIndex(types, owner, index);
|
|
43
|
+
case "array":
|
|
44
|
+
return isNumberIndex(index) ? flattened(types, owner, type.element) : builtInIndex(index);
|
|
45
|
+
case "keyword":
|
|
46
|
+
return type.keyword === "never" ? owner : builtInIndex(index);
|
|
47
|
+
default:
|
|
48
|
+
return builtInIndex(index);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function memberType(
|
|
53
|
+
types: IndexedTypes,
|
|
54
|
+
owner: Evaluated,
|
|
55
|
+
members: readonly IrMember[],
|
|
56
|
+
index: IrType,
|
|
57
|
+
): Evaluation {
|
|
58
|
+
const key = indexKey(index);
|
|
59
|
+
const property = members.find(
|
|
60
|
+
(member) => member.kind === "property" && key !== null && propertyKey(member.name) === key,
|
|
61
|
+
);
|
|
62
|
+
if (property !== undefined) {
|
|
63
|
+
return flattened(types, owner, property.type);
|
|
64
|
+
}
|
|
65
|
+
const signature = members.find((member) => member.kind === "indexSignature");
|
|
66
|
+
if (signature !== undefined) {
|
|
67
|
+
return flattened(types, owner, signature.type);
|
|
68
|
+
}
|
|
69
|
+
return key === null || isObjectBuiltIn(key) ? OPAQUE : MISSING;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function partsIndex(
|
|
73
|
+
types: IndexedTypes,
|
|
74
|
+
owner: Evaluated,
|
|
75
|
+
parts: readonly IrType[],
|
|
76
|
+
index: IrType,
|
|
77
|
+
): Evaluation {
|
|
78
|
+
if (isNeverIntersection(types, owner, parts)) {
|
|
79
|
+
return { ...owner, type: NEVER };
|
|
80
|
+
}
|
|
81
|
+
const found = parts.map((type) => types.index({ ...owner, type }, index));
|
|
82
|
+
if (found.some((part) => part.kind === "opaque")) {
|
|
83
|
+
return OPAQUE;
|
|
84
|
+
}
|
|
85
|
+
const read = parts.map((type, at) => ({ type, found: found[at] as Evaluation }));
|
|
86
|
+
const kept = declaredFirst(types, owner, indexKey(index), read).flatMap((part) =>
|
|
87
|
+
part.kind === "type" ? [part.type] : [],
|
|
88
|
+
);
|
|
89
|
+
return kept.length === 0 ? MISSING : { ...owner, type: intersectionType(kept) };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function unionIndex(types: IndexedTypes, owner: Evaluated, index: IrType): Evaluation {
|
|
93
|
+
const found = types
|
|
94
|
+
.membersOf(owner)
|
|
95
|
+
.map((member) => (member.kind === "type" ? types.index(member, index) : member));
|
|
96
|
+
if (found.some((member) => member.kind === "missing")) {
|
|
97
|
+
return MISSING;
|
|
98
|
+
}
|
|
99
|
+
if (found.some((member) => member.kind === "opaque")) {
|
|
100
|
+
return OPAQUE;
|
|
101
|
+
}
|
|
102
|
+
return { ...owner, type: unionType((found as Evaluated[]).map((member) => member.type)) };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* A member read through `FlattenedDeepRequired`: a value that is only arrays (and `undefined` or
|
|
107
|
+
* `null`) is replaced by its elements, anything else loses `undefined` and `null`.
|
|
108
|
+
*/
|
|
109
|
+
function flattened(types: IndexedTypes, owner: Evaluated, type: IrType): Evaluation {
|
|
110
|
+
const member: Evaluated = { ...owner, type };
|
|
111
|
+
if (!owner.deep) {
|
|
112
|
+
return types.expand(member);
|
|
113
|
+
}
|
|
114
|
+
const members = types.membersOf(member);
|
|
115
|
+
if (members.some((candidate) => candidate.kind !== "type")) {
|
|
116
|
+
return OPAQUE;
|
|
117
|
+
}
|
|
118
|
+
const present = (members as Evaluated[]).filter((candidate) => !isNullish(candidate.type));
|
|
119
|
+
const elements = present.map((candidate) => arrayElement(candidate.type));
|
|
120
|
+
if (present.length > 0 && elements.every((element) => element !== null)) {
|
|
121
|
+
return types.expand({ ...owner, type: unionType(elements as IrType[]) });
|
|
122
|
+
}
|
|
123
|
+
return { ...owner, type: unionType(present.map((candidate) => candidate.type)) };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** The element of an expanded member; expanding already dropped `readonly`. */
|
|
127
|
+
function arrayElement(type: IrType): IrType | null {
|
|
128
|
+
return type.kind === "array" ? type.element : null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function indexKey(index: IrType): string | null {
|
|
132
|
+
if (index.kind === "stringLiteral") {
|
|
133
|
+
return index.value;
|
|
134
|
+
}
|
|
135
|
+
return index.kind === "numberLiteral" ? String(index.value) : null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function isNumberIndex(index: IrType): boolean {
|
|
139
|
+
const key = indexKey(index);
|
|
140
|
+
return (index.kind === "keyword" && index.keyword === "number") || /^\d+$/.test(key ?? "");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function isObjectBuiltIn(key: string): boolean {
|
|
144
|
+
return key in {};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** A key of a primitive or an array: a built-in member is opaque, any other key is missing. */
|
|
148
|
+
function builtInIndex(index: IrType): Evaluation {
|
|
149
|
+
const key = indexKey(index);
|
|
150
|
+
const isBuiltIn = key === null || key in String.prototype || key in Array.prototype;
|
|
151
|
+
return isBuiltIn || key in Number.prototype ? OPAQUE : MISSING;
|
|
152
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { kebabCase } from "scule";
|
|
2
|
+
import { WARNING_CODES, warningText } from "../domain/warnings.js";
|
|
3
|
+
import { GENERATOR_FLAGS, hostList } from "./cli-arguments.js";
|
|
4
|
+
import { cliError } from "./cli-errors.js";
|
|
5
|
+
import { resolveLocationUrl } from "./cli-output.js";
|
|
6
|
+
import type { RefLimitOptions } from "./ref-limits.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name
|
|
10
|
+
* of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not
|
|
11
|
+
* read gets a warning, as an unknown flag gets a notice.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export type ApiSettings = Readonly<Record<string, unknown>>;
|
|
15
|
+
|
|
16
|
+
/** The setting that names the output file. */
|
|
17
|
+
export const OUTPUT_SETTING = "output";
|
|
18
|
+
|
|
19
|
+
/** The setting that lists the API's output fixes. */
|
|
20
|
+
export const FIX_SETTING = "fix";
|
|
21
|
+
|
|
22
|
+
const LOCAL_REF_ROOT_SETTING = "localRefRoot";
|
|
23
|
+
const REMOTE_REF_HOSTS_SETTING = "remoteRefHosts";
|
|
24
|
+
|
|
25
|
+
/** `--content-never` is accepted and has no effect, as on the command line. */
|
|
26
|
+
const IGNORED_SETTINGS = ["contentNever"] as const;
|
|
27
|
+
|
|
28
|
+
const CAMEL_CASE_SETTINGS = [
|
|
29
|
+
OUTPUT_SETTING,
|
|
30
|
+
FIX_SETTING,
|
|
31
|
+
LOCAL_REF_ROOT_SETTING,
|
|
32
|
+
REMOTE_REF_HOSTS_SETTING,
|
|
33
|
+
...GENERATOR_FLAGS,
|
|
34
|
+
...IGNORED_SETTINGS,
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const KNOWN_SETTINGS = new Set<string>([
|
|
38
|
+
...CAMEL_CASE_SETTINGS,
|
|
39
|
+
...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
/** The warning for each setting of an API that no code reads. */
|
|
43
|
+
export function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {
|
|
44
|
+
return Object.keys(settings)
|
|
45
|
+
.filter((key) => !KNOWN_SETTINGS.has(key))
|
|
46
|
+
.map((key) =>
|
|
47
|
+
warningText(
|
|
48
|
+
`API ${apiName}: the setting \`${key}\` is not an openapi-typesafe option and is ignored`,
|
|
49
|
+
WARNING_CODES.CONFIG_SETTING_UNKNOWN,
|
|
50
|
+
),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */
|
|
55
|
+
function settingValue(settings: ApiSettings, name: string): unknown {
|
|
56
|
+
return name in settings ? settings[name] : settings[kebabCase(name)];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function hasSetting(settings: ApiSettings, name: string): boolean {
|
|
60
|
+
return name in settings || kebabCase(name) in settings;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function invalidSetting(apiName: string, name: string, expected: string): Error {
|
|
64
|
+
return cliError(
|
|
65
|
+
"CLI_CONFIG_INVALID",
|
|
66
|
+
`API ${apiName}: \`${kebabCase(name)}\` in x-openapi-ts must be ${expected}`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** `local-ref-root: dir`, relative to the config file; empty means the config file's directory. */
|
|
71
|
+
function localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {
|
|
72
|
+
if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {
|
|
73
|
+
return {};
|
|
74
|
+
}
|
|
75
|
+
const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? "";
|
|
76
|
+
if (typeof value !== "string") {
|
|
77
|
+
throw invalidSetting(apiName, LOCAL_REF_ROOT_SETTING, "a directory path");
|
|
78
|
+
}
|
|
79
|
+
return { localRefRoot: resolveLocationUrl(value === "" ? "." : value, configRoot) };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */
|
|
83
|
+
function remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {
|
|
84
|
+
if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {
|
|
85
|
+
return {};
|
|
86
|
+
}
|
|
87
|
+
const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];
|
|
88
|
+
const entries = [value].flat();
|
|
89
|
+
if (entries.some((entry) => typeof entry !== "string")) {
|
|
90
|
+
throw invalidSetting(apiName, REMOTE_REF_HOSTS_SETTING, "a host list");
|
|
91
|
+
}
|
|
92
|
+
return { remoteRefHosts: hostList(entries) ?? [] };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same
|
|
97
|
+
* name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a
|
|
98
|
+
* value of another type.
|
|
99
|
+
*/
|
|
100
|
+
export function apiRefLimitOptions(
|
|
101
|
+
apiName: string,
|
|
102
|
+
settings: ApiSettings,
|
|
103
|
+
configRoot: URL,
|
|
104
|
+
): RefLimitOptions {
|
|
105
|
+
return {
|
|
106
|
+
...localRefRootOf(apiName, settings, configRoot),
|
|
107
|
+
...remoteRefHostsOf(apiName, settings),
|
|
108
|
+
};
|
|
109
|
+
}
|
package/src/cli/cli-arguments.ts
CHANGED
|
@@ -122,8 +122,11 @@ function lastString(value: unknown): string | undefined {
|
|
|
122
122
|
return optionalString(Array.isArray(value) ? value.at(-1) : value);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
/**
|
|
126
|
-
|
|
125
|
+
/**
|
|
126
|
+
* `--remote-ref-hosts a.example,b.example`, repeatable; an empty value allows no host. The
|
|
127
|
+
* `remote-ref-hosts` setting of a `redocly.yaml` API is read the same way.
|
|
128
|
+
*/
|
|
129
|
+
export function hostList(value: unknown): string[] | undefined {
|
|
127
130
|
if (value === undefined) {
|
|
128
131
|
return undefined;
|
|
129
132
|
}
|
package/src/cli/help-text.ts
CHANGED
|
@@ -4,7 +4,7 @@ export const HELP_TEXT = [
|
|
|
4
4
|
" $ openapi-typesafe [input] [options]",
|
|
5
5
|
"",
|
|
6
6
|
"Options",
|
|
7
|
-
" --help
|
|
7
|
+
" --help Show this help",
|
|
8
8
|
" --version Display the version",
|
|
9
9
|
" --redocly [path], -c Specify path to Redocly config (default: redocly.yaml)",
|
|
10
10
|
" --output, -o Specify output file (if not specified in redocly.yaml)",
|
|
@@ -20,8 +20,8 @@ export const HELP_TEXT = [
|
|
|
20
20
|
" --additional-properties Treat schema objects as if `additionalProperties: true` is set",
|
|
21
21
|
" --empty-objects-unknown Generate `unknown` instead of" +
|
|
22
22
|
" `Record<string, never>` for empty objects",
|
|
23
|
-
" --default-non-nullable
|
|
24
|
-
"
|
|
23
|
+
" --default-non-nullable A property with a `default` is required" +
|
|
24
|
+
" (default: true; =false makes it optional)",
|
|
25
25
|
" --properties-required-by-default",
|
|
26
26
|
" Treat schema objects as if `required` is" +
|
|
27
27
|
" set to all properties by default",
|
|
@@ -35,7 +35,7 @@ export const HELP_TEXT = [
|
|
|
35
35
|
" undefined by schema",
|
|
36
36
|
" --alphabetize Sort object keys alphabetically",
|
|
37
37
|
" --exclude-deprecated Exclude deprecated types",
|
|
38
|
-
" --root-types Export
|
|
38
|
+
" --root-types Export `components` types as root-level aliases",
|
|
39
39
|
" --root-types-no-schema-prefix",
|
|
40
40
|
' Do not add "Schema" prefix to types at' +
|
|
41
41
|
" the root level (should only be used with --root-types)",
|
package/src/cli/redocly-apis.ts
CHANGED
|
@@ -2,6 +2,13 @@ import { kebabCase } from "scule";
|
|
|
2
2
|
import type { RedoclyConfig } from "../application/ports/redocly-config-source.js";
|
|
3
3
|
import type { OutputFixName } from "../domain/output-fixes.js";
|
|
4
4
|
import type { GeneratorOptions } from "../types.js";
|
|
5
|
+
import {
|
|
6
|
+
type ApiSettings,
|
|
7
|
+
apiRefLimitOptions,
|
|
8
|
+
FIX_SETTING,
|
|
9
|
+
OUTPUT_SETTING,
|
|
10
|
+
unknownSettingWarnings,
|
|
11
|
+
} from "./api-settings.js";
|
|
5
12
|
import { GENERATOR_FLAGS, type GeneratorFlags } from "./cli-arguments.js";
|
|
6
13
|
import { cliError } from "./cli-errors.js";
|
|
7
14
|
import { type CliRun, emitOutput, resolveLocationUrl } from "./cli-output.js";
|
|
@@ -14,11 +21,6 @@ import { refLimitOptions } from "./ref-limits.js";
|
|
|
14
21
|
/** The key of an API's openapi-typesafe settings in `redocly.yaml`. */
|
|
15
22
|
const REDOCLY_CONFIG_KEY = "x-openapi-ts";
|
|
16
23
|
|
|
17
|
-
/** The setting of an API that lists its output fixes. */
|
|
18
|
-
const FIX_SETTING = "fix";
|
|
19
|
-
|
|
20
|
-
type ApiSettings = Readonly<Record<string, unknown>>;
|
|
21
|
-
|
|
22
24
|
interface RedoclyApi {
|
|
23
25
|
readonly name: string;
|
|
24
26
|
readonly root: string;
|
|
@@ -59,19 +61,23 @@ function configRootOf(redocly: RedoclyConfig, cwd: URL): URL {
|
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
async function generateApi(run: CliRun, redocly: RedoclyConfig, api: RedoclyApi): Promise<void> {
|
|
62
|
-
if (!api.settings?.
|
|
64
|
+
if (!api.settings?.[OUTPUT_SETTING]) {
|
|
63
65
|
throw cliError(
|
|
64
66
|
"CLI_CONFIG_OUTPUT_MISSING",
|
|
65
67
|
`API ${api.name} is missing an \`${REDOCLY_CONFIG_KEY}.output\` key. ` +
|
|
66
68
|
`See ${MULTIPLE_SCHEMAS_DOCS_URL}`,
|
|
67
69
|
);
|
|
68
70
|
}
|
|
69
|
-
const
|
|
71
|
+
for (const warning of unknownSettingWarnings(api.name, api.settings)) {
|
|
72
|
+
run.deps.logger.warn(warning);
|
|
73
|
+
}
|
|
74
|
+
const output = String(api.settings[OUTPUT_SETTING]);
|
|
70
75
|
const configRoot = configRootOf(redocly, run.deps.cwd);
|
|
71
76
|
const options: GeneratorOptions = {
|
|
72
77
|
...run.args.generatorFlags,
|
|
73
78
|
...apiFlags(api.settings),
|
|
74
79
|
...refLimitOptions(run.args, run.deps.cwd),
|
|
80
|
+
...apiRefLimitOptions(api.name, api.settings, configRoot),
|
|
75
81
|
...fixOption(apiFixNames(api.settings) ?? run.args.fix),
|
|
76
82
|
redocly,
|
|
77
83
|
};
|
package/src/cli/run-cli.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Logger } from "../application/ports/logger.js";
|
|
2
2
|
import type { RedoclyConfig } from "../application/ports/redocly-config-source.js";
|
|
3
|
+
import { WARNING_CODES, warningText } from "../domain/warnings.js";
|
|
3
4
|
import type { SchemaSource } from "../types.js";
|
|
4
5
|
import { ineffectiveFlagNotices, parseCliArguments } from "./cli-arguments.js";
|
|
5
6
|
import type { CliDependencies } from "./cli-dependencies.js";
|
|
@@ -84,7 +85,10 @@ async function generate(run: CliRun): Promise<unknown[]> {
|
|
|
84
85
|
}
|
|
85
86
|
if (run.args.input) {
|
|
86
87
|
run.deps.logger.warn(
|
|
87
|
-
|
|
88
|
+
warningText(
|
|
89
|
+
"APIs are specified both in Redocly Config and CLI argument. Only using Redocly config.",
|
|
90
|
+
WARNING_CODES.CLI_INPUT_IGNORED,
|
|
91
|
+
),
|
|
88
92
|
);
|
|
89
93
|
}
|
|
90
94
|
return generateRedoclyApis(run, redocly);
|
package/src/domain/errors.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { redactUrlCredentials } from "./url-credentials.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Typed errors (ENGINEERING_PLAN 4.6, ADR-011). Every expected failure of the generator and the CLI
|
|
3
5
|
* is an `OpenAPITypesafeError` with a stable machine-readable `code` and structured `details`. The
|
|
@@ -48,13 +50,17 @@ export interface OpenAPITypesafeErrorInit {
|
|
|
48
50
|
readonly cause?: unknown;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* The base of every expected failure; check `code`, not the class or the message. The message
|
|
55
|
+
* never shows the user info of a URL (`url-credentials.ts`).
|
|
56
|
+
*/
|
|
52
57
|
export class OpenAPITypesafeError extends Error {
|
|
53
58
|
readonly code: ErrorCode;
|
|
54
59
|
readonly details: ErrorDetails;
|
|
55
60
|
|
|
56
61
|
constructor(init: OpenAPITypesafeErrorInit) {
|
|
57
|
-
|
|
62
|
+
const message = redactUrlCredentials(init.message);
|
|
63
|
+
super(message, init.cause === undefined ? undefined : { cause: init.cause });
|
|
58
64
|
this.name = "OpenAPITypesafeError";
|
|
59
65
|
this.code = init.code;
|
|
60
66
|
this.details = init.details ?? {};
|
|
@@ -33,6 +33,9 @@ export function irKeyword(keyword: IrKeyword): IrKeywordType {
|
|
|
33
33
|
return { kind: "keyword", keyword };
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/** The encoding of a string literal that does not name one. */
|
|
37
|
+
export const DEFAULT_STRING_ENCODING: IrStringEncoding = "json";
|
|
38
|
+
|
|
36
39
|
export function irString(value: string, encoding: IrStringEncoding): IrStringLiteralType {
|
|
37
40
|
return { kind: "stringLiteral", value, encoding };
|
|
38
41
|
}
|
package/src/domain/ir/nodes.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type IR: the closed set of immutable nodes that describes the TypeScript types and declarations
|
|
3
3
|
* the generator emits (ENGINEERING_PLAN §4.2, ADR-002). Nodes are plain readonly data with a `kind`
|
|
4
|
-
* discriminator; every consumer dispatches with an exhaustive `switch`, so a new
|
|
5
|
-
* build wherever it must be handled.
|
|
4
|
+
* discriminator; every consumer in this package dispatches with an exhaustive `switch`, so a new
|
|
5
|
+
* kind breaks the build wherever it must be handled. For users the set is open: a minor release
|
|
6
|
+
* may add a kind (ADR-034), so code outside the package must keep a node of an unknown kind as it
|
|
7
|
+
* is, and a `switch` over `kind` needs a `default` branch.
|
|
6
8
|
*
|
|
7
9
|
* Utility types (`Omit`, `Record`, `WithRequired`, `Extract`) are `reference` nodes with type
|
|
8
10
|
* arguments, built by named constructors: the printer has nothing special to do for them.
|
|
@@ -35,7 +37,8 @@ export interface IrKeywordType {
|
|
|
35
37
|
export interface IrStringLiteralType {
|
|
36
38
|
readonly kind: "stringLiteral";
|
|
37
39
|
readonly value: string;
|
|
38
|
-
|
|
40
|
+
/** How the printer writes the value; unset is `json`. A detail of the printer. */
|
|
41
|
+
readonly encoding?: IrStringEncoding;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/** Finite number; a negative value prints with a leading minus sign. */
|
|
@@ -112,9 +115,9 @@ export interface IrRawType {
|
|
|
112
115
|
readonly kind: "raw";
|
|
113
116
|
readonly text: string;
|
|
114
117
|
/**
|
|
115
|
-
* The
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
+
* @internal The TypeScript node the bridge printed the text from. The reverse bridge (the
|
|
119
|
+
* deprecated `ts.Node` callbacks, ADR-004) hands it back unchanged. Set by the generator only:
|
|
120
|
+
* read it as opaque, never set it, and expect it to go away in 2.0.
|
|
118
121
|
*/
|
|
119
122
|
readonly origin?: unknown;
|
|
120
123
|
}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* `/a/{name}`, match the same URLs, so a client cannot tell which one a request is for.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/** `[^{}]` keeps the scan linear: `[^}]` retried from every `{` of a long run of them. */
|
|
8
|
+
const PATH_PARAMETER_RE = /\{[^{}]+\}/g;
|
|
8
9
|
const PATH_PREFIX = "/";
|
|
9
10
|
const UNNAMED_PARAMETER = "{}";
|
|
10
11
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URLs with user info (`https://user:token@host/…`) can reach a message: the CLI input, a `$ref`,
|
|
3
|
+
* a redirect. Messages end up in CI job logs, so the user info is hidden in every one (audit B2,
|
|
4
|
+
* F12). Fetch refuses such URLs anyway, so a message never needs the credentials.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The user info after a scheme: everything up to an `@` that comes before the end of the
|
|
9
|
+
* authority. The class stops at `/`, so a scan never runs past the next `://`; it stays linear.
|
|
10
|
+
*/
|
|
11
|
+
const URL_USER_INFO = /:\/\/[^\s/?#@]*@/g;
|
|
12
|
+
|
|
13
|
+
const REDACTED_USER_INFO = "://***@";
|
|
14
|
+
|
|
15
|
+
/** The text with the user info of every URL in it replaced by `***`. */
|
|
16
|
+
export function redactUrlCredentials(text: string): string {
|
|
17
|
+
return text.replace(URL_USER_INFO, () => REDACTED_USER_INFO);
|
|
18
|
+
}
|
package/src/domain/warnings.ts
CHANGED
|
@@ -6,10 +6,18 @@
|
|
|
6
6
|
|
|
7
7
|
/** Every warning code. */
|
|
8
8
|
export const WARNING_CODES = {
|
|
9
|
+
CLI_INPUT_IGNORED: "CLI_INPUT_IGNORED",
|
|
10
|
+
CONFIG_SETTING_UNKNOWN: "CONFIG_SETTING_UNKNOWN",
|
|
11
|
+
DISCRIMINATOR_MAPPING_INVALID: "DISCRIMINATOR_MAPPING_INVALID",
|
|
9
12
|
DISCRIMINATOR_VALUE_NOT_ALLOWED: "DISCRIMINATOR_VALUE_NOT_ALLOWED",
|
|
10
13
|
ENUM_VALUES_EXCLUDED: "ENUM_VALUES_EXCLUDED",
|
|
14
|
+
FIX_NEEDS_OPTION: "FIX_NEEDS_OPTION",
|
|
15
|
+
LEGACY_CALLBACK_DEPRECATED: "LEGACY_CALLBACK_DEPRECATED",
|
|
16
|
+
LINT_PROBLEM: "LINT_PROBLEM",
|
|
11
17
|
PATH_TEMPLATES_IDENTICAL: "PATH_TEMPLATES_IDENTICAL",
|
|
12
18
|
QUERYSTRING_NEXT_TO_QUERY: "QUERYSTRING_NEXT_TO_QUERY",
|
|
19
|
+
REF_CIRCULAR: "REF_CIRCULAR",
|
|
20
|
+
REF_NOT_FOUND: "REF_NOT_FOUND",
|
|
13
21
|
} as const;
|
|
14
22
|
|
|
15
23
|
export type WarningCode = (typeof WARNING_CODES)[keyof typeof WARNING_CODES];
|
package/src/index.ts
CHANGED
|
@@ -48,6 +48,7 @@ export {
|
|
|
48
48
|
OutputFix,
|
|
49
49
|
type OutputFixName,
|
|
50
50
|
} from "./domain/output-fixes.js";
|
|
51
|
+
export { WARNING_CODES, type WarningCode } from "./domain/warnings.js";
|
|
51
52
|
export { default as transformComponentsObject } from "./transform/components-object.js";
|
|
52
53
|
export { default as transformHeaderObject } from "./transform/header-object.js";
|
|
53
54
|
export { default as transformMediaTypeObject } from "./transform/media-type-object.js";
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { createTransformContext, schemaLocation } from "../api/transform-context.js";
|
|
2
2
|
import { pathItemType } from "../application/transform/document/path-item.js";
|
|
3
3
|
import type { IrType } from "../domain/ir/nodes.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { PathItemMethod } from "../domain/openapi/path-item-object.js";
|
|
5
5
|
import type { PathItemObject, TransformNodeOptions } from "../types.js";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* The operation methods of a path item: openapi-typescript's eight, plus the OpenAPI 3.2 `query`
|
|
9
|
+
* (ADR-020), as `HttpMethod` of openapi-typesafe-helpers lists them.
|
|
10
|
+
*/
|
|
11
|
+
export type Method = PathItemMethod;
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Transform PathItem nodes (4.8.9)
|
|
@@ -3,8 +3,6 @@ import type { Readable } from "node:stream";
|
|
|
3
3
|
import type { Config as RedoclyConfig } from "@redocly/openapi-core";
|
|
4
4
|
import type { ts } from "../adapters/type-ast-bridge/typescript-types.js";
|
|
5
5
|
import type { FooterEntry } from "../api/footer-entry.js";
|
|
6
|
-
import type { Logger } from "../application/ports/logger.js";
|
|
7
|
-
import type { DocumentFooter } from "../application/transform/transform-context.js";
|
|
8
6
|
import type { IrPropertySignature, IrType } from "../domain/ir/nodes.js";
|
|
9
7
|
import type { OutputFix, OutputFixName } from "../domain/output-fixes.js";
|
|
10
8
|
import type { ReferenceObject } from "./openapi-common.js";
|
|
@@ -74,7 +72,7 @@ export interface OpenAPITSBaseOptions {
|
|
|
74
72
|
lint?: boolean;
|
|
75
73
|
/** (optional) Should logging be suppressed? (necessary for STDOUT) */
|
|
76
74
|
silent?: boolean;
|
|
77
|
-
/**
|
|
75
|
+
/** Accepted for compatibility with openapi-typescript; not read. */
|
|
78
76
|
version?: number;
|
|
79
77
|
/** (optional) Export type instead of interface */
|
|
80
78
|
exportType?: boolean;
|
|
@@ -197,28 +195,22 @@ export interface OpenAPITSIrOptions extends OpenAPITSBaseOptions, IrCallbackOpti
|
|
|
197
195
|
/** Either form of the generator options. */
|
|
198
196
|
export type GeneratorOptions = OpenAPITSOptions | OpenAPITSIrOptions;
|
|
199
197
|
|
|
200
|
-
/**
|
|
198
|
+
/**
|
|
199
|
+
* Context passed to all submodules, and to the callbacks as `options.ctx`. To call an exported
|
|
200
|
+
* transformer outside a run, build one with the fields of openapi-typescript's context; the
|
|
201
|
+
* fields openapi-typesafe added are optional.
|
|
202
|
+
*/
|
|
201
203
|
export interface GlobalContext {
|
|
202
204
|
// user options
|
|
203
205
|
additionalProperties: boolean;
|
|
204
206
|
alphabetize: boolean;
|
|
205
207
|
arrayLength: boolean;
|
|
206
|
-
|
|
208
|
+
/** `format: binary` and `contentMediaType` strings become `Blob` (default: false). */
|
|
209
|
+
binaryAsBlob?: boolean;
|
|
207
210
|
defaultNonNullable: boolean;
|
|
208
211
|
discriminators: {
|
|
209
212
|
objects: Record<string, DiscriminatorObject>;
|
|
210
213
|
refsHandled: string[];
|
|
211
|
-
/**
|
|
212
|
-
* @internal With the `discriminator-values` fix: for each enum the scan added to a
|
|
213
|
-
* member and each inherited discriminator object, the enum of the owner's property and the
|
|
214
|
-
* location it is typed at.
|
|
215
|
-
*/
|
|
216
|
-
enumParents?: ReadonlyMap<object, { readonly schema: SchemaObject; readonly path: string }>;
|
|
217
|
-
/**
|
|
218
|
-
* @internal With the `discriminator-values` fix: for each schema, the properties of the
|
|
219
|
-
* discriminators it inherits besides `objects[ref]`, which it redefines too.
|
|
220
|
-
*/
|
|
221
|
-
otherProperties?: Readonly<Record<string, readonly string[]>>;
|
|
222
214
|
};
|
|
223
215
|
emptyObjectsUnknown: boolean;
|
|
224
216
|
enum: boolean;
|
|
@@ -235,24 +227,12 @@ export interface GlobalContext {
|
|
|
235
227
|
* callbacks may add IR declarations or TypeScript nodes.
|
|
236
228
|
*/
|
|
237
229
|
injectFooter: FooterEntry[];
|
|
230
|
+
pathParamsAsTypes: boolean;
|
|
238
231
|
/**
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*/
|
|
242
|
-
runFooter?: DocumentFooter;
|
|
243
|
-
/**
|
|
244
|
-
* @internal The deprecated callback forms this run has warned about (once each). Not an
|
|
245
|
-
* option; do not set it.
|
|
246
|
-
*/
|
|
247
|
-
legacyCallbackWarnings?: Set<LegacyCallbackName>;
|
|
248
|
-
/**
|
|
249
|
-
* @internal Where this run reports warnings and debug output. Not an option; a context without
|
|
250
|
-
* it logs to the terminal.
|
|
232
|
+
* Whether the callbacks below take IR (`OpenAPITSIrOptions`) or TypeScript nodes
|
|
233
|
+
* (default: false, TypeScript nodes).
|
|
251
234
|
*/
|
|
252
|
-
|
|
253
|
-
pathParamsAsTypes: boolean;
|
|
254
|
-
/** Whether the callbacks below take IR (`OpenAPITSIrOptions`) or TypeScript nodes. */
|
|
255
|
-
irCallbacks: boolean;
|
|
235
|
+
irCallbacks?: boolean;
|
|
256
236
|
postTransform: GeneratorOptions["postTransform"];
|
|
257
237
|
propertiesRequiredByDefault: boolean;
|
|
258
238
|
rootTypes: boolean;
|
|
@@ -67,6 +67,7 @@ export interface ParameterObject extends Extensable {
|
|
|
67
67
|
/** The schema defining the type used for the parameter. */
|
|
68
68
|
schema?: SchemaObject;
|
|
69
69
|
/** Example of the parameter’s potential value. */
|
|
70
|
+
// biome-ignore lint/suspicious/noExplicitAny: public type under semver (ADR-034)
|
|
70
71
|
example?: any;
|
|
71
72
|
/** Examples of the parameter’s potential value. */
|
|
72
73
|
examples?: { [name: string]: ExampleObject | ReferenceObject };
|
|
@@ -111,6 +112,7 @@ export interface MediaTypeObject extends Extensable {
|
|
|
111
112
|
* referencing a schema which contains an example, the example value SHALL override the example
|
|
112
113
|
* provided by the schema.
|
|
113
114
|
*/
|
|
115
|
+
// biome-ignore lint/suspicious/noExplicitAny: public type under semver (ADR-034)
|
|
114
116
|
example?: any;
|
|
115
117
|
/**
|
|
116
118
|
* Examples of the media type. Each example object SHOULD match the media type and specified
|
|
@@ -188,6 +190,7 @@ export interface ExampleObject extends Extensable {
|
|
|
188
190
|
* represent examples of media types that cannot naturally represented in JSON or YAML, use a
|
|
189
191
|
* string value to contain the example, escaping where necessary.
|
|
190
192
|
*/
|
|
193
|
+
// biome-ignore lint/suspicious/noExplicitAny: public type under semver (ADR-034)
|
|
191
194
|
value?: any;
|
|
192
195
|
/**
|
|
193
196
|
* A URI that points to the literal example. This provides the capability to reference examples
|
|
@@ -21,6 +21,7 @@ export type SchemaObject = {
|
|
|
21
21
|
/** Additional external documentation for this schema. */
|
|
22
22
|
externalDocs?: ExternalDocumentationObject;
|
|
23
23
|
/** @deprecated */
|
|
24
|
+
// biome-ignore lint/suspicious/noExplicitAny: public type under semver (ADR-034)
|
|
24
25
|
example?: any;
|
|
25
26
|
title?: string;
|
|
26
27
|
description?: string;
|
|
@@ -47,6 +48,7 @@ export type SchemaObject = {
|
|
|
47
48
|
allOf?: (SchemaObject | ReferenceObject)[];
|
|
48
49
|
anyOf?: (SchemaObject | ReferenceObject)[];
|
|
49
50
|
required?: string[];
|
|
51
|
+
// biome-ignore lint/suspicious/noExplicitAny: public type under semver (ADR-034)
|
|
50
52
|
[key: `x-${string}`]: any;
|
|
51
53
|
} & (
|
|
52
54
|
| StringSubtype
|