openapi-typesafe 1.0.0-rc.0 → 1.0.0-rc.1
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/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 +15 -5
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +15 -5
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs +3 -0
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs.map +1 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs +3 -0
- package/dist/adapters/type-ast-bridge/ir-to-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/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 +88 -0
- package/dist/api/discriminator-patch.cjs.map +1 -0
- package/dist/api/discriminator-patch.mjs +82 -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-run.cjs +18 -3
- package/dist/api/document-run.cjs.map +1 -1
- package/dist/api/document-run.mjs +19 -4
- 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/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 +3 -1
- package/dist/api/transform-context.cjs.map +1 -1
- package/dist/api/transform-context.mjs +3 -1
- 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 +5 -0
- package/dist/application/print/type-printer.cjs.map +1 -1
- package/dist/application/print/type-printer.mjs +5 -0
- 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 +40 -8
- package/dist/application/transform/document/parameters.cjs.map +1 -1
- package/dist/application/transform/document/parameters.mjs +41 -9
- 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 +54 -28
- package/dist/application/transform/document/paths.cjs.map +1 -1
- package/dist/application/transform/document/paths.mjs +53 -29
- 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 +33 -0
- package/dist/application/transform/footer/evaluation.cjs.map +1 -0
- package/dist/application/transform/footer/evaluation.mjs +26 -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 +246 -0
- package/dist/application/transform/footer/type-evaluation.cjs.map +1 -0
- package/dist/application/transform/footer/type-evaluation.mjs +244 -0
- package/dist/application/transform/footer/type-evaluation.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/cli-arguments.cjs +11 -3
- package/dist/cli/cli-arguments.cjs.map +1 -1
- package/dist/cli/cli-arguments.mjs +11 -3
- 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/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 +7 -3
- package/dist/cli/redocly-apis.cjs.map +1 -1
- package/dist/cli/redocly-apis.mjs +8 -4
- 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 +15 -2
- package/dist/cli/run-cli.cjs.map +1 -1
- package/dist/cli/run-cli.mjs +16 -3
- package/dist/cli/run-cli.mjs.map +1 -1
- package/dist/domain/errors.cjs +2 -0
- package/dist/domain/errors.cjs.map +1 -1
- package/dist/domain/errors.mjs +2 -0
- package/dist/domain/errors.mjs.map +1 -1
- package/dist/domain/ir/constructors.cjs +5 -1
- package/dist/domain/ir/constructors.cjs.map +1 -1
- package/dist/domain/ir/constructors.mjs +5 -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/warnings.cjs +15 -0
- package/dist/domain/warnings.cjs.map +1 -0
- package/dist/domain/warnings.mjs +12 -0
- package/dist/domain/warnings.mjs.map +1 -0
- package/dist/index.d.cts +29 -0
- package/dist/index.d.mts +29 -0
- package/dist/index.d.ts +29 -0
- 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/package.json +1 -1
- package/src/adapters/redocly-loader/redocly-config-source.ts +41 -6
- package/src/adapters/redocly-loader/redocly-schema-loader.ts +22 -6
- package/src/adapters/type-ast-bridge/ir-to-typescript.ts +3 -0
- package/src/adapters/type-ast-bridge/typescript-to-ir.ts +26 -12
- 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 +147 -0
- package/src/api/discriminator-scan.ts +78 -90
- package/src/api/document-run.ts +24 -6
- package/src/api/enum-values-warnings.ts +21 -0
- package/src/api/path-template-warnings.ts +27 -0
- package/src/api/transform-context.ts +7 -1
- package/src/api/transform-schema.ts +88 -4
- 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 +6 -0
- 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 +76 -11
- 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 +99 -37
- 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 +47 -0
- package/src/application/transform/footer/shared-enum-names.ts +86 -0
- package/src/application/transform/footer/type-evaluation.ts +294 -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/cli-arguments.ts +13 -3
- 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/main.ts +6 -0
- package/src/cli/redocly-apis.ts +8 -4
- package/src/cli/ref-limits.ts +2 -2
- package/src/cli/run-cli.ts +20 -3
- package/src/domain/errors.ts +2 -0
- package/src/domain/ir/constructors.ts +6 -1
- package/src/domain/ir/nodes.ts +2 -1
- 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 +31 -0
- package/src/domain/openapi/schema-object.ts +2 -0
- package/src/domain/output-fixes.ts +43 -2
- package/src/domain/warnings.ts +20 -0
- package/src/transform/components-object.ts +3 -1
- package/src/types/generator-options.ts +11 -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,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const jsonPointer = require('../../../domain/openapi/json-pointer.cjs');
|
|
4
|
+
const generatedShape = require('./generated-shape.cjs');
|
|
5
|
+
|
|
6
|
+
const NAMED_ROOTS = /* @__PURE__ */ new Set(["paths", "webhooks"]);
|
|
7
|
+
function leadingSegmentsOf(pointer) {
|
|
8
|
+
return NAMED_ROOTS.has(pointer.rootSegment) ? 1 : 2;
|
|
9
|
+
}
|
|
10
|
+
function refPointerOf(ref) {
|
|
11
|
+
const [rootSegment, ...segments] = jsonPointer.parseRefPointer(ref);
|
|
12
|
+
return rootSegment === void 0 ? null : { rootSegment, segments };
|
|
13
|
+
}
|
|
14
|
+
function leadingNode(pointer, refs) {
|
|
15
|
+
let node = refs.resolve(`#/${pointer.rootSegment}`);
|
|
16
|
+
for (const segment of pointer.segments.slice(0, leadingSegmentsOf(pointer))) {
|
|
17
|
+
node = generatedShape.isJsonObject(node) ? generatedShape.followRefs(node[segment], refs) : void 0;
|
|
18
|
+
}
|
|
19
|
+
return node;
|
|
20
|
+
}
|
|
21
|
+
function pointerNode(pointer, refs) {
|
|
22
|
+
let node = refs.resolve(`#/${pointer.rootSegment}`);
|
|
23
|
+
pointer.segments.forEach((segment, index) => {
|
|
24
|
+
const child = generatedShape.isJsonObject(node) || Array.isArray(node) ? node[segment] : void 0;
|
|
25
|
+
node = index === pointer.segments.length - 1 ? child : generatedShape.followRefs(child, refs);
|
|
26
|
+
});
|
|
27
|
+
return node;
|
|
28
|
+
}
|
|
29
|
+
function startsInSchema(pointer) {
|
|
30
|
+
return pointer.rootSegment === "components" && pointer.segments[0] === "schemas";
|
|
31
|
+
}
|
|
32
|
+
function isTypedAsSchema(pointer, index) {
|
|
33
|
+
const owner = pointer.segments[index - 2];
|
|
34
|
+
const isComponentParameter = pointer.rootSegment === "components" && index === 2 && owner === "parameters";
|
|
35
|
+
return owner === "content" || owner === "headers" || isComponentParameter;
|
|
36
|
+
}
|
|
37
|
+
function isParameterList(pointer, index) {
|
|
38
|
+
const next = pointer.segments[index + 1] ?? "";
|
|
39
|
+
return pointer.segments[index] === "parameters" && /^\d+$/.test(next);
|
|
40
|
+
}
|
|
41
|
+
function isOptionalHeader(pointer, index, headers) {
|
|
42
|
+
const isComponentHeader = pointer.rootSegment === "components" && index === 1;
|
|
43
|
+
if (pointer.segments[index - 1] !== "headers" || isComponentHeader || !generatedShape.isJsonObject(headers)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const header = headers[pointer.segments[index]];
|
|
47
|
+
return generatedShape.isJsonObject(header) && header.$ref === void 0 && header.required !== true;
|
|
48
|
+
}
|
|
49
|
+
function isOptionalRequestBody(container, refs) {
|
|
50
|
+
if (!generatedShape.isJsonObject(container) || container.requestBody === void 0) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const body = generatedShape.followRefs(container.requestBody, refs);
|
|
54
|
+
return !(generatedShape.isJsonObject(body) && body.required === true);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.isOptionalHeader = isOptionalHeader;
|
|
58
|
+
exports.isOptionalRequestBody = isOptionalRequestBody;
|
|
59
|
+
exports.isParameterList = isParameterList;
|
|
60
|
+
exports.isTypedAsSchema = isTypedAsSchema;
|
|
61
|
+
exports.leadingNode = leadingNode;
|
|
62
|
+
exports.leadingSegmentsOf = leadingSegmentsOf;
|
|
63
|
+
exports.pointerNode = pointerNode;
|
|
64
|
+
exports.refPointerOf = refPointerOf;
|
|
65
|
+
exports.startsInSchema = startsInSchema;
|
|
66
|
+
//# sourceMappingURL=pointer-walk.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-walk.cjs","sources":["../../../../src/application/transform/ref-pointer/pointer-walk.ts"],"sourcesContent":["import { parseRefPointer } from \"../../../domain/openapi/json-pointer.js\";\nimport type { RefResolver } from \"../schema/schema-context.js\";\nimport { followRefs, isJsonObject } from \"./generated-shape.js\";\n\n/** The parts of a `$ref` pointer that both the original and the new types walk. */\n\nexport interface RefPointer {\n readonly rootSegment: string;\n /** The segments after the root: `#/components/schemas/A` gives `[\"schemas\", \"A\"]`. */\n readonly segments: readonly string[];\n}\n\n/** Roots whose generated type is keyed by one segment: the path or webhook name. */\nconst NAMED_ROOTS: ReadonlySet<string> = new Set([\"paths\", \"webhooks\"]);\n\n/**\n * How many segments after the root index the generated root type directly: one for `paths` and\n * `webhooks` (`paths[\"/a\"]`, so the path item's own `parameters/0` is walked), two otherwise\n * (`components[\"schemas\"][\"A\"]`).\n */\nexport function leadingSegmentsOf(pointer: RefPointer): number {\n return NAMED_ROOTS.has(pointer.rootSegment) ? 1 : 2;\n}\n\nexport function refPointerOf(ref: string): RefPointer | null {\n const [rootSegment, ...segments] = parseRefPointer(ref);\n return rootSegment === undefined ? null : { rootSegment, segments };\n}\n\n/** The document node at the end of the leading segments, `$ref`s followed. */\nexport function leadingNode(pointer: RefPointer, refs: RefResolver): unknown {\n let node = refs.resolve(`#/${pointer.rootSegment}`);\n for (const segment of pointer.segments.slice(0, leadingSegmentsOf(pointer))) {\n node = isJsonObject(node) ? followRefs(node[segment], refs) : undefined;\n }\n return node;\n}\n\n/** The node at the whole pointer, without following a `$ref` at its end. */\nexport function pointerNode(pointer: RefPointer, refs: RefResolver): unknown {\n let node = refs.resolve(`#/${pointer.rootSegment}`);\n pointer.segments.forEach((segment, index) => {\n const child = isJsonObject(node) || Array.isArray(node) ? (node as never)[segment] : undefined;\n node = index === pointer.segments.length - 1 ? child : followRefs(child, refs);\n });\n return node;\n}\n\n/** Whether the leading segments name a component schema, so the walk starts inside a schema. */\nexport function startsInSchema(pointer: RefPointer): boolean {\n return pointer.rootSegment === \"components\" && pointer.segments[0] === \"schemas\";\n}\n\n/**\n * Whether the container at `index` is typed as its `schema`: a media type\n * (`content/<media type>`), a header (`headers/<name>`) or a component parameter.\n */\nexport function isTypedAsSchema(pointer: RefPointer, index: number): boolean {\n const owner = pointer.segments[index - 2];\n const isComponentParameter =\n pointer.rootSegment === \"components\" && index === 2 && owner === \"parameters\";\n return owner === \"content\" || owner === \"headers\" || isComponentParameter;\n}\n\n/**\n * Whether the segment at `index` is an operation's or path item's `parameters` list, indexed by\n * position next. The generated type groups parameters by `in` (`query`, `path`), so it has no\n * member `0`.\n */\nexport function isParameterList(pointer: RefPointer, index: number): boolean {\n const next = pointer.segments[index + 1] ?? \"\";\n return pointer.segments[index] === \"parameters\" && /^\\d+$/.test(next);\n}\n\n/**\n * Whether the segment at `index` names a response header that is an optional member: one the\n * response lists without `required: true`. A `$ref` header counts as required, as the generated\n * type has it; a component header (`components/headers/<name>`) is a member of its own.\n */\nexport function isOptionalHeader(pointer: RefPointer, index: number, headers: unknown): boolean {\n const isComponentHeader = pointer.rootSegment === \"components\" && index === 1;\n if (pointer.segments[index - 1] !== \"headers\" || isComponentHeader || !isJsonObject(headers)) {\n return false;\n }\n const header = headers[pointer.segments[index] as string];\n return isJsonObject(header) && header.$ref === undefined && header.required !== true;\n}\n\n/** A `requestBody` the operation does not mark `required` is an optional member. */\nexport function isOptionalRequestBody(container: unknown, refs: RefResolver): boolean {\n if (!isJsonObject(container) || container.requestBody === undefined) {\n return false;\n }\n const body = followRefs(container.requestBody, refs);\n return !(isJsonObject(body) && body.required === true);\n}\n"],"names":["parseRefPointer","isJsonObject","followRefs"],"mappings":";;;;;AAaA,MAAM,8BAAmC,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,UAAU,CAAC,CAAA;AAO/D,SAAS,kBAAkB,OAAA,EAA6B;AAC7D,EAAA,OAAO,WAAA,CAAY,GAAA,CAAI,OAAA,CAAQ,WAAW,IAAI,CAAA,GAAI,CAAA;AACpD;AAEO,SAAS,aAAa,GAAA,EAAgC;AAC3D,EAAA,MAAM,CAAC,WAAA,EAAa,GAAG,QAAQ,CAAA,GAAIA,4BAAgB,GAAG,CAAA;AACtD,EAAA,OAAO,WAAA,KAAgB,MAAA,GAAY,IAAA,GAAO,EAAE,aAAa,QAAA,EAAS;AACpE;AAGO,SAAS,WAAA,CAAY,SAAqB,IAAA,EAA4B;AAC3E,EAAA,IAAI,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,EAAA,EAAK,OAAA,CAAQ,WAAW,CAAA,CAAE,CAAA;AAClD,EAAA,KAAA,MAAW,OAAA,IAAW,QAAQ,QAAA,CAAS,KAAA,CAAM,GAAG,iBAAA,CAAkB,OAAO,CAAC,CAAA,EAAG;AAC3E,IAAA,IAAA,GAAOC,2BAAA,CAAa,IAAI,CAAA,GAAIC,yBAAA,CAAW,KAAK,OAAO,CAAA,EAAG,IAAI,CAAA,GAAI,MAAA;AAAA,EAChE;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,WAAA,CAAY,SAAqB,IAAA,EAA4B;AAC3E,EAAA,IAAI,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,EAAA,EAAK,OAAA,CAAQ,WAAW,CAAA,CAAE,CAAA;AAClD,EAAA,OAAA,CAAQ,QAAA,CAAS,OAAA,CAAQ,CAAC,OAAA,EAAS,KAAA,KAAU;AAC3C,IAAA,MAAM,KAAA,GAAQD,2BAAA,CAAa,IAAI,CAAA,IAAK,KAAA,CAAM,QAAQ,IAAI,CAAA,GAAK,IAAA,CAAe,OAAO,CAAA,GAAI,MAAA;AACrF,IAAA,IAAA,GAAO,KAAA,KAAU,QAAQ,QAAA,CAAS,MAAA,GAAS,IAAI,KAAA,GAAQC,yBAAA,CAAW,OAAO,IAAI,CAAA;AAAA,EAC/E,CAAC,CAAA;AACD,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,eAAe,OAAA,EAA8B;AAC3D,EAAA,OAAO,QAAQ,WAAA,KAAgB,YAAA,IAAgB,OAAA,CAAQ,QAAA,CAAS,CAAC,CAAA,KAAM,SAAA;AACzE;AAMO,SAAS,eAAA,CAAgB,SAAqB,KAAA,EAAwB;AAC3E,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,QAAA,CAAS,KAAA,GAAQ,CAAC,CAAA;AACxC,EAAA,MAAM,uBACJ,OAAA,CAAQ,WAAA,KAAgB,YAAA,IAAgB,KAAA,KAAU,KAAK,KAAA,KAAU,YAAA;AACnE,EAAA,OAAO,KAAA,KAAU,SAAA,IAAa,KAAA,KAAU,SAAA,IAAa,oBAAA;AACvD;AAOO,SAAS,eAAA,CAAgB,SAAqB,KAAA,EAAwB;AAC3E,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,QAAA,CAAS,KAAA,GAAQ,CAAC,CAAA,IAAK,EAAA;AAC5C,EAAA,OAAO,QAAQ,QAAA,CAAS,KAAK,MAAM,YAAA,IAAgB,OAAA,CAAQ,KAAK,IAAI,CAAA;AACtE;AAOO,SAAS,gBAAA,CAAiB,OAAA,EAAqB,KAAA,EAAe,OAAA,EAA2B;AAC9F,EAAA,MAAM,iBAAA,GAAoB,OAAA,CAAQ,WAAA,KAAgB,YAAA,IAAgB,KAAA,KAAU,CAAA;AAC5E,EAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,KAAA,GAAQ,CAAC,CAAA,KAAM,aAAa,iBAAA,IAAqB,CAACD,2BAAA,CAAa,OAAO,CAAA,EAAG;AAC5F,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAW,CAAA;AACxD,EAAA,OAAOA,4BAAa,MAAM,CAAA,IAAK,OAAO,IAAA,KAAS,MAAA,IAAa,OAAO,QAAA,KAAa,IAAA;AAClF;AAGO,SAAS,qBAAA,CAAsB,WAAoB,IAAA,EAA4B;AACpF,EAAA,IAAI,CAACA,2BAAA,CAAa,SAAS,CAAA,IAAK,SAAA,CAAU,gBAAgB,MAAA,EAAW;AACnE,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAA,GAAOC,yBAAA,CAAW,SAAA,CAAU,WAAA,EAAa,IAAI,CAAA;AACnD,EAAA,OAAO,EAAED,2BAAA,CAAa,IAAI,CAAA,IAAK,KAAK,QAAA,KAAa,IAAA,CAAA;AACnD;;;;;;;;;;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { parseRefPointer } from '../../../domain/openapi/json-pointer.mjs';
|
|
2
|
+
import { isJsonObject, followRefs } from './generated-shape.mjs';
|
|
3
|
+
|
|
4
|
+
const NAMED_ROOTS = /* @__PURE__ */ new Set(["paths", "webhooks"]);
|
|
5
|
+
function leadingSegmentsOf(pointer) {
|
|
6
|
+
return NAMED_ROOTS.has(pointer.rootSegment) ? 1 : 2;
|
|
7
|
+
}
|
|
8
|
+
function refPointerOf(ref) {
|
|
9
|
+
const [rootSegment, ...segments] = parseRefPointer(ref);
|
|
10
|
+
return rootSegment === void 0 ? null : { rootSegment, segments };
|
|
11
|
+
}
|
|
12
|
+
function leadingNode(pointer, refs) {
|
|
13
|
+
let node = refs.resolve(`#/${pointer.rootSegment}`);
|
|
14
|
+
for (const segment of pointer.segments.slice(0, leadingSegmentsOf(pointer))) {
|
|
15
|
+
node = isJsonObject(node) ? followRefs(node[segment], refs) : void 0;
|
|
16
|
+
}
|
|
17
|
+
return node;
|
|
18
|
+
}
|
|
19
|
+
function pointerNode(pointer, refs) {
|
|
20
|
+
let node = refs.resolve(`#/${pointer.rootSegment}`);
|
|
21
|
+
pointer.segments.forEach((segment, index) => {
|
|
22
|
+
const child = isJsonObject(node) || Array.isArray(node) ? node[segment] : void 0;
|
|
23
|
+
node = index === pointer.segments.length - 1 ? child : followRefs(child, refs);
|
|
24
|
+
});
|
|
25
|
+
return node;
|
|
26
|
+
}
|
|
27
|
+
function startsInSchema(pointer) {
|
|
28
|
+
return pointer.rootSegment === "components" && pointer.segments[0] === "schemas";
|
|
29
|
+
}
|
|
30
|
+
function isTypedAsSchema(pointer, index) {
|
|
31
|
+
const owner = pointer.segments[index - 2];
|
|
32
|
+
const isComponentParameter = pointer.rootSegment === "components" && index === 2 && owner === "parameters";
|
|
33
|
+
return owner === "content" || owner === "headers" || isComponentParameter;
|
|
34
|
+
}
|
|
35
|
+
function isParameterList(pointer, index) {
|
|
36
|
+
const next = pointer.segments[index + 1] ?? "";
|
|
37
|
+
return pointer.segments[index] === "parameters" && /^\d+$/.test(next);
|
|
38
|
+
}
|
|
39
|
+
function isOptionalHeader(pointer, index, headers) {
|
|
40
|
+
const isComponentHeader = pointer.rootSegment === "components" && index === 1;
|
|
41
|
+
if (pointer.segments[index - 1] !== "headers" || isComponentHeader || !isJsonObject(headers)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const header = headers[pointer.segments[index]];
|
|
45
|
+
return isJsonObject(header) && header.$ref === void 0 && header.required !== true;
|
|
46
|
+
}
|
|
47
|
+
function isOptionalRequestBody(container, refs) {
|
|
48
|
+
if (!isJsonObject(container) || container.requestBody === void 0) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const body = followRefs(container.requestBody, refs);
|
|
52
|
+
return !(isJsonObject(body) && body.required === true);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { isOptionalHeader, isOptionalRequestBody, isParameterList, isTypedAsSchema, leadingNode, leadingSegmentsOf, pointerNode, refPointerOf, startsInSchema };
|
|
56
|
+
//# sourceMappingURL=pointer-walk.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-walk.mjs","sources":["../../../../src/application/transform/ref-pointer/pointer-walk.ts"],"sourcesContent":["import { parseRefPointer } from \"../../../domain/openapi/json-pointer.js\";\nimport type { RefResolver } from \"../schema/schema-context.js\";\nimport { followRefs, isJsonObject } from \"./generated-shape.js\";\n\n/** The parts of a `$ref` pointer that both the original and the new types walk. */\n\nexport interface RefPointer {\n readonly rootSegment: string;\n /** The segments after the root: `#/components/schemas/A` gives `[\"schemas\", \"A\"]`. */\n readonly segments: readonly string[];\n}\n\n/** Roots whose generated type is keyed by one segment: the path or webhook name. */\nconst NAMED_ROOTS: ReadonlySet<string> = new Set([\"paths\", \"webhooks\"]);\n\n/**\n * How many segments after the root index the generated root type directly: one for `paths` and\n * `webhooks` (`paths[\"/a\"]`, so the path item's own `parameters/0` is walked), two otherwise\n * (`components[\"schemas\"][\"A\"]`).\n */\nexport function leadingSegmentsOf(pointer: RefPointer): number {\n return NAMED_ROOTS.has(pointer.rootSegment) ? 1 : 2;\n}\n\nexport function refPointerOf(ref: string): RefPointer | null {\n const [rootSegment, ...segments] = parseRefPointer(ref);\n return rootSegment === undefined ? null : { rootSegment, segments };\n}\n\n/** The document node at the end of the leading segments, `$ref`s followed. */\nexport function leadingNode(pointer: RefPointer, refs: RefResolver): unknown {\n let node = refs.resolve(`#/${pointer.rootSegment}`);\n for (const segment of pointer.segments.slice(0, leadingSegmentsOf(pointer))) {\n node = isJsonObject(node) ? followRefs(node[segment], refs) : undefined;\n }\n return node;\n}\n\n/** The node at the whole pointer, without following a `$ref` at its end. */\nexport function pointerNode(pointer: RefPointer, refs: RefResolver): unknown {\n let node = refs.resolve(`#/${pointer.rootSegment}`);\n pointer.segments.forEach((segment, index) => {\n const child = isJsonObject(node) || Array.isArray(node) ? (node as never)[segment] : undefined;\n node = index === pointer.segments.length - 1 ? child : followRefs(child, refs);\n });\n return node;\n}\n\n/** Whether the leading segments name a component schema, so the walk starts inside a schema. */\nexport function startsInSchema(pointer: RefPointer): boolean {\n return pointer.rootSegment === \"components\" && pointer.segments[0] === \"schemas\";\n}\n\n/**\n * Whether the container at `index` is typed as its `schema`: a media type\n * (`content/<media type>`), a header (`headers/<name>`) or a component parameter.\n */\nexport function isTypedAsSchema(pointer: RefPointer, index: number): boolean {\n const owner = pointer.segments[index - 2];\n const isComponentParameter =\n pointer.rootSegment === \"components\" && index === 2 && owner === \"parameters\";\n return owner === \"content\" || owner === \"headers\" || isComponentParameter;\n}\n\n/**\n * Whether the segment at `index` is an operation's or path item's `parameters` list, indexed by\n * position next. The generated type groups parameters by `in` (`query`, `path`), so it has no\n * member `0`.\n */\nexport function isParameterList(pointer: RefPointer, index: number): boolean {\n const next = pointer.segments[index + 1] ?? \"\";\n return pointer.segments[index] === \"parameters\" && /^\\d+$/.test(next);\n}\n\n/**\n * Whether the segment at `index` names a response header that is an optional member: one the\n * response lists without `required: true`. A `$ref` header counts as required, as the generated\n * type has it; a component header (`components/headers/<name>`) is a member of its own.\n */\nexport function isOptionalHeader(pointer: RefPointer, index: number, headers: unknown): boolean {\n const isComponentHeader = pointer.rootSegment === \"components\" && index === 1;\n if (pointer.segments[index - 1] !== \"headers\" || isComponentHeader || !isJsonObject(headers)) {\n return false;\n }\n const header = headers[pointer.segments[index] as string];\n return isJsonObject(header) && header.$ref === undefined && header.required !== true;\n}\n\n/** A `requestBody` the operation does not mark `required` is an optional member. */\nexport function isOptionalRequestBody(container: unknown, refs: RefResolver): boolean {\n if (!isJsonObject(container) || container.requestBody === undefined) {\n return false;\n }\n const body = followRefs(container.requestBody, refs);\n return !(isJsonObject(body) && body.required === true);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const constructors = require('../../../domain/ir/constructors.cjs');
|
|
4
|
+
const refType = require('../ref-type.cjs');
|
|
5
|
+
const generatedShape = require('./generated-shape.cjs');
|
|
6
|
+
const pointerWalk = require('./pointer-walk.cjs');
|
|
7
|
+
|
|
8
|
+
const DEFS_KEYWORD = "$defs";
|
|
9
|
+
function present(walk) {
|
|
10
|
+
return walk.presence === "present" ? walk.type : constructors.irReference("NonNullable", [walk.type]);
|
|
11
|
+
}
|
|
12
|
+
function indexEntries(walk, key, keyword, refs) {
|
|
13
|
+
const owner = generatedShape.followRefs(walk.node, refs);
|
|
14
|
+
const child = generatedShape.isJsonObject(owner) ? owner[keyword] : void 0;
|
|
15
|
+
return {
|
|
16
|
+
...walk,
|
|
17
|
+
type: constructors.irIndexedAccess(present(walk), constructors.irKeyword(key)),
|
|
18
|
+
node: child,
|
|
19
|
+
presence: generatedShape.schemaPresence(child, refs)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function nameStep(walk, name, isLast, input) {
|
|
23
|
+
const owner = generatedShape.followRefs(walk.node, input.refs);
|
|
24
|
+
const properties = generatedShape.isJsonObject(owner) && generatedShape.isJsonObject(owner.properties) ? owner.properties : {};
|
|
25
|
+
const type = walk.presence === "present" ? refType.indexKeyword(walk.type, name, isLast) : refType.indexBy(present(walk), name);
|
|
26
|
+
return {
|
|
27
|
+
...walk,
|
|
28
|
+
type,
|
|
29
|
+
node: properties[name],
|
|
30
|
+
isName: false,
|
|
31
|
+
presence: generatedShape.propertyPresence(walk.node, name, input.options, input.refs)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function defsStep(walk, owner, isLast) {
|
|
35
|
+
const defs = generatedShape.isJsonObject(owner) && generatedShape.isJsonObject(owner[DEFS_KEYWORD]) ? owner[DEFS_KEYWORD] : {};
|
|
36
|
+
return {
|
|
37
|
+
...walk,
|
|
38
|
+
type: refType.indexKeyword(present(walk), DEFS_KEYWORD, isLast),
|
|
39
|
+
node: { properties: defs, required: Object.keys(defs) },
|
|
40
|
+
isName: true,
|
|
41
|
+
presence: "present"
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const SHAPED_KEYWORDS = /* @__PURE__ */ new Set([
|
|
45
|
+
"properties",
|
|
46
|
+
"items",
|
|
47
|
+
"additionalProperties"
|
|
48
|
+
]);
|
|
49
|
+
function hasKeywordMember(owner, segment) {
|
|
50
|
+
if (!SHAPED_KEYWORDS.has(segment) || !generatedShape.isJsonObject(owner)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return segment === "items" ? generatedShape.isArrayShape(owner) : generatedShape.isObjectShape(owner);
|
|
54
|
+
}
|
|
55
|
+
function keywordStep(walk, segment, isLast, input) {
|
|
56
|
+
const owner = generatedShape.followRefs(walk.node, input.refs);
|
|
57
|
+
if (!hasKeywordMember(owner, segment)) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
switch (segment) {
|
|
61
|
+
case "properties":
|
|
62
|
+
return { ...walk, isName: true };
|
|
63
|
+
case "items":
|
|
64
|
+
return indexEntries(walk, "number", "items", input.refs);
|
|
65
|
+
case "additionalProperties":
|
|
66
|
+
return indexEntries(walk, "string", "additionalProperties", input.refs);
|
|
67
|
+
case DEFS_KEYWORD:
|
|
68
|
+
return defsStep(walk, owner, isLast);
|
|
69
|
+
default:
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function containerStep(walk, index, input) {
|
|
74
|
+
const segment = input.pointer.segments[index];
|
|
75
|
+
const owner = generatedShape.followRefs(walk.node, input.refs);
|
|
76
|
+
const isOptional = segment === "requestBody" && pointerWalk.isOptionalRequestBody(owner, input.refs) || pointerWalk.isOptionalHeader(input.pointer, index, owner);
|
|
77
|
+
return {
|
|
78
|
+
...walk,
|
|
79
|
+
type: refType.indexBy(present(walk), segment),
|
|
80
|
+
node: generatedShape.isJsonObject(owner) ? owner[segment] : void 0,
|
|
81
|
+
presence: isOptional ? "absent" : "present"
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function step(walk, index, input) {
|
|
85
|
+
const { segments } = input.pointer;
|
|
86
|
+
const segment = segments[index];
|
|
87
|
+
const isLast = index === segments.length - 1;
|
|
88
|
+
if (walk.isSchema) {
|
|
89
|
+
return walk.isName ? nameStep(walk, segment, isLast, input) : keywordStep(walk, segment, isLast, input);
|
|
90
|
+
}
|
|
91
|
+
if (segment === "schema" && pointerWalk.isTypedAsSchema(input.pointer, index)) {
|
|
92
|
+
const owner = generatedShape.followRefs(walk.node, input.refs);
|
|
93
|
+
const schema = generatedShape.isJsonObject(owner) ? owner.schema : void 0;
|
|
94
|
+
const presence = walk.presence === "absent" ? "absent" : generatedShape.schemaPresence(schema, input.refs);
|
|
95
|
+
return { ...walk, node: schema, isSchema: true, presence };
|
|
96
|
+
}
|
|
97
|
+
return pointerWalk.isParameterList(input.pointer, index) ? null : containerStep(walk, index, input);
|
|
98
|
+
}
|
|
99
|
+
function typedWalk(input) {
|
|
100
|
+
const { pointer } = input;
|
|
101
|
+
const node = pointerWalk.leadingNode(pointer, input.refs);
|
|
102
|
+
const isSchema = pointerWalk.startsInSchema(pointer);
|
|
103
|
+
let walk = {
|
|
104
|
+
type: refType.indexBy(
|
|
105
|
+
refType.rootType(pointer.rootSegment, false),
|
|
106
|
+
...pointer.segments.slice(0, pointerWalk.leadingSegmentsOf(pointer))
|
|
107
|
+
),
|
|
108
|
+
node,
|
|
109
|
+
isSchema,
|
|
110
|
+
isName: false,
|
|
111
|
+
presence: isSchema ? generatedShape.schemaPresence(node, input.refs) : "present"
|
|
112
|
+
};
|
|
113
|
+
for (let index = pointerWalk.leadingSegmentsOf(pointer); index < pointer.segments.length; index++) {
|
|
114
|
+
const next = step(walk, index, input);
|
|
115
|
+
if (next === null) {
|
|
116
|
+
return { kind: "untyped", index };
|
|
117
|
+
}
|
|
118
|
+
walk = next;
|
|
119
|
+
}
|
|
120
|
+
return { kind: "typed", walk };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
exports.typedWalk = typedWalk;
|
|
124
|
+
//# sourceMappingURL=typed-walk.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typed-walk.cjs","sources":["../../../../src/application/transform/ref-pointer/typed-walk.ts"],"sourcesContent":["import { irIndexedAccess, irKeyword, irReference } from \"../../../domain/ir/constructors.js\";\nimport type { IrKeyword, IrType } from \"../../../domain/ir/nodes.js\";\nimport { indexBy, indexKeyword, rootType } from \"../ref-type.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport {\n followRefs,\n isArrayShape,\n isJsonObject,\n isObjectShape,\n type Presence,\n propertyPresence,\n schemaPresence,\n} from \"./generated-shape.js\";\nimport {\n isOptionalHeader,\n isOptionalRequestBody,\n isParameterList,\n isTypedAsSchema,\n leadingNode,\n leadingSegmentsOf,\n type RefPointer,\n startsInSchema,\n} from \"./pointer-walk.js\";\n\n/**\n * The type of a `$ref` pointer as the generated types have it: the `schema` of a media type,\n * header or component parameter is its type, `items` is indexed by `number`,\n * `additionalProperties` by `string`, and a value that may be `undefined` or `null` is wrapped in\n * `NonNullable` before it is indexed. The walk stops at a segment with no type of its own\n * (`allOf/0`, `definitions/A`, operation `parameters/0`): the caller types the target itself.\n */\n\nconst DEFS_KEYWORD = \"$defs\";\n\nexport interface TypedWalk {\n readonly type: IrType;\n /** The document node the type stands for (not followed through a `$ref`). */\n readonly node: unknown;\n readonly isSchema: boolean;\n /** The segment is a property or `$defs` name, not a keyword. */\n readonly isName: boolean;\n readonly presence: Presence;\n}\n\nexport interface TypedWalkInput {\n readonly pointer: RefPointer;\n readonly options: SchemaOptions;\n readonly refs: RefResolver;\n}\n\n/** The walk result: a type, or the index of the first segment that has no type. */\nexport type TypedWalkResult =\n | { readonly kind: \"typed\"; readonly walk: TypedWalk }\n | { readonly kind: \"untyped\"; readonly index: number };\n\nfunction present(walk: TypedWalk): IrType {\n return walk.presence === \"present\" ? walk.type : irReference(\"NonNullable\", [walk.type]);\n}\n\nfunction indexEntries(walk: TypedWalk, key: IrKeyword, keyword: string, refs: RefResolver) {\n const owner = followRefs(walk.node, refs);\n const child = isJsonObject(owner) ? owner[keyword] : undefined;\n return {\n ...walk,\n type: irIndexedAccess(present(walk), irKeyword(key)),\n node: child,\n presence: schemaPresence(child, refs),\n };\n}\n\nfunction nameStep(walk: TypedWalk, name: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followRefs(walk.node, input.refs);\n const properties = isJsonObject(owner) && isJsonObject(owner.properties) ? owner.properties : {};\n const type =\n walk.presence === \"present\"\n ? indexKeyword(walk.type, name, isLast)\n : indexBy(present(walk), name);\n return {\n ...walk,\n type,\n node: properties[name],\n isName: false,\n presence: propertyPresence(walk.node, name, input.options, input.refs),\n };\n}\n\n/** `$defs` is optional (`NonNullable` when more follows); its members are present. */\nfunction defsStep(walk: TypedWalk, owner: unknown, isLast: boolean): TypedWalk {\n const defs = isJsonObject(owner) && isJsonObject(owner[DEFS_KEYWORD]) ? owner[DEFS_KEYWORD] : {};\n return {\n ...walk,\n type: indexKeyword(present(walk), DEFS_KEYWORD, isLast),\n node: { properties: defs, required: Object.keys(defs) },\n isName: true,\n presence: \"present\",\n };\n}\n\nconst SHAPED_KEYWORDS: ReadonlySet<string> = new Set([\n \"properties\",\n \"items\",\n \"additionalProperties\",\n]);\n\n/**\n * Whether the keyword gives the owner's generated type a member: `items` only an array,\n * `properties` and `additionalProperties` only an object (`type: string` ignores them). A node\n * that is not in the document is indexed as the keyword says.\n */\nfunction hasKeywordMember(owner: unknown, segment: string): boolean {\n if (!SHAPED_KEYWORDS.has(segment) || !isJsonObject(owner)) {\n return true;\n }\n return segment === \"items\" ? isArrayShape(owner) : isObjectShape(owner);\n}\n\nfunction keywordStep(walk: TypedWalk, segment: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followRefs(walk.node, input.refs);\n if (!hasKeywordMember(owner, segment)) {\n return null;\n }\n switch (segment) {\n case \"properties\":\n return { ...walk, isName: true };\n case \"items\":\n return indexEntries(walk, \"number\", \"items\", input.refs);\n case \"additionalProperties\":\n return indexEntries(walk, \"string\", \"additionalProperties\", input.refs);\n case DEFS_KEYWORD:\n return defsStep(walk, owner, isLast);\n default:\n return null;\n }\n}\n\nfunction containerStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk {\n const segment = input.pointer.segments[index] as string;\n const owner = followRefs(walk.node, input.refs);\n const isOptional =\n (segment === \"requestBody\" && isOptionalRequestBody(owner, input.refs)) ||\n isOptionalHeader(input.pointer, index, owner);\n return {\n ...walk,\n type: indexBy(present(walk), segment),\n node: isJsonObject(owner) ? owner[segment] : undefined,\n presence: isOptional ? \"absent\" : \"present\",\n };\n}\n\nfunction step(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const { segments } = input.pointer;\n const segment = segments[index] as string;\n const isLast = index === segments.length - 1;\n if (walk.isSchema) {\n return walk.isName\n ? nameStep(walk, segment, isLast, input)\n : keywordStep(walk, segment, isLast, input);\n }\n if (segment === \"schema\" && isTypedAsSchema(input.pointer, index)) {\n const owner = followRefs(walk.node, input.refs);\n const schema = isJsonObject(owner) ? owner.schema : undefined;\n // The container's type is its schema's type: an optional header stays optional.\n const presence = walk.presence === \"absent\" ? \"absent\" : schemaPresence(schema, input.refs);\n return { ...walk, node: schema, isSchema: true, presence };\n }\n return isParameterList(input.pointer, index) ? null : containerStep(walk, index, input);\n}\n\n/** Walk the whole pointer; see the module comment. */\nexport function typedWalk(input: TypedWalkInput): TypedWalkResult {\n const { pointer } = input;\n const node = leadingNode(pointer, input.refs);\n const isSchema = startsInSchema(pointer);\n let walk: TypedWalk = {\n type: indexBy(\n rootType(pointer.rootSegment, false),\n ...pointer.segments.slice(0, leadingSegmentsOf(pointer)),\n ),\n node,\n isSchema,\n isName: false,\n presence: isSchema ? schemaPresence(node, input.refs) : \"present\",\n };\n for (let index = leadingSegmentsOf(pointer); index < pointer.segments.length; index++) {\n const next = step(walk, index, input);\n if (next === null) {\n return { kind: \"untyped\", index };\n }\n walk = next;\n }\n return { kind: \"typed\", walk };\n}\n"],"names":["irReference","followRefs","isJsonObject","irIndexedAccess","irKeyword","schemaPresence","indexKeyword","indexBy","propertyPresence","isArrayShape","isObjectShape","isOptionalRequestBody","isOptionalHeader","isTypedAsSchema","isParameterList","leadingNode","startsInSchema","rootType","leadingSegmentsOf"],"mappings":";;;;;;;AAgCA,MAAM,YAAA,GAAe,OAAA;AAuBrB,SAAS,QAAQ,IAAA,EAAyB;AACxC,EAAA,OAAO,IAAA,CAAK,QAAA,KAAa,SAAA,GAAY,IAAA,CAAK,IAAA,GAAOA,yBAAY,aAAA,EAAe,CAAC,IAAA,CAAK,IAAI,CAAC,CAAA;AACzF;AAEA,SAAS,YAAA,CAAa,IAAA,EAAiB,GAAA,EAAgB,OAAA,EAAiB,IAAA,EAAmB;AACzF,EAAA,MAAM,KAAA,GAAQC,yBAAA,CAAW,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AACxC,EAAA,MAAM,QAAQC,2BAAA,CAAa,KAAK,CAAA,GAAI,KAAA,CAAM,OAAO,CAAA,GAAI,MAAA;AACrD,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,MAAMC,4BAAA,CAAgB,OAAA,CAAQ,IAAI,CAAA,EAAGC,sBAAA,CAAU,GAAG,CAAC,CAAA;AAAA,IACnD,IAAA,EAAM,KAAA;AAAA,IACN,QAAA,EAAUC,6BAAA,CAAe,KAAA,EAAO,IAAI;AAAA,GACtC;AACF;AAEA,SAAS,QAAA,CAAS,IAAA,EAAiB,IAAA,EAAc,MAAA,EAAiB,KAAA,EAAuB;AACvF,EAAA,MAAM,KAAA,GAAQJ,yBAAA,CAAW,IAAA,CAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAC9C,EAAA,MAAM,UAAA,GAAaC,2BAAA,CAAa,KAAK,CAAA,IAAKA,2BAAA,CAAa,MAAM,UAAU,CAAA,GAAI,KAAA,CAAM,UAAA,GAAa,EAAC;AAC/F,EAAA,MAAM,IAAA,GACJ,IAAA,CAAK,QAAA,KAAa,SAAA,GACdI,qBAAa,IAAA,CAAK,IAAA,EAAM,IAAA,EAAM,MAAM,CAAA,GACpCC,eAAA,CAAQ,OAAA,CAAQ,IAAI,GAAG,IAAI,CAAA;AACjC,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,IAAA;AAAA,IACA,IAAA,EAAM,WAAW,IAAI,CAAA;AAAA,IACrB,MAAA,EAAQ,KAAA;AAAA,IACR,QAAA,EAAUC,gCAAiB,IAAA,CAAK,IAAA,EAAM,MAAM,KAAA,CAAM,OAAA,EAAS,MAAM,IAAI;AAAA,GACvE;AACF;AAGA,SAAS,QAAA,CAAS,IAAA,EAAiB,KAAA,EAAgB,MAAA,EAA4B;AAC7E,EAAA,MAAM,IAAA,GAAON,2BAAA,CAAa,KAAK,CAAA,IAAKA,2BAAA,CAAa,KAAA,CAAM,YAAY,CAAC,CAAA,GAAI,KAAA,CAAM,YAAY,CAAA,GAAI,EAAC;AAC/F,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,MAAMI,oBAAA,CAAa,OAAA,CAAQ,IAAI,CAAA,EAAG,cAAc,MAAM,CAAA;AAAA,IACtD,IAAA,EAAM,EAAE,UAAA,EAAY,IAAA,EAAM,UAAU,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAE;AAAA,IACtD,MAAA,EAAQ,IAAA;AAAA,IACR,QAAA,EAAU;AAAA,GACZ;AACF;AAEA,MAAM,eAAA,uBAA2C,GAAA,CAAI;AAAA,EACnD,YAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;AAOD,SAAS,gBAAA,CAAiB,OAAgB,OAAA,EAA0B;AAClE,EAAA,IAAI,CAAC,gBAAgB,GAAA,CAAI,OAAO,KAAK,CAACJ,2BAAA,CAAa,KAAK,CAAA,EAAG;AACzD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,YAAY,OAAA,GAAUO,2BAAA,CAAa,KAAK,CAAA,GAAIC,6BAAc,KAAK,CAAA;AACxE;AAEA,SAAS,WAAA,CAAY,IAAA,EAAiB,OAAA,EAAiB,MAAA,EAAiB,KAAA,EAAuB;AAC7F,EAAA,MAAM,KAAA,GAAQT,yBAAA,CAAW,IAAA,CAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAC9C,EAAA,IAAI,CAAC,gBAAA,CAAiB,KAAA,EAAO,OAAO,CAAA,EAAG;AACrC,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,QAAQ,OAAA;AAAS,IACf,KAAK,YAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAK;AAAA,IACjC,KAAK,OAAA;AACH,MAAA,OAAO,YAAA,CAAa,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS,MAAM,IAAI,CAAA;AAAA,IACzD,KAAK,sBAAA;AACH,MAAA,OAAO,YAAA,CAAa,IAAA,EAAM,QAAA,EAAU,sBAAA,EAAwB,MAAM,IAAI,CAAA;AAAA,IACxE,KAAK,YAAA;AACH,MAAA,OAAO,QAAA,CAAS,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAAA,IACrC;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAEA,SAAS,aAAA,CAAc,IAAA,EAAiB,KAAA,EAAe,KAAA,EAAkC;AACvF,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAQA,yBAAA,CAAW,IAAA,CAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAC9C,EAAA,MAAM,UAAA,GACH,OAAA,KAAY,aAAA,IAAiBU,iCAAA,CAAsB,KAAA,EAAO,KAAA,CAAM,IAAI,CAAA,IACrEC,4BAAA,CAAiB,KAAA,CAAM,OAAA,EAAS,KAAA,EAAO,KAAK,CAAA;AAC9C,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,IAAA,EAAML,eAAA,CAAQ,OAAA,CAAQ,IAAI,GAAG,OAAO,CAAA;AAAA,IACpC,MAAML,2BAAA,CAAa,KAAK,CAAA,GAAI,KAAA,CAAM,OAAO,CAAA,GAAI,MAAA;AAAA,IAC7C,QAAA,EAAU,aAAa,QAAA,GAAW;AAAA,GACpC;AACF;AAEA,SAAS,IAAA,CAAK,IAAA,EAAiB,KAAA,EAAe,KAAA,EAAyC;AACrF,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,KAAA,CAAM,OAAA;AAC3B,EAAA,MAAM,OAAA,GAAU,SAAS,KAAK,CAAA;AAC9B,EAAA,MAAM,MAAA,GAAS,KAAA,KAAU,QAAA,CAAS,MAAA,GAAS,CAAA;AAC3C,EAAA,IAAI,KAAK,QAAA,EAAU;AACjB,IAAA,OAAO,IAAA,CAAK,MAAA,GACR,QAAA,CAAS,IAAA,EAAM,OAAA,EAAS,MAAA,EAAQ,KAAK,CAAA,GACrC,WAAA,CAAY,IAAA,EAAM,OAAA,EAAS,MAAA,EAAQ,KAAK,CAAA;AAAA,EAC9C;AACA,EAAA,IAAI,YAAY,QAAA,IAAYW,2BAAA,CAAgB,KAAA,CAAM,OAAA,EAAS,KAAK,CAAA,EAAG;AACjE,IAAA,MAAM,KAAA,GAAQZ,yBAAA,CAAW,IAAA,CAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAC9C,IAAA,MAAM,MAAA,GAASC,2BAAA,CAAa,KAAK,CAAA,GAAI,MAAM,MAAA,GAAS,MAAA;AAEpD,IAAA,MAAM,QAAA,GAAW,KAAK,QAAA,KAAa,QAAA,GAAW,WAAWG,6BAAA,CAAe,MAAA,EAAQ,MAAM,IAAI,CAAA;AAC1F,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,MAAM,MAAA,EAAQ,QAAA,EAAU,MAAM,QAAA,EAAS;AAAA,EAC3D;AACA,EAAA,OAAOS,2BAAA,CAAgB,MAAM,OAAA,EAAS,KAAK,IAAI,IAAA,GAAO,aAAA,CAAc,IAAA,EAAM,KAAA,EAAO,KAAK,CAAA;AACxF;AAGO,SAAS,UAAU,KAAA,EAAwC;AAChE,EAAA,MAAM,EAAE,SAAQ,GAAI,KAAA;AACpB,EAAA,MAAM,IAAA,GAAOC,uBAAA,CAAY,OAAA,EAAS,KAAA,CAAM,IAAI,CAAA;AAC5C,EAAA,MAAM,QAAA,GAAWC,2BAAe,OAAO,CAAA;AACvC,EAAA,IAAI,IAAA,GAAkB;AAAA,IACpB,IAAA,EAAMT,eAAA;AAAA,MACJU,gBAAA,CAAS,OAAA,CAAQ,WAAA,EAAa,KAAK,CAAA;AAAA,MACnC,GAAG,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,EAAGC,6BAAA,CAAkB,OAAO,CAAC;AAAA,KACzD;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA,EAAQ,KAAA;AAAA,IACR,UAAU,QAAA,GAAWb,6BAAA,CAAe,IAAA,EAAM,KAAA,CAAM,IAAI,CAAA,GAAI;AAAA,GAC1D;AACA,EAAA,KAAA,IAAS,KAAA,GAAQa,8BAAkB,OAAO,CAAA,EAAG,QAAQ,OAAA,CAAQ,QAAA,CAAS,QAAQ,KAAA,EAAA,EAAS;AACrF,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,EAAM,KAAA,EAAO,KAAK,CAAA;AACpC,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAM;AAAA,IAClC;AACA,IAAA,IAAA,GAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAK;AAC/B;;"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { irReference, irIndexedAccess, irKeyword } from '../../../domain/ir/constructors.mjs';
|
|
2
|
+
import { indexBy, rootType, indexKeyword } from '../ref-type.mjs';
|
|
3
|
+
import { schemaPresence, followRefs, isJsonObject, propertyPresence, isArrayShape, isObjectShape } from './generated-shape.mjs';
|
|
4
|
+
import { leadingNode, startsInSchema, leadingSegmentsOf, isTypedAsSchema, isParameterList, isOptionalRequestBody, isOptionalHeader } from './pointer-walk.mjs';
|
|
5
|
+
|
|
6
|
+
const DEFS_KEYWORD = "$defs";
|
|
7
|
+
function present(walk) {
|
|
8
|
+
return walk.presence === "present" ? walk.type : irReference("NonNullable", [walk.type]);
|
|
9
|
+
}
|
|
10
|
+
function indexEntries(walk, key, keyword, refs) {
|
|
11
|
+
const owner = followRefs(walk.node, refs);
|
|
12
|
+
const child = isJsonObject(owner) ? owner[keyword] : void 0;
|
|
13
|
+
return {
|
|
14
|
+
...walk,
|
|
15
|
+
type: irIndexedAccess(present(walk), irKeyword(key)),
|
|
16
|
+
node: child,
|
|
17
|
+
presence: schemaPresence(child, refs)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function nameStep(walk, name, isLast, input) {
|
|
21
|
+
const owner = followRefs(walk.node, input.refs);
|
|
22
|
+
const properties = isJsonObject(owner) && isJsonObject(owner.properties) ? owner.properties : {};
|
|
23
|
+
const type = walk.presence === "present" ? indexKeyword(walk.type, name, isLast) : indexBy(present(walk), name);
|
|
24
|
+
return {
|
|
25
|
+
...walk,
|
|
26
|
+
type,
|
|
27
|
+
node: properties[name],
|
|
28
|
+
isName: false,
|
|
29
|
+
presence: propertyPresence(walk.node, name, input.options, input.refs)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function defsStep(walk, owner, isLast) {
|
|
33
|
+
const defs = isJsonObject(owner) && isJsonObject(owner[DEFS_KEYWORD]) ? owner[DEFS_KEYWORD] : {};
|
|
34
|
+
return {
|
|
35
|
+
...walk,
|
|
36
|
+
type: indexKeyword(present(walk), DEFS_KEYWORD, isLast),
|
|
37
|
+
node: { properties: defs, required: Object.keys(defs) },
|
|
38
|
+
isName: true,
|
|
39
|
+
presence: "present"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const SHAPED_KEYWORDS = /* @__PURE__ */ new Set([
|
|
43
|
+
"properties",
|
|
44
|
+
"items",
|
|
45
|
+
"additionalProperties"
|
|
46
|
+
]);
|
|
47
|
+
function hasKeywordMember(owner, segment) {
|
|
48
|
+
if (!SHAPED_KEYWORDS.has(segment) || !isJsonObject(owner)) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return segment === "items" ? isArrayShape(owner) : isObjectShape(owner);
|
|
52
|
+
}
|
|
53
|
+
function keywordStep(walk, segment, isLast, input) {
|
|
54
|
+
const owner = followRefs(walk.node, input.refs);
|
|
55
|
+
if (!hasKeywordMember(owner, segment)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
switch (segment) {
|
|
59
|
+
case "properties":
|
|
60
|
+
return { ...walk, isName: true };
|
|
61
|
+
case "items":
|
|
62
|
+
return indexEntries(walk, "number", "items", input.refs);
|
|
63
|
+
case "additionalProperties":
|
|
64
|
+
return indexEntries(walk, "string", "additionalProperties", input.refs);
|
|
65
|
+
case DEFS_KEYWORD:
|
|
66
|
+
return defsStep(walk, owner, isLast);
|
|
67
|
+
default:
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function containerStep(walk, index, input) {
|
|
72
|
+
const segment = input.pointer.segments[index];
|
|
73
|
+
const owner = followRefs(walk.node, input.refs);
|
|
74
|
+
const isOptional = segment === "requestBody" && isOptionalRequestBody(owner, input.refs) || isOptionalHeader(input.pointer, index, owner);
|
|
75
|
+
return {
|
|
76
|
+
...walk,
|
|
77
|
+
type: indexBy(present(walk), segment),
|
|
78
|
+
node: isJsonObject(owner) ? owner[segment] : void 0,
|
|
79
|
+
presence: isOptional ? "absent" : "present"
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function step(walk, index, input) {
|
|
83
|
+
const { segments } = input.pointer;
|
|
84
|
+
const segment = segments[index];
|
|
85
|
+
const isLast = index === segments.length - 1;
|
|
86
|
+
if (walk.isSchema) {
|
|
87
|
+
return walk.isName ? nameStep(walk, segment, isLast, input) : keywordStep(walk, segment, isLast, input);
|
|
88
|
+
}
|
|
89
|
+
if (segment === "schema" && isTypedAsSchema(input.pointer, index)) {
|
|
90
|
+
const owner = followRefs(walk.node, input.refs);
|
|
91
|
+
const schema = isJsonObject(owner) ? owner.schema : void 0;
|
|
92
|
+
const presence = walk.presence === "absent" ? "absent" : schemaPresence(schema, input.refs);
|
|
93
|
+
return { ...walk, node: schema, isSchema: true, presence };
|
|
94
|
+
}
|
|
95
|
+
return isParameterList(input.pointer, index) ? null : containerStep(walk, index, input);
|
|
96
|
+
}
|
|
97
|
+
function typedWalk(input) {
|
|
98
|
+
const { pointer } = input;
|
|
99
|
+
const node = leadingNode(pointer, input.refs);
|
|
100
|
+
const isSchema = startsInSchema(pointer);
|
|
101
|
+
let walk = {
|
|
102
|
+
type: indexBy(
|
|
103
|
+
rootType(pointer.rootSegment, false),
|
|
104
|
+
...pointer.segments.slice(0, leadingSegmentsOf(pointer))
|
|
105
|
+
),
|
|
106
|
+
node,
|
|
107
|
+
isSchema,
|
|
108
|
+
isName: false,
|
|
109
|
+
presence: isSchema ? schemaPresence(node, input.refs) : "present"
|
|
110
|
+
};
|
|
111
|
+
for (let index = leadingSegmentsOf(pointer); index < pointer.segments.length; index++) {
|
|
112
|
+
const next = step(walk, index, input);
|
|
113
|
+
if (next === null) {
|
|
114
|
+
return { kind: "untyped", index };
|
|
115
|
+
}
|
|
116
|
+
walk = next;
|
|
117
|
+
}
|
|
118
|
+
return { kind: "typed", walk };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export { typedWalk };
|
|
122
|
+
//# sourceMappingURL=typed-walk.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typed-walk.mjs","sources":["../../../../src/application/transform/ref-pointer/typed-walk.ts"],"sourcesContent":["import { irIndexedAccess, irKeyword, irReference } from \"../../../domain/ir/constructors.js\";\nimport type { IrKeyword, IrType } from \"../../../domain/ir/nodes.js\";\nimport { indexBy, indexKeyword, rootType } from \"../ref-type.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport {\n followRefs,\n isArrayShape,\n isJsonObject,\n isObjectShape,\n type Presence,\n propertyPresence,\n schemaPresence,\n} from \"./generated-shape.js\";\nimport {\n isOptionalHeader,\n isOptionalRequestBody,\n isParameterList,\n isTypedAsSchema,\n leadingNode,\n leadingSegmentsOf,\n type RefPointer,\n startsInSchema,\n} from \"./pointer-walk.js\";\n\n/**\n * The type of a `$ref` pointer as the generated types have it: the `schema` of a media type,\n * header or component parameter is its type, `items` is indexed by `number`,\n * `additionalProperties` by `string`, and a value that may be `undefined` or `null` is wrapped in\n * `NonNullable` before it is indexed. The walk stops at a segment with no type of its own\n * (`allOf/0`, `definitions/A`, operation `parameters/0`): the caller types the target itself.\n */\n\nconst DEFS_KEYWORD = \"$defs\";\n\nexport interface TypedWalk {\n readonly type: IrType;\n /** The document node the type stands for (not followed through a `$ref`). */\n readonly node: unknown;\n readonly isSchema: boolean;\n /** The segment is a property or `$defs` name, not a keyword. */\n readonly isName: boolean;\n readonly presence: Presence;\n}\n\nexport interface TypedWalkInput {\n readonly pointer: RefPointer;\n readonly options: SchemaOptions;\n readonly refs: RefResolver;\n}\n\n/** The walk result: a type, or the index of the first segment that has no type. */\nexport type TypedWalkResult =\n | { readonly kind: \"typed\"; readonly walk: TypedWalk }\n | { readonly kind: \"untyped\"; readonly index: number };\n\nfunction present(walk: TypedWalk): IrType {\n return walk.presence === \"present\" ? walk.type : irReference(\"NonNullable\", [walk.type]);\n}\n\nfunction indexEntries(walk: TypedWalk, key: IrKeyword, keyword: string, refs: RefResolver) {\n const owner = followRefs(walk.node, refs);\n const child = isJsonObject(owner) ? owner[keyword] : undefined;\n return {\n ...walk,\n type: irIndexedAccess(present(walk), irKeyword(key)),\n node: child,\n presence: schemaPresence(child, refs),\n };\n}\n\nfunction nameStep(walk: TypedWalk, name: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followRefs(walk.node, input.refs);\n const properties = isJsonObject(owner) && isJsonObject(owner.properties) ? owner.properties : {};\n const type =\n walk.presence === \"present\"\n ? indexKeyword(walk.type, name, isLast)\n : indexBy(present(walk), name);\n return {\n ...walk,\n type,\n node: properties[name],\n isName: false,\n presence: propertyPresence(walk.node, name, input.options, input.refs),\n };\n}\n\n/** `$defs` is optional (`NonNullable` when more follows); its members are present. */\nfunction defsStep(walk: TypedWalk, owner: unknown, isLast: boolean): TypedWalk {\n const defs = isJsonObject(owner) && isJsonObject(owner[DEFS_KEYWORD]) ? owner[DEFS_KEYWORD] : {};\n return {\n ...walk,\n type: indexKeyword(present(walk), DEFS_KEYWORD, isLast),\n node: { properties: defs, required: Object.keys(defs) },\n isName: true,\n presence: \"present\",\n };\n}\n\nconst SHAPED_KEYWORDS: ReadonlySet<string> = new Set([\n \"properties\",\n \"items\",\n \"additionalProperties\",\n]);\n\n/**\n * Whether the keyword gives the owner's generated type a member: `items` only an array,\n * `properties` and `additionalProperties` only an object (`type: string` ignores them). A node\n * that is not in the document is indexed as the keyword says.\n */\nfunction hasKeywordMember(owner: unknown, segment: string): boolean {\n if (!SHAPED_KEYWORDS.has(segment) || !isJsonObject(owner)) {\n return true;\n }\n return segment === \"items\" ? isArrayShape(owner) : isObjectShape(owner);\n}\n\nfunction keywordStep(walk: TypedWalk, segment: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followRefs(walk.node, input.refs);\n if (!hasKeywordMember(owner, segment)) {\n return null;\n }\n switch (segment) {\n case \"properties\":\n return { ...walk, isName: true };\n case \"items\":\n return indexEntries(walk, \"number\", \"items\", input.refs);\n case \"additionalProperties\":\n return indexEntries(walk, \"string\", \"additionalProperties\", input.refs);\n case DEFS_KEYWORD:\n return defsStep(walk, owner, isLast);\n default:\n return null;\n }\n}\n\nfunction containerStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk {\n const segment = input.pointer.segments[index] as string;\n const owner = followRefs(walk.node, input.refs);\n const isOptional =\n (segment === \"requestBody\" && isOptionalRequestBody(owner, input.refs)) ||\n isOptionalHeader(input.pointer, index, owner);\n return {\n ...walk,\n type: indexBy(present(walk), segment),\n node: isJsonObject(owner) ? owner[segment] : undefined,\n presence: isOptional ? \"absent\" : \"present\",\n };\n}\n\nfunction step(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const { segments } = input.pointer;\n const segment = segments[index] as string;\n const isLast = index === segments.length - 1;\n if (walk.isSchema) {\n return walk.isName\n ? nameStep(walk, segment, isLast, input)\n : keywordStep(walk, segment, isLast, input);\n }\n if (segment === \"schema\" && isTypedAsSchema(input.pointer, index)) {\n const owner = followRefs(walk.node, input.refs);\n const schema = isJsonObject(owner) ? owner.schema : undefined;\n // The container's type is its schema's type: an optional header stays optional.\n const presence = walk.presence === \"absent\" ? \"absent\" : schemaPresence(schema, input.refs);\n return { ...walk, node: schema, isSchema: true, presence };\n }\n return isParameterList(input.pointer, index) ? null : containerStep(walk, index, input);\n}\n\n/** Walk the whole pointer; see the module comment. */\nexport function typedWalk(input: TypedWalkInput): TypedWalkResult {\n const { pointer } = input;\n const node = leadingNode(pointer, input.refs);\n const isSchema = startsInSchema(pointer);\n let walk: TypedWalk = {\n type: indexBy(\n rootType(pointer.rootSegment, false),\n ...pointer.segments.slice(0, leadingSegmentsOf(pointer)),\n ),\n node,\n isSchema,\n isName: false,\n presence: isSchema ? schemaPresence(node, input.refs) : \"present\",\n };\n for (let index = leadingSegmentsOf(pointer); index < pointer.segments.length; index++) {\n const next = step(walk, index, input);\n if (next === null) {\n return { kind: \"untyped\", index };\n }\n walk = next;\n }\n return { kind: \"typed\", walk };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const errors = require('../../domain/errors.cjs');
|
|
4
4
|
const constructors = require('../../domain/ir/constructors.cjs');
|
|
5
|
+
const propertyName = require('../../domain/ir/property-name.cjs');
|
|
5
6
|
const jsonPointer = require('../../domain/openapi/json-pointer.cjs');
|
|
6
7
|
|
|
7
8
|
class InvalidRefError extends errors.OpenAPITypesafeError {
|
|
@@ -20,8 +21,8 @@ function indexBy(type, ...segments) {
|
|
|
20
21
|
type
|
|
21
22
|
);
|
|
22
23
|
}
|
|
23
|
-
function extractVariantsWith(type, propertyName) {
|
|
24
|
-
const probe = constructors.irProperty(
|
|
24
|
+
function extractVariantsWith(type, propertyName$1) {
|
|
25
|
+
const probe = constructors.irProperty(propertyName.toPropertyName(propertyName$1), constructors.irKeyword("unknown"));
|
|
25
26
|
return constructors.irReference("Extract", [type, constructors.irObject([probe])]);
|
|
26
27
|
}
|
|
27
28
|
const DEFS_KEYWORD = "$defs";
|
|
@@ -53,5 +54,9 @@ function refType(ref, options = {}) {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
exports.InvalidRefError = InvalidRefError;
|
|
57
|
+
exports.extractVariantsWith = extractVariantsWith;
|
|
58
|
+
exports.indexBy = indexBy;
|
|
59
|
+
exports.indexKeyword = indexKeyword;
|
|
56
60
|
exports.refType = refType;
|
|
61
|
+
exports.rootType = rootType;
|
|
57
62
|
//# sourceMappingURL=ref-type.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ref-type.cjs","sources":["../../../src/application/transform/ref-type.ts"],"sourcesContent":["import { ERROR_CODES, OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport {\n irIndexedAccess,\n irKeyword,\n irObject,\n irProperty,\n irReference,\n irString,\n} from \"../../domain/ir/constructors.js\";\nimport type { IrType } from \"../../domain/ir/nodes.js\";\nimport { parseRefPointer } from \"../../domain/openapi/json-pointer.js\";\n\n/** Where a referenced parameter lives in the generated `parameters` type. */\nexport interface RefParameterTarget {\n readonly in: string;\n readonly name: string;\n}\n\nexport interface RefTypeOptions {\n /** Wrap the root in `FlattenedDeepRequired<…>`. */\n readonly isDeep?: boolean;\n /** Segments to narrow with `Extract<T, { segment: unknown }>` before indexing. */\n readonly extractProperties?: readonly string[];\n /** Set when the `$ref` resolves to a parameter object: its last segment indexes `in`, `name`. */\n readonly parameter?: RefParameterTarget | null;\n}\n\nexport class InvalidRefError extends OpenAPITypesafeError {\n constructor(ref: string) {\n super({\n code: ERROR_CODES.SCHEMA_REF_INVALID,\n message: `Error parsing $ref: ${ref}. Is this a valid $ref?`,\n details: { ref },\n });\n this.name = \"InvalidRefError\";\n }\n}\n\n/** Segments that index into the root type, always as escaped string literal types. */\
|
|
1
|
+
{"version":3,"file":"ref-type.cjs","sources":["../../../src/application/transform/ref-type.ts"],"sourcesContent":["import { ERROR_CODES, OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport {\n irIndexedAccess,\n irKeyword,\n irObject,\n irProperty,\n irReference,\n irString,\n} from \"../../domain/ir/constructors.js\";\nimport type { IrType } from \"../../domain/ir/nodes.js\";\nimport { toPropertyName } from \"../../domain/ir/property-name.js\";\nimport { parseRefPointer } from \"../../domain/openapi/json-pointer.js\";\n\n/** Where a referenced parameter lives in the generated `parameters` type. */\nexport interface RefParameterTarget {\n readonly in: string;\n readonly name: string;\n}\n\nexport interface RefTypeOptions {\n /** Wrap the root in `FlattenedDeepRequired<…>`. */\n readonly isDeep?: boolean;\n /** Segments to narrow with `Extract<T, { segment: unknown }>` before indexing. */\n readonly extractProperties?: readonly string[];\n /** Set when the `$ref` resolves to a parameter object: its last segment indexes `in`, `name`. */\n readonly parameter?: RefParameterTarget | null;\n}\n\nexport class InvalidRefError extends OpenAPITypesafeError {\n constructor(ref: string) {\n super({\n code: ERROR_CODES.SCHEMA_REF_INVALID,\n message: `Error parsing $ref: ${ref}. Is this a valid $ref?`,\n details: { ref },\n });\n this.name = \"InvalidRefError\";\n }\n}\n\n/** Segments that index into the root type, always as escaped string literal types. */\nexport function indexBy(type: IrType, ...segments: readonly string[]): IrType {\n return segments.reduce<IrType>(\n (object, segment) => irIndexedAccess(object, irString(segment, \"escaped\")),\n type,\n );\n}\n\n/**\n * `Extract<T, { name: unknown }>`. The original wrote the name as an identifier even when it is\n * not one (`{ content-type: unknown }`), which is a syntax error; it is now quoted like any other\n * property name, and an identifier stays as it was.\n */\nexport function extractVariantsWith(type: IrType, propertyName: string): IrType {\n const probe = irProperty(toPropertyName(propertyName), irKeyword(\"unknown\"));\n return irReference(\"Extract\", [type, irObject([probe])]);\n}\n\nconst DEFS_KEYWORD = \"$defs\";\n\n/**\n * Index by `segment`. A `$defs` member is optional (it is a keyword, not data), so when more\n * segments follow it is wrapped in `NonNullable<…>` first; otherwise the next index fails on\n * `undefined` (upstream #2664).\n */\nexport function indexKeyword(type: IrType, segment: string, isLast: boolean): IrType {\n const indexed = indexBy(type, segment);\n return segment === DEFS_KEYWORD && !isLast ? irReference(\"NonNullable\", [indexed]) : indexed;\n}\n\nexport function rootType(rootSegment: string, isDeep: boolean): IrType {\n return irReference(isDeep ? `FlattenedDeepRequired<${rootSegment}>` : rootSegment);\n}\n\n/**\n * The indexed-access type of a `$ref` into the generated types (the original `oapiRef`), for\n * example `components[\"schemas\"][\"Foo\"]`. The first three segments index directly. After them,\n * `properties` segments are skipped (objects are flattened, upstream issue 1742), a parameter's\n * last segment becomes `[in][name]`, and listed segments are narrowed with `Extract` first.\n *\n * Throws InvalidRefError when the `$ref` has no pointer.\n */\nexport function refType(ref: string, options: RefTypeOptions = {}): IrType {\n const [rootSegment, ...pointer] = parseRefPointer(ref);\n if (rootSegment === undefined) {\n throw new InvalidRefError(ref);\n }\n const extracted = new Set(options.extractProperties ?? []);\n const lastIndex = pointer.length - 1;\n const leading = indexBy(rootType(rootSegment, options.isDeep ?? false), ...pointer.slice(0, 2));\n return pointer.slice(2).reduce<IrType>((type, segment, offset) => {\n if (segment === \"properties\") {\n return type;\n }\n if (options.parameter && offset + 2 === lastIndex) {\n return indexBy(type, options.parameter.in, options.parameter.name);\n }\n const isLast = offset + 2 === lastIndex;\n return extracted.has(segment)\n ? indexBy(extractVariantsWith(type, segment), segment)\n : indexKeyword(type, segment, isLast);\n }, leading);\n}\n"],"names":["OpenAPITypesafeError","ERROR_CODES","irIndexedAccess","irString","propertyName","irProperty","toPropertyName","irKeyword","irReference","irObject","parseRefPointer"],"mappings":";;;;;;;AA4BO,MAAM,wBAAwBA,2BAAA,CAAqB;AAAA,EACxD,YAAY,GAAA,EAAa;AACvB,IAAA,KAAA,CAAM;AAAA,MACJ,MAAMC,kBAAA,CAAY,kBAAA;AAAA,MAClB,OAAA,EAAS,uBAAuB,GAAG,CAAA,uBAAA,CAAA;AAAA,MACnC,OAAA,EAAS,EAAE,GAAA;AAAI,KAChB,CAAA;AACD,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAGO,SAAS,OAAA,CAAQ,SAAiB,QAAA,EAAqC;AAC5E,EAAA,OAAO,QAAA,CAAS,MAAA;AAAA,IACd,CAAC,QAAQ,OAAA,KAAYC,4BAAA,CAAgB,QAAQC,qBAAA,CAAS,OAAA,EAAS,SAAS,CAAC,CAAA;AAAA,IACzE;AAAA,GACF;AACF;AAOO,SAAS,mBAAA,CAAoB,MAAcC,cAAA,EAA8B;AAC9E,EAAA,MAAM,QAAQC,uBAAA,CAAWC,2BAAA,CAAeF,cAAY,CAAA,EAAGG,sBAAA,CAAU,SAAS,CAAC,CAAA;AAC3E,EAAA,OAAOC,wBAAA,CAAY,WAAW,CAAC,IAAA,EAAMC,sBAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACzD;AAEA,MAAM,YAAA,GAAe,OAAA;AAOd,SAAS,YAAA,CAAa,IAAA,EAAc,OAAA,EAAiB,MAAA,EAAyB;AACnF,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AACrC,EAAA,OAAO,OAAA,KAAY,gBAAgB,CAAC,MAAA,GAASD,yBAAY,aAAA,EAAe,CAAC,OAAO,CAAC,CAAA,GAAI,OAAA;AACvF;AAEO,SAAS,QAAA,CAAS,aAAqB,MAAA,EAAyB;AACrE,EAAA,OAAOA,wBAAA,CAAY,MAAA,GAAS,CAAA,sBAAA,EAAyB,WAAW,MAAM,WAAW,CAAA;AACnF;AAUO,SAAS,OAAA,CAAQ,GAAA,EAAa,OAAA,GAA0B,EAAC,EAAW;AACzE,EAAA,MAAM,CAAC,WAAA,EAAa,GAAG,OAAO,CAAA,GAAIE,4BAAgB,GAAG,CAAA;AACrD,EAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,IAAA,MAAM,IAAI,gBAAgB,GAAG,CAAA;AAAA,EAC/B;AACA,EAAA,MAAM,YAAY,IAAI,GAAA,CAAI,OAAA,CAAQ,iBAAA,IAAqB,EAAE,CAAA;AACzD,EAAA,MAAM,SAAA,GAAY,QAAQ,MAAA,GAAS,CAAA;AACnC,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,QAAA,CAAS,WAAA,EAAa,OAAA,CAAQ,MAAA,IAAU,KAAK,CAAA,EAAG,GAAG,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA;AAC9F,EAAA,OAAO,OAAA,CAAQ,MAAM,CAAC,CAAA,CAAE,OAAe,CAAC,IAAA,EAAM,SAAS,MAAA,KAAW;AAChE,IAAA,IAAI,YAAY,YAAA,EAAc;AAC5B,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI,OAAA,CAAQ,SAAA,IAAa,MAAA,GAAS,CAAA,KAAM,SAAA,EAAW;AACjD,MAAA,OAAO,QAAQ,IAAA,EAAM,OAAA,CAAQ,UAAU,EAAA,EAAI,OAAA,CAAQ,UAAU,IAAI,CAAA;AAAA,IACnE;AACA,IAAA,MAAM,MAAA,GAAS,SAAS,CAAA,KAAM,SAAA;AAC9B,IAAA,OAAO,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA,GACxB,QAAQ,mBAAA,CAAoB,IAAA,EAAM,OAAO,CAAA,EAAG,OAAO,CAAA,GACnD,YAAA,CAAa,IAAA,EAAM,SAAS,MAAM,CAAA;AAAA,EACxC,GAAG,OAAO,CAAA;AACZ;;;;;;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OpenAPITypesafeError, ERROR_CODES } from '../../domain/errors.mjs';
|
|
2
2
|
import { irIndexedAccess, irReference, irProperty, irKeyword, irObject, irString } from '../../domain/ir/constructors.mjs';
|
|
3
|
+
import { toPropertyName } from '../../domain/ir/property-name.mjs';
|
|
3
4
|
import { parseRefPointer } from '../../domain/openapi/json-pointer.mjs';
|
|
4
5
|
|
|
5
6
|
class InvalidRefError extends OpenAPITypesafeError {
|
|
@@ -19,7 +20,7 @@ function indexBy(type, ...segments) {
|
|
|
19
20
|
);
|
|
20
21
|
}
|
|
21
22
|
function extractVariantsWith(type, propertyName) {
|
|
22
|
-
const probe = irProperty(
|
|
23
|
+
const probe = irProperty(toPropertyName(propertyName), irKeyword("unknown"));
|
|
23
24
|
return irReference("Extract", [type, irObject([probe])]);
|
|
24
25
|
}
|
|
25
26
|
const DEFS_KEYWORD = "$defs";
|
|
@@ -50,5 +51,5 @@ function refType(ref, options = {}) {
|
|
|
50
51
|
}, leading);
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
export { InvalidRefError, refType };
|
|
54
|
+
export { InvalidRefError, extractVariantsWith, indexBy, indexKeyword, refType, rootType };
|
|
54
55
|
//# sourceMappingURL=ref-type.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ref-type.mjs","sources":["../../../src/application/transform/ref-type.ts"],"sourcesContent":["import { ERROR_CODES, OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport {\n irIndexedAccess,\n irKeyword,\n irObject,\n irProperty,\n irReference,\n irString,\n} from \"../../domain/ir/constructors.js\";\nimport type { IrType } from \"../../domain/ir/nodes.js\";\nimport { parseRefPointer } from \"../../domain/openapi/json-pointer.js\";\n\n/** Where a referenced parameter lives in the generated `parameters` type. */\nexport interface RefParameterTarget {\n readonly in: string;\n readonly name: string;\n}\n\nexport interface RefTypeOptions {\n /** Wrap the root in `FlattenedDeepRequired<…>`. */\n readonly isDeep?: boolean;\n /** Segments to narrow with `Extract<T, { segment: unknown }>` before indexing. */\n readonly extractProperties?: readonly string[];\n /** Set when the `$ref` resolves to a parameter object: its last segment indexes `in`, `name`. */\n readonly parameter?: RefParameterTarget | null;\n}\n\nexport class InvalidRefError extends OpenAPITypesafeError {\n constructor(ref: string) {\n super({\n code: ERROR_CODES.SCHEMA_REF_INVALID,\n message: `Error parsing $ref: ${ref}. Is this a valid $ref?`,\n details: { ref },\n });\n this.name = \"InvalidRefError\";\n }\n}\n\n/** Segments that index into the root type, always as escaped string literal types. */\
|
|
1
|
+
{"version":3,"file":"ref-type.mjs","sources":["../../../src/application/transform/ref-type.ts"],"sourcesContent":["import { ERROR_CODES, OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport {\n irIndexedAccess,\n irKeyword,\n irObject,\n irProperty,\n irReference,\n irString,\n} from \"../../domain/ir/constructors.js\";\nimport type { IrType } from \"../../domain/ir/nodes.js\";\nimport { toPropertyName } from \"../../domain/ir/property-name.js\";\nimport { parseRefPointer } from \"../../domain/openapi/json-pointer.js\";\n\n/** Where a referenced parameter lives in the generated `parameters` type. */\nexport interface RefParameterTarget {\n readonly in: string;\n readonly name: string;\n}\n\nexport interface RefTypeOptions {\n /** Wrap the root in `FlattenedDeepRequired<…>`. */\n readonly isDeep?: boolean;\n /** Segments to narrow with `Extract<T, { segment: unknown }>` before indexing. */\n readonly extractProperties?: readonly string[];\n /** Set when the `$ref` resolves to a parameter object: its last segment indexes `in`, `name`. */\n readonly parameter?: RefParameterTarget | null;\n}\n\nexport class InvalidRefError extends OpenAPITypesafeError {\n constructor(ref: string) {\n super({\n code: ERROR_CODES.SCHEMA_REF_INVALID,\n message: `Error parsing $ref: ${ref}. Is this a valid $ref?`,\n details: { ref },\n });\n this.name = \"InvalidRefError\";\n }\n}\n\n/** Segments that index into the root type, always as escaped string literal types. */\nexport function indexBy(type: IrType, ...segments: readonly string[]): IrType {\n return segments.reduce<IrType>(\n (object, segment) => irIndexedAccess(object, irString(segment, \"escaped\")),\n type,\n );\n}\n\n/**\n * `Extract<T, { name: unknown }>`. The original wrote the name as an identifier even when it is\n * not one (`{ content-type: unknown }`), which is a syntax error; it is now quoted like any other\n * property name, and an identifier stays as it was.\n */\nexport function extractVariantsWith(type: IrType, propertyName: string): IrType {\n const probe = irProperty(toPropertyName(propertyName), irKeyword(\"unknown\"));\n return irReference(\"Extract\", [type, irObject([probe])]);\n}\n\nconst DEFS_KEYWORD = \"$defs\";\n\n/**\n * Index by `segment`. A `$defs` member is optional (it is a keyword, not data), so when more\n * segments follow it is wrapped in `NonNullable<…>` first; otherwise the next index fails on\n * `undefined` (upstream #2664).\n */\nexport function indexKeyword(type: IrType, segment: string, isLast: boolean): IrType {\n const indexed = indexBy(type, segment);\n return segment === DEFS_KEYWORD && !isLast ? irReference(\"NonNullable\", [indexed]) : indexed;\n}\n\nexport function rootType(rootSegment: string, isDeep: boolean): IrType {\n return irReference(isDeep ? `FlattenedDeepRequired<${rootSegment}>` : rootSegment);\n}\n\n/**\n * The indexed-access type of a `$ref` into the generated types (the original `oapiRef`), for\n * example `components[\"schemas\"][\"Foo\"]`. The first three segments index directly. After them,\n * `properties` segments are skipped (objects are flattened, upstream issue 1742), a parameter's\n * last segment becomes `[in][name]`, and listed segments are narrowed with `Extract` first.\n *\n * Throws InvalidRefError when the `$ref` has no pointer.\n */\nexport function refType(ref: string, options: RefTypeOptions = {}): IrType {\n const [rootSegment, ...pointer] = parseRefPointer(ref);\n if (rootSegment === undefined) {\n throw new InvalidRefError(ref);\n }\n const extracted = new Set(options.extractProperties ?? []);\n const lastIndex = pointer.length - 1;\n const leading = indexBy(rootType(rootSegment, options.isDeep ?? false), ...pointer.slice(0, 2));\n return pointer.slice(2).reduce<IrType>((type, segment, offset) => {\n if (segment === \"properties\") {\n return type;\n }\n if (options.parameter && offset + 2 === lastIndex) {\n return indexBy(type, options.parameter.in, options.parameter.name);\n }\n const isLast = offset + 2 === lastIndex;\n return extracted.has(segment)\n ? indexBy(extractVariantsWith(type, segment), segment)\n : indexKeyword(type, segment, isLast);\n }, leading);\n}\n"],"names":[],"mappings":";;;;;AA4BO,MAAM,wBAAwB,oBAAA,CAAqB;AAAA,EACxD,YAAY,GAAA,EAAa;AACvB,IAAA,KAAA,CAAM;AAAA,MACJ,MAAM,WAAA,CAAY,kBAAA;AAAA,MAClB,OAAA,EAAS,uBAAuB,GAAG,CAAA,uBAAA,CAAA;AAAA,MACnC,OAAA,EAAS,EAAE,GAAA;AAAI,KAChB,CAAA;AACD,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAGO,SAAS,OAAA,CAAQ,SAAiB,QAAA,EAAqC;AAC5E,EAAA,OAAO,QAAA,CAAS,MAAA;AAAA,IACd,CAAC,QAAQ,OAAA,KAAY,eAAA,CAAgB,QAAQ,QAAA,CAAS,OAAA,EAAS,SAAS,CAAC,CAAA;AAAA,IACzE;AAAA,GACF;AACF;AAOO,SAAS,mBAAA,CAAoB,MAAc,YAAA,EAA8B;AAC9E,EAAA,MAAM,QAAQ,UAAA,CAAW,cAAA,CAAe,YAAY,CAAA,EAAG,SAAA,CAAU,SAAS,CAAC,CAAA;AAC3E,EAAA,OAAO,WAAA,CAAY,WAAW,CAAC,IAAA,EAAM,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACzD;AAEA,MAAM,YAAA,GAAe,OAAA;AAOd,SAAS,YAAA,CAAa,IAAA,EAAc,OAAA,EAAiB,MAAA,EAAyB;AACnF,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AACrC,EAAA,OAAO,OAAA,KAAY,gBAAgB,CAAC,MAAA,GAAS,YAAY,aAAA,EAAe,CAAC,OAAO,CAAC,CAAA,GAAI,OAAA;AACvF;AAEO,SAAS,QAAA,CAAS,aAAqB,MAAA,EAAyB;AACrE,EAAA,OAAO,WAAA,CAAY,MAAA,GAAS,CAAA,sBAAA,EAAyB,WAAW,MAAM,WAAW,CAAA;AACnF;AAUO,SAAS,OAAA,CAAQ,GAAA,EAAa,OAAA,GAA0B,EAAC,EAAW;AACzE,EAAA,MAAM,CAAC,WAAA,EAAa,GAAG,OAAO,CAAA,GAAI,gBAAgB,GAAG,CAAA;AACrD,EAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,IAAA,MAAM,IAAI,gBAAgB,GAAG,CAAA;AAAA,EAC/B;AACA,EAAA,MAAM,YAAY,IAAI,GAAA,CAAI,OAAA,CAAQ,iBAAA,IAAqB,EAAE,CAAA;AACzD,EAAA,MAAM,SAAA,GAAY,QAAQ,MAAA,GAAS,CAAA;AACnC,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,QAAA,CAAS,WAAA,EAAa,OAAA,CAAQ,MAAA,IAAU,KAAK,CAAA,EAAG,GAAG,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA;AAC9F,EAAA,OAAO,OAAA,CAAQ,MAAM,CAAC,CAAA,CAAE,OAAe,CAAC,IAAA,EAAM,SAAS,MAAA,KAAW;AAChE,IAAA,IAAI,YAAY,YAAA,EAAc;AAC5B,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI,OAAA,CAAQ,SAAA,IAAa,MAAA,GAAS,CAAA,KAAM,SAAA,EAAW;AACjD,MAAA,OAAO,QAAQ,IAAA,EAAM,OAAA,CAAQ,UAAU,EAAA,EAAI,OAAA,CAAQ,UAAU,IAAI,CAAA;AAAA,IACnE;AACA,IAAA,MAAM,MAAA,GAAS,SAAS,CAAA,KAAM,SAAA;AAC9B,IAAA,OAAO,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA,GACxB,QAAQ,mBAAA,CAAoB,IAAA,EAAM,OAAO,CAAA,EAAG,OAAO,CAAA,GACnD,YAAA,CAAa,IAAA,EAAM,SAAS,MAAM,CAAA;AAAA,EACxC,GAAG,OAAO,CAAA;AACZ;;"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const outputFixes = require('../../../domain/output-fixes.cjs');
|
|
4
|
+
|
|
5
|
+
const NO_FLAGS = { isReadOnly: false, isWriteOnly: false };
|
|
6
|
+
function ownFlags(schema) {
|
|
7
|
+
return { isReadOnly: Boolean(schema.readOnly), isWriteOnly: Boolean(schema.writeOnly) };
|
|
8
|
+
}
|
|
9
|
+
function merged(left, right) {
|
|
10
|
+
return {
|
|
11
|
+
isReadOnly: left.isReadOnly || right.isReadOnly,
|
|
12
|
+
isWriteOnly: left.isWriteOnly || right.isWriteOnly
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function appliedFlags(schema, context, seen) {
|
|
16
|
+
if (typeof schema !== "object" || schema === null || seen.has(schema)) {
|
|
17
|
+
return NO_FLAGS;
|
|
18
|
+
}
|
|
19
|
+
const inner = /* @__PURE__ */ new Set([...seen, schema]);
|
|
20
|
+
const object = schema;
|
|
21
|
+
const target = typeof object.$ref === "string" ? context.refs.resolve(object.$ref) : void 0;
|
|
22
|
+
return (object.allOf ?? []).reduce(
|
|
23
|
+
(flags, member) => merged(flags, appliedFlags(member, context, inner)),
|
|
24
|
+
merged(ownFlags(object), appliedFlags(target, context, inner))
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
function propertyAccessFlags(value, context) {
|
|
28
|
+
if (typeof value !== "object") {
|
|
29
|
+
return NO_FLAGS;
|
|
30
|
+
}
|
|
31
|
+
if (!context.options.fixes.has(outputFixes.OutputFix.READ_WRITE_REFS)) {
|
|
32
|
+
return ownFlags(value);
|
|
33
|
+
}
|
|
34
|
+
return appliedFlags(value, context, /* @__PURE__ */ new Set());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
exports.propertyAccessFlags = propertyAccessFlags;
|
|
38
|
+
//# sourceMappingURL=access-flags.cjs.map
|