openapi-typesafe 1.0.0-rc.1 → 1.0.0-rc.3
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/node-deprecations/node-deprecations.cjs +14 -0
- package/dist/adapters/node-deprecations/node-deprecations.cjs.map +1 -0
- package/dist/adapters/node-deprecations/node-deprecations.mjs +12 -0
- package/dist/adapters/node-deprecations/node-deprecations.mjs.map +1 -0
- 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 +14 -0
- package/dist/api/default-ports.cjs.map +1 -1
- package/dist/api/default-ports.mjs +12 -1
- package/dist/api/default-ports.mjs.map +1 -1
- package/dist/api/discriminator-conflict-warnings.cjs +1 -1
- package/dist/api/discriminator-conflict-warnings.cjs.map +1 -1
- package/dist/api/discriminator-conflict-warnings.mjs +2 -2
- package/dist/api/discriminator-conflict-warnings.mjs.map +1 -1
- package/dist/api/discriminator-patch.cjs +8 -4
- package/dist/api/discriminator-patch.cjs.map +1 -1
- package/dist/api/discriminator-patch.mjs +9 -5
- package/dist/api/discriminator-patch.mjs.map +1 -1
- package/dist/api/discriminator-scan.cjs +2 -2
- package/dist/api/discriminator-scan.cjs.map +1 -1
- package/dist/api/discriminator-scan.mjs +3 -3
- package/dist/api/discriminator-scan.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 +6 -3
- package/dist/api/document-run.cjs.map +1 -1
- package/dist/api/document-run.mjs +6 -3
- 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 +7 -1
- package/dist/api/legacy-callback-warning.cjs.map +1 -1
- package/dist/api/legacy-callback-warning.mjs +8 -2
- 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 +3 -2
- package/dist/api/openapi-ts.cjs.map +1 -1
- package/dist/api/openapi-ts.mjs +4 -3
- package/dist/api/openapi-ts.mjs.map +1 -1
- package/dist/api/string-to-ast.cjs +7 -9
- package/dist/api/string-to-ast.cjs.map +1 -1
- package/dist/api/string-to-ast.mjs +8 -9
- package/dist/api/string-to-ast.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 +2 -2
- package/dist/api/transform-schema.cjs.map +1 -1
- package/dist/api/transform-schema.mjs +3 -3
- 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/components.cjs +1 -1
- package/dist/application/transform/document/components.cjs.map +1 -1
- package/dist/application/transform/document/components.mjs +2 -2
- package/dist/application/transform/document/components.mjs.map +1 -1
- package/dist/application/transform/document/parameters.cjs +2 -2
- package/dist/application/transform/document/parameters.cjs.map +1 -1
- package/dist/application/transform/document/parameters.mjs +3 -3
- package/dist/application/transform/document/parameters.mjs.map +1 -1
- package/dist/application/transform/document/paths.cjs +2 -2
- package/dist/application/transform/document/paths.cjs.map +1 -1
- package/dist/application/transform/document/paths.mjs +3 -3
- 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/application/transform/ref-pointer/pointer-type.cjs +1 -1
- package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/pointer-type.mjs +2 -2
- package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -1
- package/dist/application/transform/schema/access-flags.cjs +1 -1
- package/dist/application/transform/schema/access-flags.cjs.map +1 -1
- package/dist/application/transform/schema/access-flags.mjs +2 -2
- package/dist/application/transform/schema/access-flags.mjs.map +1 -1
- package/dist/application/transform/schema/array-type.cjs +2 -2
- package/dist/application/transform/schema/array-type.cjs.map +1 -1
- package/dist/application/transform/schema/array-type.mjs +3 -3
- package/dist/application/transform/schema/array-type.mjs.map +1 -1
- package/dist/application/transform/schema/composition-type.cjs +3 -3
- package/dist/application/transform/schema/composition-type.cjs.map +1 -1
- package/dist/application/transform/schema/composition-type.mjs +4 -4
- package/dist/application/transform/schema/composition-type.mjs.map +1 -1
- package/dist/application/transform/schema/enum-rule.cjs +3 -5
- package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
- package/dist/application/transform/schema/enum-rule.mjs +4 -6
- package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
- package/dist/application/transform/schema/presence-members.cjs +1 -1
- package/dist/application/transform/schema/presence-members.cjs.map +1 -1
- package/dist/application/transform/schema/presence-members.mjs +2 -2
- package/dist/application/transform/schema/presence-members.mjs.map +1 -1
- package/dist/application/transform/schema/required-variants.cjs +2 -2
- package/dist/application/transform/schema/required-variants.cjs.map +1 -1
- package/dist/application/transform/schema/required-variants.mjs +3 -3
- package/dist/application/transform/schema/required-variants.mjs.map +1 -1
- package/dist/application/transform/schema/unevaluated-properties.cjs +1 -1
- package/dist/application/transform/schema/unevaluated-properties.cjs.map +1 -1
- package/dist/application/transform/schema/unevaluated-properties.mjs +2 -2
- package/dist/application/transform/schema/unevaluated-properties.mjs.map +1 -1
- package/dist/application/transform/schema-comment.cjs +1 -1
- package/dist/application/transform/schema-comment.cjs.map +1 -1
- package/dist/application/transform/schema-comment.mjs +2 -2
- package/dist/application/transform/schema-comment.mjs.map +1 -1
- 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/deprecations.cjs +11 -0
- package/dist/domain/deprecations.cjs.map +1 -0
- package/dist/domain/deprecations.mjs +9 -0
- package/dist/domain/deprecations.mjs.map +1 -0
- 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/output-fixes.cjs +11 -14
- package/dist/domain/output-fixes.cjs.map +1 -1
- package/dist/domain/output-fixes.mjs +11 -13
- package/dist/domain/output-fixes.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 +8 -1
- package/dist/domain/warnings.cjs.map +1 -1
- package/dist/domain/warnings.mjs +8 -1
- package/dist/domain/warnings.mjs.map +1 -1
- package/dist/index.cjs +4 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1185 -59
- package/dist/index.d.mts +1185 -59
- package/dist/index.d.ts +1185 -59
- package/dist/index.mjs +4 -2
- 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 +5 -4
- package/src/adapters/node-deprecations/node-deprecations.ts +14 -0
- 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 +23 -0
- package/src/api/discriminator-conflict-warnings.ts +2 -2
- package/src/api/discriminator-patch.ts +11 -7
- package/src/api/discriminator-scan.ts +3 -3
- package/src/api/document-refs.ts +19 -15
- package/src/api/document-run.ts +14 -6
- package/src/api/footer-sink.ts +34 -2
- package/src/api/legacy-callback-warning.ts +16 -5
- package/src/api/legacy-ts-helpers.ts +7 -5
- package/src/api/legacy-utils.ts +1 -1
- package/src/api/openapi-ts.ts +8 -2
- package/src/api/run-context.ts +37 -0
- package/src/api/string-to-ast.ts +11 -15
- package/src/api/transform-context.ts +10 -8
- package/src/api/transform-schema.ts +9 -8
- package/src/application/ports/deprecation-reporter.ts +9 -0
- package/src/application/print/type-printer.ts +2 -1
- package/src/application/transform/document/components.ts +2 -2
- package/src/application/transform/document/parameters.ts +4 -3
- package/src/application/transform/document/paths.ts +4 -3
- 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/application/transform/ref-pointer/pointer-type.ts +2 -4
- package/src/application/transform/schema/access-flags.ts +2 -2
- package/src/application/transform/schema/array-type.ts +3 -5
- package/src/application/transform/schema/composition-type.ts +4 -4
- package/src/application/transform/schema/enum-rule.ts +4 -6
- package/src/application/transform/schema/presence-members.ts +2 -2
- package/src/application/transform/schema/required-variants.ts +3 -3
- package/src/application/transform/schema/unevaluated-properties.ts +2 -2
- package/src/application/transform/schema-comment.ts +2 -2
- 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/deprecations.ts +15 -0
- package/src/domain/errors.ts +16 -4
- 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/output-fixes.ts +16 -16
- package/src/domain/url-credentials.ts +18 -0
- package/src/domain/warnings.ts +7 -0
- package/src/index.ts +3 -6
- 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
package/src/api/document-refs.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseRef } from "@redocly/openapi-core/lib/ref-utils.js";
|
|
2
2
|
import type { Logger } from "../application/ports/logger.js";
|
|
3
|
+
import { WARNING_CODES, warningText } from "../domain/warnings.js";
|
|
3
4
|
import { defaultLogger } from "./default-ports.js";
|
|
4
5
|
|
|
5
6
|
/** `$ref` resolution and the document walk that the generator's pre-pass uses. */
|
|
@@ -11,9 +12,13 @@ export interface ResolveRefOptions {
|
|
|
11
12
|
logger?: Logger;
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
16
|
+
return typeof value === "object" && value !== null;
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
/** Resolve a `$ref` in a document; warns and returns undefined when it cannot. */
|
|
15
20
|
export function resolveDocumentRef<T>(
|
|
16
|
-
schema:
|
|
21
|
+
schema: unknown,
|
|
17
22
|
$ref: string,
|
|
18
23
|
options: ResolveRefOptions,
|
|
19
24
|
): T | undefined {
|
|
@@ -23,30 +28,29 @@ export function resolveDocumentRef<T>(
|
|
|
23
28
|
if (!pointer.length) {
|
|
24
29
|
return undefined;
|
|
25
30
|
}
|
|
26
|
-
let node = schema;
|
|
31
|
+
let node: unknown = schema;
|
|
27
32
|
for (const key of pointer) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
logger.warn(`Could not resolve $ref "${$ref}"`);
|
|
33
|
+
const child = isObject(node) ? node[key] : undefined;
|
|
34
|
+
if (!child) {
|
|
35
|
+
logger.warn(warningText(`Could not resolve $ref "${$ref}"`, WARNING_CODES.REF_NOT_FOUND));
|
|
32
36
|
return undefined;
|
|
33
37
|
}
|
|
38
|
+
node = child;
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
// if this is also a $ref, keep tracing
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
const next = isObject(node) ? node.$ref : undefined;
|
|
43
|
+
if (typeof next === "string" && next) {
|
|
44
|
+
if (visited.includes(next)) {
|
|
45
|
+
logger.warn(
|
|
46
|
+
warningText(`Could not resolve circular $ref "${$ref}"`, WARNING_CODES.REF_CIRCULAR),
|
|
47
|
+
);
|
|
40
48
|
return undefined;
|
|
41
49
|
}
|
|
42
|
-
return resolveDocumentRef(schema,
|
|
43
|
-
...options,
|
|
44
|
-
logger,
|
|
45
|
-
visited: [...visited, node.$ref],
|
|
46
|
-
});
|
|
50
|
+
return resolveDocumentRef(schema, next, { ...options, logger, visited: [...visited, next] });
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
return node;
|
|
53
|
+
return node as T;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
/** Call `cb` for every object in a JSON-serializable (non-circular) value, depth first. */
|
package/src/api/document-run.ts
CHANGED
|
@@ -2,6 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
import type { Config as RedoclyConfig } from "@redocly/openapi-core";
|
|
4
4
|
import { sourceEmptyError } from "../adapters/redocly-loader/schema-load-errors.js";
|
|
5
|
+
import type { DeprecationReporter } from "../application/ports/deprecation-reporter.js";
|
|
5
6
|
import type { Logger } from "../application/ports/logger.js";
|
|
6
7
|
import type { RefAccess, SchemaLoader } from "../application/ports/schema-loader.js";
|
|
7
8
|
import { withStackOverflowReported } from "../application/stack-overflow.js";
|
|
@@ -11,17 +12,22 @@ import {
|
|
|
11
12
|
outputFixNamesOf,
|
|
12
13
|
resolveOutputFixes,
|
|
13
14
|
} from "../domain/output-fixes.js";
|
|
14
|
-
import
|
|
15
|
+
import { WARNING_CODES, warningText } from "../domain/warnings.js";
|
|
16
|
+
import type { GeneratorOptions, OpenAPI3, SchemaSource } from "../types.js";
|
|
17
|
+
import { processCwd } from "./default-ports.js";
|
|
15
18
|
import { warnDiscriminatorValueConflicts } from "./discriminator-conflict-warnings.js";
|
|
16
19
|
import { findDiscriminators } from "./discriminator-scan.js";
|
|
17
20
|
import { resolveDocumentRef } from "./document-refs.js";
|
|
18
21
|
import { warnIdenticalPathTemplates } from "./path-template-warnings.js";
|
|
22
|
+
import type { RunContext } from "./run-context.js";
|
|
19
23
|
import { warnUnsupportedFeatures } from "./unsupported-feature-warnings.js";
|
|
20
24
|
|
|
21
25
|
/** The ports of one generator run, wired by the Node API or the CLI (ENGINEERING_PLAN 4.5). */
|
|
22
26
|
export interface GeneratorPorts {
|
|
23
27
|
readonly loader: SchemaLoader;
|
|
24
28
|
readonly logger: Logger;
|
|
29
|
+
/** Where the run reports the deprecated callback forms (ADR-004). */
|
|
30
|
+
readonly deprecations: DeprecationReporter;
|
|
25
31
|
/** The Redocly config the loader uses; the run's context exposes it as `ctx.redoc`. */
|
|
26
32
|
readonly redoc: RedoclyConfig;
|
|
27
33
|
/** A monotonic time in milliseconds, for debug durations. */
|
|
@@ -31,12 +37,12 @@ export interface GeneratorPorts {
|
|
|
31
37
|
/** A validated, bundled document and the context of one generator run. */
|
|
32
38
|
export interface DocumentRun {
|
|
33
39
|
readonly schema: OpenAPI3;
|
|
34
|
-
readonly ctx:
|
|
40
|
+
readonly ctx: RunContext;
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
/** The context fields that are user flags, with the original defaults. */
|
|
38
44
|
type ContextFlags = Omit<
|
|
39
|
-
|
|
45
|
+
RunContext,
|
|
40
46
|
| "discriminators"
|
|
41
47
|
| "injectFooter"
|
|
42
48
|
| "redoc"
|
|
@@ -44,6 +50,7 @@ type ContextFlags = Omit<
|
|
|
44
50
|
| "runFooter"
|
|
45
51
|
| "legacyCallbackWarnings"
|
|
46
52
|
| "logger"
|
|
53
|
+
| "deprecations"
|
|
47
54
|
| "fix"
|
|
48
55
|
>;
|
|
49
56
|
|
|
@@ -56,7 +63,7 @@ function sourceCwd(options: GeneratorOptions): URL {
|
|
|
56
63
|
if (cwd instanceof URL) {
|
|
57
64
|
return cwd.pathname.endsWith("/") ? cwd : new URL(`${cwd.pathname}/`, cwd);
|
|
58
65
|
}
|
|
59
|
-
const directory = path.resolve(cwd === undefined ?
|
|
66
|
+
const directory = path.resolve(cwd === undefined ? processCwd() : cwd.toString());
|
|
60
67
|
return pathToFileURL(path.join(directory, path.sep));
|
|
61
68
|
}
|
|
62
69
|
|
|
@@ -119,7 +126,7 @@ function contextFlags(options: GeneratorOptions): ContextFlags {
|
|
|
119
126
|
function outputFixesOf(options: GeneratorOptions, logger: Logger): readonly OutputFix[] {
|
|
120
127
|
const names = outputFixNamesOf(options.fix ?? []);
|
|
121
128
|
for (const notice of ineffectiveFixNotices(names, (option) => options[option] === true)) {
|
|
122
|
-
logger.warn(notice);
|
|
129
|
+
logger.warn(warningText(notice, WARNING_CODES.FIX_NEEDS_OPTION));
|
|
123
130
|
}
|
|
124
131
|
return [...resolveOutputFixes(names)];
|
|
125
132
|
}
|
|
@@ -156,7 +163,7 @@ export async function createDocumentRun(
|
|
|
156
163
|
refAccess: refAccessOf(options, cwd),
|
|
157
164
|
});
|
|
158
165
|
warnAboutDocument(schema, fix, logger);
|
|
159
|
-
const ctx:
|
|
166
|
+
const ctx: RunContext = {
|
|
160
167
|
...contextFlags(options),
|
|
161
168
|
fix,
|
|
162
169
|
// The scan walks every schema before the transform does, so on a larger stack, where loading
|
|
@@ -172,6 +179,7 @@ export async function createDocumentRun(
|
|
|
172
179
|
redoc: ports.redoc,
|
|
173
180
|
resolve: ($ref) => resolveDocumentRef(schema, $ref, { silent, logger }),
|
|
174
181
|
logger,
|
|
182
|
+
deprecations: ports.deprecations,
|
|
175
183
|
};
|
|
176
184
|
return { schema, ctx };
|
|
177
185
|
}
|
package/src/api/footer-sink.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { FooterSink } from "../application/transform/footer/document-footer
|
|
|
4
4
|
import type {
|
|
5
5
|
IrDeclaration,
|
|
6
6
|
IrInterfaceDeclaration,
|
|
7
|
+
IrMember,
|
|
7
8
|
IrPropertySignature,
|
|
8
9
|
} from "../domain/ir/nodes.js";
|
|
9
10
|
import { declaresTypeAlias, type FooterEntry, isIrDeclaration } from "./footer-entry.js";
|
|
@@ -16,6 +17,12 @@ const OPERATIONS_NAME = "operations";
|
|
|
16
17
|
*/
|
|
17
18
|
export class ContextFooterSink implements FooterSink {
|
|
18
19
|
private readonly footer: FooterEntry[];
|
|
20
|
+
/**
|
|
21
|
+
* The IR `operations` entry this sink wrote last, with its members array that only this sink
|
|
22
|
+
* holds. Adding to it in place keeps a run linear: copying the members on every operation was
|
|
23
|
+
* quadratic (about 0.4 s on Microsoft Graph beta).
|
|
24
|
+
*/
|
|
25
|
+
private owned: OwnedOperations | null = null;
|
|
19
26
|
|
|
20
27
|
constructor(footer: FooterEntry[]) {
|
|
21
28
|
this.footer = footer;
|
|
@@ -35,6 +42,11 @@ export class ContextFooterSink implements FooterSink {
|
|
|
35
42
|
* the member in place, as in the original.
|
|
36
43
|
*/
|
|
37
44
|
addOperation(build: () => IrPropertySignature): void {
|
|
45
|
+
const owned = this.currentOwnedOperations();
|
|
46
|
+
if (owned !== null) {
|
|
47
|
+
owned.members.push(build());
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
38
50
|
const existing = this.findOperations();
|
|
39
51
|
if (existing !== null && !isIrDeclaration(existing.entry)) {
|
|
40
52
|
const ts = loadTypeScript();
|
|
@@ -45,9 +57,23 @@ export class ContextFooterSink implements FooterSink {
|
|
|
45
57
|
return;
|
|
46
58
|
}
|
|
47
59
|
const index = existing?.index ?? this.footer.push(emptyOperations()) - 1;
|
|
48
|
-
|
|
60
|
+
this.takeOwnership(index).members.push(build());
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The owned entry, unless user code replaced or moved it in the footer since. */
|
|
64
|
+
private currentOwnedOperations(): OwnedOperations | null {
|
|
65
|
+
const owned = this.owned;
|
|
66
|
+
return owned !== null && this.footer[owned.index] === owned.entry ? owned : null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Replace the IR entry at `index` with a copy whose members array only this sink holds. */
|
|
70
|
+
private takeOwnership(index: number): OwnedOperations {
|
|
49
71
|
const operations = this.footer[index] as IrInterfaceDeclaration;
|
|
50
|
-
|
|
72
|
+
const members: IrMember[] = [...operations.members];
|
|
73
|
+
const entry: IrInterfaceDeclaration = { ...operations, members };
|
|
74
|
+
this.footer[index] = entry;
|
|
75
|
+
this.owned = { entry, members, index };
|
|
76
|
+
return this.owned;
|
|
51
77
|
}
|
|
52
78
|
|
|
53
79
|
/** The first `operations` interface: the generator's (IR) or a user's (TypeScript). */
|
|
@@ -62,6 +88,12 @@ export class ContextFooterSink implements FooterSink {
|
|
|
62
88
|
}
|
|
63
89
|
}
|
|
64
90
|
|
|
91
|
+
interface OwnedOperations {
|
|
92
|
+
readonly entry: IrInterfaceDeclaration;
|
|
93
|
+
readonly members: IrMember[];
|
|
94
|
+
readonly index: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
65
97
|
function emptyOperations(): IrInterfaceDeclaration {
|
|
66
98
|
return { kind: "interface", name: OPERATIONS_NAME, isExported: true, members: [], comments: [] };
|
|
67
99
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { DEPRECATION_CODES, type DeprecationCode } from "../domain/deprecations.js";
|
|
2
|
+
import type { LegacyCallbackName } from "../types.js";
|
|
3
|
+
import { defaultDeprecationReporter } from "./default-ports.js";
|
|
4
|
+
import type { RunContext } from "./run-context.js";
|
|
3
5
|
|
|
4
6
|
/** Where the IR callbacks are documented; the warning points users there. */
|
|
5
7
|
export const IR_CALLBACKS_GUIDE_URL =
|
|
@@ -11,6 +13,12 @@ const USES: Readonly<Record<LegacyCallbackName, string>> = {
|
|
|
11
13
|
transformProperty: "`transformProperty` receives TypeScript nodes",
|
|
12
14
|
};
|
|
13
15
|
|
|
16
|
+
const CODES: Readonly<Record<LegacyCallbackName, DeprecationCode>> = {
|
|
17
|
+
transform: DEPRECATION_CODES.OPENAPI_TYPESAFE_DEP_TS_TRANSFORM,
|
|
18
|
+
postTransform: DEPRECATION_CODES.OPENAPI_TYPESAFE_DEP_TS_POST_TRANSFORM,
|
|
19
|
+
transformProperty: DEPRECATION_CODES.OPENAPI_TYPESAFE_DEP_TS_TRANSFORM_PROPERTY,
|
|
20
|
+
};
|
|
21
|
+
|
|
14
22
|
function message(name: LegacyCallbackName): string {
|
|
15
23
|
return (
|
|
16
24
|
`${USES[name]}. This form works in 1.x through the TypeScript bridge and is removed in 2.0. ` +
|
|
@@ -18,12 +26,15 @@ function message(name: LegacyCallbackName): string {
|
|
|
18
26
|
);
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
/**
|
|
22
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Report a deprecated callback form once per run and callback, as a deprecation (not through the
|
|
31
|
+
* logger, so `silent` does not hide it). The Node.js reporter shows each code once per process.
|
|
32
|
+
*/
|
|
33
|
+
export function warnLegacyCallback(ctx: RunContext, name: LegacyCallbackName): void {
|
|
23
34
|
ctx.legacyCallbackWarnings ??= new Set();
|
|
24
35
|
if (ctx.legacyCallbackWarnings.has(name)) {
|
|
25
36
|
return;
|
|
26
37
|
}
|
|
27
38
|
ctx.legacyCallbackWarnings.add(name);
|
|
28
|
-
(ctx.
|
|
39
|
+
(ctx.deprecations ?? defaultDeprecationReporter()).report(CODES[name], message(name));
|
|
29
40
|
}
|
|
@@ -103,7 +103,7 @@ export function tsDedupe(types: TypeInput[]): ts.TypeNode[] {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/** @deprecated The generator keeps its own enum registry per run; kept for 1.x (ADR-004). */
|
|
106
|
-
export const enumCache
|
|
106
|
+
export const enumCache: Map<string, ts.EnumDeclaration> = new Map();
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
109
|
* Create a TS enum (with sanitized name and members)
|
|
@@ -114,7 +114,7 @@ export function tsEnum(
|
|
|
114
114
|
members: (string | number)[],
|
|
115
115
|
metadata?: { name?: string; description?: string | null }[],
|
|
116
116
|
options?: { export?: boolean; shouldCache?: boolean },
|
|
117
|
-
) {
|
|
117
|
+
): ts.EnumDeclaration {
|
|
118
118
|
const ts = loadTypeScript();
|
|
119
119
|
let enumName = sanitizeMemberName(name);
|
|
120
120
|
enumName = `${enumName.charAt(0).toUpperCase()}${enumName.substring(1)}`;
|
|
@@ -149,7 +149,7 @@ export function tsArrayLiteralExpression(
|
|
|
149
149
|
elementType: TypeInput,
|
|
150
150
|
values: (string | number)[],
|
|
151
151
|
options?: { export?: boolean; readonly?: boolean; injectFooter?: FooterEntry[] },
|
|
152
|
-
) {
|
|
152
|
+
): ts.VariableStatement {
|
|
153
153
|
const ts = loadTypeScript();
|
|
154
154
|
let variableName = sanitizeMemberName(name);
|
|
155
155
|
variableName = `${variableName.charAt(0).toLowerCase()}${variableName.substring(1)}`;
|
|
@@ -223,7 +223,7 @@ function enumMemberName(value: string | number, explicitName: string | undefined
|
|
|
223
223
|
export function tsEnumMember(
|
|
224
224
|
value: string | number,
|
|
225
225
|
metadata: { name?: string; description?: string | null } = {},
|
|
226
|
-
) {
|
|
226
|
+
): ts.EnumMember {
|
|
227
227
|
const ts = loadTypeScript();
|
|
228
228
|
const name = enumMemberName(value, metadata.name);
|
|
229
229
|
const member = ts.factory.createEnumMember(name, toValueExpression(ts, value));
|
|
@@ -281,7 +281,9 @@ export function tsModifiers(modifiers: { readonly?: boolean; export?: boolean })
|
|
|
281
281
|
* Create a valid property index
|
|
282
282
|
* @deprecated Kept for 1.x; removed in 2.0 (ADR-004, decision 9).
|
|
283
283
|
*/
|
|
284
|
-
export function tsPropertyIndex(
|
|
284
|
+
export function tsPropertyIndex(
|
|
285
|
+
index: string | number,
|
|
286
|
+
): ts.Identifier | ts.NumericLiteral | ts.StringLiteral {
|
|
285
287
|
const ts = loadTypeScript();
|
|
286
288
|
if (
|
|
287
289
|
(typeof index === "number" && !(index < 0)) ||
|
package/src/api/legacy-utils.ts
CHANGED
|
@@ -90,7 +90,7 @@ export type { ResolveRefOptions } from "./document-refs.js";
|
|
|
90
90
|
* @deprecated Kept for 1.x; removed in 2.0 (ADR-004, decision 9).
|
|
91
91
|
*/
|
|
92
92
|
export function resolveRef<T>(
|
|
93
|
-
schema:
|
|
93
|
+
schema: unknown,
|
|
94
94
|
$ref: string,
|
|
95
95
|
options: ResolveRefOptions,
|
|
96
96
|
): T | undefined {
|
package/src/api/openapi-ts.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { withStackOverflowReported } from "../application/stack-overflow.js";
|
|
|
3
3
|
import type { IrDeclaration } from "../domain/ir/nodes.js";
|
|
4
4
|
import type { GeneratorOptions, SchemaSource } from "../types.js";
|
|
5
5
|
import {
|
|
6
|
+
DEFAULT_REMOTE_DOCUMENT_LIMITS,
|
|
7
|
+
defaultDeprecationReporter,
|
|
6
8
|
defaultLogger,
|
|
7
9
|
defaultRedoclyConfig,
|
|
8
10
|
monotonicNow,
|
|
@@ -33,7 +35,10 @@ export async function generateDeclarations(
|
|
|
33
35
|
return result;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* The default ports: the terminal logger, Node.js deprecation warnings, the given or default
|
|
40
|
+
* Redocly config, Redocly loading.
|
|
41
|
+
*/
|
|
37
42
|
export async function defaultGeneratorPorts(options: GeneratorOptions): Promise<GeneratorPorts> {
|
|
38
43
|
const logger = defaultLogger(options.silent ?? false);
|
|
39
44
|
const redoc = options.redocly ?? (await defaultRedoclyConfig());
|
|
@@ -42,8 +47,9 @@ export async function defaultGeneratorPorts(options: GeneratorOptions): Promise<
|
|
|
42
47
|
logger,
|
|
43
48
|
now: monotonicNow,
|
|
44
49
|
remoteRefTimeoutMs: REMOTE_REF_TIMEOUT_MS,
|
|
50
|
+
remoteDocumentLimits: DEFAULT_REMOTE_DOCUMENT_LIMITS,
|
|
45
51
|
});
|
|
46
|
-
return { loader, logger, redoc, now: monotonicNow };
|
|
52
|
+
return { loader, logger, deprecations: defaultDeprecationReporter(), redoc, now: monotonicNow };
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
/**
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { DeprecationReporter } from "../application/ports/deprecation-reporter.js";
|
|
2
|
+
import type { Logger } from "../application/ports/logger.js";
|
|
3
|
+
import type { DocumentFooter } from "../application/transform/transform-context.js";
|
|
4
|
+
import type { GlobalContext, LegacyCallbackName, SchemaObject } from "../types.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The context the generator builds for a run: the public `GlobalContext` plus the run's own
|
|
8
|
+
* state. The state is not part of the public type, so it can change in a minor release; every
|
|
9
|
+
* field is optional, so a context a user builds by hand is a valid `RunContext` without it.
|
|
10
|
+
* Callbacks receive this object as `options.ctx` and may spread it; the state travels with it.
|
|
11
|
+
*/
|
|
12
|
+
export interface RunContext extends GlobalContext {
|
|
13
|
+
readonly discriminators: GlobalContext["discriminators"] & {
|
|
14
|
+
/**
|
|
15
|
+
* With the `discriminator-values` fix: for each enum the scan added to a member and each
|
|
16
|
+
* inherited discriminator object, the enum of the owner's property and the location it is
|
|
17
|
+
* typed at.
|
|
18
|
+
*/
|
|
19
|
+
readonly enumParents?: ReadonlyMap<
|
|
20
|
+
object,
|
|
21
|
+
{ readonly schema: SchemaObject; readonly path: string }
|
|
22
|
+
>;
|
|
23
|
+
/**
|
|
24
|
+
* With the `discriminator-values` fix: for each schema, the properties of the discriminators
|
|
25
|
+
* it inherits besides `objects[ref]`, which it redefines too.
|
|
26
|
+
*/
|
|
27
|
+
readonly otherProperties?: Readonly<Record<string, readonly string[]>>;
|
|
28
|
+
};
|
|
29
|
+
/** Footer state of this run (enum registry and enum naming), created on first use. */
|
|
30
|
+
runFooter?: DocumentFooter;
|
|
31
|
+
/** The deprecated callback forms this run has warned about (once each). */
|
|
32
|
+
legacyCallbackWarnings?: Set<LegacyCallbackName>;
|
|
33
|
+
/** Where this run reports warnings and debug output; without it, the terminal. */
|
|
34
|
+
logger?: Logger;
|
|
35
|
+
/** Where this run reports deprecated forms; without it, Node.js `DeprecationWarning`s. */
|
|
36
|
+
deprecations?: DeprecationReporter;
|
|
37
|
+
}
|
package/src/api/string-to-ast.ts
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
import { deprecate } from "node:util";
|
|
2
1
|
import { parseStatements } from "../adapters/type-ast-bridge/ir-declarations-to-typescript.js";
|
|
3
2
|
import { loadTypeScript } from "../adapters/type-ast-bridge/load-typescript.js";
|
|
3
|
+
import { DEPRECATION_CODES } from "../domain/deprecations.js";
|
|
4
|
+
import { defaultDeprecationReporter } from "./default-ports.js";
|
|
4
5
|
import { IR_CALLBACKS_GUIDE_URL } from "./legacy-callback-warning.js";
|
|
5
6
|
|
|
6
7
|
const STRING_TO_AST_DEPRECATION =
|
|
7
8
|
"stringToAST() is deprecated and removed in 2.0. Return TypeScript type text from an IR " +
|
|
8
9
|
`callback (irCallbacks: true) instead: ${IR_CALLBACKS_GUIDE_URL}`;
|
|
9
10
|
|
|
10
|
-
/** Node's deprecation code for `stringToAST`, so users can filter or trace the warning. */
|
|
11
|
-
export const STRING_TO_AST_DEPRECATION_CODE = "OPENAPI_TYPESAFE_DEP_STRING_TO_AST";
|
|
12
|
-
|
|
13
|
-
function parseSource(source: string): unknown[] {
|
|
14
|
-
return [...parseStatements(loadTypeScript(), source)];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
11
|
/**
|
|
18
12
|
* Convert an arbitrary string to TS (assuming it’s valid). Parses with the TypeScript bridge, so
|
|
19
|
-
* it needs TypeScript 6 or earlier (or `@typescript/typescript6`). Node
|
|
20
|
-
* on the first call only.
|
|
13
|
+
* it needs TypeScript 6 or earlier (or `@typescript/typescript6`). Emits a Node.js
|
|
14
|
+
* `DeprecationWarning` (`OPENAPI_TYPESAFE_DEP_STRING_TO_AST`) on the first call only.
|
|
21
15
|
* @deprecated Kept for 1.x; removed in 2.0 (ADR-004, decision 7). Use type text in IR callbacks.
|
|
22
16
|
*/
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
);
|
|
17
|
+
export function stringToAST(source: string): unknown[] {
|
|
18
|
+
defaultDeprecationReporter().report(
|
|
19
|
+
DEPRECATION_CODES.OPENAPI_TYPESAFE_DEP_STRING_TO_AST,
|
|
20
|
+
STRING_TO_AST_DEPRECATION,
|
|
21
|
+
);
|
|
22
|
+
return [...parseStatements(loadTypeScript(), source)];
|
|
23
|
+
}
|
|
@@ -11,22 +11,24 @@ import type {
|
|
|
11
11
|
TransformDiagnostics,
|
|
12
12
|
TransformOptions,
|
|
13
13
|
} from "../application/transform/transform-context.js";
|
|
14
|
-
import type {
|
|
14
|
+
import type { TransformNodeOptions } from "../types.js";
|
|
15
15
|
import { defaultLogger, monotonicNow } from "./default-ports.js";
|
|
16
16
|
import { ContextFooterSink } from "./footer-sink.js";
|
|
17
|
+
import type { RunContext } from "./run-context.js";
|
|
17
18
|
import { schemaCallbacks } from "./schema-callbacks.js";
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
|
-
* Builds the ported transformers' context from the original `GlobalContext
|
|
21
|
-
* discriminators, the run footer and the user callbacks (see
|
|
21
|
+
* Builds the ported transformers' context from the original `GlobalContext` (in a run, a
|
|
22
|
+
* `RunContext`): options, refs, discriminators, the run footer and the user callbacks (see
|
|
23
|
+
* `schema-callbacks.ts`).
|
|
22
24
|
*/
|
|
23
25
|
|
|
24
|
-
function transformOptions(ctx:
|
|
26
|
+
function transformOptions(ctx: RunContext): TransformOptions {
|
|
25
27
|
return {
|
|
26
28
|
additionalProperties: ctx.additionalProperties,
|
|
27
29
|
alphabetize: ctx.alphabetize,
|
|
28
30
|
arrayLength: ctx.arrayLength,
|
|
29
|
-
binaryAsBlob: ctx.binaryAsBlob,
|
|
31
|
+
binaryAsBlob: ctx.binaryAsBlob ?? false,
|
|
30
32
|
conditionalEnums: ctx.conditionalEnums,
|
|
31
33
|
dedupeEnums: ctx.dedupeEnums,
|
|
32
34
|
defaultNonNullable: ctx.defaultNonNullable,
|
|
@@ -50,7 +52,7 @@ function transformOptions(ctx: GlobalContext): TransformOptions {
|
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
/** One footer per run: it holds the enum registry, so it lives on the run's context. */
|
|
53
|
-
function runFooter(ctx:
|
|
55
|
+
function runFooter(ctx: RunContext): DocumentFooter {
|
|
54
56
|
ctx.runFooter ??= new RunFooter(new ContextFooterSink(ctx.injectFooter), ctx.dedupeEnums);
|
|
55
57
|
return ctx.runFooter;
|
|
56
58
|
}
|
|
@@ -60,7 +62,7 @@ const CASING: NameCasing = { pascalCase: (text) => changeCase.pascalCase(text) }
|
|
|
60
62
|
/**
|
|
61
63
|
* A monotonic clock and the run's logger (the default one for a user's own context), "ts" group.
|
|
62
64
|
*/
|
|
63
|
-
function diagnostics(ctx:
|
|
65
|
+
function diagnostics(ctx: RunContext): TransformDiagnostics {
|
|
64
66
|
const logger = ctx.logger ?? defaultLogger(ctx.silent);
|
|
65
67
|
return {
|
|
66
68
|
now: monotonicNow,
|
|
@@ -69,7 +71,7 @@ function diagnostics(ctx: GlobalContext): TransformDiagnostics {
|
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
/** The ported transformers' context for one call from a legacy transformer. */
|
|
72
|
-
export function createTransformContext(ctx:
|
|
74
|
+
export function createTransformContext(ctx: RunContext): TransformContext {
|
|
73
75
|
return {
|
|
74
76
|
options: transformOptions(ctx),
|
|
75
77
|
refs: { resolve: (ref) => ctx.resolve(ref) },
|
|
@@ -9,13 +9,14 @@ import {
|
|
|
9
9
|
} from "../application/transform/footer/shared-enum-names.js";
|
|
10
10
|
import type { IrDeclaration } from "../domain/ir/nodes.js";
|
|
11
11
|
import type { DocumentObject } from "../domain/openapi/document-object.js";
|
|
12
|
-
import {
|
|
12
|
+
import { FIX } from "../domain/output-fixes.js";
|
|
13
13
|
import type { GlobalContext, OpenAPI3 } from "../types.js";
|
|
14
14
|
import { FirstSchemaNameRecorder } from "./discriminator-enum-names.js";
|
|
15
15
|
import { documentDeclarations, type TransformedDocument } from "./document-declarations.js";
|
|
16
16
|
import { excludedValuesWarning } from "./enum-values-warnings.js";
|
|
17
17
|
import { type FooterEntry, isIrDeclaration } from "./footer-entry.js";
|
|
18
18
|
import { ContextFooterSink } from "./footer-sink.js";
|
|
19
|
+
import type { RunContext } from "./run-context.js";
|
|
19
20
|
import { createTransformContext } from "./transform-context.js";
|
|
20
21
|
|
|
21
22
|
const OPERATIONS_NAME = "operations";
|
|
@@ -46,11 +47,11 @@ interface EnumNameRecorder extends SharedEnumNames {
|
|
|
46
47
|
*/
|
|
47
48
|
function sharedEnumNamesOf(
|
|
48
49
|
document: DocumentObject,
|
|
49
|
-
ctx:
|
|
50
|
+
ctx: RunContext,
|
|
50
51
|
recorder: EnumNameRecorder,
|
|
51
52
|
): SharedEnumNames {
|
|
52
53
|
const injectFooter: FooterEntry[] = [];
|
|
53
|
-
const scratch:
|
|
54
|
+
const scratch: RunContext = {
|
|
54
55
|
...ctx,
|
|
55
56
|
injectFooter,
|
|
56
57
|
runFooter: new RunFooter(new ContextFooterSink(injectFooter), true, recorder),
|
|
@@ -64,14 +65,14 @@ function sharedEnumNamesOf(
|
|
|
64
65
|
|
|
65
66
|
/** The recorder of the run's fixes, or null where the first schema's name needs no first pass. */
|
|
66
67
|
function enumNameRecorderOf(ctx: GlobalContext): EnumNameRecorder | null {
|
|
67
|
-
if (ctx.fix?.includes(
|
|
68
|
+
if (ctx.fix?.includes(FIX.DEDUPE_ENUM_NAMES)) {
|
|
68
69
|
return new SharedEnumNameRecorder();
|
|
69
70
|
}
|
|
70
|
-
return ctx.fix?.includes(
|
|
71
|
+
return ctx.fix?.includes(FIX.DISCRIMINATOR_VALUES) ? new FirstSchemaNameRecorder() : null;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
/** With a naming fix, `--enum` and `--dedupe-enums`, the run's footer names shared enums. */
|
|
74
|
-
function withSharedEnumNames(document: DocumentObject, ctx:
|
|
75
|
+
function withSharedEnumNames(document: DocumentObject, ctx: RunContext): void {
|
|
75
76
|
const recorder = ctx.runFooter === undefined ? enumNameRecorderOf(ctx) : null;
|
|
76
77
|
if (recorder === null || !ctx.enum || !ctx.dedupeEnums) {
|
|
77
78
|
return;
|
|
@@ -87,7 +88,7 @@ function withSharedEnumNames(document: DocumentObject, ctx: GlobalContext): void
|
|
|
87
88
|
function enumValuesChecked(
|
|
88
89
|
body: readonly IrDeclaration[],
|
|
89
90
|
footer: FooterEntry[],
|
|
90
|
-
ctx:
|
|
91
|
+
ctx: RunContext,
|
|
91
92
|
): FooterEntry[] {
|
|
92
93
|
if (!ctx.enumValues) {
|
|
93
94
|
return footer;
|
|
@@ -102,7 +103,7 @@ function enumValuesChecked(
|
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
/** @internal Root types, the footer, then the closing declarations (Phase 5, step 6). */
|
|
105
|
-
export function transformDocument(schema: OpenAPI3, ctx:
|
|
106
|
+
export function transformDocument(schema: OpenAPI3, ctx: RunContext): TransformedDocument {
|
|
106
107
|
const document = schema as DocumentObject;
|
|
107
108
|
withSharedEnumNames(document, ctx);
|
|
108
109
|
const context = createTransformContext(ctx);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DeprecationCode } from "../../domain/deprecations.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Where the generator reports the use of something 2.0 removes (ENGINEERING_PLAN 4.5). The
|
|
5
|
+
* adapter decides how often a code is shown; the Node.js one shows each code once per process.
|
|
6
|
+
*/
|
|
7
|
+
export interface DeprecationReporter {
|
|
8
|
+
report(code: DeprecationCode, message: string): void;
|
|
9
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assertNever } from "../../domain/assert-never.js";
|
|
2
|
+
import { DEFAULT_STRING_ENCODING } from "../../domain/ir/constructors.js";
|
|
2
3
|
import type {
|
|
3
4
|
IrIndexedAccessType,
|
|
4
5
|
IrMember,
|
|
@@ -196,7 +197,7 @@ function printLeafType(type: IrLeafType): string {
|
|
|
196
197
|
case "keyword":
|
|
197
198
|
return type.keyword;
|
|
198
199
|
case "stringLiteral":
|
|
199
|
-
return printStringLiteral(type.value, type.encoding);
|
|
200
|
+
return printStringLiteral(type.value, type.encoding ?? DEFAULT_STRING_ENCODING);
|
|
200
201
|
case "numberLiteral":
|
|
201
202
|
return printNumberLiteral(type.value);
|
|
202
203
|
case "booleanLiteral":
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
singularizeComponentKind,
|
|
20
20
|
} from "../../../domain/openapi/components-object.js";
|
|
21
21
|
import { createRef } from "../../../domain/openapi/json-pointer.js";
|
|
22
|
-
import {
|
|
22
|
+
import { FIX } from "../../../domain/output-fixes.js";
|
|
23
23
|
import { type DeprecatedEntryFilter, documentEntries } from "../document-entries.js";
|
|
24
24
|
import type { SchemaLocation } from "../schema/schema-context.js";
|
|
25
25
|
import { transformSchema } from "../schema/schema-transform.js";
|
|
@@ -174,7 +174,7 @@ export function componentsType(
|
|
|
174
174
|
// A plain object, as in the original: its key order (integer-like names first) is the
|
|
175
175
|
// output order.
|
|
176
176
|
const aliases: Record<string, IrTypeAliasDeclaration> = {};
|
|
177
|
-
const displaced = context.options.fixes.has(
|
|
177
|
+
const displaced = context.options.fixes.has(FIX.ROOT_TYPE_NUMBERING) ? [] : null;
|
|
178
178
|
const isKept = (item: unknown) => kept.has(item as object);
|
|
179
179
|
const request = { components, isKept, aliases, displaced };
|
|
180
180
|
const declaredKinds = DECLARED_COMPONENT_KINDS.filter((kind) => components[kind] !== undefined);
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
QUERYSTRING_LOCATION,
|
|
17
17
|
} from "../../../domain/openapi/parameter-object.js";
|
|
18
18
|
import type { SchemaObject } from "../../../domain/openapi/schema-object.js";
|
|
19
|
-
import {
|
|
19
|
+
import { FIX } from "../../../domain/output-fixes.js";
|
|
20
20
|
import { refType } from "../ref-type.js";
|
|
21
21
|
import type { SchemaLocation } from "../schema/schema-context.js";
|
|
22
22
|
import { withSchemaComment } from "../schema-comment.js";
|
|
@@ -24,7 +24,8 @@ import type { TransformContext } from "../transform-context.js";
|
|
|
24
24
|
import { isExplodedQueryObject } from "./exploded-query.js";
|
|
25
25
|
import { parameterType } from "./parameter.js";
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
/** `[^{}]` keeps the scan linear: `[^}]` retried from every `{` of a long run of them. */
|
|
28
|
+
const PATH_TEMPLATE_RE = /\{([^{}]+)\}/g;
|
|
28
29
|
|
|
29
30
|
/** A parameter as written in the document, and the object its `$ref` points to. */
|
|
30
31
|
interface ParameterEntry {
|
|
@@ -165,7 +166,7 @@ function querystringMember(
|
|
|
165
166
|
/** With `exploded-query-objects`, whether the parameter's object keys are keys of `query`. */
|
|
166
167
|
function isExplodedEntry(entry: ResolvedEntry, context: TransformContext): boolean {
|
|
167
168
|
return (
|
|
168
|
-
context.options.fixes.has(
|
|
169
|
+
context.options.fixes.has(FIX.EXPLODED_QUERY_OBJECTS) &&
|
|
169
170
|
isExplodedQueryObject(entry.resolved, context.refs)
|
|
170
171
|
);
|
|
171
172
|
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
pathItemOperations,
|
|
15
15
|
} from "../../../domain/openapi/path-item-object.js";
|
|
16
16
|
import type { ReferenceSchema, SchemaObject } from "../../../domain/openapi/schema-object.js";
|
|
17
|
-
import {
|
|
17
|
+
import { FIX } from "../../../domain/output-fixes.js";
|
|
18
18
|
import { documentEntries } from "../document-entries.js";
|
|
19
19
|
import { refType } from "../ref-type.js";
|
|
20
20
|
import type { TransformContext } from "../transform-context.js";
|
|
@@ -35,7 +35,8 @@ import {
|
|
|
35
35
|
} from "./path-template-replace.js";
|
|
36
36
|
import { assignabilityProof } from "./type-assignability.js";
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
/** `[^{}]` keeps the scan linear: `[^}]` retried from every `{` of a long run of them. */
|
|
39
|
+
const PATH_PARAMETER_RE = /\{[^{}]+\}/g;
|
|
39
40
|
|
|
40
41
|
/** Placeholders by parameter schema type; anything else is a string placeholder. */
|
|
41
42
|
const PLACEHOLDERS: ReadonlyMap<unknown, PathPlaceholder> = new Map([
|
|
@@ -111,7 +112,7 @@ function pathTemplateParts(
|
|
|
111
112
|
const schema = parameters.get(match.slice(1, -1))?.schema as SchemaObject | undefined;
|
|
112
113
|
return { match, type: PLACEHOLDERS.get(schema?.type) ?? STRING_PLACEHOLDER };
|
|
113
114
|
});
|
|
114
|
-
return context.options.fixes.has(
|
|
115
|
+
return context.options.fixes.has(FIX.PATH_PARAM_TYPE_NAMES)
|
|
115
116
|
? splitTemplateParts(url, matches)
|
|
116
117
|
: replacedTemplateParts(url, matches);
|
|
117
118
|
}
|