openapi-typesafe 1.0.0-rc.0 → 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-config-source.cjs +21 -2
- package/dist/adapters/redocly-loader/redocly-config-source.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-config-source.mjs +22 -3
- package/dist/adapters/redocly-loader/redocly-config-source.mjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +34 -11
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +33 -10
- 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 +5 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs.map +1 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs +5 -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/adapters/type-ast-bridge/typescript-to-ir.cjs +15 -9
- package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs.map +1 -1
- package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs +15 -9
- package/dist/adapters/type-ast-bridge/typescript-to-ir.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-conflict-warnings.cjs +25 -0
- package/dist/api/discriminator-conflict-warnings.cjs.map +1 -0
- package/dist/api/discriminator-conflict-warnings.mjs +23 -0
- package/dist/api/discriminator-conflict-warnings.mjs.map +1 -0
- package/dist/api/discriminator-enum-names.cjs +19 -0
- package/dist/api/discriminator-enum-names.cjs.map +1 -0
- package/dist/api/discriminator-enum-names.mjs +17 -0
- package/dist/api/discriminator-enum-names.mjs.map +1 -0
- package/dist/api/discriminator-enum-parent.cjs +59 -0
- package/dist/api/discriminator-enum-parent.cjs.map +1 -0
- package/dist/api/discriminator-enum-parent.mjs +57 -0
- package/dist/api/discriminator-enum-parent.mjs.map +1 -0
- package/dist/api/discriminator-enum.cjs +25 -0
- package/dist/api/discriminator-enum.cjs.map +1 -1
- package/dist/api/discriminator-enum.mjs +25 -1
- package/dist/api/discriminator-enum.mjs.map +1 -1
- package/dist/api/discriminator-other-owners.cjs +67 -0
- package/dist/api/discriminator-other-owners.cjs.map +1 -0
- package/dist/api/discriminator-other-owners.mjs +64 -0
- package/dist/api/discriminator-other-owners.mjs.map +1 -0
- package/dist/api/discriminator-patch.cjs +92 -0
- package/dist/api/discriminator-patch.cjs.map +1 -0
- package/dist/api/discriminator-patch.mjs +86 -0
- package/dist/api/discriminator-patch.mjs.map +1 -0
- package/dist/api/discriminator-scan.cjs +50 -65
- package/dist/api/discriminator-scan.cjs.map +1 -1
- package/dist/api/discriminator-scan.mjs +44 -59
- 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 +21 -4
- package/dist/api/document-run.cjs.map +1 -1
- package/dist/api/document-run.mjs +22 -5
- package/dist/api/document-run.mjs.map +1 -1
- package/dist/api/enum-values-warnings.cjs +16 -0
- package/dist/api/enum-values-warnings.cjs.map +1 -0
- package/dist/api/enum-values-warnings.mjs +14 -0
- package/dist/api/enum-values-warnings.mjs.map +1 -0
- 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/path-template-warnings.cjs +21 -0
- package/dist/api/path-template-warnings.cjs.map +1 -0
- package/dist/api/path-template-warnings.mjs +19 -0
- package/dist/api/path-template-warnings.mjs.map +1 -0
- package/dist/api/transform-context.cjs +4 -2
- package/dist/api/transform-context.cjs.map +1 -1
- package/dist/api/transform-context.mjs +4 -2
- package/dist/api/transform-context.mjs.map +1 -1
- package/dist/api/transform-schema.cjs +52 -3
- package/dist/api/transform-schema.cjs.map +1 -1
- package/dist/api/transform-schema.mjs +53 -4
- package/dist/api/transform-schema.mjs.map +1 -1
- package/dist/api/unsupported-feature-warnings.cjs +6 -1
- package/dist/api/unsupported-feature-warnings.cjs.map +1 -1
- package/dist/api/unsupported-feature-warnings.mjs +6 -1
- package/dist/api/unsupported-feature-warnings.mjs.map +1 -1
- package/dist/application/print/type-printer.cjs +7 -1
- package/dist/application/print/type-printer.cjs.map +1 -1
- package/dist/application/print/type-printer.mjs +7 -1
- package/dist/application/print/type-printer.mjs.map +1 -1
- package/dist/application/transform/document/assignability.cjs +144 -0
- package/dist/application/transform/document/assignability.cjs.map +1 -0
- package/dist/application/transform/document/assignability.mjs +138 -0
- package/dist/application/transform/document/assignability.mjs.map +1 -0
- package/dist/application/transform/document/components.cjs +2 -2
- package/dist/application/transform/document/components.cjs.map +1 -1
- package/dist/application/transform/document/components.mjs +4 -4
- package/dist/application/transform/document/components.mjs.map +1 -1
- package/dist/application/transform/document/declared-types.cjs +66 -0
- package/dist/application/transform/document/declared-types.cjs.map +1 -0
- package/dist/application/transform/document/declared-types.mjs +63 -0
- package/dist/application/transform/document/declared-types.mjs.map +1 -0
- package/dist/application/transform/document/document.cjs +32 -9
- package/dist/application/transform/document/document.cjs.map +1 -1
- package/dist/application/transform/document/document.mjs +34 -11
- package/dist/application/transform/document/document.mjs.map +1 -1
- package/dist/application/transform/document/exploded-query.cjs +46 -0
- package/dist/application/transform/document/exploded-query.cjs.map +1 -0
- package/dist/application/transform/document/exploded-query.mjs +43 -0
- package/dist/application/transform/document/exploded-query.mjs.map +1 -0
- package/dist/application/transform/document/global-type-references.cjs +63 -0
- package/dist/application/transform/document/global-type-references.cjs.map +1 -0
- package/dist/application/transform/document/global-type-references.mjs +61 -0
- package/dist/application/transform/document/global-type-references.mjs.map +1 -0
- package/dist/application/transform/document/list-assignability.cjs +54 -0
- package/dist/application/transform/document/list-assignability.cjs.map +1 -0
- package/dist/application/transform/document/list-assignability.mjs +52 -0
- package/dist/application/transform/document/list-assignability.mjs.map +1 -0
- package/dist/application/transform/document/parameters.cjs +41 -9
- package/dist/application/transform/document/parameters.cjs.map +1 -1
- package/dist/application/transform/document/parameters.mjs +42 -10
- package/dist/application/transform/document/parameters.mjs.map +1 -1
- package/dist/application/transform/document/path-key-overlaps.cjs +83 -33
- package/dist/application/transform/document/path-key-overlaps.cjs.map +1 -1
- package/dist/application/transform/document/path-key-overlaps.mjs +83 -33
- package/dist/application/transform/document/path-key-overlaps.mjs.map +1 -1
- package/dist/application/transform/document/path-template-replace.cjs +48 -0
- package/dist/application/transform/document/path-template-replace.cjs.map +1 -0
- package/dist/application/transform/document/path-template-replace.mjs +45 -0
- package/dist/application/transform/document/path-template-replace.mjs.map +1 -0
- package/dist/application/transform/document/paths.cjs +55 -29
- package/dist/application/transform/document/paths.cjs.map +1 -1
- package/dist/application/transform/document/paths.mjs +54 -30
- package/dist/application/transform/document/paths.mjs.map +1 -1
- package/dist/application/transform/document/root-type-aliases.cjs +15 -14
- package/dist/application/transform/document/root-type-aliases.cjs.map +1 -1
- package/dist/application/transform/document/root-type-aliases.mjs +15 -13
- package/dist/application/transform/document/root-type-aliases.mjs.map +1 -1
- package/dist/application/transform/document/template-key-match.cjs +128 -0
- package/dist/application/transform/document/template-key-match.cjs.map +1 -0
- package/dist/application/transform/document/template-key-match.mjs +125 -0
- package/dist/application/transform/document/template-key-match.mjs.map +1 -0
- package/dist/application/transform/document/type-assignability.cjs +192 -0
- package/dist/application/transform/document/type-assignability.cjs.map +1 -0
- package/dist/application/transform/document/type-assignability.mjs +190 -0
- package/dist/application/transform/document/type-assignability.mjs.map +1 -0
- package/dist/application/transform/document/type-key.cjs +70 -0
- package/dist/application/transform/document/type-key.cjs.map +1 -0
- package/dist/application/transform/document/type-key.mjs +68 -0
- package/dist/application/transform/document/type-key.mjs.map +1 -0
- package/dist/application/transform/document/type-resolution.cjs +131 -0
- package/dist/application/transform/document/type-resolution.cjs.map +1 -0
- package/dist/application/transform/document/type-resolution.mjs +125 -0
- package/dist/application/transform/document/type-resolution.mjs.map +1 -0
- package/dist/application/transform/footer/document-footer.cjs +66 -4
- package/dist/application/transform/footer/document-footer.cjs.map +1 -1
- package/dist/application/transform/footer/document-footer.mjs +67 -5
- package/dist/application/transform/footer/document-footer.mjs.map +1 -1
- package/dist/application/transform/footer/enum-naming.cjs +17 -0
- package/dist/application/transform/footer/enum-naming.cjs.map +1 -1
- package/dist/application/transform/footer/enum-naming.mjs +17 -1
- package/dist/application/transform/footer/enum-naming.mjs.map +1 -1
- package/dist/application/transform/footer/enum-values-check.cjs +129 -0
- package/dist/application/transform/footer/enum-values-check.cjs.map +1 -0
- package/dist/application/transform/footer/enum-values-check.mjs +127 -0
- package/dist/application/transform/footer/enum-values-check.mjs.map +1 -0
- package/dist/application/transform/footer/evaluation.cjs +42 -0
- package/dist/application/transform/footer/evaluation.cjs.map +1 -0
- package/dist/application/transform/footer/evaluation.mjs +33 -0
- package/dist/application/transform/footer/evaluation.mjs.map +1 -0
- package/dist/application/transform/footer/shared-enum-names.cjs +60 -0
- package/dist/application/transform/footer/shared-enum-names.cjs.map +1 -0
- package/dist/application/transform/footer/shared-enum-names.mjs +57 -0
- package/dist/application/transform/footer/shared-enum-names.mjs.map +1 -0
- package/dist/application/transform/footer/type-evaluation.cjs +138 -0
- package/dist/application/transform/footer/type-evaluation.cjs.map +1 -0
- package/dist/application/transform/footer/type-evaluation.mjs +136 -0
- package/dist/application/transform/footer/type-evaluation.mjs.map +1 -0
- 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/footer/type-rules.cjs +172 -0
- package/dist/application/transform/footer/type-rules.cjs.map +1 -0
- package/dist/application/transform/footer/type-rules.mjs +166 -0
- package/dist/application/transform/footer/type-rules.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/generated-location.cjs +138 -0
- package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/generated-location.mjs +136 -0
- package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/generated-shape.cjs +171 -0
- package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/generated-shape.mjs +162 -0
- package/dist/application/transform/ref-pointer/generated-shape.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/inline-cycles.cjs +44 -0
- package/dist/application/transform/ref-pointer/inline-cycles.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/inline-cycles.mjs +42 -0
- package/dist/application/transform/ref-pointer/inline-cycles.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/original-index.cjs +62 -0
- package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/original-index.mjs +60 -0
- package/dist/application/transform/ref-pointer/original-index.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/pointer-type.cjs +60 -0
- package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/pointer-type.mjs +57 -0
- package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/pointer-walk.cjs +66 -0
- package/dist/application/transform/ref-pointer/pointer-walk.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/pointer-walk.mjs +56 -0
- package/dist/application/transform/ref-pointer/pointer-walk.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/typed-walk.cjs +124 -0
- package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/typed-walk.mjs +122 -0
- package/dist/application/transform/ref-pointer/typed-walk.mjs.map +1 -0
- package/dist/application/transform/ref-type.cjs +7 -2
- package/dist/application/transform/ref-type.cjs.map +1 -1
- package/dist/application/transform/ref-type.mjs +3 -2
- package/dist/application/transform/ref-type.mjs.map +1 -1
- package/dist/application/transform/schema/access-flags.cjs +38 -0
- package/dist/application/transform/schema/access-flags.cjs.map +1 -0
- package/dist/application/transform/schema/access-flags.mjs +36 -0
- package/dist/application/transform/schema/access-flags.mjs.map +1 -0
- package/dist/application/transform/schema/array-type.cjs +32 -1
- package/dist/application/transform/schema/array-type.cjs.map +1 -1
- package/dist/application/transform/schema/array-type.mjs +33 -2
- package/dist/application/transform/schema/array-type.mjs.map +1 -1
- package/dist/application/transform/schema/composition-type.cjs +50 -15
- package/dist/application/transform/schema/composition-type.cjs.map +1 -1
- package/dist/application/transform/schema/composition-type.mjs +50 -15
- package/dist/application/transform/schema/composition-type.mjs.map +1 -1
- package/dist/application/transform/schema/core-type.cjs +3 -1
- package/dist/application/transform/schema/core-type.cjs.map +1 -1
- package/dist/application/transform/schema/core-type.mjs +3 -1
- package/dist/application/transform/schema/core-type.mjs.map +1 -1
- package/dist/application/transform/schema/discriminated-union.cjs +30 -0
- package/dist/application/transform/schema/discriminated-union.cjs.map +1 -0
- package/dist/application/transform/schema/discriminated-union.mjs +27 -0
- package/dist/application/transform/schema/discriminated-union.mjs.map +1 -0
- package/dist/application/transform/schema/discriminator-property.cjs +3 -2
- package/dist/application/transform/schema/discriminator-property.cjs.map +1 -1
- package/dist/application/transform/schema/discriminator-property.mjs +3 -2
- package/dist/application/transform/schema/discriminator-property.mjs.map +1 -1
- package/dist/application/transform/schema/enum-rule.cjs +66 -10
- package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
- package/dist/application/transform/schema/enum-rule.mjs +67 -12
- package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
- package/dist/application/transform/schema/inherited-discriminator.cjs +29 -0
- package/dist/application/transform/schema/inherited-discriminator.cjs.map +1 -0
- package/dist/application/transform/schema/inherited-discriminator.mjs +26 -0
- package/dist/application/transform/schema/inherited-discriminator.mjs.map +1 -0
- package/dist/application/transform/schema/object-type.cjs +38 -25
- package/dist/application/transform/schema/object-type.cjs.map +1 -1
- package/dist/application/transform/schema/object-type.mjs +39 -27
- package/dist/application/transform/schema/object-type.mjs.map +1 -1
- package/dist/application/transform/schema/required-variants.cjs +45 -0
- package/dist/application/transform/schema/required-variants.cjs.map +1 -0
- package/dist/application/transform/schema/required-variants.mjs +42 -0
- package/dist/application/transform/schema/required-variants.mjs.map +1 -0
- package/dist/application/transform/schema/schema-transform.cjs +2 -2
- package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
- package/dist/application/transform/schema/schema-transform.mjs +2 -2
- package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
- package/dist/application/transform/schema-comment.cjs +51 -5
- package/dist/application/transform/schema-comment.cjs.map +1 -1
- package/dist/application/transform/schema-comment.mjs +50 -6
- package/dist/application/transform/schema-comment.mjs.map +1 -1
- package/dist/application/transform/type-combinators.mjs +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 +12 -3
- package/dist/cli/cli-arguments.cjs.map +1 -1
- package/dist/cli/cli-arguments.mjs +12 -4
- package/dist/cli/cli-arguments.mjs.map +1 -1
- package/dist/cli/cli-errors.cjs +3 -2
- package/dist/cli/cli-errors.cjs.map +1 -1
- package/dist/cli/cli-errors.mjs +3 -2
- package/dist/cli/cli-errors.mjs.map +1 -1
- package/dist/cli/cli-output.cjs +8 -3
- package/dist/cli/cli-output.cjs.map +1 -1
- package/dist/cli/cli-output.mjs +9 -4
- package/dist/cli/cli-output.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/main.cjs +5 -0
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.mjs +5 -0
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/redocly-apis.cjs +15 -7
- package/dist/cli/redocly-apis.cjs.map +1 -1
- package/dist/cli/redocly-apis.mjs +15 -7
- package/dist/cli/redocly-apis.mjs.map +1 -1
- package/dist/cli/ref-limits.cjs +1 -1
- package/dist/cli/ref-limits.cjs.map +1 -1
- package/dist/cli/ref-limits.mjs +2 -2
- package/dist/cli/ref-limits.mjs.map +1 -1
- package/dist/cli/run-cli.cjs +20 -3
- package/dist/cli/run-cli.cjs.map +1 -1
- package/dist/cli/run-cli.mjs +21 -4
- package/dist/cli/run-cli.mjs.map +1 -1
- package/dist/domain/errors.cjs +6 -1
- package/dist/domain/errors.cjs.map +1 -1
- package/dist/domain/errors.mjs +6 -1
- package/dist/domain/errors.mjs.map +1 -1
- package/dist/domain/ir/constructors.cjs +7 -1
- package/dist/domain/ir/constructors.cjs.map +1 -1
- package/dist/domain/ir/constructors.mjs +6 -2
- package/dist/domain/ir/constructors.mjs.map +1 -1
- package/dist/domain/openapi/admitted-values.cjs +75 -0
- package/dist/domain/openapi/admitted-values.cjs.map +1 -0
- package/dist/domain/openapi/admitted-values.mjs +72 -0
- package/dist/domain/openapi/admitted-values.mjs.map +1 -0
- package/dist/domain/openapi/discriminated-union.cjs +68 -0
- package/dist/domain/openapi/discriminated-union.cjs.map +1 -0
- package/dist/domain/openapi/discriminated-union.mjs +62 -0
- package/dist/domain/openapi/discriminated-union.mjs.map +1 -0
- package/dist/domain/openapi/discriminator-conflicts.cjs +143 -0
- package/dist/domain/openapi/discriminator-conflicts.cjs.map +1 -0
- package/dist/domain/openapi/discriminator-conflicts.mjs +141 -0
- package/dist/domain/openapi/discriminator-conflicts.mjs.map +1 -0
- package/dist/domain/openapi/parameter-object.cjs.map +1 -1
- package/dist/domain/openapi/parameter-object.mjs.map +1 -1
- package/dist/domain/openapi/path-templates.cjs +23 -0
- package/dist/domain/openapi/path-templates.cjs.map +1 -0
- package/dist/domain/openapi/path-templates.mjs +21 -0
- package/dist/domain/openapi/path-templates.mjs.map +1 -0
- package/dist/domain/output-fixes.cjs +36 -1
- package/dist/domain/output-fixes.cjs.map +1 -1
- package/dist/domain/output-fixes.mjs +36 -1
- 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 +23 -0
- package/dist/domain/warnings.cjs.map +1 -0
- package/dist/domain/warnings.mjs +20 -0
- package/dist/domain/warnings.mjs.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1182 -46
- package/dist/index.d.mts +1182 -46
- package/dist/index.d.ts +1182 -46
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/transform/components-object.cjs +2 -1
- package/dist/transform/components-object.cjs.map +1 -1
- package/dist/transform/components-object.mjs +2 -1
- package/dist/transform/components-object.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-config-source.ts +41 -6
- package/src/adapters/redocly-loader/redocly-schema-loader.ts +44 -13
- 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 +5 -1
- package/src/adapters/type-ast-bridge/print-typescript.ts +3 -1
- package/src/adapters/type-ast-bridge/typescript-to-ir.ts +26 -12
- package/src/adapters/type-ast-bridge/typescript-types.ts +57 -5
- package/src/api/default-ports.ts +16 -0
- package/src/api/discriminator-conflict-warnings.ts +43 -0
- package/src/api/discriminator-enum-names.ts +26 -0
- package/src/api/discriminator-enum-parent.ts +129 -0
- package/src/api/discriminator-enum.ts +39 -0
- package/src/api/discriminator-other-owners.ts +97 -0
- package/src/api/discriminator-patch.ts +152 -0
- package/src/api/discriminator-scan.ts +78 -90
- package/src/api/document-refs.ts +19 -15
- package/src/api/document-run.ts +32 -11
- package/src/api/enum-values-warnings.ts +21 -0
- 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/path-template-warnings.ts +27 -0
- package/src/api/run-context.ts +34 -0
- package/src/api/transform-context.ts +17 -9
- package/src/api/transform-schema.ts +90 -5
- package/src/api/unsupported-feature-warnings.ts +8 -1
- package/src/application/ports/redocly-config-source.ts +5 -1
- package/src/application/print/type-printer.ts +8 -1
- package/src/application/transform/document/assignability.ts +203 -0
- package/src/application/transform/document/components.ts +6 -6
- package/src/application/transform/document/declared-types.ts +93 -0
- package/src/application/transform/document/document.ts +71 -13
- package/src/application/transform/document/exploded-query.ts +91 -0
- package/src/application/transform/document/global-type-references.ts +78 -0
- package/src/application/transform/document/list-assignability.ts +87 -0
- package/src/application/transform/document/parameters.ts +78 -12
- package/src/application/transform/document/path-key-overlaps.ts +148 -59
- package/src/application/transform/document/path-template-replace.ts +90 -0
- package/src/application/transform/document/paths.ts +101 -38
- package/src/application/transform/document/root-type-aliases.ts +29 -28
- package/src/application/transform/document/template-key-match.ts +183 -0
- package/src/application/transform/document/type-assignability.ts +268 -0
- package/src/application/transform/document/type-key.ts +80 -0
- package/src/application/transform/document/type-resolution.ts +163 -0
- package/src/application/transform/footer/document-footer.ts +91 -6
- package/src/application/transform/footer/enum-naming.ts +29 -0
- package/src/application/transform/footer/enum-values-check.ts +171 -0
- package/src/application/transform/footer/evaluation.ts +57 -0
- package/src/application/transform/footer/shared-enum-names.ts +86 -0
- package/src/application/transform/footer/type-evaluation.ts +167 -0
- package/src/application/transform/footer/type-indexing.ts +152 -0
- package/src/application/transform/footer/type-rules.ts +269 -0
- package/src/application/transform/ref-pointer/generated-location.ts +211 -0
- package/src/application/transform/ref-pointer/generated-shape.ts +275 -0
- package/src/application/transform/ref-pointer/inline-cycles.ts +56 -0
- package/src/application/transform/ref-pointer/original-index.ts +95 -0
- package/src/application/transform/ref-pointer/pointer-type.ts +92 -0
- package/src/application/transform/ref-pointer/pointer-walk.ts +96 -0
- package/src/application/transform/ref-pointer/typed-walk.ts +192 -0
- package/src/application/transform/ref-type.ts +11 -6
- package/src/application/transform/schema/access-flags.ts +63 -0
- package/src/application/transform/schema/array-type.ts +66 -5
- package/src/application/transform/schema/composition-type.ts +96 -24
- package/src/application/transform/schema/core-type.ts +8 -4
- package/src/application/transform/schema/discriminated-union.ts +58 -0
- package/src/application/transform/schema/discriminator-property.ts +8 -3
- package/src/application/transform/schema/enum-rule.ts +136 -13
- package/src/application/transform/schema/inherited-discriminator.ts +54 -0
- package/src/application/transform/schema/object-type.ts +51 -33
- package/src/application/transform/schema/required-variants.ts +88 -0
- package/src/application/transform/schema/schema-context.ts +26 -0
- package/src/application/transform/schema/schema-transform.ts +2 -2
- package/src/application/transform/schema-comment.ts +84 -4
- package/src/cli/api-settings.ts +109 -0
- package/src/cli/cli-arguments.ts +18 -5
- package/src/cli/cli-dependencies.ts +5 -0
- package/src/cli/cli-errors.ts +4 -2
- package/src/cli/cli-output.ts +18 -4
- package/src/cli/help-text.ts +4 -4
- package/src/cli/main.ts +6 -0
- package/src/cli/redocly-apis.ts +21 -11
- package/src/cli/ref-limits.ts +2 -2
- package/src/cli/run-cli.ts +25 -4
- package/src/domain/errors.ts +10 -2
- package/src/domain/ir/constructors.ts +9 -1
- package/src/domain/ir/nodes.ts +11 -7
- package/src/domain/openapi/admitted-values.ts +113 -0
- package/src/domain/openapi/discriminated-union.ts +109 -0
- package/src/domain/openapi/discriminator-conflicts.ts +251 -0
- package/src/domain/openapi/parameter-object.ts +4 -0
- package/src/domain/openapi/path-templates.ts +32 -0
- package/src/domain/openapi/schema-object.ts +2 -0
- package/src/domain/output-fixes.ts +43 -2
- package/src/domain/url-credentials.ts +18 -0
- package/src/domain/warnings.ts +28 -0
- package/src/index.ts +1 -0
- package/src/transform/components-object.ts +3 -1
- package/src/transform/path-item-object.ts +6 -2
- package/src/types/generator-options.ts +12 -21
- 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/dist/application/transform/document/path-item-conflicts.cjs +0 -51
- package/dist/application/transform/document/path-item-conflicts.cjs.map +0 -1
- package/dist/application/transform/document/path-item-conflicts.mjs +0 -49
- package/dist/application/transform/document/path-item-conflicts.mjs.map +0 -1
- package/src/application/transform/document/path-item-conflicts.ts +0 -79
|
@@ -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,269 @@
|
|
|
1
|
+
import { irObject, irProperty } from "../../../domain/ir/constructors.js";
|
|
2
|
+
import type {
|
|
3
|
+
IrMember,
|
|
4
|
+
IrObjectType,
|
|
5
|
+
IrPropertySignature,
|
|
6
|
+
IrType,
|
|
7
|
+
} from "../../../domain/ir/nodes.js";
|
|
8
|
+
import { toPropertyName } from "../../../domain/ir/property-name.js";
|
|
9
|
+
import {
|
|
10
|
+
type Evaluated,
|
|
11
|
+
type Evaluation,
|
|
12
|
+
MISSING,
|
|
13
|
+
OPAQUE,
|
|
14
|
+
propertyKey,
|
|
15
|
+
unionType,
|
|
16
|
+
} from "./evaluation.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Rules of TypeScript about intersections, `Omit` and `Extract` that the `--enum-values` check
|
|
20
|
+
* needs (ADR-027). They read the types as written, before `FlattenedDeepRequired`.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** The part of the evaluator these rules use. */
|
|
24
|
+
export interface TypeExpansion {
|
|
25
|
+
membersOf(value: Evaluated): readonly Evaluation[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A unit value of a type: a literal, `null` or `undefined`. */
|
|
29
|
+
type Unit = string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The parts an intersection is made of, nested intersections flattened: each object type, or
|
|
33
|
+
* `null` for a part that is not one.
|
|
34
|
+
*/
|
|
35
|
+
function objectParts(
|
|
36
|
+
types: TypeExpansion,
|
|
37
|
+
value: Evaluated,
|
|
38
|
+
parts: readonly IrType[],
|
|
39
|
+
): (IrObjectType | null)[] {
|
|
40
|
+
return parts.flatMap((part) => {
|
|
41
|
+
const members = types.membersOf({ ...value, type: part });
|
|
42
|
+
const [only] = members;
|
|
43
|
+
if (members.length !== 1 || only?.kind !== "type") {
|
|
44
|
+
return [null];
|
|
45
|
+
}
|
|
46
|
+
if (only.type.kind === "intersection") {
|
|
47
|
+
return objectParts(types, only, only.type.types);
|
|
48
|
+
}
|
|
49
|
+
return [only.type.kind === "object" ? only.type : null];
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function unitOf(type: IrType): Unit | null {
|
|
54
|
+
switch (type.kind) {
|
|
55
|
+
case "stringLiteral":
|
|
56
|
+
return `s:${type.value}`;
|
|
57
|
+
case "numberLiteral":
|
|
58
|
+
return `n:${type.value}`;
|
|
59
|
+
case "booleanLiteral":
|
|
60
|
+
return `b:${type.value}`;
|
|
61
|
+
case "keyword":
|
|
62
|
+
return type.keyword === "null" || type.keyword === "undefined" ? type.keyword : null;
|
|
63
|
+
default:
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** The unit values of a type made only of units, or `null` where it has other values. */
|
|
69
|
+
function unitsOf(types: TypeExpansion, value: Evaluated, type: IrType): ReadonlySet<Unit> | null {
|
|
70
|
+
const units = types.membersOf({ ...value, type }).map((member) => {
|
|
71
|
+
return member.kind === "type" ? unitOf(member.type) : null;
|
|
72
|
+
});
|
|
73
|
+
return units.includes(null) ? null : new Set(units as Unit[]);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function propertiesNamed(objects: readonly IrObjectType[], key: string): IrPropertySignature[] {
|
|
77
|
+
return objects.flatMap((object) => {
|
|
78
|
+
const members: readonly IrMember[] = object.members;
|
|
79
|
+
return members.filter(
|
|
80
|
+
(member): member is IrPropertySignature =>
|
|
81
|
+
member.kind === "property" && propertyKey(member.name) === key,
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Whether properties of the same name share no unit value, one of them required. */
|
|
87
|
+
function isNeverProperty(
|
|
88
|
+
types: TypeExpansion,
|
|
89
|
+
value: Evaluated,
|
|
90
|
+
found: IrPropertySignature[],
|
|
91
|
+
): boolean {
|
|
92
|
+
if (found.length < 2 || found.every((property) => property.isOptional)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const sets = found.map((property) => unitsOf(types, value, property.type));
|
|
96
|
+
if (sets.includes(null)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
// At least two properties, so at least two sets.
|
|
100
|
+
const [first, ...rest] = sets as [ReadonlySet<Unit>, ...ReadonlySet<Unit>[]];
|
|
101
|
+
const shared = [...first].filter((unit) => rest.every((set) => set.has(unit)));
|
|
102
|
+
return shared.length === 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Whether an intersection has `null` or `undefined` next to an object: `null & { a: 1 }`. */
|
|
106
|
+
function isNullishObject(types: TypeExpansion, value: Evaluated, parts: readonly IrType[]) {
|
|
107
|
+
const singles = parts.map((part) => {
|
|
108
|
+
const members = types.membersOf({ ...value, type: part });
|
|
109
|
+
const [only] = members;
|
|
110
|
+
return members.length === 1 && only?.kind === "type" ? only.type : null;
|
|
111
|
+
});
|
|
112
|
+
const isNullish = (type: IrType | null) =>
|
|
113
|
+
type?.kind === "keyword" && (type.keyword === "null" || type.keyword === "undefined");
|
|
114
|
+
return singles.some(isNullish) && singles.some((type) => type?.kind === "object");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Whether TypeScript reduces an intersection to `never`: `null` or `undefined` meets an object,
|
|
119
|
+
* or objects share a property with literal types that have no value in common, one of them
|
|
120
|
+
* requiring it (`{ a: "x" } & { a: "y" }`). Other properties are left alone, so the answer is
|
|
121
|
+
* sure where it is yes.
|
|
122
|
+
*/
|
|
123
|
+
export function isNeverIntersection(
|
|
124
|
+
types: TypeExpansion,
|
|
125
|
+
value: Evaluated,
|
|
126
|
+
parts: readonly IrType[],
|
|
127
|
+
): boolean {
|
|
128
|
+
if (isNullishObject(types, value, parts)) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
const objects = objectParts(types, value, parts).filter((part) => part !== null);
|
|
132
|
+
if (objects.length < 2) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const keys = new Set(
|
|
136
|
+
objects.flatMap((object) =>
|
|
137
|
+
object.members.flatMap((member) =>
|
|
138
|
+
member.kind === "property" ? [propertyKey(member.name)] : [],
|
|
139
|
+
),
|
|
140
|
+
),
|
|
141
|
+
);
|
|
142
|
+
const valueOfKeys = { ...value, deep: false };
|
|
143
|
+
return [...keys].some((key) =>
|
|
144
|
+
isNeverProperty(types, valueOfKeys, propertiesNamed(objects, key)),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Whether `key` reaches only an index signature of this object: it declares no such property. */
|
|
149
|
+
function isSignatureOnly(types: TypeExpansion, value: Evaluated, key: string | null): boolean {
|
|
150
|
+
const members = types.membersOf(value);
|
|
151
|
+
const [only] = members;
|
|
152
|
+
if (
|
|
153
|
+
key === null ||
|
|
154
|
+
members.length !== 1 ||
|
|
155
|
+
only?.kind !== "type" ||
|
|
156
|
+
only.type.kind !== "object"
|
|
157
|
+
) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
const { members: declared } = only.type;
|
|
161
|
+
const hasSignature = declared.some((member) => member.kind === "indexSignature");
|
|
162
|
+
return hasSignature && propertiesNamed([only.type], key).length === 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* The parts of an intersection indexed by `index`, as TypeScript reads them: where one part
|
|
167
|
+
* declares the property, the index signatures of the others do not take part
|
|
168
|
+
* (`{ a: X } & { [key: string]: Y }` gives `X` for `a`).
|
|
169
|
+
*/
|
|
170
|
+
export function declaredFirst(
|
|
171
|
+
types: TypeExpansion,
|
|
172
|
+
value: Evaluated,
|
|
173
|
+
key: string | null,
|
|
174
|
+
parts: readonly { readonly type: IrType; readonly found: Evaluation }[],
|
|
175
|
+
): Evaluation[] {
|
|
176
|
+
const bySignature = parts.map(({ type }) => isSignatureOnly(types, { ...value, type }, key));
|
|
177
|
+
const isDeclared = parts.some(({ found }, at) => found.kind === "type" && !bySignature[at]);
|
|
178
|
+
return parts.filter((_, at) => !(isDeclared && bySignature[at])).map(({ found }) => found);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Whether a member of `membersOf` has `key` as a property that `{ key: unknown }` accepts: written
|
|
183
|
+
* and, outside `FlattenedDeepRequired`, required. An index signature does not count, as in
|
|
184
|
+
* TypeScript. Such a member is expanded, parts included, so it is an object, an intersection of
|
|
185
|
+
* members, or a primitive or array type, which has no such property; a type the evaluator cannot
|
|
186
|
+
* read makes `membersOf` opaque instead.
|
|
187
|
+
*/
|
|
188
|
+
function hasKey(value: Evaluated, key: string): boolean {
|
|
189
|
+
const { type } = value;
|
|
190
|
+
if (type.kind === "intersection") {
|
|
191
|
+
return type.types.some((part) => hasKey({ ...value, type: part }, key));
|
|
192
|
+
}
|
|
193
|
+
if (type.kind !== "object") {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
return propertiesNamed([type], key).some((property) => value.deep || !property.isOptional);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* `Extract<T, { key: unknown }>`: the members of `T` that have `key`. When none has it the
|
|
201
|
+
* result is `never`; it is `missing` here, as the location then types nothing.
|
|
202
|
+
*/
|
|
203
|
+
export function extracted(types: TypeExpansion, value: Evaluated, key: string): Evaluation {
|
|
204
|
+
const members = types.membersOf(value);
|
|
205
|
+
if (members.some((member) => member.kind !== "type")) {
|
|
206
|
+
return OPAQUE;
|
|
207
|
+
}
|
|
208
|
+
const kept = (members as Evaluated[]).filter((member) => hasKey(member, key));
|
|
209
|
+
if (kept.length === 0) {
|
|
210
|
+
return MISSING;
|
|
211
|
+
}
|
|
212
|
+
return { ...value, type: unionType(kept.map((member) => member.type)) };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function omittedKeys(types: TypeExpansion, value: Evaluated, keys: IrType): Set<string> | null {
|
|
216
|
+
const members = types.membersOf({ ...value, type: keys });
|
|
217
|
+
const names = members.map((member) =>
|
|
218
|
+
member.kind === "type" && member.type.kind === "stringLiteral" ? member.type.value : null,
|
|
219
|
+
);
|
|
220
|
+
return names.includes(null) ? null : new Set(names as string[]);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Whether two members name the same property: merging them would need their intersection. */
|
|
224
|
+
function hasSharedProperty(members: readonly IrMember[]): boolean {
|
|
225
|
+
const names = members.flatMap((member) =>
|
|
226
|
+
member.kind === "property" ? [propertyKey(member.name)] : [],
|
|
227
|
+
);
|
|
228
|
+
return new Set(names).size !== names.length;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* `Omit<T, K>` for literal keys `K` over an object or an intersection of objects. A string index
|
|
233
|
+
* signature makes `keyof T` all strings, so only the index signatures are left.
|
|
234
|
+
*/
|
|
235
|
+
export function omitted(types: TypeExpansion, value: Evaluated, keys: IrType): Evaluation {
|
|
236
|
+
const names = omittedKeys(types, value, keys);
|
|
237
|
+
const objects = objectParts(types, value, [value.type]);
|
|
238
|
+
if (names === null || objects.length === 0 || objects.includes(null)) {
|
|
239
|
+
return OPAQUE;
|
|
240
|
+
}
|
|
241
|
+
const members = (objects as IrObjectType[]).flatMap((object) => object.members);
|
|
242
|
+
if (hasSharedProperty(members)) {
|
|
243
|
+
return OPAQUE;
|
|
244
|
+
}
|
|
245
|
+
const signatures = members.filter((member) => member.kind === "indexSignature");
|
|
246
|
+
const kept =
|
|
247
|
+
signatures.length > 0
|
|
248
|
+
? signatures
|
|
249
|
+
: members.filter(
|
|
250
|
+
(member) => member.kind !== "property" || !names.has(propertyKey(member.name)),
|
|
251
|
+
);
|
|
252
|
+
return { ...value, type: { kind: "object", members: kept } };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** The `--read-write-markers` types and their one member (`READ_WRITE_MARKER_TYPES`). */
|
|
256
|
+
const READ_WRITE_MARKER_KEYS: ReadonlyMap<string, string> = new Map([
|
|
257
|
+
["$Read", "$read"],
|
|
258
|
+
["$Write", "$write"],
|
|
259
|
+
]);
|
|
260
|
+
|
|
261
|
+
/** `$Read<T>` is `{ readonly $read: T }`: an object, which holds no enum value. */
|
|
262
|
+
export function markerObject(name: string, argument: Evaluated): Evaluated | null {
|
|
263
|
+
const key = READ_WRITE_MARKER_KEYS.get(name);
|
|
264
|
+
if (key === undefined) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
const member = irProperty(toPropertyName(key), argument.type, { isReadonly: true });
|
|
268
|
+
return { ...argument, type: irObject([member]) };
|
|
269
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { createRef } from "../../../domain/openapi/json-pointer.js";
|
|
2
|
+
import type { RefResolver } from "../schema/schema-context.js";
|
|
3
|
+
import { isJsonObject } from "./generated-shape.js";
|
|
4
|
+
import {
|
|
5
|
+
leadingSegmentsOf,
|
|
6
|
+
type RefPointer,
|
|
7
|
+
refPointerOf,
|
|
8
|
+
startsInSchema,
|
|
9
|
+
} from "./pointer-walk.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Where the generator types the node a `$ref` points at: the location path it passes down, which
|
|
13
|
+
* also names the node's `--enum` declaration and `--enum-values` array. A target written inline
|
|
14
|
+
* (ADR-026) is typed there, so it shares the generator's enum instead of declaring a second one
|
|
15
|
+
* named after the pointer: two TypeScript enums with the same members are not assignable.
|
|
16
|
+
*
|
|
17
|
+
* The path follows the generator: `properties` is skipped; `allOf/N`, `items`, `prefixItems/N`,
|
|
18
|
+
* `patternProperties/P` and `additionalProperties` type their schema at the parent's location;
|
|
19
|
+
* the `schema` of a parameter, header or media type is typed at the container's; a positional
|
|
20
|
+
* parameter is named by `in` and `name`. A `$ref` crossed on the way continues at its target's
|
|
21
|
+
* location. A node under a schema keyword the generator does not type (`definitions/A`, `not`) is
|
|
22
|
+
* typed nowhere else, so it keeps its pointer as its location.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface GeneratedLocation {
|
|
26
|
+
readonly path: string;
|
|
27
|
+
/** The node is an `additionalProperties` value, as `transformNested` is told. */
|
|
28
|
+
readonly isFromAdditionalProperties: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface LocationWalk {
|
|
32
|
+
readonly path: readonly string[];
|
|
33
|
+
readonly node: unknown;
|
|
34
|
+
readonly isSchema: boolean;
|
|
35
|
+
readonly isFromAdditionalProperties: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** One step: the segments it adds to the path, the node it moves to, the segments it reads. */
|
|
39
|
+
interface Step {
|
|
40
|
+
readonly path: readonly string[];
|
|
41
|
+
readonly child: unknown;
|
|
42
|
+
readonly length: 1 | 2;
|
|
43
|
+
readonly isSchema: boolean;
|
|
44
|
+
readonly isFromAdditionalProperties?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Keywords followed by a name or position whose schema is typed at the parent's location. */
|
|
48
|
+
const PARENT_LOCATION_PAIRS: ReadonlySet<string> = new Set([
|
|
49
|
+
"allOf",
|
|
50
|
+
"prefixItems",
|
|
51
|
+
"patternProperties",
|
|
52
|
+
]);
|
|
53
|
+
/** Keywords whose schema is typed at the parent's location as a record value. */
|
|
54
|
+
const RECORD_VALUE_KEYWORDS: ReadonlySet<string> = new Set([
|
|
55
|
+
"additionalProperties",
|
|
56
|
+
"unevaluatedProperties",
|
|
57
|
+
]);
|
|
58
|
+
/** Keywords followed by a name or position that both stay in the location. */
|
|
59
|
+
const KEPT_PAIRS: ReadonlySet<string> = new Set(["anyOf", "oneOf", "$defs"]);
|
|
60
|
+
/** The other schema keywords the generator types: at the parent's location. */
|
|
61
|
+
const PARENT_LOCATION_KEYWORDS: ReadonlySet<string> = new Set(["items", ...RECORD_VALUE_KEYWORDS]);
|
|
62
|
+
const INDEX_RE = /^\d+$/;
|
|
63
|
+
|
|
64
|
+
function childOf(node: unknown, segment: string | undefined): unknown {
|
|
65
|
+
return (isJsonObject(node) || Array.isArray(node)) && segment !== undefined
|
|
66
|
+
? (node as Readonly<Record<string, unknown>>)[segment]
|
|
67
|
+
: undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function pairStep(value: unknown, next: string | undefined, path: readonly string[]): Step {
|
|
71
|
+
return { path, child: childOf(value, next), length: 2, isSchema: true };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The step through a schema keyword; null for a keyword the generator does not type. */
|
|
75
|
+
function schemaStep(node: unknown, segment: string, next: string | undefined): Step | null {
|
|
76
|
+
const value = childOf(node, segment);
|
|
77
|
+
const named = next === undefined ? [] : [next];
|
|
78
|
+
if (segment === "properties") {
|
|
79
|
+
return pairStep(value, next, named);
|
|
80
|
+
}
|
|
81
|
+
if (PARENT_LOCATION_PAIRS.has(segment) || (segment === "items" && Array.isArray(value))) {
|
|
82
|
+
return pairStep(value, next, []);
|
|
83
|
+
}
|
|
84
|
+
if (KEPT_PAIRS.has(segment)) {
|
|
85
|
+
return pairStep(value, next, [segment, ...named]);
|
|
86
|
+
}
|
|
87
|
+
if (!PARENT_LOCATION_KEYWORDS.has(segment)) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const isRecordValue = RECORD_VALUE_KEYWORDS.has(segment);
|
|
91
|
+
return {
|
|
92
|
+
path: [],
|
|
93
|
+
child: value,
|
|
94
|
+
length: 1,
|
|
95
|
+
isSchema: true,
|
|
96
|
+
isFromAdditionalProperties: isRecordValue,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** A path item's own parameters sit under one more `parameters` segment (`pathItemType`). */
|
|
101
|
+
function isPathItem(path: readonly string[]): boolean {
|
|
102
|
+
const [root, section] = path;
|
|
103
|
+
return (
|
|
104
|
+
(path.length === 2 && (root === "paths" || root === "webhooks")) ||
|
|
105
|
+
(path.length === 3 && root === "components" && section === "pathItems")
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** `parameters/N`: the parameter is named by `in` and `name` (a `$ref` one is crossed later). */
|
|
110
|
+
function parameterStep(walk: LocationWalk, next: string): Step {
|
|
111
|
+
const entry = childOf(childOf(walk.node, "parameters"), next);
|
|
112
|
+
const where = isJsonObject(entry) ? [String(entry.in), String(entry.name)] : [];
|
|
113
|
+
const prefix = isPathItem(walk.path) ? ["parameters"] : [];
|
|
114
|
+
return { path: [...prefix, "parameters", ...where], child: entry, length: 2, isSchema: false };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function documentStep(walk: LocationWalk, segments: readonly string[], index: number): Step {
|
|
118
|
+
const segment = segments[index] as string;
|
|
119
|
+
const next = segments[index + 1];
|
|
120
|
+
const value = childOf(walk.node, segment);
|
|
121
|
+
if (segment === "schema") {
|
|
122
|
+
return { path: [], child: value, length: 1, isSchema: true };
|
|
123
|
+
}
|
|
124
|
+
if (segment === "parameters" && next !== undefined && INDEX_RE.test(next)) {
|
|
125
|
+
return parameterStep(walk, next);
|
|
126
|
+
}
|
|
127
|
+
// A header's `content` entries are typed at `headers/<name>/<media type>` (`headerType`).
|
|
128
|
+
if (segment === "content" && segments[index - 2] === "headers") {
|
|
129
|
+
const path = next === undefined ? [] : [next];
|
|
130
|
+
return { path, child: childOf(value, next), length: 2, isSchema: false };
|
|
131
|
+
}
|
|
132
|
+
return { path: [segment], child: value, length: 1, isSchema: false };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function stepAt(walk: LocationWalk, pointer: RefPointer, index: number): Step | null {
|
|
136
|
+
const { segments } = pointer;
|
|
137
|
+
const segment = segments[index] as string;
|
|
138
|
+
if (index < leadingSegmentsOf(pointer)) {
|
|
139
|
+
const child = childOf(walk.node, segment);
|
|
140
|
+
return { path: [segment], child, length: 1, isSchema: startsInSchema(pointer) };
|
|
141
|
+
}
|
|
142
|
+
return walk.isSchema
|
|
143
|
+
? schemaStep(walk.node, segment, segments[index + 1])
|
|
144
|
+
: documentStep(walk, segments, index);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function refOf(node: unknown): string | null {
|
|
148
|
+
return isJsonObject(node) && typeof node.$ref === "string" ? node.$ref : null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The walk at a crossed `$ref`'s target, through `$ref`s to `$ref`s; null where the target has
|
|
153
|
+
* no generated location. A cycle of `$ref`s has no node.
|
|
154
|
+
*/
|
|
155
|
+
function crossed(
|
|
156
|
+
walk: LocationWalk,
|
|
157
|
+
ref: string,
|
|
158
|
+
refs: RefResolver,
|
|
159
|
+
seen: readonly string[],
|
|
160
|
+
): LocationWalk | null {
|
|
161
|
+
if (seen.includes(ref)) {
|
|
162
|
+
return { ...walk, node: undefined };
|
|
163
|
+
}
|
|
164
|
+
const target = walkTo(ref, refs, seen);
|
|
165
|
+
const inner = refOf(target?.node);
|
|
166
|
+
return target === null || inner === null ? target : crossed(target, inner, refs, [...seen, ref]);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function walkTo(ref: string, refs: RefResolver, seen: readonly string[]): LocationWalk | null {
|
|
170
|
+
const pointer = refPointerOf(ref);
|
|
171
|
+
if (pointer === null || seen.includes(ref)) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
const root = pointer.rootSegment;
|
|
175
|
+
let walk: LocationWalk = {
|
|
176
|
+
path: [root],
|
|
177
|
+
node: refs.resolve(`#/${root}`),
|
|
178
|
+
isSchema: false,
|
|
179
|
+
isFromAdditionalProperties: false,
|
|
180
|
+
};
|
|
181
|
+
for (let index = 0; index < pointer.segments.length; ) {
|
|
182
|
+
const step = stepAt(walk, pointer, index);
|
|
183
|
+
if (step === null) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
index += step.length;
|
|
187
|
+
walk = {
|
|
188
|
+
path: [...walk.path, ...step.path],
|
|
189
|
+
node: step.child,
|
|
190
|
+
isSchema: step.isSchema,
|
|
191
|
+
isFromAdditionalProperties: step.isFromAdditionalProperties === true,
|
|
192
|
+
};
|
|
193
|
+
const inner = refOf(walk.node);
|
|
194
|
+
const target = inner !== null && index < pointer.segments.length;
|
|
195
|
+
const next = target ? crossed(walk, inner, refs, [...seen, ref]) : walk;
|
|
196
|
+
if (next === null) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
walk = next;
|
|
200
|
+
}
|
|
201
|
+
return walk;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** The location the generator types the node at `ref` with; see the module comment. */
|
|
205
|
+
export function generatedLocationOf(ref: string, refs: RefResolver): GeneratedLocation {
|
|
206
|
+
const walk = walkTo(ref, refs, []);
|
|
207
|
+
return {
|
|
208
|
+
path: walk === null ? ref : createRef(walk.path),
|
|
209
|
+
isFromAdditionalProperties: walk?.isFromAdditionalProperties ?? false,
|
|
210
|
+
};
|
|
211
|
+
}
|