openapi-typesafe 1.0.0-rc.2 → 1.0.0-rc.4
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/CHANGELOG.md +1831 -0
- package/dist/adapters/node-deprecations/node-deprecations.cjs +14 -0
- package/dist/adapters/node-deprecations/node-deprecations.cjs.map +1 -0
- package/dist/adapters/node-deprecations/node-deprecations.mjs +12 -0
- package/dist/adapters/node-deprecations/node-deprecations.mjs.map +1 -0
- package/dist/adapters/node-file-system/file-claims.cjs +105 -0
- package/dist/adapters/node-file-system/file-claims.cjs.map +1 -0
- package/dist/adapters/node-file-system/file-claims.mjs +95 -0
- package/dist/adapters/node-file-system/file-claims.mjs.map +1 -0
- package/dist/adapters/node-file-system/file-identity.cjs +82 -0
- package/dist/adapters/node-file-system/file-identity.cjs.map +1 -0
- package/dist/adapters/node-file-system/file-identity.mjs +74 -0
- package/dist/adapters/node-file-system/file-identity.mjs.map +1 -0
- package/dist/adapters/node-file-system/node-file-system.cjs +90 -14
- package/dist/adapters/node-file-system/node-file-system.cjs.map +1 -1
- package/dist/adapters/node-file-system/node-file-system.mjs +90 -14
- package/dist/adapters/node-file-system/node-file-system.mjs.map +1 -1
- package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs +75 -0
- package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs.map +1 -0
- package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs +72 -0
- package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs.map +1 -0
- package/dist/adapters/redocly-loader/bundled-ref-repair.cjs +1 -1
- package/dist/adapters/redocly-loader/bundled-ref-repair.cjs.map +1 -1
- package/dist/adapters/redocly-loader/bundled-ref-repair.mjs +2 -2
- package/dist/adapters/redocly-loader/bundled-ref-repair.mjs.map +1 -1
- package/dist/adapters/redocly-loader/loaded-documents.cjs +28 -0
- package/dist/adapters/redocly-loader/loaded-documents.cjs.map +1 -0
- package/dist/adapters/redocly-loader/loaded-documents.mjs +21 -0
- package/dist/adapters/redocly-loader/loaded-documents.mjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +14 -15
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +12 -13
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.cjs +31 -3
- package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.mjs +31 -3
- package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-holders.cjs +2 -2
- package/dist/adapters/redocly-loader/ref-holders.cjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-holders.mjs +3 -3
- package/dist/adapters/redocly-loader/ref-holders.mjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-body-limit.cjs +50 -0
- package/dist/adapters/redocly-loader/remote-body-limit.cjs.map +1 -0
- package/dist/adapters/redocly-loader/remote-body-limit.mjs +48 -0
- package/dist/adapters/redocly-loader/remote-body-limit.mjs.map +1 -0
- package/dist/adapters/redocly-loader/remote-fetch.cjs +35 -6
- package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-fetch.mjs +35 -6
- package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-node-limit.cjs +47 -0
- package/dist/adapters/redocly-loader/remote-node-limit.cjs.map +1 -0
- package/dist/adapters/redocly-loader/remote-node-limit.mjs +44 -0
- package/dist/adapters/redocly-loader/remote-node-limit.mjs.map +1 -0
- package/dist/adapters/redocly-loader/schema-load-errors.cjs +32 -8
- package/dist/adapters/redocly-loader/schema-load-errors.cjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-load-errors.mjs +32 -9
- package/dist/adapters/redocly-loader/schema-load-errors.mjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-source.cjs +11 -7
- package/dist/adapters/redocly-loader/schema-source.cjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-source.mjs +12 -8
- package/dist/adapters/redocly-loader/schema-source.mjs.map +1 -1
- package/dist/adapters/redocly-loader/unsupported-keys.cjs +3 -5
- package/dist/adapters/redocly-loader/unsupported-keys.cjs.map +1 -1
- package/dist/adapters/redocly-loader/unsupported-keys.mjs +3 -5
- package/dist/adapters/redocly-loader/unsupported-keys.mjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.cjs +6 -4
- package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.mjs +6 -4
- package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
- package/dist/api/default-ports.cjs +19 -2
- package/dist/api/default-ports.cjs.map +1 -1
- package/dist/api/default-ports.mjs +19 -3
- package/dist/api/default-ports.mjs.map +1 -1
- package/dist/api/discriminator-conflict-warnings.cjs +1 -1
- package/dist/api/discriminator-conflict-warnings.cjs.map +1 -1
- package/dist/api/discriminator-conflict-warnings.mjs +2 -2
- package/dist/api/discriminator-conflict-warnings.mjs.map +1 -1
- package/dist/api/discriminator-enum-parent.cjs +2 -2
- package/dist/api/discriminator-enum-parent.cjs.map +1 -1
- package/dist/api/discriminator-enum-parent.mjs +3 -3
- package/dist/api/discriminator-enum-parent.mjs.map +1 -1
- package/dist/api/discriminator-other-owners.cjs +5 -3
- package/dist/api/discriminator-other-owners.cjs.map +1 -1
- package/dist/api/discriminator-other-owners.mjs +5 -3
- package/dist/api/discriminator-other-owners.mjs.map +1 -1
- package/dist/api/discriminator-patch.cjs +8 -4
- package/dist/api/discriminator-patch.cjs.map +1 -1
- package/dist/api/discriminator-patch.mjs +9 -5
- package/dist/api/discriminator-patch.mjs.map +1 -1
- package/dist/api/discriminator-scan.cjs +17 -10
- package/dist/api/discriminator-scan.cjs.map +1 -1
- package/dist/api/discriminator-scan.mjs +18 -11
- package/dist/api/discriminator-scan.mjs.map +1 -1
- package/dist/api/document-run.cjs +4 -3
- package/dist/api/document-run.cjs.map +1 -1
- package/dist/api/document-run.mjs +4 -3
- package/dist/api/document-run.mjs.map +1 -1
- package/dist/api/legacy-callback-warning.cjs +7 -4
- package/dist/api/legacy-callback-warning.cjs.map +1 -1
- package/dist/api/legacy-callback-warning.mjs +8 -5
- package/dist/api/legacy-callback-warning.mjs.map +1 -1
- package/dist/api/legacy-utils.cjs.map +1 -1
- package/dist/api/legacy-utils.mjs.map +1 -1
- package/dist/api/openapi-ts.cjs +9 -5
- package/dist/api/openapi-ts.cjs.map +1 -1
- package/dist/api/openapi-ts.mjs +10 -7
- package/dist/api/openapi-ts.mjs.map +1 -1
- package/dist/api/schema-callbacks.cjs +36 -12
- package/dist/api/schema-callbacks.cjs.map +1 -1
- package/dist/api/schema-callbacks.mjs +36 -12
- package/dist/api/schema-callbacks.mjs.map +1 -1
- package/dist/api/string-to-ast.cjs +7 -9
- package/dist/api/string-to-ast.cjs.map +1 -1
- package/dist/api/string-to-ast.mjs +8 -9
- package/dist/api/string-to-ast.mjs.map +1 -1
- package/dist/api/transform-context.cjs +7 -3
- package/dist/api/transform-context.cjs.map +1 -1
- package/dist/api/transform-context.mjs +7 -3
- package/dist/api/transform-context.mjs.map +1 -1
- package/dist/api/transform-schema.cjs +42 -12
- package/dist/api/transform-schema.cjs.map +1 -1
- package/dist/api/transform-schema.mjs +44 -14
- package/dist/api/transform-schema.mjs.map +1 -1
- package/dist/application/print/text-writer.cjs +10 -3
- package/dist/application/print/text-writer.cjs.map +1 -1
- package/dist/application/print/text-writer.mjs +10 -3
- package/dist/application/print/text-writer.mjs.map +1 -1
- package/dist/application/stack-overflow.cjs +2 -1
- package/dist/application/stack-overflow.cjs.map +1 -1
- package/dist/application/stack-overflow.mjs +2 -1
- package/dist/application/stack-overflow.mjs.map +1 -1
- 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-type-names.cjs +23 -0
- package/dist/application/transform/document/declared-type-names.cjs.map +1 -0
- package/dist/application/transform/document/declared-type-names.mjs +20 -0
- package/dist/application/transform/document/declared-type-names.mjs.map +1 -0
- package/dist/application/transform/document/defs-root.cjs +1 -1
- package/dist/application/transform/document/defs-root.cjs.map +1 -1
- package/dist/application/transform/document/defs-root.mjs +2 -2
- package/dist/application/transform/document/defs-root.mjs.map +1 -1
- package/dist/application/transform/document/document.cjs +4 -1
- package/dist/application/transform/document/document.cjs.map +1 -1
- package/dist/application/transform/document/document.mjs +3 -2
- package/dist/application/transform/document/document.mjs.map +1 -1
- package/dist/application/transform/document/enum-names-given-back.cjs +62 -0
- package/dist/application/transform/document/enum-names-given-back.cjs.map +1 -0
- package/dist/application/transform/document/enum-names-given-back.mjs +58 -0
- package/dist/application/transform/document/enum-names-given-back.mjs.map +1 -0
- package/dist/application/transform/document/global-type-references.cjs +1 -0
- package/dist/application/transform/document/global-type-references.cjs.map +1 -1
- package/dist/application/transform/document/global-type-references.mjs +1 -1
- package/dist/application/transform/document/global-type-references.mjs.map +1 -1
- package/dist/application/transform/document/media-type.cjs +2 -2
- package/dist/application/transform/document/media-type.cjs.map +1 -1
- package/dist/application/transform/document/media-type.mjs +3 -3
- package/dist/application/transform/document/media-type.mjs.map +1 -1
- package/dist/application/transform/document/operation-keys-written.cjs +26 -0
- package/dist/application/transform/document/operation-keys-written.cjs.map +1 -0
- package/dist/application/transform/document/operation-keys-written.mjs +24 -0
- package/dist/application/transform/document/operation-keys-written.mjs.map +1 -0
- package/dist/application/transform/document/operation.cjs +1 -1
- package/dist/application/transform/document/operation.cjs.map +1 -1
- package/dist/application/transform/document/operation.mjs +2 -2
- package/dist/application/transform/document/operation.mjs.map +1 -1
- package/dist/application/transform/document/parameter-entries.cjs +34 -0
- package/dist/application/transform/document/parameter-entries.cjs.map +1 -0
- package/dist/application/transform/document/parameter-entries.mjs +30 -0
- package/dist/application/transform/document/parameter-entries.mjs.map +1 -0
- package/dist/application/transform/document/parameter.cjs +12 -4
- package/dist/application/transform/document/parameter.cjs.map +1 -1
- package/dist/application/transform/document/parameter.mjs +13 -5
- package/dist/application/transform/document/parameter.mjs.map +1 -1
- package/dist/application/transform/document/parameters.cjs +7 -30
- package/dist/application/transform/document/parameters.cjs.map +1 -1
- package/dist/application/transform/document/parameters.mjs +8 -31
- package/dist/application/transform/document/parameters.mjs.map +1 -1
- package/dist/application/transform/document/path-item.cjs +11 -14
- package/dist/application/transform/document/path-item.cjs.map +1 -1
- package/dist/application/transform/document/path-item.mjs +12 -16
- package/dist/application/transform/document/path-item.mjs.map +1 -1
- package/dist/application/transform/document/paths-enum.cjs +1 -0
- package/dist/application/transform/document/paths-enum.cjs.map +1 -1
- package/dist/application/transform/document/paths-enum.mjs +1 -1
- package/dist/application/transform/document/paths-enum.mjs.map +1 -1
- package/dist/application/transform/document/paths.cjs +6 -2
- package/dist/application/transform/document/paths.cjs.map +1 -1
- package/dist/application/transform/document/paths.mjs +8 -4
- package/dist/application/transform/document/paths.mjs.map +1 -1
- package/dist/application/transform/document/referenced-parameter.cjs +80 -0
- package/dist/application/transform/document/referenced-parameter.cjs.map +1 -0
- package/dist/application/transform/document/referenced-parameter.mjs +78 -0
- package/dist/application/transform/document/referenced-parameter.mjs.map +1 -0
- package/dist/application/transform/document/request-body.cjs +1 -1
- package/dist/application/transform/document/request-body.cjs.map +1 -1
- package/dist/application/transform/document/request-body.mjs +2 -2
- package/dist/application/transform/document/request-body.mjs.map +1 -1
- package/dist/application/transform/document/response.cjs +2 -2
- package/dist/application/transform/document/response.cjs.map +1 -1
- package/dist/application/transform/document/response.mjs +3 -3
- package/dist/application/transform/document/response.mjs.map +1 -1
- package/dist/application/transform/document/responses.cjs +1 -1
- package/dist/application/transform/document/responses.cjs.map +1 -1
- package/dist/application/transform/document/responses.mjs +2 -2
- package/dist/application/transform/document/responses.mjs.map +1 -1
- package/dist/application/transform/document/root-type-aliases.cjs +8 -23
- package/dist/application/transform/document/root-type-aliases.cjs.map +1 -1
- package/dist/application/transform/document/root-type-aliases.mjs +8 -24
- package/dist/application/transform/document/root-type-aliases.mjs.map +1 -1
- package/dist/application/transform/document/type-resolution.cjs +3 -1
- package/dist/application/transform/document/type-resolution.cjs.map +1 -1
- package/dist/application/transform/document/type-resolution.mjs +3 -1
- package/dist/application/transform/document/type-resolution.mjs.map +1 -1
- package/dist/application/transform/document/webhooks.cjs +1 -1
- package/dist/application/transform/document/webhooks.cjs.map +1 -1
- package/dist/application/transform/document/webhooks.mjs +2 -2
- package/dist/application/transform/document/webhooks.mjs.map +1 -1
- package/dist/application/transform/footer/document-footer.cjs +10 -2
- package/dist/application/transform/footer/document-footer.cjs.map +1 -1
- package/dist/application/transform/footer/document-footer.mjs +10 -2
- package/dist/application/transform/footer/document-footer.mjs.map +1 -1
- package/dist/application/transform/footer/enum-name-claims.cjs +48 -0
- package/dist/application/transform/footer/enum-name-claims.cjs.map +1 -0
- package/dist/application/transform/footer/enum-name-claims.mjs +46 -0
- package/dist/application/transform/footer/enum-name-claims.mjs.map +1 -0
- package/dist/application/transform/footer/operation-keys.cjs +23 -0
- package/dist/application/transform/footer/operation-keys.cjs.map +1 -0
- package/dist/application/transform/footer/operation-keys.mjs +21 -0
- package/dist/application/transform/footer/operation-keys.mjs.map +1 -0
- package/dist/application/transform/footer/type-evaluation.cjs +4 -4
- package/dist/application/transform/footer/type-evaluation.cjs.map +1 -1
- package/dist/application/transform/footer/type-evaluation.mjs +4 -4
- package/dist/application/transform/footer/type-evaluation.mjs.map +1 -1
- package/dist/application/transform/helper-types.cjs +1 -1
- package/dist/application/transform/helper-types.cjs.map +1 -1
- package/dist/application/transform/helper-types.mjs +1 -1
- package/dist/application/transform/helper-types.mjs.map +1 -1
- package/dist/application/transform/numbered-names.cjs +9 -0
- package/dist/application/transform/numbered-names.cjs.map +1 -1
- package/dist/application/transform/numbered-names.mjs +9 -1
- package/dist/application/transform/numbered-names.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/generated-location.cjs +1 -1
- package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/generated-location.mjs +2 -2
- package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/pointer-type.cjs +1 -1
- package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/pointer-type.mjs +2 -2
- package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -1
- package/dist/application/transform/ref-type.cjs +2 -1
- package/dist/application/transform/ref-type.cjs.map +1 -1
- package/dist/application/transform/ref-type.mjs +2 -1
- package/dist/application/transform/ref-type.mjs.map +1 -1
- package/dist/application/transform/schema/access-flags.cjs +1 -1
- package/dist/application/transform/schema/access-flags.cjs.map +1 -1
- package/dist/application/transform/schema/access-flags.mjs +2 -2
- package/dist/application/transform/schema/access-flags.mjs.map +1 -1
- package/dist/application/transform/schema/array-type.cjs +2 -2
- package/dist/application/transform/schema/array-type.cjs.map +1 -1
- package/dist/application/transform/schema/array-type.mjs +3 -3
- package/dist/application/transform/schema/array-type.mjs.map +1 -1
- package/dist/application/transform/schema/composition-type.cjs +4 -4
- package/dist/application/transform/schema/composition-type.cjs.map +1 -1
- package/dist/application/transform/schema/composition-type.mjs +6 -6
- package/dist/application/transform/schema/composition-type.mjs.map +1 -1
- package/dist/application/transform/schema/enum-rule.cjs +4 -6
- package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
- package/dist/application/transform/schema/enum-rule.mjs +6 -8
- package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
- package/dist/application/transform/schema/object-type.cjs +3 -3
- package/dist/application/transform/schema/object-type.cjs.map +1 -1
- package/dist/application/transform/schema/object-type.mjs +4 -4
- package/dist/application/transform/schema/object-type.mjs.map +1 -1
- package/dist/application/transform/schema/presence-members.cjs +1 -1
- package/dist/application/transform/schema/presence-members.cjs.map +1 -1
- package/dist/application/transform/schema/presence-members.mjs +2 -2
- package/dist/application/transform/schema/presence-members.mjs.map +1 -1
- package/dist/application/transform/schema/ref-siblings.cjs +47 -0
- package/dist/application/transform/schema/ref-siblings.cjs.map +1 -0
- package/dist/application/transform/schema/ref-siblings.mjs +45 -0
- package/dist/application/transform/schema/ref-siblings.mjs.map +1 -0
- package/dist/application/transform/schema/required-variants.cjs +2 -2
- package/dist/application/transform/schema/required-variants.cjs.map +1 -1
- package/dist/application/transform/schema/required-variants.mjs +3 -3
- package/dist/application/transform/schema/required-variants.mjs.map +1 -1
- package/dist/application/transform/schema/schema-transform.cjs +4 -2
- package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
- package/dist/application/transform/schema/schema-transform.mjs +4 -2
- package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
- package/dist/application/transform/schema/unevaluated-properties.cjs +1 -1
- package/dist/application/transform/schema/unevaluated-properties.cjs.map +1 -1
- package/dist/application/transform/schema/unevaluated-properties.mjs +2 -2
- package/dist/application/transform/schema/unevaluated-properties.mjs.map +1 -1
- package/dist/application/transform/schema-comment.cjs +6 -2
- package/dist/application/transform/schema-comment.cjs.map +1 -1
- package/dist/application/transform/schema-comment.mjs +7 -3
- package/dist/application/transform/schema-comment.mjs.map +1 -1
- package/dist/cli/api-settings.cjs +62 -6
- package/dist/cli/api-settings.cjs.map +1 -1
- package/dist/cli/api-settings.mjs +60 -7
- package/dist/cli/api-settings.mjs.map +1 -1
- package/dist/cli/api-writes.cjs +72 -0
- package/dist/cli/api-writes.cjs.map +1 -0
- package/dist/cli/api-writes.mjs +69 -0
- package/dist/cli/api-writes.mjs.map +1 -0
- package/dist/cli/cli-errors.cjs +12 -1
- package/dist/cli/cli-errors.cjs.map +1 -1
- package/dist/cli/cli-errors.mjs +12 -1
- package/dist/cli/cli-errors.mjs.map +1 -1
- package/dist/cli/cli-output.cjs +106 -1
- package/dist/cli/cli-output.cjs.map +1 -1
- package/dist/cli/cli-output.mjs +99 -2
- package/dist/cli/cli-output.mjs.map +1 -1
- package/dist/cli/main.cjs +5 -1
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.mjs +6 -2
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/redocly-apis.cjs +82 -36
- package/dist/cli/redocly-apis.cjs.map +1 -1
- package/dist/cli/redocly-apis.mjs +85 -39
- package/dist/cli/redocly-apis.mjs.map +1 -1
- package/dist/cli/run-cli.cjs +13 -7
- package/dist/cli/run-cli.cjs.map +1 -1
- package/dist/cli/run-cli.mjs +14 -8
- package/dist/cli/run-cli.mjs.map +1 -1
- package/dist/domain/append-all.cjs +10 -0
- package/dist/domain/append-all.cjs.map +1 -0
- package/dist/domain/append-all.mjs +8 -0
- package/dist/domain/append-all.mjs.map +1 -0
- package/dist/domain/cause-secrets.cjs +37 -0
- package/dist/domain/cause-secrets.cjs.map +1 -0
- package/dist/domain/cause-secrets.mjs +35 -0
- package/dist/domain/cause-secrets.mjs.map +1 -0
- package/dist/domain/deprecations.cjs +11 -0
- package/dist/domain/deprecations.cjs.map +1 -0
- package/dist/domain/deprecations.mjs +9 -0
- package/dist/domain/deprecations.mjs.map +1 -0
- package/dist/domain/errors.cjs +9 -3
- package/dist/domain/errors.cjs.map +1 -1
- package/dist/domain/errors.mjs +9 -3
- package/dist/domain/errors.mjs.map +1 -1
- package/dist/domain/ir/identifier-text.cjs.map +1 -1
- package/dist/domain/ir/identifier-text.mjs +1 -1
- package/dist/domain/ir/identifier-text.mjs.map +1 -1
- package/dist/domain/ir/ir-shape.cjs +187 -0
- package/dist/domain/ir/ir-shape.cjs.map +1 -0
- package/dist/domain/ir/ir-shape.mjs +184 -0
- package/dist/domain/ir/ir-shape.mjs.map +1 -0
- package/dist/domain/ir/newer-identifier-ranges.cjs +182 -29
- package/dist/domain/ir/newer-identifier-ranges.cjs.map +1 -1
- package/dist/domain/ir/newer-identifier-ranges.mjs +182 -29
- package/dist/domain/ir/newer-identifier-ranges.mjs.map +1 -1
- package/dist/domain/openapi/alias-expansion.cjs +3 -1
- package/dist/domain/openapi/alias-expansion.cjs.map +1 -1
- package/dist/domain/openapi/alias-expansion.mjs +3 -1
- package/dist/domain/openapi/alias-expansion.mjs.map +1 -1
- package/dist/domain/openapi/discriminated-union.cjs +3 -3
- package/dist/domain/openapi/discriminated-union.cjs.map +1 -1
- package/dist/domain/openapi/discriminated-union.mjs +4 -4
- package/dist/domain/openapi/discriminated-union.mjs.map +1 -1
- package/dist/domain/openapi/discriminator-conflicts.cjs +10 -6
- package/dist/domain/openapi/discriminator-conflicts.cjs.map +1 -1
- package/dist/domain/openapi/discriminator-conflicts.mjs +11 -7
- package/dist/domain/openapi/discriminator-conflicts.mjs.map +1 -1
- package/dist/domain/openapi/json-pointer.cjs +43 -1
- package/dist/domain/openapi/json-pointer.cjs.map +1 -1
- package/dist/domain/openapi/json-pointer.mjs +40 -2
- package/dist/domain/openapi/json-pointer.mjs.map +1 -1
- package/dist/domain/openapi/schema-dialect.cjs +15 -0
- package/dist/domain/openapi/schema-dialect.cjs.map +1 -0
- package/dist/domain/openapi/schema-dialect.mjs +12 -0
- package/dist/domain/openapi/schema-dialect.mjs.map +1 -0
- package/dist/domain/openapi/unsupported-features.cjs +1 -1
- package/dist/domain/openapi/unsupported-features.cjs.map +1 -1
- package/dist/domain/openapi/unsupported-features.mjs +2 -2
- package/dist/domain/openapi/unsupported-features.mjs.map +1 -1
- package/dist/domain/output-fixes.cjs +25 -14
- package/dist/domain/output-fixes.cjs.map +1 -1
- package/dist/domain/output-fixes.mjs +25 -13
- package/dist/domain/output-fixes.mjs.map +1 -1
- package/dist/domain/url-secrets.cjs +48 -0
- package/dist/domain/url-secrets.cjs.map +1 -0
- package/dist/domain/url-secrets.mjs +45 -0
- package/dist/domain/url-secrets.mjs.map +1 -0
- package/dist/domain/warnings.cjs +0 -1
- package/dist/domain/warnings.cjs.map +1 -1
- package/dist/domain/warnings.mjs +0 -1
- package/dist/domain/warnings.mjs.map +1 -1
- package/dist/index.cjs +2 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -20
- package/dist/index.d.mts +57 -20
- package/dist/index.d.ts +57 -20
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -6
- package/src/adapters/node-deprecations/node-deprecations.ts +14 -0
- package/src/adapters/node-file-system/file-claims.ts +138 -0
- package/src/adapters/node-file-system/file-identity.ts +137 -0
- package/src/adapters/node-file-system/node-file-system.ts +145 -18
- package/src/adapters/redocly-loader/bundled-mapping-copies.ts +95 -0
- package/src/adapters/redocly-loader/bundled-ref-repair.ts +2 -2
- package/src/adapters/redocly-loader/loaded-documents.ts +46 -0
- package/src/adapters/redocly-loader/redocly-schema-loader.ts +18 -24
- package/src/adapters/redocly-loader/ref-access.ts +37 -3
- package/src/adapters/redocly-loader/ref-holders.ts +3 -3
- package/src/adapters/redocly-loader/remote-body-limit.ts +66 -0
- package/src/adapters/redocly-loader/remote-fetch.ts +74 -11
- package/src/adapters/redocly-loader/remote-node-limit.ts +62 -0
- package/src/adapters/redocly-loader/schema-load-errors.ts +52 -13
- package/src/adapters/redocly-loader/schema-source.ts +20 -8
- package/src/adapters/redocly-loader/unsupported-keys.ts +3 -7
- package/src/adapters/terminal-logger/terminal-logger.ts +10 -5
- package/src/api/default-ports.ts +40 -4
- package/src/api/discriminator-conflict-warnings.ts +2 -2
- package/src/api/discriminator-enum-parent.ts +3 -3
- package/src/api/discriminator-other-owners.ts +5 -3
- package/src/api/discriminator-patch.ts +9 -6
- package/src/api/discriminator-scan.ts +19 -11
- package/src/api/document-run.ts +9 -3
- package/src/api/legacy-callback-warning.ts +13 -6
- package/src/api/legacy-utils.ts +5 -1
- package/src/api/openapi-ts.ts +26 -7
- package/src/api/run-context.ts +6 -0
- package/src/api/schema-callbacks.ts +60 -17
- package/src/api/string-to-ast.ts +11 -15
- package/src/api/transform-context.ts +7 -3
- package/src/api/transform-schema.ts +67 -15
- package/src/application/ports/deprecation-reporter.ts +9 -0
- package/src/application/ports/file-system.ts +39 -0
- package/src/application/ports/schema-loader.ts +11 -1
- package/src/application/print/text-writer.ts +10 -3
- package/src/application/stack-overflow.ts +9 -5
- package/src/application/transform/document/components.ts +4 -4
- package/src/application/transform/document/declared-type-names.ts +36 -0
- package/src/application/transform/document/defs-root.ts +2 -2
- package/src/application/transform/document/document.ts +4 -3
- package/src/application/transform/document/enum-names-given-back.ts +91 -0
- package/src/application/transform/document/global-type-references.ts +1 -1
- package/src/application/transform/document/media-type.ts +4 -3
- package/src/application/transform/document/operation-keys-written.ts +27 -0
- package/src/application/transform/document/operation.ts +2 -2
- package/src/application/transform/document/parameter-entries.ts +70 -0
- package/src/application/transform/document/parameter.ts +21 -9
- package/src/application/transform/document/parameters.ts +13 -58
- package/src/application/transform/document/path-item.ts +13 -31
- package/src/application/transform/document/paths-enum.ts +1 -1
- package/src/application/transform/document/paths.ts +8 -4
- package/src/application/transform/document/referenced-parameter.ts +146 -0
- package/src/application/transform/document/request-body.ts +2 -2
- package/src/application/transform/document/response.ts +3 -3
- package/src/application/transform/document/responses.ts +2 -2
- package/src/application/transform/document/root-type-aliases.ts +17 -38
- package/src/application/transform/document/type-resolution.ts +2 -1
- package/src/application/transform/document/webhooks.ts +2 -2
- package/src/application/transform/footer/document-footer.ts +18 -1
- package/src/application/transform/footer/enum-name-claims.ts +62 -0
- package/src/application/transform/footer/operation-keys.ts +28 -0
- package/src/application/transform/footer/type-evaluation.ts +4 -4
- package/src/application/transform/helper-types.ts +6 -5
- package/src/application/transform/numbered-names.ts +15 -0
- package/src/application/transform/ref-pointer/generated-location.ts +2 -2
- package/src/application/transform/ref-pointer/pointer-type.ts +2 -4
- package/src/application/transform/ref-type.ts +2 -1
- package/src/application/transform/schema/access-flags.ts +2 -2
- package/src/application/transform/schema/array-type.ts +3 -5
- package/src/application/transform/schema/composition-type.ts +6 -6
- package/src/application/transform/schema/enum-rule.ts +10 -8
- package/src/application/transform/schema/object-type.ts +4 -4
- package/src/application/transform/schema/presence-members.ts +2 -2
- package/src/application/transform/schema/ref-siblings.ts +76 -0
- package/src/application/transform/schema/required-variants.ts +3 -3
- package/src/application/transform/schema/schema-context.ts +3 -0
- package/src/application/transform/schema/schema-transform.ts +4 -2
- package/src/application/transform/schema/unevaluated-properties.ts +2 -2
- package/src/application/transform/schema-comment.ts +7 -3
- package/src/application/transform/transform-context.ts +5 -0
- package/src/cli/api-settings.ts +82 -7
- package/src/cli/api-writes.ts +117 -0
- package/src/cli/cli-dependencies.ts +21 -4
- package/src/cli/cli-errors.ts +20 -1
- package/src/cli/cli-output.ts +186 -7
- package/src/cli/main.ts +6 -3
- package/src/cli/redocly-apis.ts +153 -48
- package/src/cli/run-cli.ts +37 -8
- package/src/domain/append-all.ts +10 -0
- package/src/domain/cause-secrets.ts +52 -0
- package/src/domain/deprecations.ts +15 -0
- package/src/domain/errors.ts +22 -7
- package/src/domain/ir/identifier-text.ts +6 -5
- package/src/domain/ir/ir-shape.ts +299 -0
- package/src/domain/ir/newer-identifier-ranges.ts +183 -30
- package/src/domain/openapi/alias-expansion.ts +4 -1
- package/src/domain/openapi/discriminated-union.ts +6 -4
- package/src/domain/openapi/discriminator-conflicts.ts +21 -7
- package/src/domain/openapi/document-object.ts +2 -0
- package/src/domain/openapi/json-pointer.ts +96 -7
- package/src/domain/openapi/schema-dialect.ts +22 -0
- package/src/domain/openapi/unsupported-features.ts +2 -2
- package/src/domain/output-fixes.ts +37 -18
- package/src/domain/url-secrets.ts +72 -0
- package/src/domain/warnings.ts +0 -1
- package/src/index.ts +2 -6
- package/src/types/generator-options.ts +1 -1
- package/dist/cli/main.d.cts +0 -2
- package/dist/cli/main.d.mts +0 -2
- package/dist/cli/main.d.ts +0 -2
- package/dist/domain/url-credentials.cjs +0 -10
- package/dist/domain/url-credentials.cjs.map +0 -1
- package/dist/domain/url-credentials.mjs +0 -8
- package/dist/domain/url-credentials.mjs.map +0 -1
- package/src/domain/url-credentials.ts +0 -18
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import type { ClaimedFile } from "../../application/ports/file-system.js";
|
|
4
|
+
import { creationPath, type FileNumber, type PathQueries } from "./file-identity.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Claiming an output on Node's `fs` (ADR-043, decision 1): the file is opened for appending,
|
|
8
|
+
* which creates it when it is missing (also through a symbolic link) and never truncates it.
|
|
9
|
+
* The device and file number of the open file are its identity. A claim or a write that fails
|
|
10
|
+
* removes the directories it created.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The directories that do not exist yet on the way to `directory`, deepest first: the ones a
|
|
15
|
+
* recursive `fs.mkdirSync` creates. They are listed before it runs, in the form of `directory`
|
|
16
|
+
* itself: on Windows the path that `fs.mkdirSync` returns did not match that form, so comparing
|
|
17
|
+
* with it found no new directory and a failed run left them behind.
|
|
18
|
+
*/
|
|
19
|
+
export function missingDirectories(
|
|
20
|
+
directory: string,
|
|
21
|
+
exists: (candidate: string) => boolean,
|
|
22
|
+
): string[] {
|
|
23
|
+
const missing: string[] = [];
|
|
24
|
+
for (let current = directory; !exists(current); current = path.dirname(current)) {
|
|
25
|
+
missing.push(current);
|
|
26
|
+
if (path.dirname(current) === current) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return missing;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The identity of an open file: its device and file number, or its stored path on a file system
|
|
35
|
+
* that reports the file number 0 (FAT, some network shares), which proves nothing.
|
|
36
|
+
*/
|
|
37
|
+
export function claimIdentity(number: FileNumber, storedPath: () => string): string {
|
|
38
|
+
return number.file === 0n ? `path:${storedPath()}` : `${number.device}:${number.file}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function identityOf(descriptor: number, filePath: string): string {
|
|
42
|
+
const status = fs.fstatSync(descriptor, { bigint: true });
|
|
43
|
+
return claimIdentity({ device: status.dev, file: status.ino }, () =>
|
|
44
|
+
fs.realpathSync.native(filePath),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function errorCodeOf(error: unknown): unknown {
|
|
49
|
+
return error instanceof Error && "code" in error ? error.code : undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Remove the new directories, deepest first, until one holds another file. */
|
|
53
|
+
function removeDirectories(directories: readonly string[]): void {
|
|
54
|
+
for (const directory of directories) {
|
|
55
|
+
try {
|
|
56
|
+
fs.rmdirSync(directory);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
const code = errorCodeOf(error);
|
|
59
|
+
// Another output or the user put a file there since: the directory and its parents stay.
|
|
60
|
+
if (code === "ENOTEMPTY" || code === "EEXIST") {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// Removed since: nothing to remove, but its parents may still be empty. Windows also gives
|
|
64
|
+
// ENOENT for a file put in its place, which must fail like any other path it cannot remove.
|
|
65
|
+
if (code !== "ENOENT" || fs.lstatSync(directory, { throwIfNoEntry: false }) !== undefined) {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Create `directory` and give the directories that this created. Through a link to a missing
|
|
74
|
+
* directory it creates the link's target, as a write through the link would, so the path to
|
|
75
|
+
* create and the new directories are real paths, where links are already followed. A recursive
|
|
76
|
+
* `mkdir` that fails part of the way (a directory name too long for the file system) keeps the
|
|
77
|
+
* directories above the failing one, so the ones that exist now are removed here.
|
|
78
|
+
*/
|
|
79
|
+
function createDirectory(directory: string, queries: PathQueries): string[] {
|
|
80
|
+
const target = creationPath(directory, queries);
|
|
81
|
+
const missing = missingDirectories(target, fs.existsSync);
|
|
82
|
+
try {
|
|
83
|
+
fs.mkdirSync(target, { recursive: true });
|
|
84
|
+
} catch (error) {
|
|
85
|
+
removeDirectories(missing.filter((created) => fs.existsSync(created)));
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
return missing;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Open `filePath` for appending, which creates it, and give its identity and whether it is new. */
|
|
92
|
+
function openClaim(filePath: string): { identity: string; createdFile: string | undefined } {
|
|
93
|
+
const isCreated = !fs.existsSync(filePath);
|
|
94
|
+
const descriptor = fs.openSync(filePath, "a");
|
|
95
|
+
try {
|
|
96
|
+
const identity = identityOf(descriptor, filePath);
|
|
97
|
+
// A link to a missing file created its target: that file is what the claim removes.
|
|
98
|
+
return { identity, createdFile: isCreated ? fs.realpathSync.native(filePath) : undefined };
|
|
99
|
+
} finally {
|
|
100
|
+
fs.closeSync(descriptor);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Claim the file at `filePath`; the caller turns a failure into a typed error. A claim that fails
|
|
106
|
+
* after creating directories (a file name too long for the file system) removes them again.
|
|
107
|
+
*/
|
|
108
|
+
export function claimFileAt(filePath: string, queries: PathQueries): ClaimedFile {
|
|
109
|
+
const directories = createDirectory(path.dirname(filePath), queries);
|
|
110
|
+
let opened: ReturnType<typeof openClaim>;
|
|
111
|
+
try {
|
|
112
|
+
opened = openClaim(filePath);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
removeDirectories(directories);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
const { identity, createdFile } = opened;
|
|
118
|
+
return {
|
|
119
|
+
identity,
|
|
120
|
+
release: () => {
|
|
121
|
+
if (createdFile !== undefined) {
|
|
122
|
+
fs.rmSync(createdFile, { force: true });
|
|
123
|
+
}
|
|
124
|
+
removeDirectories(directories);
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Write `contents` to `filePath`, creating its directory; a failed write removes what it made. */
|
|
130
|
+
export function writeFileAt(filePath: string, contents: string, queries: PathQueries): void {
|
|
131
|
+
const directories = createDirectory(path.dirname(filePath), queries);
|
|
132
|
+
try {
|
|
133
|
+
fs.writeFileSync(filePath, contents, "utf8");
|
|
134
|
+
} catch (error) {
|
|
135
|
+
removeDirectories(directories);
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The identity of a file path, also of one that does not exist yet (an output before the first
|
|
5
|
+
* run). Two paths are one file when their keys are equal: the real path of the nearest existing
|
|
6
|
+
* ancestor (links resolved, letter case as stored on disk) followed by the segments that do not
|
|
7
|
+
* exist yet, compared in the letter case rules of the file system that will hold them. Equal keys
|
|
8
|
+
* prove one file; different keys do not prove two (Unicode normalization, full case folding):
|
|
9
|
+
* the CLI claims every output before writing to decide those (ADR-043, decision 1).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** A device and a file number: one file, also through a hard link. */
|
|
13
|
+
export interface FileNumber {
|
|
14
|
+
readonly device: bigint;
|
|
15
|
+
readonly file: bigint;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** The file-system queries the identity needs; Node's `fs` in production, a fake in tests. */
|
|
19
|
+
export interface PathQueries {
|
|
20
|
+
/** The file number of a path, following links; undefined when it cannot be read. */
|
|
21
|
+
status(filePath: string): FileNumber | undefined;
|
|
22
|
+
/** The path with every link resolved, in the letter case stored on disk. */
|
|
23
|
+
realPath(filePath: string): string;
|
|
24
|
+
/** The names in a directory; empty when it cannot be listed. */
|
|
25
|
+
entries(directory: string): readonly string[];
|
|
26
|
+
/** The target of a symbolic link as written in it; undefined for a path that is no link. */
|
|
27
|
+
linkTarget(filePath: string): string | undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The most links followed for one path. Linux follows at most 40 (MAXSYMLINKS) and macOS 32
|
|
32
|
+
* before it fails with ELOOP; a longer chain is a loop, and the path is taken as missing.
|
|
33
|
+
*/
|
|
34
|
+
const MAX_LINK_HOPS = 40;
|
|
35
|
+
|
|
36
|
+
/** Whether two file numbers name one file. */
|
|
37
|
+
export function isSameFileNumber(left: FileNumber, right: FileNumber): boolean {
|
|
38
|
+
// Some file systems (FAT, some network shares) report no file number: 0 then proves nothing.
|
|
39
|
+
return left.file !== 0n && left.file === right.file && left.device === right.device;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function hasLetters(text: string): boolean {
|
|
43
|
+
return text.toLowerCase() !== text.toUpperCase();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function flipCase(text: string): string {
|
|
47
|
+
return [...text]
|
|
48
|
+
.map((character) => {
|
|
49
|
+
const upper = character.toUpperCase();
|
|
50
|
+
return character === upper ? character.toLowerCase() : upper;
|
|
51
|
+
})
|
|
52
|
+
.join("");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Whether a directory entry is also found under its name in the other letter case. */
|
|
56
|
+
function isFoundInOtherCase(entryPath: string, queries: PathQueries): boolean | undefined {
|
|
57
|
+
const status = queries.status(entryPath);
|
|
58
|
+
if (!status) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const flipped = path.join(path.dirname(entryPath), flipCase(path.basename(entryPath)));
|
|
62
|
+
const flippedStatus = queries.status(flipped);
|
|
63
|
+
return flippedStatus !== undefined && isSameFileNumber(status, flippedStatus);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Whether new names in `directory` ignore letter case. It is asked of the file system, not
|
|
68
|
+
* assumed from the OS: macOS and Windows volumes can be case-sensitive, and Linux mounts can
|
|
69
|
+
* ignore case. An entry of the directory is looked up in the other case; without one with
|
|
70
|
+
* letters, the directory itself is. With nothing to look up, names are taken as case-sensitive.
|
|
71
|
+
*/
|
|
72
|
+
function ignoresCase(directory: string, queries: PathQueries): boolean {
|
|
73
|
+
const candidates = [
|
|
74
|
+
...queries
|
|
75
|
+
.entries(directory)
|
|
76
|
+
.filter(hasLetters)
|
|
77
|
+
.map((name) => path.join(directory, name)),
|
|
78
|
+
...(hasLetters(path.basename(directory)) ? [directory] : []),
|
|
79
|
+
];
|
|
80
|
+
for (const candidate of candidates) {
|
|
81
|
+
const answer = isFoundInOtherCase(candidate, queries);
|
|
82
|
+
if (answer !== undefined) {
|
|
83
|
+
return answer;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The nearest ancestor of `filePath` that exists (or the path itself), and the rest below it. A
|
|
91
|
+
* link to a missing file or directory is followed to its target, which a write would create: so
|
|
92
|
+
* `link/x.ts` with `link -> missing` is `missing/x.ts`. A relative target is read from the real
|
|
93
|
+
* directory of the link, as the system does: with `a -> real/sub` and
|
|
94
|
+
* `real/sub/link -> ../missing`, `a/link` is `real/missing`, not `missing`.
|
|
95
|
+
*/
|
|
96
|
+
function nearestExisting(filePath: string, queries: PathQueries): [string, string[]] {
|
|
97
|
+
const missing: string[] = [];
|
|
98
|
+
let current = path.resolve(filePath);
|
|
99
|
+
let hops = 0;
|
|
100
|
+
while (queries.status(current) === undefined) {
|
|
101
|
+
const target = hops < MAX_LINK_HOPS ? queries.linkTarget(current) : undefined;
|
|
102
|
+
if (target !== undefined) {
|
|
103
|
+
current = path.resolve(queries.realPath(path.dirname(current)), target);
|
|
104
|
+
hops += 1;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const parent = path.dirname(current);
|
|
108
|
+
if (parent === current) {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
missing.unshift(path.basename(current));
|
|
112
|
+
current = parent;
|
|
113
|
+
}
|
|
114
|
+
return [current, missing];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The path that a write to `filePath` creates, with links followed also where their target is
|
|
119
|
+
* missing: `link/x.ts` with `link -> missing` is the real path of `missing/x.ts`. `mkdir` does not
|
|
120
|
+
* follow a link to a missing directory on Linux and Windows, so the directories are created here.
|
|
121
|
+
*/
|
|
122
|
+
export function creationPath(filePath: string, queries: PathQueries): string {
|
|
123
|
+
const [existing, missing] = nearestExisting(filePath, queries);
|
|
124
|
+
return path.join(queries.realPath(existing), ...missing);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** The key of a path: equal keys are one file, whether or not it exists yet. */
|
|
128
|
+
export function fileIdentityKey(filePath: string, queries: PathQueries): string {
|
|
129
|
+
const [existing, missing] = nearestExisting(filePath, queries);
|
|
130
|
+
const realExisting = queries.realPath(existing);
|
|
131
|
+
if (missing.length === 0) {
|
|
132
|
+
return realExisting;
|
|
133
|
+
}
|
|
134
|
+
const isCaseIgnored = ignoresCase(realExisting, queries);
|
|
135
|
+
const rest = isCaseIgnored ? missing.map((segment) => segment.toLowerCase()) : missing;
|
|
136
|
+
return path.join(realExisting, ...rest);
|
|
137
|
+
}
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import type {
|
|
4
|
-
|
|
3
|
+
import type {
|
|
4
|
+
ClaimedFile,
|
|
5
|
+
DirectoryCheck,
|
|
6
|
+
FileClaims,
|
|
7
|
+
FileIdentity,
|
|
8
|
+
FileReader,
|
|
9
|
+
FileWriter,
|
|
10
|
+
} from "../../application/ports/file-system.js";
|
|
11
|
+
import { ERROR_CODES, type ErrorCode, OpenAPITypesafeError } from "../../domain/errors.js";
|
|
12
|
+
import { claimFileAt, writeFileAt } from "./file-claims.js";
|
|
13
|
+
import {
|
|
14
|
+
type FileNumber,
|
|
15
|
+
fileIdentityKey,
|
|
16
|
+
isSameFileNumber,
|
|
17
|
+
type PathQueries,
|
|
18
|
+
} from "./file-identity.js";
|
|
5
19
|
|
|
6
20
|
/** The file ports on Node's `fs`, with the failures as typed errors (ADR-011). */
|
|
7
21
|
|
|
@@ -9,36 +23,149 @@ function causeMessage(cause: unknown): string {
|
|
|
9
23
|
return cause instanceof Error ? cause.message : String(cause);
|
|
10
24
|
}
|
|
11
25
|
|
|
12
|
-
|
|
26
|
+
/**
|
|
27
|
+
* The file number of a path, or undefined when it cannot be read. A missing output is the common
|
|
28
|
+
* case; any other failure (no access, a file used as a directory) is reported by the read or write
|
|
29
|
+
* that follows, so the identity check does not report it a second time.
|
|
30
|
+
*/
|
|
31
|
+
function statusOf(filePath: string): FileNumber | undefined {
|
|
32
|
+
try {
|
|
33
|
+
const status = fs.statSync(filePath, { bigint: true });
|
|
34
|
+
return { device: status.dev, file: status.ino };
|
|
35
|
+
} catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The native `realpath` resolves symbolic links and returns the letter case stored on disk, which
|
|
42
|
+
* the JavaScript one does not do on a case-insensitive file system. A path that vanished since its
|
|
43
|
+
* status was read keeps its own spelling.
|
|
44
|
+
*/
|
|
45
|
+
function realPathOf(filePath: string): string {
|
|
46
|
+
try {
|
|
47
|
+
return fs.realpathSync.native(filePath);
|
|
48
|
+
} catch {
|
|
49
|
+
return filePath;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** A directory that cannot be listed has no entry to tell its letter case rules by. */
|
|
54
|
+
function entriesOf(directory: string): readonly string[] {
|
|
55
|
+
try {
|
|
56
|
+
return fs.readdirSync(directory);
|
|
57
|
+
} catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The target of a symbolic link, as written in it; undefined for a path that is no link or cannot
|
|
64
|
+
* be read. The key then treats the path as missing, and the claim at write time decides.
|
|
65
|
+
*/
|
|
66
|
+
function linkTargetOf(filePath: string): string | undefined {
|
|
67
|
+
try {
|
|
68
|
+
return fs.readlinkSync(filePath);
|
|
69
|
+
} catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const NODE_PATH_QUERIES: PathQueries = {
|
|
75
|
+
status: statusOf,
|
|
76
|
+
realPath: realPathOf,
|
|
77
|
+
entries: entriesOf,
|
|
78
|
+
linkTarget: linkTargetOf,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** The path of a `file:` URL, or undefined for a URL that names no file on this platform. */
|
|
82
|
+
function localPathOf(file: URL): string | undefined {
|
|
83
|
+
try {
|
|
84
|
+
return fileURLToPath(file);
|
|
85
|
+
} catch {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* A failed read or write as a typed error. The location is named by its path, or by the URL when
|
|
92
|
+
* it names no local file: computing the path must not throw a second, untyped error here.
|
|
93
|
+
*/
|
|
94
|
+
function fileError(code: ErrorCode, verb: string, file: URL, cause: unknown): OpenAPITypesafeError {
|
|
95
|
+
const name = localPathOf(file) ?? file.href;
|
|
96
|
+
return new OpenAPITypesafeError({
|
|
97
|
+
code,
|
|
98
|
+
message: `Cannot ${verb} ${name}: ${causeMessage(cause)}`,
|
|
99
|
+
details: { file: name },
|
|
100
|
+
cause,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Run a step that writes `file`, with its failure as `OUTPUT_WRITE_FAILED`. */
|
|
105
|
+
function typedWrite<T>(file: URL, step: () => T): T {
|
|
106
|
+
try {
|
|
107
|
+
return step();
|
|
108
|
+
} catch (cause) {
|
|
109
|
+
throw fileError(ERROR_CODES.OUTPUT_WRITE_FAILED, "write", file, cause);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
class NodeFileSystem implements FileReader, FileWriter, FileIdentity, DirectoryCheck, FileClaims {
|
|
13
114
|
readText(file: URL): string {
|
|
14
115
|
try {
|
|
15
116
|
return fs.readFileSync(file, "utf8");
|
|
16
117
|
} catch (cause) {
|
|
17
|
-
throw
|
|
18
|
-
code: ERROR_CODES.OUTPUT_READ_FAILED,
|
|
19
|
-
message: `Cannot read ${fileURLToPath(file)}: ${causeMessage(cause)}`,
|
|
20
|
-
details: { file: fileURLToPath(file) },
|
|
21
|
-
cause,
|
|
22
|
-
});
|
|
118
|
+
throw fileError(ERROR_CODES.OUTPUT_READ_FAILED, "read", file, cause);
|
|
23
119
|
}
|
|
24
120
|
}
|
|
25
121
|
|
|
26
122
|
writeText(file: URL, contents: string): void {
|
|
27
123
|
try {
|
|
28
|
-
|
|
29
|
-
fs.writeFileSync(file, contents, "utf8");
|
|
124
|
+
writeFileAt(fileURLToPath(file), contents, NODE_PATH_QUERIES);
|
|
30
125
|
} catch (cause) {
|
|
31
|
-
throw
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
126
|
+
throw fileError(ERROR_CODES.OUTPUT_WRITE_FAILED, "write", file, cause);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
claimFile(file: URL): ClaimedFile {
|
|
131
|
+
const claim = typedWrite(file, () => claimFileAt(fileURLToPath(file), NODE_PATH_QUERIES));
|
|
132
|
+
return {
|
|
133
|
+
identity: claim.identity,
|
|
134
|
+
release: () => typedWrite(file, () => claim.release()),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
isDirectory(file: URL): boolean {
|
|
139
|
+
try {
|
|
140
|
+
return fs.statSync(file).isDirectory();
|
|
141
|
+
} catch {
|
|
142
|
+
// Missing or unreadable: not a directory; the write that follows reports a failure.
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
isSameFile(left: URL, right: URL): boolean {
|
|
148
|
+
const leftPath = fileURLToPath(left);
|
|
149
|
+
const rightPath = fileURLToPath(right);
|
|
150
|
+
if (leftPath === rightPath) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
const leftStatus = statusOf(leftPath);
|
|
154
|
+
const rightStatus = statusOf(rightPath);
|
|
155
|
+
if (leftStatus && rightStatus && isSameFileNumber(leftStatus, rightStatus)) {
|
|
156
|
+
return true;
|
|
37
157
|
}
|
|
158
|
+
return (
|
|
159
|
+
fileIdentityKey(leftPath, NODE_PATH_QUERIES) === fileIdentityKey(rightPath, NODE_PATH_QUERIES)
|
|
160
|
+
);
|
|
38
161
|
}
|
|
39
162
|
}
|
|
40
163
|
|
|
41
164
|
/** File access for the CLI. */
|
|
42
|
-
export function createNodeFileSystem(): FileReader &
|
|
165
|
+
export function createNodeFileSystem(): FileReader &
|
|
166
|
+
FileWriter &
|
|
167
|
+
FileIdentity &
|
|
168
|
+
DirectoryCheck &
|
|
169
|
+
FileClaims {
|
|
43
170
|
return new NodeFileSystem();
|
|
44
171
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { childPointer, ROOT_POINTER } from "../../domain/openapi/json-pointer.js";
|
|
2
|
+
import { findRefHolders } from "./ref-holders.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Redocly 1.x bundles every discriminator `mapping` value as if it were an external `$ref`: it
|
|
6
|
+
* stores the target schema under the raw last segment of the pointer. For a local schema whose
|
|
7
|
+
* key needs an escape (`a~b`, written `a~0b`; `c/d`, written `c~1d`) that segment is no existing
|
|
8
|
+
* key, so the bundle added `a~0b` and `c~1d` to `components.schemas` as copies of `a~b` and
|
|
9
|
+
* `c/d`, and the generator wrote each type twice. A copy is the very object of the schema it
|
|
10
|
+
* copies, so a key the bundle added whose value is the value of a key the document had is removed,
|
|
11
|
+
* and the mapping values and `$ref`s that name it point at the original.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
type Schemas = Record<string, unknown>;
|
|
15
|
+
|
|
16
|
+
const SCHEMAS_POINTER = childPointer(childPointer(ROOT_POINTER, "components"), "schemas");
|
|
17
|
+
|
|
18
|
+
function isContainer(value: unknown): value is Record<string, unknown> {
|
|
19
|
+
return typeof value === "object" && value !== null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function schemasOf(document: unknown): Schemas | undefined {
|
|
23
|
+
const components = isContainer(document) ? document.components : undefined;
|
|
24
|
+
const schemas = isContainer(components) ? components.schemas : undefined;
|
|
25
|
+
return isContainer(schemas) ? schemas : undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The keys of `components.schemas` before bundling: the bundle edits the document in place. */
|
|
29
|
+
export function schemaKeysOf(document: unknown): ReadonlySet<string> {
|
|
30
|
+
return new Set(Object.keys(schemasOf(document) ?? {}));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Each key the bundle added as a copy, with the pointer of the schema it copies. */
|
|
34
|
+
function copiesIn(schemas: Schemas, keysBefore: ReadonlySet<string>): Map<string, string> {
|
|
35
|
+
const originals = new Map<unknown, string>();
|
|
36
|
+
for (const key of keysBefore) {
|
|
37
|
+
if (Object.hasOwn(schemas, key) && !originals.has(schemas[key])) {
|
|
38
|
+
originals.set(schemas[key], key);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const copies = new Map<string, string>();
|
|
42
|
+
for (const [key, value] of Object.entries(schemas)) {
|
|
43
|
+
const original = keysBefore.has(key) ? undefined : originals.get(value);
|
|
44
|
+
if (original !== undefined) {
|
|
45
|
+
copies.set(`${SCHEMAS_POINTER}/${key}`, childPointer(SCHEMAS_POINTER, original));
|
|
46
|
+
delete schemas[key];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return copies;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Every `discriminator.mapping` object of the document; the walk has its own stack. */
|
|
53
|
+
function mappingsOf(document: unknown): Record<string, unknown>[] {
|
|
54
|
+
const mappings: Record<string, unknown>[] = [];
|
|
55
|
+
const visited = new WeakSet<object>();
|
|
56
|
+
const pending: unknown[] = [document];
|
|
57
|
+
for (let next = pending.pop(); next !== undefined; next = pending.pop()) {
|
|
58
|
+
if (!isContainer(next) || visited.has(next)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
visited.add(next);
|
|
62
|
+
const mapping = isContainer(next.discriminator) ? next.discriminator.mapping : undefined;
|
|
63
|
+
if (isContainer(mapping)) {
|
|
64
|
+
mappings.push(mapping);
|
|
65
|
+
}
|
|
66
|
+
// One push per child: spreading an array of millions of children overflows the stack.
|
|
67
|
+
for (const child of Object.values(next)) {
|
|
68
|
+
pending.push(child);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return mappings;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Remove the bundle's copies of the document's own schemas, in place. */
|
|
75
|
+
export function removeBundledMappingCopies(
|
|
76
|
+
bundled: unknown,
|
|
77
|
+
keysBefore: ReadonlySet<string>,
|
|
78
|
+
): void {
|
|
79
|
+
const schemas = schemasOf(bundled);
|
|
80
|
+
const copies = schemas === undefined ? new Map<string, string>() : copiesIn(schemas, keysBefore);
|
|
81
|
+
if (copies.size === 0) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
for (const mapping of mappingsOf(bundled)) {
|
|
85
|
+
for (const [name, value] of Object.entries(mapping)) {
|
|
86
|
+
const original = typeof value === "string" ? copies.get(value) : undefined;
|
|
87
|
+
if (original !== undefined) {
|
|
88
|
+
mapping[name] = original;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (const { node } of findRefHolders(bundled)) {
|
|
93
|
+
node.$ref = copies.get(node.$ref) ?? node.$ref;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { childPointer, parseRefPointer, ROOT_POINTER } from "../../domain/openapi/json-pointer.js";
|
|
2
2
|
import { findRefHolders } from "./ref-holders.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -48,7 +48,7 @@ function repairedRef(document: unknown, ref: string): string | null {
|
|
|
48
48
|
if (!resolves(document, raw)) {
|
|
49
49
|
return null;
|
|
50
50
|
}
|
|
51
|
-
return
|
|
51
|
+
return raw.reduce((pointer, key) => childPointer(pointer, key), ROOT_POINTER);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/** Repair the local `$ref`s of a bundled document in place, as Redocly's bundle edits it. */
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import type { BaseResolver, Document } from "@redocly/openapi-core";
|
|
4
|
+
import type { LoadedDocument } from "./unsupported-keys.js";
|
|
5
|
+
|
|
6
|
+
/** The documents one load read, from the Redocly resolver's cache. */
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The root document and every other document the resolver loaded, as far as they parsed. A root
|
|
10
|
+
* read from a file or URL is in the resolver cache too, and is listed once. A `$ref` that failed
|
|
11
|
+
* to load leaves a rejected entry in the cache, also when bundling did not need it (an example's
|
|
12
|
+
* `$ref`): that entry is no document, and must not fail the listing.
|
|
13
|
+
*/
|
|
14
|
+
export async function loadedDocuments(
|
|
15
|
+
root: Document,
|
|
16
|
+
resolver: BaseResolver,
|
|
17
|
+
): Promise<LoadedDocument[]> {
|
|
18
|
+
const settled = await Promise.allSettled(resolver.cache.values());
|
|
19
|
+
const cached = settled.flatMap((entry) => (entry.status === "fulfilled" ? [entry.value] : []));
|
|
20
|
+
const bySource = new Map<string, unknown>([[root.source.absoluteRef, root.parsed]]);
|
|
21
|
+
for (const document of cached) {
|
|
22
|
+
if ("parsed" in document && !bySource.has(document.source.absoluteRef)) {
|
|
23
|
+
bySource.set(document.source.absoluteRef, document.parsed);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return [...bySource].map(([source, parsed]) => ({ source, parsed }));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The local files the load read: the root, when it is a file, and every `$ref`'d file. Redocly
|
|
31
|
+
* names a local document by its absolute path and a remote one by its URL. An inline root (a
|
|
32
|
+
* string, object, buffer or stream) has a made-up path in the working directory, so it is left
|
|
33
|
+
* out unless it was read from a file.
|
|
34
|
+
*/
|
|
35
|
+
export async function localFilesRead(
|
|
36
|
+
root: Document,
|
|
37
|
+
resolver: BaseResolver,
|
|
38
|
+
isRootAFile: boolean,
|
|
39
|
+
): Promise<URL[]> {
|
|
40
|
+
const documents = await loadedDocuments(root, resolver);
|
|
41
|
+
return documents
|
|
42
|
+
.map(({ source }) => source)
|
|
43
|
+
.filter((source) => path.isAbsolute(source))
|
|
44
|
+
.filter((source) => isRootAFile || source !== root.source.absoluteRef)
|
|
45
|
+
.map((source) => pathToFileURL(source));
|
|
46
|
+
}
|