openapi-typesafe 1.0.0-rc.3 → 1.0.0-rc.5
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 +1972 -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 +97 -14
- package/dist/adapters/node-file-system/node-file-system.cjs.map +1 -1
- package/dist/adapters/node-file-system/node-file-system.mjs +97 -14
- package/dist/adapters/node-file-system/node-file-system.mjs.map +1 -1
- package/dist/adapters/pipe-safe-writer/pipe-safe-writer.cjs +19 -0
- package/dist/adapters/pipe-safe-writer/pipe-safe-writer.cjs.map +1 -0
- package/dist/adapters/pipe-safe-writer/pipe-safe-writer.mjs +17 -0
- package/dist/adapters/pipe-safe-writer/pipe-safe-writer.mjs.map +1 -0
- package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs +48 -0
- package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs.map +1 -0
- package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs +45 -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/component-schemas.cjs +17 -0
- package/dist/adapters/redocly-loader/component-schemas.cjs.map +1 -0
- package/dist/adapters/redocly-loader/component-schemas.mjs +14 -0
- package/dist/adapters/redocly-loader/component-schemas.mjs.map +1 -0
- 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/mapping-schema-names.cjs +22 -0
- package/dist/adapters/redocly-loader/mapping-schema-names.cjs.map +1 -0
- package/dist/adapters/redocly-loader/mapping-schema-names.mjs +20 -0
- package/dist/adapters/redocly-loader/mapping-schema-names.mjs.map +1 -0
- package/dist/adapters/redocly-loader/query-named-components.cjs +137 -0
- package/dist/adapters/redocly-loader/query-named-components.cjs.map +1 -0
- package/dist/adapters/redocly-loader/query-named-components.mjs +134 -0
- package/dist/adapters/redocly-loader/query-named-components.mjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +40 -29
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +38 -27
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.cjs +45 -4
- package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.mjs +45 -4
- package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-holders.cjs +52 -10
- package/dist/adapters/redocly-loader/ref-holders.cjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-holders.mjs +53 -12
- 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 +40 -9
- package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-fetch.mjs +40 -9
- package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-node-limit.cjs +61 -0
- package/dist/adapters/redocly-loader/remote-node-limit.cjs.map +1 -0
- package/dist/adapters/redocly-loader/remote-node-limit.mjs +58 -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 +18 -9
- package/dist/adapters/redocly-loader/schema-source.cjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-source.mjs +20 -11
- 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 +10 -4
- package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.mjs +10 -4
- package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
- package/dist/api/default-ports.cjs +14 -2
- package/dist/api/default-ports.cjs.map +1 -1
- package/dist/api/default-ports.mjs +14 -2
- package/dist/api/default-ports.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 +5 -1
- package/dist/api/discriminator-patch.cjs.map +1 -1
- package/dist/api/discriminator-patch.mjs +5 -1
- package/dist/api/discriminator-patch.mjs.map +1 -1
- package/dist/api/discriminator-scan.cjs +15 -8
- package/dist/api/discriminator-scan.cjs.map +1 -1
- package/dist/api/discriminator-scan.mjs +15 -8
- package/dist/api/discriminator-scan.mjs.map +1 -1
- package/dist/api/document-refs.cjs +16 -1
- package/dist/api/document-refs.cjs.map +1 -1
- package/dist/api/document-refs.mjs +16 -1
- package/dist/api/document-refs.mjs.map +1 -1
- package/dist/api/document-run.cjs +6 -12
- package/dist/api/document-run.cjs.map +1 -1
- package/dist/api/document-run.mjs +6 -12
- package/dist/api/document-run.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 -6
- package/dist/api/openapi-ts.cjs.map +1 -1
- package/dist/api/openapi-ts.mjs +10 -8
- package/dist/api/openapi-ts.mjs.map +1 -1
- package/dist/api/ref-limit-options.cjs +63 -0
- package/dist/api/ref-limit-options.cjs.map +1 -0
- package/dist/api/ref-limit-options.mjs +57 -0
- package/dist/api/ref-limit-options.mjs.map +1 -0
- 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/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 +47 -10
- package/dist/api/transform-schema.cjs.map +1 -1
- package/dist/api/transform-schema.mjs +48 -11
- 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/declared-value-types.cjs +36 -0
- package/dist/application/transform/declared-value-types.cjs.map +1 -0
- package/dist/application/transform/declared-value-types.mjs +34 -0
- package/dist/application/transform/declared-value-types.mjs.map +1 -0
- package/dist/application/transform/document/components.cjs +1 -1
- package/dist/application/transform/document/components.cjs.map +1 -1
- package/dist/application/transform/document/components.mjs +2 -2
- package/dist/application/transform/document/components.mjs.map +1 -1
- package/dist/application/transform/document/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 +7 -2
- package/dist/application/transform/document/document.cjs.map +1 -1
- package/dist/application/transform/document/document.mjs +6 -3
- 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/exploded-query-values.cjs +63 -0
- package/dist/application/transform/document/exploded-query-values.cjs.map +1 -0
- package/dist/application/transform/document/exploded-query-values.mjs +59 -0
- package/dist/application/transform/document/exploded-query-values.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/header.cjs +11 -3
- package/dist/application/transform/document/header.cjs.map +1 -1
- package/dist/application/transform/document/header.mjs +10 -2
- package/dist/application/transform/document/header.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 +29 -34
- package/dist/application/transform/document/parameters.cjs.map +1 -1
- package/dist/application/transform/document/parameters.mjs +29 -34
- package/dist/application/transform/document/parameters.mjs.map +1 -1
- package/dist/application/transform/document/path-item.cjs +15 -17
- package/dist/application/transform/document/path-item.cjs.map +1 -1
- package/dist/application/transform/document/path-item.mjs +15 -19
- package/dist/application/transform/document/path-item.mjs.map +1 -1
- package/dist/application/transform/document/path-template-key.cjs +84 -0
- package/dist/application/transform/document/path-template-key.cjs.map +1 -0
- package/dist/application/transform/document/path-template-key.mjs +79 -0
- package/dist/application/transform/document/path-template-key.mjs.map +1 -0
- package/dist/application/transform/document/path-template-refs.cjs +70 -0
- package/dist/application/transform/document/path-template-refs.cjs.map +1 -0
- package/dist/application/transform/document/path-template-refs.mjs +67 -0
- package/dist/application/transform/document/path-template-refs.mjs.map +1 -0
- package/dist/application/transform/document/paths-enum.cjs +8 -6
- package/dist/application/transform/document/paths-enum.cjs.map +1 -1
- package/dist/application/transform/document/paths-enum.mjs +8 -7
- package/dist/application/transform/document/paths-enum.mjs.map +1 -1
- package/dist/application/transform/document/paths.cjs +43 -67
- package/dist/application/transform/document/paths.cjs.map +1 -1
- package/dist/application/transform/document/paths.mjs +42 -68
- 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 +10 -3
- package/dist/application/transform/document/webhooks.cjs.map +1 -1
- package/dist/application/transform/document/webhooks.mjs +10 -3
- package/dist/application/transform/document/webhooks.mjs.map +1 -1
- package/dist/application/transform/footer/document-footer.cjs +16 -5
- package/dist/application/transform/footer/document-footer.cjs.map +1 -1
- package/dist/application/transform/footer/document-footer.mjs +16 -5
- 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 +3 -3
- package/dist/application/transform/helper-types.cjs.map +1 -1
- package/dist/application/transform/helper-types.mjs +3 -3
- 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 +5 -5
- package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/generated-location.mjs +3 -3
- package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/generated-shape.cjs +47 -66
- package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/generated-shape.mjs +36 -50
- package/dist/application/transform/ref-pointer/generated-shape.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/inline-cycles.cjs +2 -2
- package/dist/application/transform/ref-pointer/inline-cycles.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/inline-cycles.mjs +1 -1
- package/dist/application/transform/ref-pointer/inline-cycles.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/located-node.cjs +23 -0
- package/dist/application/transform/ref-pointer/located-node.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/located-node.mjs +18 -0
- package/dist/application/transform/ref-pointer/located-node.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/original-index.cjs +68 -13
- package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/original-index.mjs +70 -15
- package/dist/application/transform/ref-pointer/original-index.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/pointer-type.cjs +2 -2
- package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/pointer-type.mjs +1 -1
- package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/pointer-walk.cjs +54 -13
- package/dist/application/transform/ref-pointer/pointer-walk.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/pointer-walk.mjs +46 -7
- package/dist/application/transform/ref-pointer/pointer-walk.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/property-shape.cjs +52 -0
- package/dist/application/transform/ref-pointer/property-shape.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/property-shape.mjs +45 -0
- package/dist/application/transform/ref-pointer/property-shape.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/typed-walk.cjs +79 -21
- package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/typed-walk.mjs +76 -18
- package/dist/application/transform/ref-pointer/typed-walk.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.map +1 -1
- package/dist/application/transform/schema/access-flags.mjs.map +1 -1
- package/dist/application/transform/schema/composition-type.cjs +1 -1
- package/dist/application/transform/schema/composition-type.cjs.map +1 -1
- package/dist/application/transform/schema/composition-type.mjs +2 -2
- package/dist/application/transform/schema/composition-type.mjs.map +1 -1
- package/dist/application/transform/schema/enum-rule.cjs +1 -1
- package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
- package/dist/application/transform/schema/enum-rule.mjs +2 -2
- package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
- package/dist/application/transform/schema/index-signature-type.cjs +21 -0
- package/dist/application/transform/schema/index-signature-type.cjs.map +1 -0
- package/dist/application/transform/schema/index-signature-type.mjs +19 -0
- package/dist/application/transform/schema/index-signature-type.mjs.map +1 -0
- package/dist/application/transform/schema/input-location.cjs +23 -0
- package/dist/application/transform/schema/input-location.cjs.map +1 -0
- package/dist/application/transform/schema/input-location.mjs +21 -0
- package/dist/application/transform/schema/input-location.mjs.map +1 -0
- package/dist/application/transform/schema/object-type.cjs +18 -8
- package/dist/application/transform/schema/object-type.cjs.map +1 -1
- package/dist/application/transform/schema/object-type.mjs +19 -9
- package/dist/application/transform/schema/object-type.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/schema-transform.cjs +6 -3
- package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
- package/dist/application/transform/schema/schema-transform.mjs +6 -3
- package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
- package/dist/application/transform/schema/unevaluated-properties.cjs +2 -30
- package/dist/application/transform/schema/unevaluated-properties.cjs.map +1 -1
- package/dist/application/transform/schema/unevaluated-properties.mjs +3 -31
- package/dist/application/transform/schema/unevaluated-properties.mjs.map +1 -1
- package/dist/application/transform/schema-comment.cjs +5 -1
- package/dist/application/transform/schema-comment.cjs.map +1 -1
- package/dist/application/transform/schema-comment.mjs +5 -1
- package/dist/application/transform/schema-comment.mjs.map +1 -1
- package/dist/cli/api-logger.cjs +13 -0
- package/dist/cli/api-logger.cjs.map +1 -0
- package/dist/cli/api-logger.mjs +11 -0
- package/dist/cli/api-logger.mjs.map +1 -0
- package/dist/cli/api-settings.cjs +57 -9
- package/dist/cli/api-settings.cjs.map +1 -1
- package/dist/cli/api-settings.mjs +56 -11
- 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-arguments.cjs +51 -11
- package/dist/cli/cli-arguments.cjs.map +1 -1
- package/dist/cli/cli-arguments.mjs +51 -11
- package/dist/cli/cli-arguments.mjs.map +1 -1
- package/dist/cli/cli-errors.cjs +29 -1
- package/dist/cli/cli-errors.cjs.map +1 -1
- package/dist/cli/cli-errors.mjs +29 -2
- package/dist/cli/cli-errors.mjs.map +1 -1
- package/dist/cli/cli-output.cjs +111 -4
- package/dist/cli/cli-output.cjs.map +1 -1
- package/dist/cli/cli-output.mjs +104 -5
- package/dist/cli/cli-output.mjs.map +1 -1
- package/dist/cli/main.cjs +13 -3
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.mjs +14 -4
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/redocly-apis.cjs +94 -37
- package/dist/cli/redocly-apis.cjs.map +1 -1
- package/dist/cli/redocly-apis.mjs +99 -42
- package/dist/cli/redocly-apis.mjs.map +1 -1
- package/dist/cli/ref-limits.cjs +15 -1
- package/dist/cli/ref-limits.cjs.map +1 -1
- package/dist/cli/ref-limits.mjs +15 -2
- package/dist/cli/ref-limits.mjs.map +1 -1
- package/dist/cli/run-cli.cjs +37 -14
- package/dist/cli/run-cli.cjs.map +1 -1
- package/dist/cli/run-cli.mjs +39 -16
- 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 +52 -0
- package/dist/domain/cause-secrets.cjs.map +1 -0
- package/dist/domain/cause-secrets.mjs +50 -0
- package/dist/domain/cause-secrets.mjs.map +1 -0
- package/dist/domain/errors.cjs +11 -3
- package/dist/domain/errors.cjs.map +1 -1
- package/dist/domain/errors.mjs +11 -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/location-text.cjs +9 -0
- package/dist/domain/location-text.cjs.map +1 -0
- package/dist/domain/location-text.mjs +7 -0
- package/dist/domain/location-text.mjs.map +1 -0
- 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/document-places.cjs +55 -0
- package/dist/domain/openapi/document-places.cjs.map +1 -0
- package/dist/domain/openapi/document-places.mjs +53 -0
- package/dist/domain/openapi/document-places.mjs.map +1 -0
- 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 +20 -0
- package/dist/domain/output-fixes.cjs.map +1 -1
- package/dist/domain/output-fixes.mjs +20 -0
- package/dist/domain/output-fixes.mjs.map +1 -1
- package/dist/domain/terminal-text.cjs +31 -0
- package/dist/domain/terminal-text.cjs.map +1 -0
- package/dist/domain/terminal-text.mjs +29 -0
- package/dist/domain/terminal-text.mjs.map +1 -0
- 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 +1 -0
- package/dist/domain/warnings.cjs.map +1 -1
- package/dist/domain/warnings.mjs +1 -0
- package/dist/domain/warnings.mjs.map +1 -1
- package/dist/index.d.cts +46 -20
- package/dist/index.d.mts +46 -20
- package/dist/index.d.ts +46 -20
- package/package.json +4 -5
- 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 +158 -18
- package/src/adapters/pipe-safe-writer/pipe-safe-writer.ts +29 -0
- package/src/adapters/redocly-loader/bundled-mapping-copies.ts +60 -0
- package/src/adapters/redocly-loader/bundled-ref-repair.ts +2 -2
- package/src/adapters/redocly-loader/component-schemas.ts +19 -0
- package/src/adapters/redocly-loader/loaded-documents.ts +46 -0
- package/src/adapters/redocly-loader/mapping-schema-names.ts +25 -0
- package/src/adapters/redocly-loader/query-named-components.ts +201 -0
- package/src/adapters/redocly-loader/redocly-schema-loader.ts +64 -38
- package/src/adapters/redocly-loader/ref-access.ts +51 -4
- package/src/adapters/redocly-loader/ref-holders.ts +76 -15
- package/src/adapters/redocly-loader/remote-body-limit.ts +66 -0
- package/src/adapters/redocly-loader/remote-fetch.ts +85 -13
- package/src/adapters/redocly-loader/remote-node-limit.ts +102 -0
- package/src/adapters/redocly-loader/schema-load-errors.ts +52 -13
- package/src/adapters/redocly-loader/schema-source.ts +35 -11
- package/src/adapters/redocly-loader/unsupported-keys.ts +3 -7
- package/src/adapters/terminal-logger/terminal-logger.ts +17 -6
- package/src/api/default-ports.ts +33 -4
- package/src/api/discriminator-enum-parent.ts +3 -3
- package/src/api/discriminator-other-owners.ts +5 -3
- package/src/api/discriminator-patch.ts +5 -1
- package/src/api/discriminator-scan.ts +16 -8
- package/src/api/document-refs.ts +29 -1
- package/src/api/document-run.ts +10 -19
- package/src/api/legacy-utils.ts +5 -1
- package/src/api/openapi-ts.ts +26 -8
- package/src/api/ref-limit-options.ts +76 -0
- package/src/api/run-context.ts +3 -0
- package/src/api/schema-callbacks.ts +60 -17
- package/src/api/transform-context.ts +7 -3
- package/src/api/transform-schema.ts +79 -12
- package/src/application/ports/file-system.ts +47 -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/declared-value-types.ts +42 -0
- package/src/application/transform/document/components.ts +2 -2
- 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 +8 -5
- package/src/application/transform/document/enum-names-given-back.ts +91 -0
- package/src/application/transform/document/exploded-query-values.ts +88 -0
- package/src/application/transform/document/global-type-references.ts +1 -1
- package/src/application/transform/document/header.ts +25 -5
- 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 +56 -66
- package/src/application/transform/document/path-item.ts +16 -34
- package/src/application/transform/document/path-template-key.ts +152 -0
- package/src/application/transform/document/path-template-refs.ts +106 -0
- package/src/application/transform/document/paths-enum.ts +24 -10
- package/src/application/transform/document/paths.ts +59 -125
- 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 +19 -6
- package/src/application/transform/footer/document-footer.ts +36 -9
- 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 +8 -7
- package/src/application/transform/numbered-names.ts +15 -0
- package/src/application/transform/ref-pointer/generated-location.ts +3 -3
- package/src/application/transform/ref-pointer/generated-shape.ts +67 -78
- package/src/application/transform/ref-pointer/inline-cycles.ts +1 -1
- package/src/application/transform/ref-pointer/located-node.ts +38 -0
- package/src/application/transform/ref-pointer/original-index.ts +100 -17
- package/src/application/transform/ref-pointer/pointer-type.ts +1 -1
- package/src/application/transform/ref-pointer/pointer-walk.ts +82 -8
- package/src/application/transform/ref-pointer/property-shape.ts +97 -0
- package/src/application/transform/ref-pointer/typed-walk.ts +117 -25
- package/src/application/transform/ref-type.ts +2 -1
- package/src/application/transform/schema/access-flags.ts +5 -2
- package/src/application/transform/schema/composition-type.ts +2 -2
- package/src/application/transform/schema/enum-rule.ts +6 -2
- package/src/application/transform/schema/index-signature-type.ts +31 -0
- package/src/application/transform/schema/input-location.ts +35 -0
- package/src/application/transform/schema/object-type.ts +22 -12
- package/src/application/transform/schema/ref-siblings.ts +76 -0
- package/src/application/transform/schema/schema-context.ts +3 -0
- package/src/application/transform/schema/schema-transform.ts +6 -3
- package/src/application/transform/schema/unevaluated-properties.ts +4 -44
- package/src/application/transform/schema-comment.ts +5 -1
- package/src/application/transform/transform-context.ts +5 -0
- package/src/cli/api-logger.ts +17 -0
- package/src/cli/api-settings.ts +80 -13
- package/src/cli/api-writes.ts +117 -0
- package/src/cli/cli-arguments.ts +90 -14
- package/src/cli/cli-dependencies.ts +26 -4
- package/src/cli/cli-errors.ts +42 -1
- package/src/cli/cli-output.ts +195 -15
- package/src/cli/main.ts +14 -5
- package/src/cli/redocly-apis.ts +177 -52
- package/src/cli/ref-limits.ts +21 -2
- package/src/cli/run-cli.ts +76 -15
- package/src/domain/append-all.ts +10 -0
- package/src/domain/cause-secrets.ts +86 -0
- package/src/domain/errors.ts +16 -5
- 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/location-text.ts +12 -0
- 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/document-places.ts +78 -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 +28 -2
- package/src/domain/terminal-text.ts +44 -0
- package/src/domain/url-secrets.ts +72 -0
- package/src/domain/warnings.ts +1 -0
- 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,201 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendPointer,
|
|
3
|
+
canonicalRef,
|
|
4
|
+
parseRefPointer,
|
|
5
|
+
ROOT_POINTER,
|
|
6
|
+
} from "../../domain/openapi/json-pointer.js";
|
|
7
|
+
import { findMappings, findRefHolders } from "./ref-holders.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Redocly 1.x bundles an external `$ref` into a component named after the last segment of the
|
|
11
|
+
* document's URL, without its extension, when the pointer gives no free name (a `$ref` to a whole
|
|
12
|
+
* document, or two targets with the same pointer). The query stays in that name, and a query holds
|
|
13
|
+
* API keys and signatures, so `https://host/schemas/pet?token=…` became the component
|
|
14
|
+
* `pet?token=…` in the generated file and in messages (threat model T4b). This renames such a
|
|
15
|
+
* component after the URL without its query: `pet`, with a `-2` suffix when that name is taken.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
type Components = Record<string, Record<string, unknown>>;
|
|
19
|
+
|
|
20
|
+
/** The keys of each `components` group before bundling: the bundle edits the document in place. */
|
|
21
|
+
export type ComponentKeys = ReadonlyMap<string, ReadonlySet<string>>;
|
|
22
|
+
|
|
23
|
+
/** Old and new name of each renamed component, per `components` group. */
|
|
24
|
+
type Renames = Map<string, Map<string, string>>;
|
|
25
|
+
|
|
26
|
+
const COMPONENTS_KEY = "components";
|
|
27
|
+
const REMOTE_URL_RE = /^https?:\/\//;
|
|
28
|
+
const PATH_SEPARATOR_RE = /[/\\]/;
|
|
29
|
+
const EXTENSION_RE = /\.[^.]+$/;
|
|
30
|
+
/** What Redocly puts between the base name and the rest of a component name. */
|
|
31
|
+
const NAME_SUFFIX_STARTS = ["_", "-"];
|
|
32
|
+
const FIRST_SERIAL = 2;
|
|
33
|
+
|
|
34
|
+
function isContainer(value: unknown): value is Record<string, unknown> {
|
|
35
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function componentsOf(document: unknown): Components {
|
|
39
|
+
const components = isContainer(document) ? document[COMPONENTS_KEY] : undefined;
|
|
40
|
+
if (!isContainer(components)) {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
const groups: Components = {};
|
|
44
|
+
for (const [group, entries] of Object.entries(components)) {
|
|
45
|
+
if (isContainer(entries)) {
|
|
46
|
+
groups[group] = entries;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return groups;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The keys of every `components` group of a document. */
|
|
53
|
+
export function componentKeysOf(document: unknown): ComponentKeys {
|
|
54
|
+
const keys = new Map<string, ReadonlySet<string>>();
|
|
55
|
+
for (const [group, entries] of Object.entries(componentsOf(document))) {
|
|
56
|
+
keys.set(group, new Set(Object.keys(entries)));
|
|
57
|
+
}
|
|
58
|
+
return keys;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The base name Redocly 1.34 gives a document (`refBaseName`): the last segment, no extension. */
|
|
62
|
+
function redoclyBaseName(ref: string): string {
|
|
63
|
+
return (ref.split(PATH_SEPARATOR_RE).at(-1) ?? "").replace(EXTENSION_RE, "");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The base name of the URL without its query and fragment. A URL with no last segment
|
|
68
|
+
* (`https://host/?key=…`) is named after its host, so the name is never empty.
|
|
69
|
+
*/
|
|
70
|
+
function queryFreeBaseName(url: URL): string {
|
|
71
|
+
const withoutQuery = new URL(url.pathname, url.origin).href;
|
|
72
|
+
return redoclyBaseName(withoutQuery) || url.hostname;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Each base name Redocly takes from a remote URL with a query, with the name to use instead. */
|
|
76
|
+
function queryBaseNames(documentRefs: Iterable<string>): Map<string, string> {
|
|
77
|
+
const names = new Map<string, string>();
|
|
78
|
+
for (const ref of documentRefs) {
|
|
79
|
+
const url = REMOTE_URL_RE.test(ref) && URL.canParse(ref) ? new URL(ref) : undefined;
|
|
80
|
+
if (url === undefined || url.search === "") {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const named = redoclyBaseName(ref);
|
|
84
|
+
const clean = queryFreeBaseName(url);
|
|
85
|
+
if (named !== clean) {
|
|
86
|
+
names.set(named, clean);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return names;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** The name `key` gets, or undefined when no query base name starts it. */
|
|
93
|
+
function queryFreeName(key: string, baseNames: ReadonlyMap<string, string>): string | undefined {
|
|
94
|
+
// The longest base name first: `pet?a=1` must not match as `pet?a` when both were loaded.
|
|
95
|
+
const matches = [...baseNames.keys()].filter(
|
|
96
|
+
(named) =>
|
|
97
|
+
key === named || NAME_SUFFIX_STARTS.some((start) => key.startsWith(`${named}${start}`)),
|
|
98
|
+
);
|
|
99
|
+
const named = matches.sort((a, b) => b.length - a.length)[0];
|
|
100
|
+
return named === undefined ? undefined : `${baseNames.get(named)}${key.slice(named.length)}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function freeName(name: string, taken: ReadonlySet<string>): string {
|
|
104
|
+
let free = name;
|
|
105
|
+
for (let serial = FIRST_SERIAL; taken.has(free); serial += 1) {
|
|
106
|
+
free = `${name}-${serial}`;
|
|
107
|
+
}
|
|
108
|
+
return free;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Rename the bundled components of one group in place, keeping their order. */
|
|
112
|
+
function renameGroup(
|
|
113
|
+
entries: Record<string, unknown>,
|
|
114
|
+
keysBefore: ReadonlySet<string>,
|
|
115
|
+
baseNames: ReadonlyMap<string, string>,
|
|
116
|
+
): Map<string, string> {
|
|
117
|
+
const renames = new Map<string, string>();
|
|
118
|
+
const taken = new Set(Object.keys(entries));
|
|
119
|
+
for (const key of Object.keys(entries)) {
|
|
120
|
+
const name = keysBefore.has(key) ? undefined : queryFreeName(key, baseNames);
|
|
121
|
+
if (name !== undefined) {
|
|
122
|
+
taken.delete(key);
|
|
123
|
+
const free = freeName(name, taken);
|
|
124
|
+
taken.add(free);
|
|
125
|
+
renames.set(key, free);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
129
|
+
delete entries[key];
|
|
130
|
+
entries[renames.get(key) ?? key] = value;
|
|
131
|
+
}
|
|
132
|
+
return renames;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Rewrites pointers and messages that name a renamed component. */
|
|
136
|
+
export interface ComponentRenaming {
|
|
137
|
+
/** The pointer with a renamed component's new name; any other text as it is. */
|
|
138
|
+
readonly pointer: (pointer: string) => string;
|
|
139
|
+
/** The text with each renamed component's old name replaced by its new name. */
|
|
140
|
+
readonly text: (text: string) => string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function renamedPointer(pointer: string, renames: Renames): string {
|
|
144
|
+
if (!pointer.startsWith(`${ROOT_POINTER}/`)) {
|
|
145
|
+
return pointer;
|
|
146
|
+
}
|
|
147
|
+
const [components, group = "", name = "", ...rest] = parseRefPointer(canonicalRef(pointer));
|
|
148
|
+
const renamed = components === COMPONENTS_KEY ? renames.get(group)?.get(name) : undefined;
|
|
149
|
+
return renamed === undefined
|
|
150
|
+
? pointer
|
|
151
|
+
: appendPointer(ROOT_POINTER, [COMPONENTS_KEY, group, renamed, ...rest]);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function renamedText(text: string, renames: Renames): string {
|
|
155
|
+
const pairs = [...renames.values()].flatMap((group) => [...group]);
|
|
156
|
+
// The longest old name first, so a name that starts another one does not split it.
|
|
157
|
+
pairs.sort(([a], [b]) => b.length - a.length);
|
|
158
|
+
return pairs.reduce((shown, [old, renamed]) => shown.replaceAll(old, renamed), text);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function rewriteRefs(document: unknown, renaming: ComponentRenaming): void {
|
|
162
|
+
for (const { node } of findRefHolders(document)) {
|
|
163
|
+
node.$ref = renaming.pointer(node.$ref);
|
|
164
|
+
}
|
|
165
|
+
for (const mapping of findMappings(document)) {
|
|
166
|
+
for (const [name, value] of Object.entries(mapping)) {
|
|
167
|
+
if (typeof value === "string") {
|
|
168
|
+
mapping[name] = renaming.pointer(value);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Rename, in place, the components the bundle named after a URL with a query, and every local
|
|
176
|
+
* `$ref` and `mapping` value that names them. `documentRefs` are the refs of the loaded documents.
|
|
177
|
+
*/
|
|
178
|
+
export function renameQueryNamedComponents(
|
|
179
|
+
bundled: unknown,
|
|
180
|
+
keysBefore: ComponentKeys,
|
|
181
|
+
documentRefs: Iterable<string>,
|
|
182
|
+
): ComponentRenaming {
|
|
183
|
+
const baseNames = queryBaseNames(documentRefs);
|
|
184
|
+
const renames: Renames = new Map();
|
|
185
|
+
if (baseNames.size > 0) {
|
|
186
|
+
for (const [group, entries] of Object.entries(componentsOf(bundled))) {
|
|
187
|
+
const groupRenames = renameGroup(entries, keysBefore.get(group) ?? new Set(), baseNames);
|
|
188
|
+
if (groupRenames.size > 0) {
|
|
189
|
+
renames.set(group, groupRenames);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const renaming: ComponentRenaming = {
|
|
194
|
+
pointer: (pointer) => renamedPointer(pointer, renames),
|
|
195
|
+
text: (text) => renamedText(text, renames),
|
|
196
|
+
};
|
|
197
|
+
if (renames.size > 0) {
|
|
198
|
+
rewriteRefs(bundled, renaming);
|
|
199
|
+
}
|
|
200
|
+
return renaming;
|
|
201
|
+
}
|
|
@@ -3,17 +3,31 @@ import {
|
|
|
3
3
|
type BaseResolver,
|
|
4
4
|
bundle,
|
|
5
5
|
type Document,
|
|
6
|
+
type LocationObject,
|
|
6
7
|
lintDocument,
|
|
7
8
|
type NormalizedProblem,
|
|
8
9
|
type Config as RedoclyConfig,
|
|
9
10
|
} from "@redocly/openapi-core";
|
|
10
11
|
import type { Logger } from "../../application/ports/logger.js";
|
|
11
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
LoadedSchema,
|
|
14
|
+
SchemaLoader,
|
|
15
|
+
SchemaLoadRequest,
|
|
16
|
+
} from "../../application/ports/schema-loader.js";
|
|
12
17
|
import { withStackOverflowReportedAsync } from "../../application/stack-overflow.js";
|
|
18
|
+
import { redactUrlSecrets } from "../../domain/url-secrets.js";
|
|
13
19
|
import { WARNING_CODES, warningText } from "../../domain/warnings.js";
|
|
14
20
|
import type { OpenAPI3 } from "../../types.js";
|
|
21
|
+
import { removeBundledMappingCopies, schemaKeysOf } from "./bundled-mapping-copies.js";
|
|
15
22
|
import { repairBundledRefs } from "./bundled-ref-repair.js";
|
|
23
|
+
import { loadedDocuments, localFilesRead } from "./loaded-documents.js";
|
|
16
24
|
import { findMalformedRefs, malformedRefsError } from "./malformed-refs.js";
|
|
25
|
+
import { pointMappingNamesAtSchemas } from "./mapping-schema-names.js";
|
|
26
|
+
import {
|
|
27
|
+
type ComponentRenaming,
|
|
28
|
+
componentKeysOf,
|
|
29
|
+
renameQueryNamedComponents,
|
|
30
|
+
} from "./query-named-components.js";
|
|
17
31
|
import { RefAccessResolver } from "./ref-access.js";
|
|
18
32
|
import { checkRefsResolve } from "./ref-resolution-check.js";
|
|
19
33
|
import { REF_CYCLE_MESSAGE } from "./ref-resolution-steps.js";
|
|
@@ -25,11 +39,7 @@ import {
|
|
|
25
39
|
versionUnsupportedError,
|
|
26
40
|
} from "./schema-load-errors.js";
|
|
27
41
|
import { parseSchema } from "./schema-source.js";
|
|
28
|
-
import {
|
|
29
|
-
findUnsupportedKeys,
|
|
30
|
-
type LoadedDocument,
|
|
31
|
-
unsupportedKeysError,
|
|
32
|
-
} from "./unsupported-keys.js";
|
|
42
|
+
import { findUnsupportedKeys, unsupportedKeysError } from "./unsupported-keys.js";
|
|
33
43
|
|
|
34
44
|
/**
|
|
35
45
|
* The SchemaLoader port on Redocly 1.34 (ADR-005): parse any inherited source type, then lint and
|
|
@@ -107,21 +117,6 @@ function sourceFilePath(source: URL): string {
|
|
|
107
117
|
}
|
|
108
118
|
}
|
|
109
119
|
|
|
110
|
-
/**
|
|
111
|
-
* The root document and every other document the resolver loaded, as far as they parsed. A root
|
|
112
|
-
* read from a file or URL is in the resolver cache too, and is listed once.
|
|
113
|
-
*/
|
|
114
|
-
async function loadedDocuments(root: Document, resolver: BaseResolver): Promise<LoadedDocument[]> {
|
|
115
|
-
const cached = await Promise.all(resolver.cache.values());
|
|
116
|
-
const bySource = new Map<string, unknown>([[root.source.absoluteRef, root.parsed]]);
|
|
117
|
-
for (const document of cached) {
|
|
118
|
-
if ("parsed" in document && !bySource.has(document.source.absoluteRef)) {
|
|
119
|
-
bySource.set(document.source.absoluteRef, document.parsed);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return [...bySource].map(([source, parsed]) => ({ source, parsed }));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
120
|
/** Report the document problems Redocly throws as typed errors; anything else passes through. */
|
|
126
121
|
async function rethrowDocumentError(
|
|
127
122
|
error: unknown,
|
|
@@ -148,7 +143,7 @@ class RedoclySchemaLoader implements SchemaLoader {
|
|
|
148
143
|
this.#options = options;
|
|
149
144
|
}
|
|
150
145
|
|
|
151
|
-
async load(request: SchemaLoadRequest): Promise<
|
|
146
|
+
async load(request: SchemaLoadRequest): Promise<LoadedSchema> {
|
|
152
147
|
const resolver = this.#resolver(request);
|
|
153
148
|
// Parsing is guarded too: `JSON.stringify` of a deep object source overflows the stack on
|
|
154
149
|
// Node.js 22 and 24, before linting starts.
|
|
@@ -164,7 +159,7 @@ class RedoclySchemaLoader implements SchemaLoader {
|
|
|
164
159
|
return bundled;
|
|
165
160
|
}
|
|
166
161
|
|
|
167
|
-
async #parseAndBundle(request: SchemaLoadRequest, resolver: BaseResolver): Promise<
|
|
162
|
+
async #parseAndBundle(request: SchemaLoadRequest, resolver: BaseResolver): Promise<LoadedSchema> {
|
|
168
163
|
const { logger, now } = this.#options;
|
|
169
164
|
const configLoadedAt = now();
|
|
170
165
|
logger.debug("Loaded Redoc config", "redoc", now() - configLoadedAt);
|
|
@@ -173,7 +168,11 @@ class RedoclySchemaLoader implements SchemaLoader {
|
|
|
173
168
|
const document = await parseSchema(request.source, { absoluteRef, resolver });
|
|
174
169
|
logger.debug("Parsed schema", "redoc", now() - parseStartedAt);
|
|
175
170
|
assertOpenAPI3(document.parsed);
|
|
176
|
-
|
|
171
|
+
pointMappingNamesAtSchemas(document.parsed);
|
|
172
|
+
const bundled = await this.#lintAndBundle(document, resolver, request.shouldLint);
|
|
173
|
+
const isRootAFile = request.source instanceof URL && request.source.protocol === "file:";
|
|
174
|
+
const localFiles = await localFilesRead(document, resolver, isRootAFile);
|
|
175
|
+
return { document: bundled, localFiles };
|
|
177
176
|
}
|
|
178
177
|
|
|
179
178
|
#resolver(request: SchemaLoadRequest): RefAccessResolver {
|
|
@@ -181,11 +180,14 @@ class RedoclySchemaLoader implements SchemaLoader {
|
|
|
181
180
|
const config = resolveConfigWithAccess(redoc.resolve, {
|
|
182
181
|
timeoutMs: remoteRefTimeoutMs,
|
|
183
182
|
access: request.refAccess,
|
|
183
|
+
rootUrl: request.source instanceof URL ? request.source.href : undefined,
|
|
184
184
|
maxParallelFetches: remoteDocumentLimits.maxParallelFetches,
|
|
185
|
+
bodyLimits: remoteDocumentLimits,
|
|
185
186
|
});
|
|
186
187
|
return new RefAccessResolver(config, {
|
|
187
188
|
access: request.refAccess,
|
|
188
189
|
maxRemoteDocuments: remoteDocumentLimits.maxDocuments,
|
|
190
|
+
maxRemoteNodes: remoteDocumentLimits.maxNodes,
|
|
189
191
|
});
|
|
190
192
|
}
|
|
191
193
|
|
|
@@ -210,12 +212,14 @@ class RedoclySchemaLoader implements SchemaLoader {
|
|
|
210
212
|
config: this.#options.redoc.styleguide,
|
|
211
213
|
externalRefResolver: resolver,
|
|
212
214
|
});
|
|
213
|
-
this.#report(problems);
|
|
215
|
+
this.#report(problems, document.source.absoluteRef);
|
|
214
216
|
this.#options.logger.debug("Linted schema", "lint", this.#options.now() - startedAt);
|
|
215
217
|
}
|
|
216
218
|
|
|
217
219
|
async #bundle(document: Document, resolver: BaseResolver): Promise<OpenAPI3> {
|
|
218
220
|
const startedAt = this.#options.now();
|
|
221
|
+
const schemaKeys = schemaKeysOf(document.parsed);
|
|
222
|
+
const componentKeys = componentKeysOf(document.parsed);
|
|
219
223
|
// The lint resolver: documents it already loaded are not fetched again.
|
|
220
224
|
const bundled = await bundle({
|
|
221
225
|
config: this.#options.redoc,
|
|
@@ -223,8 +227,12 @@ class RedoclySchemaLoader implements SchemaLoader {
|
|
|
223
227
|
doc: document,
|
|
224
228
|
externalRefResolver: resolver,
|
|
225
229
|
});
|
|
226
|
-
|
|
230
|
+
removeBundledMappingCopies(bundled.bundle.parsed, schemaKeys);
|
|
227
231
|
repairBundledRefs(bundled.bundle.parsed);
|
|
232
|
+
const documentRefs = resolver.getFiles();
|
|
233
|
+
const renaming = renameQueryNamedComponents(bundled.bundle.parsed, componentKeys, documentRefs);
|
|
234
|
+
// The problems name the components the bundle made, so they are shown by their new names.
|
|
235
|
+
this.#report(bundled.problems, document.source.absoluteRef, renaming);
|
|
228
236
|
this.#options.logger.debug("Bundled schema", "bundle", this.#options.now() - startedAt);
|
|
229
237
|
return bundled.bundle.parsed;
|
|
230
238
|
}
|
|
@@ -234,22 +242,22 @@ class RedoclySchemaLoader implements SchemaLoader {
|
|
|
234
242
|
* config's `.redocly.lint-ignore.yaml` lists is left out, as `redocly lint` leaves it out
|
|
235
243
|
* (upstream #2189).
|
|
236
244
|
*/
|
|
237
|
-
#report(problems: readonly NormalizedProblem[]): void {
|
|
245
|
+
#report(problems: readonly NormalizedProblem[], rootRef: string, renaming = UNRENAMED): void {
|
|
238
246
|
const errorMessages: string[] = [];
|
|
239
247
|
for (const problem of problems) {
|
|
240
248
|
if (problem.ignored === true) {
|
|
241
249
|
this.#options.logger.debug(
|
|
242
|
-
`Ignored by the lint ignore file: ${problemMessage(problem)}`,
|
|
250
|
+
`Ignored by the lint ignore file: ${problemMessage(problem, renaming, rootRef)}`,
|
|
243
251
|
"lint",
|
|
244
252
|
);
|
|
245
253
|
continue;
|
|
246
254
|
}
|
|
247
|
-
const message = problemMessage(problem);
|
|
255
|
+
const message = problemMessage(problem, renaming, rootRef);
|
|
248
256
|
if (problem.severity === "error") {
|
|
249
257
|
errorMessages.push(message);
|
|
250
258
|
this.#options.logger.error(message);
|
|
251
259
|
} else {
|
|
252
|
-
this.#options.logger.warn(lintWarningText(problem));
|
|
260
|
+
this.#options.logger.warn(lintWarningText(message, problem.ruleId));
|
|
253
261
|
}
|
|
254
262
|
}
|
|
255
263
|
if (errorMessages.length > 0) {
|
|
@@ -259,16 +267,34 @@ class RedoclySchemaLoader implements SchemaLoader {
|
|
|
259
267
|
}
|
|
260
268
|
|
|
261
269
|
/** A lint warning names its rule, which `redocly.yaml` can turn off, and ends with its code. */
|
|
262
|
-
function lintWarningText(
|
|
263
|
-
return warningText(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
270
|
+
function lintWarningText(message: string, ruleId: string): string {
|
|
271
|
+
return warningText(`${message}, rule ${ruleId}`, WARNING_CODES.LINT_PROBLEM);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Problems found before the bundle named any component. */
|
|
275
|
+
const UNRENAMED: ComponentRenaming = { pointer: (pointer) => pointer, text: (text) => text };
|
|
276
|
+
|
|
277
|
+
/** A problem location that names a JSON Pointer, not a line and column. */
|
|
278
|
+
type PointerLocation = Extract<LocationObject, { pointer: string }>;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Where a problem is: its pointer, and the document when it is not the root (URL secrets left
|
|
282
|
+
* out).
|
|
283
|
+
*/
|
|
284
|
+
function locationText(location: PointerLocation, renaming: ComponentRenaming, rootRef: string) {
|
|
285
|
+
const pointer = renaming.pointer(location.pointer);
|
|
286
|
+
const documentRef = location.source.absoluteRef;
|
|
287
|
+
return documentRef === rootRef ? pointer : `${pointer} in ${redactUrlSecrets(documentRef)}`;
|
|
267
288
|
}
|
|
268
289
|
|
|
269
|
-
function problemMessage(
|
|
270
|
-
|
|
271
|
-
|
|
290
|
+
function problemMessage(
|
|
291
|
+
problem: NormalizedProblem,
|
|
292
|
+
renaming: ComponentRenaming,
|
|
293
|
+
rootRef: string,
|
|
294
|
+
): string {
|
|
295
|
+
const location = problem.location?.[0];
|
|
296
|
+
const message = renaming.text(problem.message);
|
|
297
|
+
return location?.pointer ? `${message} at ${locationText(location, renaming, rootRef)}` : message;
|
|
272
298
|
}
|
|
273
299
|
|
|
274
300
|
/** A schema loader with one Redocly config and logger, for one or more loads. */
|
|
@@ -10,9 +10,11 @@ import {
|
|
|
10
10
|
} from "@redocly/openapi-core";
|
|
11
11
|
import type { RefAccess } from "../../application/ports/schema-loader.js";
|
|
12
12
|
import { ERROR_CODES, type OpenAPITypesafeError } from "../../domain/errors.js";
|
|
13
|
-
import {
|
|
13
|
+
import { redactUrlSecrets } from "../../domain/url-secrets.js";
|
|
14
14
|
import { aliasExpansionFailure } from "./alias-limit.js";
|
|
15
15
|
import { isHostAllowed } from "./allowed-hosts.js";
|
|
16
|
+
import { pointMappingNamesAtSchemas } from "./mapping-schema-names.js";
|
|
17
|
+
import { isParsedSource, RemoteNodeLimit } from "./remote-node-limit.js";
|
|
16
18
|
import { refForbiddenError } from "./schema-load-errors.js";
|
|
17
19
|
|
|
18
20
|
/**
|
|
@@ -92,15 +94,20 @@ function localFromRemoteRefusal(
|
|
|
92
94
|
if (!isRemoteRef(base) || isRemoteRef(absoluteRef)) {
|
|
93
95
|
return undefined;
|
|
94
96
|
}
|
|
95
|
-
const shownBase =
|
|
97
|
+
const shownBase = redactUrlSecrets(base);
|
|
96
98
|
return refForbiddenError(absoluteRef, { reason: "local-ref-from-remote", base: shownBase });
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
/** The scheme of an `http(s)` URL, in any case. */
|
|
102
|
+
const REMOTE_SCHEME_RE = /^https?:(?=\/\/)/i;
|
|
103
|
+
|
|
99
104
|
/** The limits one resolver checks; each load gets its own resolver. */
|
|
100
105
|
export interface RefAccessLimits {
|
|
101
106
|
readonly access: RefAccess;
|
|
102
107
|
/** Remote documents one load may fetch, the root included (threat model T2). */
|
|
103
108
|
readonly maxRemoteDocuments: number;
|
|
109
|
+
/** Nodes the remote documents of one load may parse into together (threat model T2). */
|
|
110
|
+
readonly maxRemoteNodes: number;
|
|
104
111
|
}
|
|
105
112
|
|
|
106
113
|
/**
|
|
@@ -110,6 +117,7 @@ export interface RefAccessLimits {
|
|
|
110
117
|
*/
|
|
111
118
|
export class RefAccessResolver extends BaseResolver {
|
|
112
119
|
readonly #limits: RefAccessLimits;
|
|
120
|
+
readonly #nodeLimit: RemoteNodeLimit;
|
|
113
121
|
readonly #refusals: OpenAPITypesafeError[] = [];
|
|
114
122
|
/** The root document's ref: it is chosen by the developer, so it is not limited. */
|
|
115
123
|
#rootRef: string | undefined;
|
|
@@ -119,6 +127,7 @@ export class RefAccessResolver extends BaseResolver {
|
|
|
119
127
|
constructor(config: ResolveConfig, limits: RefAccessLimits) {
|
|
120
128
|
super(config);
|
|
121
129
|
this.#limits = limits;
|
|
130
|
+
this.#nodeLimit = new RemoteNodeLimit(limits.maxRemoteNodes);
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
/** The first document that was refused, if any. */
|
|
@@ -126,6 +135,17 @@ export class RefAccessResolver extends BaseResolver {
|
|
|
126
135
|
return this.#refusals[0];
|
|
127
136
|
}
|
|
128
137
|
|
|
138
|
+
/**
|
|
139
|
+
* A scheme is the same in any case (RFC 3986, section 3.1), but Redocly takes only `http://` and
|
|
140
|
+
* `https://` as URLs: it read `HTTP://host/x.yaml` as a file path, and its "not found" message
|
|
141
|
+
* showed the user info and the query of the URL, which no longer looked like one. The scheme
|
|
142
|
+
* is written in lowercase first, so the `$ref` loads as the URL it is, within the same limits.
|
|
143
|
+
*/
|
|
144
|
+
override resolveExternalRef(base: string | null, ref: string): string {
|
|
145
|
+
const normalized = ref.replace(REMOTE_SCHEME_RE, (scheme) => scheme.toLowerCase());
|
|
146
|
+
return super.resolveExternalRef(base, normalized);
|
|
147
|
+
}
|
|
148
|
+
|
|
129
149
|
override resolveDocument(
|
|
130
150
|
base: string | null,
|
|
131
151
|
ref: string,
|
|
@@ -143,16 +163,43 @@ export class RefAccessResolver extends BaseResolver {
|
|
|
143
163
|
return super.resolveDocument(base, ref, isRoot);
|
|
144
164
|
}
|
|
145
165
|
|
|
146
|
-
/**
|
|
166
|
+
/**
|
|
167
|
+
* Refuse a YAML alias bomb before Redocly walks it (pre-beta test plan 10.2). A document a
|
|
168
|
+
* `$ref` loads has its own `components.schemas`, so its mapping names point at those schemas
|
|
169
|
+
* before Redocly resolves them, as the root's do (`pointMappingNamesAtSchemas`).
|
|
170
|
+
*/
|
|
147
171
|
override parseDocument(source: Source, isRoot = false): Document {
|
|
148
|
-
const document =
|
|
172
|
+
const document = this.#parsed(source, isRoot);
|
|
149
173
|
const failure = aliasExpansionFailure(document.parsed);
|
|
150
174
|
if (failure !== undefined) {
|
|
151
175
|
throw new YamlParseError(failure, source);
|
|
152
176
|
}
|
|
177
|
+
pointMappingNamesAtSchemas(document.parsed);
|
|
153
178
|
return document;
|
|
154
179
|
}
|
|
155
180
|
|
|
181
|
+
/**
|
|
182
|
+
* A remote document is parsed within the node limit; a local one as Redocly parses it. Whether
|
|
183
|
+
* a remote one is parsed at all is decided here (`isParsedSource`), since Redocly read the
|
|
184
|
+
* extension of a URL with its query.
|
|
185
|
+
*/
|
|
186
|
+
#parsed(source: Source, isRoot: boolean): Document {
|
|
187
|
+
if (!isRemoteRef(source.absoluteRef)) {
|
|
188
|
+
return super.parseDocument(source, isRoot);
|
|
189
|
+
}
|
|
190
|
+
if (!isParsedSource(source, isRoot)) {
|
|
191
|
+
return { source, parsed: source.body };
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
return this.#nodeLimit.parse(source);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
if (isRefusal(error)) {
|
|
197
|
+
this.#refusals.push(error);
|
|
198
|
+
}
|
|
199
|
+
throw new YamlParseError(error as Error, source);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
156
203
|
override async loadExternalRef(absoluteRef: string): Promise<Source> {
|
|
157
204
|
const refusal = this.#countRefusal(absoluteRef) ?? (await this.#accessRefusal(absoluteRef));
|
|
158
205
|
if (refusal !== undefined) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { childPointer, ROOT_POINTER } from "../../domain/openapi/json-pointer.js";
|
|
2
2
|
|
|
3
3
|
/** An object with a string `$ref`, and its JSON Pointer in the document. */
|
|
4
4
|
export interface RefHolder {
|
|
@@ -6,38 +6,99 @@ export interface RefHolder {
|
|
|
6
6
|
readonly pointer: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Keywords whose value is data, not OpenAPI: a `$ref` or a `discriminator` in an example, a
|
|
11
|
+
* default, a `const` or an `enum` value, or an extension is part of the data and stays as written.
|
|
12
|
+
*/
|
|
13
|
+
const DATA_KEYWORDS = new Set(["example", "examples", "default", "const", "enum"]);
|
|
14
|
+
const EXTENSION_PREFIX = "x-";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Keywords whose value maps names to objects: a property, a schema or a response may be named
|
|
18
|
+
* `default` or `example`, and is OpenAPI all the same.
|
|
19
|
+
*/
|
|
20
|
+
const NAME_MAPS = new Set([
|
|
21
|
+
"properties",
|
|
22
|
+
"patternProperties",
|
|
23
|
+
"dependentSchemas",
|
|
24
|
+
"$defs",
|
|
25
|
+
"definitions",
|
|
26
|
+
"schemas",
|
|
27
|
+
"responses",
|
|
28
|
+
"parameters",
|
|
29
|
+
"requestBodies",
|
|
30
|
+
"headers",
|
|
31
|
+
"securitySchemes",
|
|
32
|
+
"links",
|
|
33
|
+
"callbacks",
|
|
34
|
+
"pathItems",
|
|
35
|
+
"mediaTypes",
|
|
36
|
+
"content",
|
|
37
|
+
"encoding",
|
|
38
|
+
"paths",
|
|
39
|
+
"webhooks",
|
|
40
|
+
]);
|
|
41
|
+
|
|
9
42
|
interface PendingNode {
|
|
10
43
|
readonly value: object;
|
|
11
44
|
readonly pointer: string;
|
|
45
|
+
/** Whether the keys of `value` are names (of properties, schemas, responses), not keywords. */
|
|
46
|
+
readonly hasNameKeys: boolean;
|
|
12
47
|
}
|
|
13
48
|
|
|
14
|
-
function
|
|
15
|
-
return
|
|
49
|
+
function isDataKey(key: string): boolean {
|
|
50
|
+
return DATA_KEYWORDS.has(key) || key.startsWith(EXTENSION_PREFIX);
|
|
16
51
|
}
|
|
17
52
|
|
|
18
53
|
/**
|
|
19
|
-
* Every object
|
|
20
|
-
*
|
|
21
|
-
* YAML aliases (or a cycle of them) is visited
|
|
54
|
+
* Every object of a parsed document that is OpenAPI, not data (`DATA_KEYWORDS`), with its JSON
|
|
55
|
+
* Pointer, in no particular order. The walk uses its own stack, so a deeply nested document does
|
|
56
|
+
* not run out of call stack, and a node shared by YAML aliases (or a cycle of them) is visited
|
|
57
|
+
* once.
|
|
22
58
|
*/
|
|
23
|
-
|
|
24
|
-
const found:
|
|
59
|
+
function openApiNodes(document: unknown): PendingNode[] {
|
|
60
|
+
const found: PendingNode[] = [];
|
|
25
61
|
const visited = new WeakSet<object>();
|
|
26
62
|
const pending: PendingNode[] = [];
|
|
27
|
-
const enqueue = (value: unknown, pointer: string): void => {
|
|
63
|
+
const enqueue = (value: unknown, pointer: string, hasNameKeys: boolean): void => {
|
|
28
64
|
if (typeof value === "object" && value !== null && !visited.has(value)) {
|
|
29
65
|
visited.add(value);
|
|
30
|
-
pending.push({ value, pointer });
|
|
66
|
+
pending.push({ value, pointer, hasNameKeys });
|
|
31
67
|
}
|
|
32
68
|
};
|
|
33
|
-
enqueue(document,
|
|
69
|
+
enqueue(document, ROOT_POINTER, false);
|
|
34
70
|
for (let next = pending.pop(); next !== undefined; next = pending.pop()) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
71
|
+
found.push(next);
|
|
72
|
+
// One push per child: spreading an array of millions of children overflows the stack.
|
|
38
73
|
for (const [key, child] of Object.entries(next.value)) {
|
|
39
|
-
|
|
74
|
+
if (next.hasNameKeys || !isDataKey(key)) {
|
|
75
|
+
enqueue(child, childPointer(next.pointer, key), !next.hasNameKeys && NAME_MAPS.has(key));
|
|
76
|
+
}
|
|
40
77
|
}
|
|
41
78
|
}
|
|
42
79
|
return found;
|
|
43
80
|
}
|
|
81
|
+
|
|
82
|
+
function hasStringRef(value: object): value is { $ref: string } {
|
|
83
|
+
return !Array.isArray(value) && typeof (value as { $ref?: unknown }).$ref === "string";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Every object with a string `$ref` in a parsed document, outside data, in no particular order. */
|
|
87
|
+
export function findRefHolders(document: unknown): RefHolder[] {
|
|
88
|
+
return openApiNodes(document).flatMap(({ value, pointer, hasNameKeys }) =>
|
|
89
|
+
!hasNameKeys && hasStringRef(value) ? [{ node: value, pointer }] : [],
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isMapping(value: unknown): value is Record<string, unknown> {
|
|
94
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Every `discriminator.mapping` object of a parsed document, outside data. */
|
|
98
|
+
export function findMappings(document: unknown): Record<string, unknown>[] {
|
|
99
|
+
return openApiNodes(document).flatMap(({ value, hasNameKeys }) => {
|
|
100
|
+
const { discriminator } = value as { discriminator?: unknown };
|
|
101
|
+
const mapping = !hasNameKeys && isMapping(discriminator) ? discriminator.mapping : undefined;
|
|
102
|
+
return isMapping(mapping) ? [mapping] : [];
|
|
103
|
+
});
|
|
104
|
+
}
|