openapi-typesafe 0.0.0 → 1.0.0-rc.0
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/LICENSE +22 -0
- package/README.md +71 -1
- package/bin/cli.js +4 -0
- package/dist/adapters/node-file-system/node-file-system.cjs +46 -0
- package/dist/adapters/node-file-system/node-file-system.cjs.map +1 -0
- package/dist/adapters/node-file-system/node-file-system.mjs +40 -0
- package/dist/adapters/node-file-system/node-file-system.mjs.map +1 -0
- package/dist/adapters/redocly-loader/alias-limit.cjs +16 -0
- package/dist/adapters/redocly-loader/alias-limit.cjs.map +1 -0
- package/dist/adapters/redocly-loader/alias-limit.mjs +14 -0
- package/dist/adapters/redocly-loader/alias-limit.mjs.map +1 -0
- package/dist/adapters/redocly-loader/allowed-hosts.cjs +42 -0
- package/dist/adapters/redocly-loader/allowed-hosts.cjs.map +1 -0
- package/dist/adapters/redocly-loader/allowed-hosts.mjs +40 -0
- package/dist/adapters/redocly-loader/allowed-hosts.mjs.map +1 -0
- package/dist/adapters/redocly-loader/bundled-ref-repair.cjs +53 -0
- package/dist/adapters/redocly-loader/bundled-ref-repair.cjs.map +1 -0
- package/dist/adapters/redocly-loader/bundled-ref-repair.mjs +51 -0
- package/dist/adapters/redocly-loader/bundled-ref-repair.mjs.map +1 -0
- package/dist/adapters/redocly-loader/malformed-refs.cjs +41 -0
- package/dist/adapters/redocly-loader/malformed-refs.cjs.map +1 -0
- package/dist/adapters/redocly-loader/malformed-refs.mjs +38 -0
- package/dist/adapters/redocly-loader/malformed-refs.mjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-config-source.cjs +42 -0
- package/dist/adapters/redocly-loader/redocly-config-source.cjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-config-source.mjs +35 -0
- package/dist/adapters/redocly-loader/redocly-config-source.mjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +169 -0
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +167 -0
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-access.cjs +107 -0
- package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-access.mjs +99 -0
- package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-holders.cjs +31 -0
- package/dist/adapters/redocly-loader/ref-holders.cjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-holders.mjs +29 -0
- package/dist/adapters/redocly-loader/ref-holders.mjs.map +1 -0
- package/dist/adapters/redocly-loader/remote-fetch.cjs +60 -0
- package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -0
- package/dist/adapters/redocly-loader/remote-fetch.mjs +56 -0
- package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -0
- package/dist/adapters/redocly-loader/schema-load-errors.cjs +87 -0
- package/dist/adapters/redocly-loader/schema-load-errors.cjs.map +1 -0
- package/dist/adapters/redocly-loader/schema-load-errors.mjs +77 -0
- package/dist/adapters/redocly-loader/schema-load-errors.mjs.map +1 -0
- package/dist/adapters/redocly-loader/schema-source.cjs +104 -0
- package/dist/adapters/redocly-loader/schema-source.cjs.map +1 -0
- package/dist/adapters/redocly-loader/schema-source.mjs +98 -0
- package/dist/adapters/redocly-loader/schema-source.mjs.map +1 -0
- package/dist/adapters/redocly-loader/unsupported-keys.cjs +62 -0
- package/dist/adapters/redocly-loader/unsupported-keys.cjs.map +1 -0
- package/dist/adapters/redocly-loader/unsupported-keys.mjs +58 -0
- package/dist/adapters/redocly-loader/unsupported-keys.mjs.map +1 -0
- package/dist/adapters/terminal-logger/terminal-logger.cjs +67 -0
- package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -0
- package/dist/adapters/terminal-logger/terminal-logger.mjs +59 -0
- package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -0
- package/dist/adapters/type-ast-bridge/footer-nodes.cjs +21 -0
- package/dist/adapters/type-ast-bridge/footer-nodes.cjs.map +1 -0
- package/dist/adapters/type-ast-bridge/footer-nodes.mjs +17 -0
- package/dist/adapters/type-ast-bridge/footer-nodes.mjs.map +1 -0
- package/dist/adapters/type-ast-bridge/ir-declarations-to-typescript.cjs +75 -0
- package/dist/adapters/type-ast-bridge/ir-declarations-to-typescript.cjs.map +1 -0
- package/dist/adapters/type-ast-bridge/ir-declarations-to-typescript.mjs +71 -0
- package/dist/adapters/type-ast-bridge/ir-declarations-to-typescript.mjs.map +1 -0
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs +145 -0
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs.map +1 -0
- package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs +139 -0
- package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs.map +1 -0
- package/dist/adapters/type-ast-bridge/lazy-node.cjs +23 -0
- package/dist/adapters/type-ast-bridge/lazy-node.cjs.map +1 -0
- package/dist/adapters/type-ast-bridge/lazy-node.mjs +21 -0
- package/dist/adapters/type-ast-bridge/lazy-node.mjs.map +1 -0
- package/dist/adapters/type-ast-bridge/load-typescript.cjs +57 -0
- package/dist/adapters/type-ast-bridge/load-typescript.cjs.map +1 -0
- package/dist/adapters/type-ast-bridge/load-typescript.mjs +51 -0
- package/dist/adapters/type-ast-bridge/load-typescript.mjs.map +1 -0
- package/dist/adapters/type-ast-bridge/print-typescript.cjs +21 -0
- package/dist/adapters/type-ast-bridge/print-typescript.cjs.map +1 -0
- package/dist/adapters/type-ast-bridge/print-typescript.mjs +19 -0
- package/dist/adapters/type-ast-bridge/print-typescript.mjs.map +1 -0
- package/dist/adapters/type-ast-bridge/typescript-raw-text.cjs +33 -0
- package/dist/adapters/type-ast-bridge/typescript-raw-text.cjs.map +1 -0
- package/dist/adapters/type-ast-bridge/typescript-raw-text.mjs +29 -0
- package/dist/adapters/type-ast-bridge/typescript-raw-text.mjs.map +1 -0
- package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs +204 -0
- package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs.map +1 -0
- package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs +201 -0
- package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs.map +1 -0
- package/dist/api/ast-to-string.cjs +39 -0
- package/dist/api/ast-to-string.cjs.map +1 -0
- package/dist/api/ast-to-string.mjs +37 -0
- package/dist/api/ast-to-string.mjs.map +1 -0
- package/dist/api/comment-header.cjs +11 -0
- package/dist/api/comment-header.cjs.map +1 -0
- package/dist/api/comment-header.mjs +9 -0
- package/dist/api/comment-header.mjs.map +1 -0
- package/dist/api/default-ports.cjs +38 -0
- package/dist/api/default-ports.cjs.map +1 -0
- package/dist/api/default-ports.mjs +28 -0
- package/dist/api/default-ports.mjs.map +1 -0
- package/dist/api/discriminator-enum.cjs +44 -0
- package/dist/api/discriminator-enum.cjs.map +1 -0
- package/dist/api/discriminator-enum.mjs +42 -0
- package/dist/api/discriminator-enum.mjs.map +1 -0
- package/dist/api/discriminator-scan.cjs +168 -0
- package/dist/api/discriminator-scan.cjs.map +1 -0
- package/dist/api/discriminator-scan.mjs +165 -0
- package/dist/api/discriminator-scan.mjs.map +1 -0
- package/dist/api/document-declarations.cjs +28 -0
- package/dist/api/document-declarations.cjs.map +1 -0
- package/dist/api/document-declarations.mjs +26 -0
- package/dist/api/document-declarations.mjs.map +1 -0
- package/dist/api/document-refs.cjs +53 -0
- package/dist/api/document-refs.cjs.map +1 -0
- package/dist/api/document-refs.mjs +50 -0
- package/dist/api/document-refs.mjs.map +1 -0
- package/dist/api/document-run.cjs +107 -0
- package/dist/api/document-run.cjs.map +1 -0
- package/dist/api/document-run.mjs +101 -0
- package/dist/api/document-run.mjs.map +1 -0
- package/dist/api/footer-entry.cjs +18 -0
- package/dist/api/footer-entry.cjs.map +1 -0
- package/dist/api/footer-entry.mjs +15 -0
- package/dist/api/footer-entry.mjs.map +1 -0
- package/dist/api/footer-sink.cjs +53 -0
- package/dist/api/footer-sink.cjs.map +1 -0
- package/dist/api/footer-sink.mjs +51 -0
- package/dist/api/footer-sink.mjs.map +1 -0
- package/dist/api/legacy-callback-warning.cjs +25 -0
- package/dist/api/legacy-callback-warning.cjs.map +1 -0
- package/dist/api/legacy-callback-warning.mjs +22 -0
- package/dist/api/legacy-callback-warning.mjs.map +1 -0
- package/dist/api/legacy-ts-helpers.cjs +203 -0
- package/dist/api/legacy-ts-helpers.cjs.map +1 -0
- package/dist/api/legacy-ts-helpers.mjs +187 -0
- package/dist/api/legacy-ts-helpers.mjs.map +1 -0
- package/dist/api/legacy-utils.cjs +65 -0
- package/dist/api/legacy-utils.cjs.map +1 -0
- package/dist/api/legacy-utils.mjs +50 -0
- package/dist/api/legacy-utils.mjs.map +1 -0
- package/dist/api/openapi-ts.cjs +40 -0
- package/dist/api/openapi-ts.cjs.map +1 -0
- package/dist/api/openapi-ts.mjs +34 -0
- package/dist/api/openapi-ts.mjs.map +1 -0
- package/dist/api/schema-callbacks.cjs +140 -0
- package/dist/api/schema-callbacks.cjs.map +1 -0
- package/dist/api/schema-callbacks.mjs +136 -0
- package/dist/api/schema-callbacks.mjs.map +1 -0
- package/dist/api/string-to-ast.cjs +21 -0
- package/dist/api/string-to-ast.cjs.map +1 -0
- package/dist/api/string-to-ast.mjs +18 -0
- package/dist/api/string-to-ast.mjs.map +1 -0
- package/dist/api/transform-context.cjs +82 -0
- package/dist/api/transform-context.cjs.map +1 -0
- package/dist/api/transform-context.mjs +65 -0
- package/dist/api/transform-context.mjs.map +1 -0
- package/dist/api/transform-schema.cjs +31 -0
- package/dist/api/transform-schema.cjs.map +1 -0
- package/dist/api/transform-schema.mjs +26 -0
- package/dist/api/transform-schema.mjs.map +1 -0
- package/dist/api/type-helpers.cjs +85 -0
- package/dist/api/type-helpers.cjs.map +1 -0
- package/dist/api/type-helpers.mjs +66 -0
- package/dist/api/type-helpers.mjs.map +1 -0
- package/dist/api/unsupported-feature-warnings.cjs +17 -0
- package/dist/api/unsupported-feature-warnings.cjs.map +1 -0
- package/dist/api/unsupported-feature-warnings.mjs +15 -0
- package/dist/api/unsupported-feature-warnings.mjs.map +1 -0
- package/dist/application/print/comment-writer.cjs +95 -0
- package/dist/application/print/comment-writer.cjs.map +1 -0
- package/dist/application/print/comment-writer.mjs +93 -0
- package/dist/application/print/comment-writer.mjs.map +1 -0
- package/dist/application/print/declaration-printer.cjs +83 -0
- package/dist/application/print/declaration-printer.cjs.map +1 -0
- package/dist/application/print/declaration-printer.mjs +81 -0
- package/dist/application/print/declaration-printer.mjs.map +1 -0
- package/dist/application/print/literal-text.cjs +52 -0
- package/dist/application/print/literal-text.cjs.map +1 -0
- package/dist/application/print/literal-text.mjs +48 -0
- package/dist/application/print/literal-text.mjs.map +1 -0
- package/dist/application/print/print-nodes.cjs +38 -0
- package/dist/application/print/print-nodes.cjs.map +1 -0
- package/dist/application/print/print-nodes.mjs +36 -0
- package/dist/application/print/print-nodes.mjs.map +1 -0
- package/dist/application/print/print-options.cjs +6 -0
- package/dist/application/print/print-options.cjs.map +1 -0
- package/dist/application/print/print-options.mjs +4 -0
- package/dist/application/print/print-options.mjs.map +1 -0
- package/dist/application/print/text-writer.cjs +63 -0
- package/dist/application/print/text-writer.cjs.map +1 -0
- package/dist/application/print/text-writer.mjs +60 -0
- package/dist/application/print/text-writer.mjs.map +1 -0
- package/dist/application/print/type-printer.cjs +214 -0
- package/dist/application/print/type-printer.cjs.map +1 -0
- package/dist/application/print/type-printer.mjs +210 -0
- package/dist/application/print/type-printer.mjs.map +1 -0
- package/dist/application/stack-overflow.cjs +36 -0
- package/dist/application/stack-overflow.cjs.map +1 -0
- package/dist/application/stack-overflow.mjs +31 -0
- package/dist/application/stack-overflow.mjs.map +1 -0
- package/dist/application/transform/document/components.cjs +104 -0
- package/dist/application/transform/document/components.cjs.map +1 -0
- package/dist/application/transform/document/components.mjs +102 -0
- package/dist/application/transform/document/components.mjs.map +1 -0
- package/dist/application/transform/document/defs-root.cjs +18 -0
- package/dist/application/transform/document/defs-root.cjs.map +1 -0
- package/dist/application/transform/document/defs-root.mjs +16 -0
- package/dist/application/transform/document/defs-root.mjs.map +1 -0
- package/dist/application/transform/document/document-member.cjs +13 -0
- package/dist/application/transform/document/document-member.cjs.map +1 -0
- package/dist/application/transform/document/document-member.mjs +11 -0
- package/dist/application/transform/document/document-member.mjs.map +1 -0
- package/dist/application/transform/document/document.cjs +86 -0
- package/dist/application/transform/document/document.cjs.map +1 -0
- package/dist/application/transform/document/document.mjs +83 -0
- package/dist/application/transform/document/document.mjs.map +1 -0
- package/dist/application/transform/document/header.cjs +27 -0
- package/dist/application/transform/document/header.cjs.map +1 -0
- package/dist/application/transform/document/header.mjs +25 -0
- package/dist/application/transform/document/header.mjs.map +1 -0
- package/dist/application/transform/document/kept-deprecated.cjs +96 -0
- package/dist/application/transform/document/kept-deprecated.cjs.map +1 -0
- package/dist/application/transform/document/kept-deprecated.mjs +94 -0
- package/dist/application/transform/document/kept-deprecated.mjs.map +1 -0
- package/dist/application/transform/document/media-type.cjs +42 -0
- package/dist/application/transform/document/media-type.cjs.map +1 -0
- package/dist/application/transform/document/media-type.mjs +38 -0
- package/dist/application/transform/document/media-type.mjs.map +1 -0
- package/dist/application/transform/document/operation.cjs +45 -0
- package/dist/application/transform/document/operation.cjs.map +1 -0
- package/dist/application/transform/document/operation.mjs +43 -0
- package/dist/application/transform/document/operation.mjs.map +1 -0
- package/dist/application/transform/document/parameter.cjs +25 -0
- package/dist/application/transform/document/parameter.cjs.map +1 -0
- package/dist/application/transform/document/parameter.mjs +23 -0
- package/dist/application/transform/document/parameter.mjs.map +1 -0
- package/dist/application/transform/document/parameters.cjs +114 -0
- package/dist/application/transform/document/parameters.cjs.map +1 -0
- package/dist/application/transform/document/parameters.mjs +112 -0
- package/dist/application/transform/document/parameters.mjs.map +1 -0
- package/dist/application/transform/document/path-item-conflicts.cjs +51 -0
- package/dist/application/transform/document/path-item-conflicts.cjs.map +1 -0
- package/dist/application/transform/document/path-item-conflicts.mjs +49 -0
- package/dist/application/transform/document/path-item-conflicts.mjs.map +1 -0
- package/dist/application/transform/document/path-item.cjs +82 -0
- package/dist/application/transform/document/path-item.cjs.map +1 -0
- package/dist/application/transform/document/path-item.mjs +80 -0
- package/dist/application/transform/document/path-item.mjs.map +1 -0
- package/dist/application/transform/document/path-key-overlaps.cjs +57 -0
- package/dist/application/transform/document/path-key-overlaps.cjs.map +1 -0
- package/dist/application/transform/document/path-key-overlaps.mjs +55 -0
- package/dist/application/transform/document/path-key-overlaps.mjs.map +1 -0
- package/dist/application/transform/document/paths-enum.cjs +75 -0
- package/dist/application/transform/document/paths-enum.cjs.map +1 -0
- package/dist/application/transform/document/paths-enum.mjs +72 -0
- package/dist/application/transform/document/paths-enum.mjs.map +1 -0
- package/dist/application/transform/document/paths.cjs +127 -0
- package/dist/application/transform/document/paths.cjs.map +1 -0
- package/dist/application/transform/document/paths.mjs +125 -0
- package/dist/application/transform/document/paths.mjs.map +1 -0
- package/dist/application/transform/document/request-body.cjs +36 -0
- package/dist/application/transform/document/request-body.cjs.map +1 -0
- package/dist/application/transform/document/request-body.mjs +34 -0
- package/dist/application/transform/document/request-body.mjs.map +1 -0
- package/dist/application/transform/document/response.cjs +59 -0
- package/dist/application/transform/document/response.cjs.map +1 -0
- package/dist/application/transform/document/response.mjs +57 -0
- package/dist/application/transform/document/response.mjs.map +1 -0
- package/dist/application/transform/document/responses.cjs +23 -0
- package/dist/application/transform/document/responses.cjs.map +1 -0
- package/dist/application/transform/document/responses.mjs +21 -0
- package/dist/application/transform/document/responses.mjs.map +1 -0
- package/dist/application/transform/document/root-type-aliases.cjs +69 -0
- package/dist/application/transform/document/root-type-aliases.cjs.map +1 -0
- package/dist/application/transform/document/root-type-aliases.mjs +65 -0
- package/dist/application/transform/document/root-type-aliases.mjs.map +1 -0
- package/dist/application/transform/document/webhooks.cjs +19 -0
- package/dist/application/transform/document/webhooks.cjs.map +1 -0
- package/dist/application/transform/document/webhooks.mjs +17 -0
- package/dist/application/transform/document/webhooks.mjs.map +1 -0
- package/dist/application/transform/document-entries.cjs +17 -0
- package/dist/application/transform/document-entries.cjs.map +1 -0
- package/dist/application/transform/document-entries.mjs +14 -0
- package/dist/application/transform/document-entries.mjs.map +1 -0
- package/dist/application/transform/footer/document-footer.cjs +88 -0
- package/dist/application/transform/footer/document-footer.cjs.map +1 -0
- package/dist/application/transform/footer/document-footer.mjs +86 -0
- package/dist/application/transform/footer/document-footer.mjs.map +1 -0
- package/dist/application/transform/footer/enum-naming.cjs +121 -0
- package/dist/application/transform/footer/enum-naming.cjs.map +1 -0
- package/dist/application/transform/footer/enum-naming.mjs +115 -0
- package/dist/application/transform/footer/enum-naming.mjs.map +1 -0
- package/dist/application/transform/helper-types.cjs +68 -0
- package/dist/application/transform/helper-types.cjs.map +1 -0
- package/dist/application/transform/helper-types.mjs +65 -0
- package/dist/application/transform/helper-types.mjs.map +1 -0
- package/dist/application/transform/literal-type.cjs +36 -0
- package/dist/application/transform/literal-type.cjs.map +1 -0
- package/dist/application/transform/literal-type.mjs +34 -0
- package/dist/application/transform/literal-type.mjs.map +1 -0
- package/dist/application/transform/numbered-names.cjs +18 -0
- package/dist/application/transform/numbered-names.cjs.map +1 -0
- package/dist/application/transform/numbered-names.mjs +16 -0
- package/dist/application/transform/numbered-names.mjs.map +1 -0
- package/dist/application/transform/ref-type.cjs +57 -0
- package/dist/application/transform/ref-type.cjs.map +1 -0
- package/dist/application/transform/ref-type.mjs +54 -0
- package/dist/application/transform/ref-type.mjs.map +1 -0
- package/dist/application/transform/schema/array-type.cjs +105 -0
- package/dist/application/transform/schema/array-type.cjs.map +1 -0
- package/dist/application/transform/schema/array-type.mjs +103 -0
- package/dist/application/transform/schema/array-type.mjs.map +1 -0
- package/dist/application/transform/schema/composition-type.cjs +107 -0
- package/dist/application/transform/schema/composition-type.cjs.map +1 -0
- package/dist/application/transform/schema/composition-type.mjs +105 -0
- package/dist/application/transform/schema/composition-type.mjs.map +1 -0
- package/dist/application/transform/schema/core-type.cjs +84 -0
- package/dist/application/transform/schema/core-type.cjs.map +1 -0
- package/dist/application/transform/schema/core-type.mjs +82 -0
- package/dist/application/transform/schema/core-type.mjs.map +1 -0
- package/dist/application/transform/schema/discriminator-property.cjs +21 -0
- package/dist/application/transform/schema/discriminator-property.cjs.map +1 -0
- package/dist/application/transform/schema/discriminator-property.mjs +19 -0
- package/dist/application/transform/schema/discriminator-property.mjs.map +1 -0
- package/dist/application/transform/schema/enum-rule.cjs +107 -0
- package/dist/application/transform/schema/enum-rule.cjs.map +1 -0
- package/dist/application/transform/schema/enum-rule.mjs +105 -0
- package/dist/application/transform/schema/enum-rule.mjs.map +1 -0
- package/dist/application/transform/schema/object-type.cjs +173 -0
- package/dist/application/transform/schema/object-type.cjs.map +1 -0
- package/dist/application/transform/schema/object-type.mjs +170 -0
- package/dist/application/transform/schema/object-type.mjs.map +1 -0
- package/dist/application/transform/schema/presence-members.cjs +59 -0
- package/dist/application/transform/schema/presence-members.cjs.map +1 -0
- package/dist/application/transform/schema/presence-members.mjs +57 -0
- package/dist/application/transform/schema/presence-members.mjs.map +1 -0
- package/dist/application/transform/schema/schema-transform.cjs +72 -0
- package/dist/application/transform/schema/schema-transform.cjs.map +1 -0
- package/dist/application/transform/schema/schema-transform.mjs +68 -0
- package/dist/application/transform/schema/schema-transform.mjs.map +1 -0
- package/dist/application/transform/schema/unevaluated-properties.cjs +61 -0
- package/dist/application/transform/schema/unevaluated-properties.cjs.map +1 -0
- package/dist/application/transform/schema/unevaluated-properties.mjs +59 -0
- package/dist/application/transform/schema/unevaluated-properties.mjs.map +1 -0
- package/dist/application/transform/schema-comment.cjs +84 -0
- package/dist/application/transform/schema-comment.cjs.map +1 -0
- package/dist/application/transform/schema-comment.mjs +81 -0
- package/dist/application/transform/schema-comment.mjs.map +1 -0
- package/dist/application/transform/shared-types.cjs +8 -0
- package/dist/application/transform/shared-types.cjs.map +1 -0
- package/dist/application/transform/shared-types.mjs +6 -0
- package/dist/application/transform/shared-types.mjs.map +1 -0
- package/dist/application/transform/type-combinators.cjs +49 -0
- package/dist/application/transform/type-combinators.cjs.map +1 -0
- package/dist/application/transform/type-combinators.mjs +42 -0
- package/dist/application/transform/type-combinators.mjs.map +1 -0
- package/dist/cli/cli-arguments.cjs +137 -0
- package/dist/cli/cli-arguments.cjs.map +1 -0
- package/dist/cli/cli-arguments.mjs +129 -0
- package/dist/cli/cli-arguments.mjs.map +1 -0
- package/dist/cli/cli-errors.cjs +80 -0
- package/dist/cli/cli-errors.cjs.map +1 -0
- package/dist/cli/cli-errors.mjs +76 -0
- package/dist/cli/cli-errors.mjs.map +1 -0
- package/dist/cli/cli-output.cjs +37 -0
- package/dist/cli/cli-output.cjs.map +1 -0
- package/dist/cli/cli-output.mjs +30 -0
- package/dist/cli/cli-output.mjs.map +1 -0
- package/dist/cli/docs-links.cjs +6 -0
- package/dist/cli/docs-links.cjs.map +1 -0
- package/dist/cli/docs-links.mjs +4 -0
- package/dist/cli/docs-links.mjs.map +1 -0
- package/dist/cli/fix-option.cjs +19 -0
- package/dist/cli/fix-option.cjs.map +1 -0
- package/dist/cli/fix-option.mjs +16 -0
- package/dist/cli/fix-option.mjs.map +1 -0
- package/dist/cli/help-text.cjs +44 -0
- package/dist/cli/help-text.cjs.map +1 -0
- package/dist/cli/help-text.mjs +42 -0
- package/dist/cli/help-text.mjs.map +1 -0
- package/dist/cli/main.cjs +62 -0
- package/dist/cli/main.cjs.map +1 -0
- package/dist/cli/main.d.cts +2 -0
- package/dist/cli/main.d.mts +2 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.mjs +54 -0
- package/dist/cli/main.mjs.map +1 -0
- package/dist/cli/redocly-apis.cjs +65 -0
- package/dist/cli/redocly-apis.cjs.map +1 -0
- package/dist/cli/redocly-apis.mjs +62 -0
- package/dist/cli/redocly-apis.mjs.map +1 -0
- package/dist/cli/ref-limits.cjs +14 -0
- package/dist/cli/ref-limits.cjs.map +1 -0
- package/dist/cli/ref-limits.mjs +12 -0
- package/dist/cli/ref-limits.mjs.map +1 -0
- package/dist/cli/run-cli.cjs +100 -0
- package/dist/cli/run-cli.cjs.map +1 -0
- package/dist/cli/run-cli.mjs +98 -0
- package/dist/cli/run-cli.mjs.map +1 -0
- package/dist/domain/assert-never.cjs +8 -0
- package/dist/domain/assert-never.cjs.map +1 -0
- package/dist/domain/assert-never.mjs +6 -0
- package/dist/domain/assert-never.mjs.map +1 -0
- package/dist/domain/errors.cjs +50 -0
- package/dist/domain/errors.cjs.map +1 -0
- package/dist/domain/errors.mjs +46 -0
- package/dist/domain/errors.mjs.map +1 -0
- package/dist/domain/ir/constructors.cjs +89 -0
- package/dist/domain/ir/constructors.cjs.map +1 -0
- package/dist/domain/ir/constructors.mjs +71 -0
- package/dist/domain/ir/constructors.mjs.map +1 -0
- package/dist/domain/ir/identifier-text.cjs +29 -0
- package/dist/domain/ir/identifier-text.cjs.map +1 -0
- package/dist/domain/ir/identifier-text.mjs +25 -0
- package/dist/domain/ir/identifier-text.mjs.map +1 -0
- package/dist/domain/ir/newer-identifier-ranges.cjs +109 -0
- package/dist/domain/ir/newer-identifier-ranges.cjs.map +1 -0
- package/dist/domain/ir/newer-identifier-ranges.mjs +106 -0
- package/dist/domain/ir/newer-identifier-ranges.mjs.map +1 -0
- package/dist/domain/ir/normalize.cjs +32 -0
- package/dist/domain/ir/normalize.cjs.map +1 -0
- package/dist/domain/ir/normalize.mjs +29 -0
- package/dist/domain/ir/normalize.mjs.map +1 -0
- package/dist/domain/ir/property-name.cjs +19 -0
- package/dist/domain/ir/property-name.cjs.map +1 -0
- package/dist/domain/ir/property-name.mjs +16 -0
- package/dist/domain/ir/property-name.mjs.map +1 -0
- package/dist/domain/ir/raw-text-escapes.cjs +25 -0
- package/dist/domain/ir/raw-text-escapes.cjs.map +1 -0
- package/dist/domain/ir/raw-text-escapes.mjs +22 -0
- package/dist/domain/ir/raw-text-escapes.mjs.map +1 -0
- package/dist/domain/openapi/alias-expansion.cjs +50 -0
- package/dist/domain/openapi/alias-expansion.cjs.map +1 -0
- package/dist/domain/openapi/alias-expansion.mjs +45 -0
- package/dist/domain/openapi/alias-expansion.mjs.map +1 -0
- package/dist/domain/openapi/binary-content.cjs +48 -0
- package/dist/domain/openapi/binary-content.cjs.map +1 -0
- package/dist/domain/openapi/binary-content.mjs +45 -0
- package/dist/domain/openapi/binary-content.mjs.map +1 -0
- package/dist/domain/openapi/components-object.cjs +29 -0
- package/dist/domain/openapi/components-object.cjs.map +1 -0
- package/dist/domain/openapi/components-object.mjs +24 -0
- package/dist/domain/openapi/components-object.mjs.map +1 -0
- package/dist/domain/openapi/json-pointer.cjs +31 -0
- package/dist/domain/openapi/json-pointer.cjs.map +1 -0
- package/dist/domain/openapi/json-pointer.mjs +27 -0
- package/dist/domain/openapi/json-pointer.mjs.map +1 -0
- package/dist/domain/openapi/media-type-object.cjs +14 -0
- package/dist/domain/openapi/media-type-object.cjs.map +1 -0
- package/dist/domain/openapi/media-type-object.mjs +11 -0
- package/dist/domain/openapi/media-type-object.mjs.map +1 -0
- package/dist/domain/openapi/parameter-object.cjs +13 -0
- package/dist/domain/openapi/parameter-object.cjs.map +1 -0
- package/dist/domain/openapi/parameter-object.mjs +10 -0
- package/dist/domain/openapi/parameter-object.mjs.map +1 -0
- package/dist/domain/openapi/path-item-object.cjs +35 -0
- package/dist/domain/openapi/path-item-object.cjs.map +1 -0
- package/dist/domain/openapi/path-item-object.mjs +30 -0
- package/dist/domain/openapi/path-item-object.mjs.map +1 -0
- package/dist/domain/openapi/unsupported-features.cjs +87 -0
- package/dist/domain/openapi/unsupported-features.cjs.map +1 -0
- package/dist/domain/openapi/unsupported-features.mjs +84 -0
- package/dist/domain/openapi/unsupported-features.mjs.map +1 -0
- package/dist/domain/output-fixes.cjs +66 -0
- package/dist/domain/output-fixes.cjs.map +1 -0
- package/dist/domain/output-fixes.mjs +59 -0
- package/dist/domain/output-fixes.mjs.map +1 -0
- package/dist/index.cjs +98 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +812 -0
- package/dist/index.d.mts +812 -0
- package/dist/index.d.ts +812 -0
- package/dist/index.mjs +27 -0
- package/dist/index.mjs.map +1 -0
- package/dist/transform/components-object.cjs +14 -0
- package/dist/transform/components-object.cjs.map +1 -0
- package/dist/transform/components-object.mjs +10 -0
- package/dist/transform/components-object.mjs.map +1 -0
- package/dist/transform/header-object.cjs +12 -0
- package/dist/transform/header-object.cjs.map +1 -0
- package/dist/transform/header-object.mjs +10 -0
- package/dist/transform/header-object.mjs.map +1 -0
- package/dist/transform/media-type-object.cjs +12 -0
- package/dist/transform/media-type-object.cjs.map +1 -0
- package/dist/transform/media-type-object.mjs +10 -0
- package/dist/transform/media-type-object.mjs.map +1 -0
- package/dist/transform/operation-object.cjs +26 -0
- package/dist/transform/operation-object.cjs.map +1 -0
- package/dist/transform/operation-object.mjs +21 -0
- package/dist/transform/operation-object.mjs.map +1 -0
- package/dist/transform/parameter-object.cjs +12 -0
- package/dist/transform/parameter-object.cjs.map +1 -0
- package/dist/transform/parameter-object.mjs +10 -0
- package/dist/transform/parameter-object.mjs.map +1 -0
- package/dist/transform/path-item-object.cjs +12 -0
- package/dist/transform/path-item-object.cjs.map +1 -0
- package/dist/transform/path-item-object.mjs +10 -0
- package/dist/transform/path-item-object.mjs.map +1 -0
- package/dist/transform/paths-object.cjs +11 -0
- package/dist/transform/paths-object.cjs.map +1 -0
- package/dist/transform/paths-object.mjs +9 -0
- package/dist/transform/paths-object.mjs.map +1 -0
- package/dist/transform/request-body-object.cjs +12 -0
- package/dist/transform/request-body-object.cjs.map +1 -0
- package/dist/transform/request-body-object.mjs +10 -0
- package/dist/transform/request-body-object.mjs.map +1 -0
- package/dist/transform/response-object.cjs +12 -0
- package/dist/transform/response-object.cjs.map +1 -0
- package/dist/transform/response-object.mjs +10 -0
- package/dist/transform/response-object.mjs.map +1 -0
- package/dist/transform/responses-object.cjs +12 -0
- package/dist/transform/responses-object.cjs.map +1 -0
- package/dist/transform/responses-object.mjs +10 -0
- package/dist/transform/responses-object.mjs.map +1 -0
- package/dist/transform/schema-object.cjs +21 -0
- package/dist/transform/schema-object.cjs.map +1 -0
- package/dist/transform/schema-object.mjs +16 -0
- package/dist/transform/schema-object.mjs.map +1 -0
- package/package.json +115 -4
- package/src/adapters/node-file-system/node-file-system.ts +44 -0
- package/src/adapters/redocly-loader/alias-limit.ts +20 -0
- package/src/adapters/redocly-loader/allowed-hosts.ts +62 -0
- package/src/adapters/redocly-loader/bundled-ref-repair.ts +65 -0
- package/src/adapters/redocly-loader/malformed-refs.ts +61 -0
- package/src/adapters/redocly-loader/redocly-config-source.ts +43 -0
- package/src/adapters/redocly-loader/redocly-schema-loader.ts +246 -0
- package/src/adapters/redocly-loader/ref-access.ts +146 -0
- package/src/adapters/redocly-loader/ref-holders.ts +43 -0
- package/src/adapters/redocly-loader/remote-fetch.ts +104 -0
- package/src/adapters/redocly-loader/schema-load-errors.ts +124 -0
- package/src/adapters/redocly-loader/schema-source.ts +151 -0
- package/src/adapters/redocly-loader/unsupported-keys.ts +102 -0
- package/src/adapters/terminal-logger/terminal-logger.ts +98 -0
- package/src/adapters/type-ast-bridge/footer-nodes.ts +38 -0
- package/src/adapters/type-ast-bridge/ir-declarations-to-typescript.ts +100 -0
- package/src/adapters/type-ast-bridge/ir-to-typescript.ts +220 -0
- package/src/adapters/type-ast-bridge/lazy-node.ts +24 -0
- package/src/adapters/type-ast-bridge/load-typescript.ts +84 -0
- package/src/adapters/type-ast-bridge/print-typescript.ts +33 -0
- package/src/adapters/type-ast-bridge/typescript-raw-text.ts +49 -0
- package/src/adapters/type-ast-bridge/typescript-to-ir.ts +280 -0
- package/src/adapters/type-ast-bridge/typescript-types.ts +8 -0
- package/src/api/ast-to-string.ts +59 -0
- package/src/api/comment-header.ts +7 -0
- package/src/api/default-ports.ts +44 -0
- package/src/api/discriminator-enum.ts +76 -0
- package/src/api/discriminator-scan.ts +272 -0
- package/src/api/document-declarations.ts +41 -0
- package/src/api/document-refs.ts +71 -0
- package/src/api/document-run.ts +159 -0
- package/src/api/footer-entry.ts +23 -0
- package/src/api/footer-sink.ts +67 -0
- package/src/api/legacy-callback-warning.ts +29 -0
- package/src/api/legacy-ts-helpers.ts +311 -0
- package/src/api/legacy-utils.ts +118 -0
- package/src/api/openapi-ts.ts +62 -0
- package/src/api/schema-callbacks.ts +211 -0
- package/src/api/string-to-ast.ts +27 -0
- package/src/api/transform-context.ts +87 -0
- package/src/api/transform-schema.ts +39 -0
- package/src/api/type-helpers.ts +130 -0
- package/src/api/unsupported-feature-warnings.ts +26 -0
- package/src/application/ports/file-system.ts +12 -0
- package/src/application/ports/logger.ts +16 -0
- package/src/application/ports/redocly-config-source.ts +16 -0
- package/src/application/ports/schema-loader.ts +32 -0
- package/src/application/print/comment-writer.ts +91 -0
- package/src/application/print/declaration-printer.ts +100 -0
- package/src/application/print/literal-text.ts +62 -0
- package/src/application/print/print-nodes.ts +62 -0
- package/src/application/print/print-options.ts +11 -0
- package/src/application/print/text-writer.ts +83 -0
- package/src/application/print/type-printer.ts +281 -0
- package/src/application/stack-overflow.ts +54 -0
- package/src/application/transform/document/components.ts +189 -0
- package/src/application/transform/document/defs-root.ts +25 -0
- package/src/application/transform/document/document-member.ts +20 -0
- package/src/application/transform/document/document.ts +157 -0
- package/src/application/transform/document/header.ts +34 -0
- package/src/application/transform/document/kept-deprecated.ts +135 -0
- package/src/application/transform/document/media-type.ts +78 -0
- package/src/application/transform/document/operation.ts +64 -0
- package/src/application/transform/document/parameter.ts +45 -0
- package/src/application/transform/document/parameters.ts +200 -0
- package/src/application/transform/document/path-item-conflicts.ts +79 -0
- package/src/application/transform/document/path-item.ts +168 -0
- package/src/application/transform/document/path-key-overlaps.ts +112 -0
- package/src/application/transform/document/paths-enum.ts +127 -0
- package/src/application/transform/document/paths.ts +211 -0
- package/src/application/transform/document/request-body.ts +50 -0
- package/src/application/transform/document/response.ts +109 -0
- package/src/application/transform/document/responses.ts +29 -0
- package/src/application/transform/document/root-type-aliases.ts +106 -0
- package/src/application/transform/document/webhooks.ts +22 -0
- package/src/application/transform/document-entries.ts +28 -0
- package/src/application/transform/footer/document-footer.ts +127 -0
- package/src/application/transform/footer/enum-naming.ts +181 -0
- package/src/application/transform/helper-types.ts +92 -0
- package/src/application/transform/literal-type.ts +54 -0
- package/src/application/transform/numbered-names.ts +20 -0
- package/src/application/transform/ref-type.ts +97 -0
- package/src/application/transform/schema/array-type.ts +152 -0
- package/src/application/transform/schema/composition-type.ts +183 -0
- package/src/application/transform/schema/core-type.ts +115 -0
- package/src/application/transform/schema/discriminator-property.ts +28 -0
- package/src/application/transform/schema/enum-rule.ts +157 -0
- package/src/application/transform/schema/object-type.ts +271 -0
- package/src/application/transform/schema/presence-members.ts +96 -0
- package/src/application/transform/schema/schema-context.ts +110 -0
- package/src/application/transform/schema/schema-rule.ts +29 -0
- package/src/application/transform/schema/schema-transform.ts +99 -0
- package/src/application/transform/schema/unevaluated-properties.ts +105 -0
- package/src/application/transform/schema-comment.ts +116 -0
- package/src/application/transform/shared-types.ts +9 -0
- package/src/application/transform/transform-context.ts +51 -0
- package/src/application/transform/type-combinators.ts +57 -0
- package/src/cli/cli-arguments.ts +198 -0
- package/src/cli/cli-dependencies.ts +42 -0
- package/src/cli/cli-errors.ts +125 -0
- package/src/cli/cli-output.ts +53 -0
- package/src/cli/docs-links.ts +6 -0
- package/src/cli/fix-option.ts +29 -0
- package/src/cli/help-text.ts +52 -0
- package/src/cli/main.ts +67 -0
- package/src/cli/redocly-apis.ts +91 -0
- package/src/cli/ref-limits.ts +16 -0
- package/src/cli/run-cli.ts +114 -0
- package/src/domain/assert-never.ts +8 -0
- package/src/domain/errors.ts +74 -0
- package/src/domain/ir/constructors.ts +137 -0
- package/src/domain/ir/identifier-text.ts +49 -0
- package/src/domain/ir/newer-identifier-ranges.ts +109 -0
- package/src/domain/ir/nodes.ts +224 -0
- package/src/domain/ir/normalize.ts +51 -0
- package/src/domain/ir/property-name.ts +28 -0
- package/src/domain/ir/raw-text-escapes.ts +37 -0
- package/src/domain/openapi/alias-expansion.ts +72 -0
- package/src/domain/openapi/binary-content.ts +74 -0
- package/src/domain/openapi/components-object.ts +52 -0
- package/src/domain/openapi/document-object.ts +12 -0
- package/src/domain/openapi/header-object.ts +9 -0
- package/src/domain/openapi/json-pointer.ts +46 -0
- package/src/domain/openapi/media-type-object.ts +26 -0
- package/src/domain/openapi/operation-object.ts +13 -0
- package/src/domain/openapi/parameter-object.ts +30 -0
- package/src/domain/openapi/path-item-object.ts +70 -0
- package/src/domain/openapi/request-body-object.ts +7 -0
- package/src/domain/openapi/response-object.ts +14 -0
- package/src/domain/openapi/schema-object.ts +59 -0
- package/src/domain/openapi/unsupported-features.ts +139 -0
- package/src/domain/output-fixes.ts +95 -0
- package/src/index.ts +67 -0
- package/src/transform/components-object.ts +25 -0
- package/src/transform/header-object.ts +19 -0
- package/src/transform/media-type-object.ts +19 -0
- package/src/transform/operation-object.ts +36 -0
- package/src/transform/parameter-object.ts +19 -0
- package/src/transform/parameters-array.ts +19 -0
- package/src/transform/path-item-object.ts +22 -0
- package/src/transform/paths-enum.ts +8 -0
- package/src/transform/paths-object.ts +15 -0
- package/src/transform/request-body-object.ts +19 -0
- package/src/transform/response-object.ts +19 -0
- package/src/transform/responses-object.ts +19 -0
- package/src/transform/schema-object.ts +36 -0
- package/src/transform/webhooks-object.ts +15 -0
- package/src/types/generator-options.ts +267 -0
- package/src/types/openapi-common.ts +100 -0
- package/src/types/openapi-document.ts +196 -0
- package/src/types/openapi-path-item.ts +130 -0
- package/src/types/openapi-request.ts +209 -0
- package/src/types/openapi-response.ts +81 -0
- package/src/types/openapi-schema.ts +169 -0
- package/src/types/openapi-security.ts +116 -0
- package/src/types.ts +12 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { irKeyword, irObject, irProperty } from "../../../domain/ir/constructors.js";
|
|
2
|
+
import type { IrPropertyName, IrPropertySignature, IrType } from "../../../domain/ir/nodes.js";
|
|
3
|
+
import { toPropertyName } from "../../../domain/ir/property-name.js";
|
|
4
|
+
import { createRef } from "../../../domain/openapi/json-pointer.js";
|
|
5
|
+
import {
|
|
6
|
+
PARAMETER_LOCATIONS,
|
|
7
|
+
type ParameterLocation,
|
|
8
|
+
type ParameterObject,
|
|
9
|
+
type ParameterOrReference,
|
|
10
|
+
QUERYSTRING_LOCATION,
|
|
11
|
+
} from "../../../domain/openapi/parameter-object.js";
|
|
12
|
+
import type { SchemaObject } from "../../../domain/openapi/schema-object.js";
|
|
13
|
+
import { refType } from "../ref-type.js";
|
|
14
|
+
import type { SchemaLocation } from "../schema/schema-context.js";
|
|
15
|
+
import { withSchemaComment } from "../schema-comment.js";
|
|
16
|
+
import type { TransformContext } from "../transform-context.js";
|
|
17
|
+
import { parameterType } from "./parameter.js";
|
|
18
|
+
|
|
19
|
+
const PATH_TEMPLATE_RE = /\{([^}]+)\}/g;
|
|
20
|
+
|
|
21
|
+
/** A parameter as written in the document, and the object its `$ref` points to. */
|
|
22
|
+
interface ParameterEntry {
|
|
23
|
+
readonly original: ParameterOrReference;
|
|
24
|
+
readonly resolved: ParameterObject | undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** An entry whose `$ref` resolved, so its location and name are known. */
|
|
28
|
+
type ResolvedEntry = ParameterEntry & { readonly resolved: ParameterObject };
|
|
29
|
+
|
|
30
|
+
function resolveParameter(
|
|
31
|
+
parameter: ParameterOrReference,
|
|
32
|
+
context: TransformContext,
|
|
33
|
+
): ParameterObject | undefined {
|
|
34
|
+
return "$ref" in parameter
|
|
35
|
+
? (context.refs.resolve(parameter.$ref) as ParameterObject | undefined)
|
|
36
|
+
: parameter;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Required string parameters for every `{name}` in a path template. */
|
|
40
|
+
function pathTemplateParameters(path: string): ParameterObject[] {
|
|
41
|
+
return (path.match(PATH_TEMPLATE_RE) ?? []).map((match) => ({
|
|
42
|
+
name: match.slice(1, -1),
|
|
43
|
+
in: "path",
|
|
44
|
+
required: true,
|
|
45
|
+
schema: { type: "string" },
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** `--generate-path-params`: add the path template parameters the list does not define. */
|
|
50
|
+
function withPathTemplateParameters(
|
|
51
|
+
parameters: readonly ParameterOrReference[],
|
|
52
|
+
location: SchemaLocation,
|
|
53
|
+
context: TransformContext,
|
|
54
|
+
): ParameterOrReference[] {
|
|
55
|
+
const result = [...parameters];
|
|
56
|
+
if (!context.options.generatePathParams || !location.path) {
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
for (const parameter of pathTemplateParameters(location.path)) {
|
|
60
|
+
const isDefined = result.some((candidate) => {
|
|
61
|
+
const resolved = resolveParameter(candidate, context);
|
|
62
|
+
return resolved?.in === "path" && resolved.name === parameter.name;
|
|
63
|
+
});
|
|
64
|
+
if (!isDefined) {
|
|
65
|
+
result.push(parameter);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isDeprecatedParameter(parameter: ParameterObject | undefined): boolean {
|
|
72
|
+
const schema = parameter?.schema as SchemaObject | undefined;
|
|
73
|
+
return Boolean(parameter?.deprecated || schema?.deprecated);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Resolved parameters, sorted for `--alphabetize`, without deprecated ones if excluded. */
|
|
77
|
+
function parameterEntries(
|
|
78
|
+
parameters: readonly ParameterOrReference[],
|
|
79
|
+
context: TransformContext,
|
|
80
|
+
): ParameterEntry[] {
|
|
81
|
+
const entries = parameters.map((original) => ({
|
|
82
|
+
original,
|
|
83
|
+
resolved: resolveParameter(original, context),
|
|
84
|
+
}));
|
|
85
|
+
if (context.options.alphabetize) {
|
|
86
|
+
// Unlike map keys, the original sorts parameters with the default locale's `localeCompare`.
|
|
87
|
+
entries.sort((left, right) =>
|
|
88
|
+
(left.resolved?.name ?? "").localeCompare(right.resolved?.name ?? ""),
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return context.options.excludeDeprecated
|
|
92
|
+
? entries.filter(({ resolved }) => !isDeprecatedParameter(resolved))
|
|
93
|
+
: entries;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** The original quotes a name that is not text (a missing name prints as `"undefined"`). */
|
|
97
|
+
function parameterName(name: unknown): IrPropertyName {
|
|
98
|
+
return typeof name === "string" || typeof name === "number"
|
|
99
|
+
? toPropertyName(name)
|
|
100
|
+
: { kind: "string", value: String(name) };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function referencedParameterType(ref: string, resolved: ParameterObject): IrType {
|
|
104
|
+
// A `$ref` that resolves to another `$ref` is not a parameter object yet: index it as a path.
|
|
105
|
+
const isParameter = !(resolved as { $ref?: unknown }).$ref;
|
|
106
|
+
const parameter = isParameter ? { in: resolved.in, name: resolved.name } : null;
|
|
107
|
+
return refType(ref, { parameter });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function entryType(
|
|
111
|
+
{ original, resolved }: ResolvedEntry,
|
|
112
|
+
location: SchemaLocation,
|
|
113
|
+
context: TransformContext,
|
|
114
|
+
): IrType {
|
|
115
|
+
const path = createRef([location.path, "parameters", resolved.in, resolved.name]);
|
|
116
|
+
return "$ref" in original
|
|
117
|
+
? referencedParameterType(original.$ref, resolved)
|
|
118
|
+
: parameterType(resolved, { ...location, path }, context);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function parameterMember(
|
|
122
|
+
entry: ResolvedEntry,
|
|
123
|
+
location: SchemaLocation,
|
|
124
|
+
context: TransformContext,
|
|
125
|
+
): IrPropertySignature {
|
|
126
|
+
const { resolved } = entry;
|
|
127
|
+
const property = irProperty(parameterName(resolved.name), entryType(entry, location, context), {
|
|
128
|
+
isOptional: resolved.in !== "path" && !resolved.required,
|
|
129
|
+
isReadonly: context.options.immutable,
|
|
130
|
+
});
|
|
131
|
+
return withSchemaComment(property, resolved);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The `query` member typed by an `in: querystring` parameter (OpenAPI 3.2, ADR-020): the parameter
|
|
136
|
+
* is the whole query string. Null when there is none, or when `in: query` parameters sit next to
|
|
137
|
+
* it, which 3.2 does not allow; those keep their types, and a warning names the parameter.
|
|
138
|
+
*/
|
|
139
|
+
function querystringMember(
|
|
140
|
+
entries: readonly ParameterEntry[],
|
|
141
|
+
location: SchemaLocation,
|
|
142
|
+
context: TransformContext,
|
|
143
|
+
): IrPropertySignature | null {
|
|
144
|
+
const querystring = entries.find(
|
|
145
|
+
(entry): entry is ResolvedEntry => entry.resolved?.in === QUERYSTRING_LOCATION,
|
|
146
|
+
);
|
|
147
|
+
if (!querystring || entries.some((entry) => entry.resolved?.in === "query")) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
const property = irProperty(toPropertyName("query"), entryType(querystring, location, context), {
|
|
151
|
+
isOptional: !querystring.resolved.required,
|
|
152
|
+
isReadonly: context.options.immutable,
|
|
153
|
+
});
|
|
154
|
+
return withSchemaComment(property, querystring.resolved);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** One location's parameters; optional when all of them are, and `never` when there are none. */
|
|
158
|
+
function locationMember(
|
|
159
|
+
parameterIn: ParameterLocation,
|
|
160
|
+
entries: readonly ParameterEntry[],
|
|
161
|
+
location: SchemaLocation,
|
|
162
|
+
context: TransformContext,
|
|
163
|
+
): IrPropertySignature {
|
|
164
|
+
const members = entries
|
|
165
|
+
.filter((entry): entry is ResolvedEntry => entry.resolved?.in === parameterIn)
|
|
166
|
+
.map((entry) => parameterMember(entry, location, context));
|
|
167
|
+
return irProperty(
|
|
168
|
+
toPropertyName(parameterIn),
|
|
169
|
+
members.length > 0 ? irObject(members) : irKeyword("never"),
|
|
170
|
+
{
|
|
171
|
+
isOptional: members.every((member) => member.isOptional),
|
|
172
|
+
isReadonly: context.options.immutable,
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The `parameters` property of an operation or path item: one member per location, each an object
|
|
179
|
+
* of that location's parameters. `location.path` is the path template for
|
|
180
|
+
* `--generate-path-params`.
|
|
181
|
+
*/
|
|
182
|
+
export function parametersMember(
|
|
183
|
+
parameters: readonly ParameterOrReference[],
|
|
184
|
+
location: SchemaLocation,
|
|
185
|
+
context: TransformContext,
|
|
186
|
+
): IrPropertySignature {
|
|
187
|
+
const entries = parameterEntries(
|
|
188
|
+
withPathTemplateParameters(parameters, location, context),
|
|
189
|
+
context,
|
|
190
|
+
);
|
|
191
|
+
const querystring = querystringMember(entries, location, context);
|
|
192
|
+
const members = PARAMETER_LOCATIONS.map((parameterIn) =>
|
|
193
|
+
parameterIn === "query" && querystring
|
|
194
|
+
? querystring
|
|
195
|
+
: locationMember(parameterIn, entries, location, context),
|
|
196
|
+
);
|
|
197
|
+
return irProperty(toPropertyName("parameters"), irObject(members), {
|
|
198
|
+
isReadonly: context.options.immutable,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { IrMember, IrPropertySignature, IrType } from "../../../domain/ir/nodes.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Whether TypeScript surely rejects a covered path item for the index signature that covers it
|
|
5
|
+
* (roadmap R10.2). The original output compiles when every covered type is assignable to the
|
|
6
|
+
* signature's type, and that output must stay the same, so a signature is only moved when this
|
|
7
|
+
* check proves the error. It compares object types property by property, as the checker does: a
|
|
8
|
+
* property the signature needs and the covered type may lack, or a value where the signature has
|
|
9
|
+
* the `?: never` of an empty slot (a missing method, an empty parameter location), proves it. Two
|
|
10
|
+
* object properties are compared the same way, inside. Any other pair of types (references,
|
|
11
|
+
* unions, keywords) decides nothing, and that output is left as it was.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* How a property is written. `never` is the `?: never` of an empty slot; a required `never`
|
|
16
|
+
* (assignable to every type) is `unknown` and decides nothing.
|
|
17
|
+
*/
|
|
18
|
+
type Presence = "absent" | "never" | "optional" | "required" | "unknown";
|
|
19
|
+
|
|
20
|
+
function nameOf(member: IrPropertySignature): string {
|
|
21
|
+
return member.name.kind === "string" ? member.name.value : member.name.text;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function presenceOf(member: IrPropertySignature | undefined): Presence {
|
|
25
|
+
if (member === undefined) {
|
|
26
|
+
return "absent";
|
|
27
|
+
}
|
|
28
|
+
if (member.type.kind === "keyword" && member.type.keyword === "never") {
|
|
29
|
+
return member.isOptional ? "never" : "unknown";
|
|
30
|
+
}
|
|
31
|
+
return member.isOptional ? "optional" : "required";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function propertiesOf(type: IrType): ReadonlyMap<string, IrPropertySignature> | null {
|
|
35
|
+
if (type.kind !== "object") {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const properties = type.members.filter((member: IrMember): member is IrPropertySignature => {
|
|
39
|
+
return member.kind === "property";
|
|
40
|
+
});
|
|
41
|
+
return new Map(properties.map((property) => [nameOf(property), property]));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Whether the covered property's presence fails the signature's: a required value it may lack, or
|
|
46
|
+
* a value where the signature has `never` (an object is not `undefined`).
|
|
47
|
+
*/
|
|
48
|
+
function isPresenceRejected(covering: Presence, covered: Presence): boolean {
|
|
49
|
+
if (covered === "unknown") {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (covering === "required") {
|
|
53
|
+
return covered !== "required";
|
|
54
|
+
}
|
|
55
|
+
return covering === "never" && (covered === "optional" || covered === "required");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isPropertyRejected(
|
|
59
|
+
covering: IrPropertySignature,
|
|
60
|
+
covered: IrPropertySignature | undefined,
|
|
61
|
+
): boolean {
|
|
62
|
+
if (isPresenceRejected(presenceOf(covering), presenceOf(covered))) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
// A `never` is not an object type, so a slot that is empty on either side decides nothing here.
|
|
66
|
+
return covered !== undefined && isCoveredPathItemRejected(covered.type, covering.type);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Whether the covered type is surely not assignable to the covering signature's type. */
|
|
70
|
+
export function isCoveredPathItemRejected(covered: IrType, covering: IrType): boolean {
|
|
71
|
+
const coveredProperties = propertiesOf(covered);
|
|
72
|
+
const coveringProperties = propertiesOf(covering);
|
|
73
|
+
if (coveredProperties === null || coveringProperties === null) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return [...coveringProperties].some(([name, property]) =>
|
|
77
|
+
isPropertyRejected(property, coveredProperties.get(name)),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { irKeyword, irObject, irProperty } from "../../../domain/ir/constructors.js";
|
|
2
|
+
import type { IrMember, IrPropertySignature, IrType } from "../../../domain/ir/nodes.js";
|
|
3
|
+
import { toPropertyName } from "../../../domain/ir/property-name.js";
|
|
4
|
+
import { createRef } from "../../../domain/openapi/json-pointer.js";
|
|
5
|
+
import type { OperationObject } from "../../../domain/openapi/operation-object.js";
|
|
6
|
+
import type {
|
|
7
|
+
ParameterObject,
|
|
8
|
+
ParameterOrReference,
|
|
9
|
+
} from "../../../domain/openapi/parameter-object.js";
|
|
10
|
+
import {
|
|
11
|
+
ADDITIONAL_OPERATIONS_KEY,
|
|
12
|
+
HTTP_METHODS,
|
|
13
|
+
type OperationEntry,
|
|
14
|
+
type PathItemMethod,
|
|
15
|
+
type PathItemObject,
|
|
16
|
+
QUERY_METHOD,
|
|
17
|
+
} from "../../../domain/openapi/path-item-object.js";
|
|
18
|
+
import { documentEntries } from "../document-entries.js";
|
|
19
|
+
import { refType } from "../ref-type.js";
|
|
20
|
+
import type { SchemaLocation } from "../schema/schema-context.js";
|
|
21
|
+
import type { TransformContext } from "../transform-context.js";
|
|
22
|
+
import { documentMember } from "./document-member.js";
|
|
23
|
+
import { operationMembers } from "./operation.js";
|
|
24
|
+
import { parametersMember } from "./parameters.js";
|
|
25
|
+
|
|
26
|
+
/** Redocly reads `#` in an operation ID as a pointer, so it is replaced (upstream issue #1542). */
|
|
27
|
+
const HASH_RE = /#/g;
|
|
28
|
+
|
|
29
|
+
/** Whether the method has an operation, not removed by `--exclude-deprecated`. */
|
|
30
|
+
function isIncluded(
|
|
31
|
+
operation: OperationEntry | undefined,
|
|
32
|
+
context: TransformContext,
|
|
33
|
+
): operation is OperationEntry {
|
|
34
|
+
if (!operation) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const resolved =
|
|
38
|
+
"$ref" in operation
|
|
39
|
+
? (context.refs.resolve(operation.$ref) as OperationObject | undefined)
|
|
40
|
+
: operation;
|
|
41
|
+
return !(context.options.excludeDeprecated && resolved?.deprecated);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Path item parameters followed by the operation's, keyed by location and name, so an operation
|
|
46
|
+
* parameter replaces the path item parameter it redefines (upstream issue #1798).
|
|
47
|
+
*/
|
|
48
|
+
function mergedParameters(
|
|
49
|
+
pathItem: PathItemObject,
|
|
50
|
+
operation: OperationObject,
|
|
51
|
+
context: TransformContext,
|
|
52
|
+
): ParameterOrReference[] {
|
|
53
|
+
const byKey = new Map<string, ParameterOrReference>();
|
|
54
|
+
for (const parameter of [...(pathItem.parameters ?? []), ...(operation.parameters ?? [])]) {
|
|
55
|
+
const resolved =
|
|
56
|
+
"$ref" in parameter
|
|
57
|
+
? (context.refs.resolve(parameter.$ref) as ParameterObject | undefined)
|
|
58
|
+
: parameter;
|
|
59
|
+
byKey.set(`${resolved?.in}-${resolved?.name}`, parameter);
|
|
60
|
+
}
|
|
61
|
+
return [...byKey.values()];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* An operation with an `operationId` goes into the `operations` interface and is referenced from
|
|
66
|
+
* the path item; others are written inline.
|
|
67
|
+
*/
|
|
68
|
+
function operationType(
|
|
69
|
+
pathItem: PathItemObject,
|
|
70
|
+
operation: OperationObject,
|
|
71
|
+
location: SchemaLocation,
|
|
72
|
+
context: TransformContext,
|
|
73
|
+
): IrType {
|
|
74
|
+
const merged = { ...operation, parameters: mergedParameters(pathItem, operation, context) };
|
|
75
|
+
if (!operation.operationId) {
|
|
76
|
+
return irObject(operationMembers(merged, location, context));
|
|
77
|
+
}
|
|
78
|
+
const operationId = operation.operationId.replace(HASH_RE, "/");
|
|
79
|
+
context.footer.addOperation(() =>
|
|
80
|
+
irProperty(toPropertyName(operationId), irObject(operationMembers(merged, location, context)), {
|
|
81
|
+
isReadonly: context.options.immutable,
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
return refType(createRef(["operations", operationId]));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** An included operation, the member name it gets and its location below the path item. */
|
|
88
|
+
interface DeclaredOperation {
|
|
89
|
+
readonly name: string;
|
|
90
|
+
readonly operation: OperationEntry;
|
|
91
|
+
readonly path: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function operationMember(
|
|
95
|
+
{ name, operation, path }: DeclaredOperation,
|
|
96
|
+
pathItem: PathItemObject,
|
|
97
|
+
location: SchemaLocation,
|
|
98
|
+
context: TransformContext,
|
|
99
|
+
): IrPropertySignature {
|
|
100
|
+
const type =
|
|
101
|
+
"$ref" in operation
|
|
102
|
+
? refType(operation.$ref)
|
|
103
|
+
: operationType(pathItem, operation, { ...location, path }, context);
|
|
104
|
+
return documentMember(name, type, operation, { isReadonly: context.options.immutable });
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** A method member: the operation, or `?: never` when there is none or it is excluded. */
|
|
108
|
+
function methodMember(
|
|
109
|
+
method: PathItemMethod,
|
|
110
|
+
pathItem: PathItemObject,
|
|
111
|
+
location: SchemaLocation,
|
|
112
|
+
context: TransformContext,
|
|
113
|
+
): IrPropertySignature {
|
|
114
|
+
const operation = pathItem[method];
|
|
115
|
+
if (!isIncluded(operation, context)) {
|
|
116
|
+
const isReadonly = context.options.immutable;
|
|
117
|
+
return irProperty(toPropertyName(method), irKeyword("never"), { isOptional: true, isReadonly });
|
|
118
|
+
}
|
|
119
|
+
const path = createRef([location.path, method]);
|
|
120
|
+
return operationMember({ name: method, operation, path }, pathItem, location, context);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* `additionalOperations` (OpenAPI 3.2): the included operations keyed by their exact method name,
|
|
125
|
+
* or null when the path item has none left.
|
|
126
|
+
*/
|
|
127
|
+
function additionalOperationsMember(
|
|
128
|
+
pathItem: PathItemObject,
|
|
129
|
+
location: SchemaLocation,
|
|
130
|
+
context: TransformContext,
|
|
131
|
+
): IrPropertySignature | null {
|
|
132
|
+
const entries = documentEntries(pathItem.additionalOperations ?? {}, context.options);
|
|
133
|
+
const members = entries
|
|
134
|
+
.filter(([, operation]) => isIncluded(operation, context))
|
|
135
|
+
.map(([method, operation]) => {
|
|
136
|
+
const path = createRef([location.path, ADDITIONAL_OPERATIONS_KEY, method]);
|
|
137
|
+
return operationMember({ name: method, operation, path }, pathItem, location, context);
|
|
138
|
+
});
|
|
139
|
+
return members.length > 0
|
|
140
|
+
? irProperty(toPropertyName(ADDITIONAL_OPERATIONS_KEY), irObject(members), {
|
|
141
|
+
isReadonly: context.options.immutable,
|
|
142
|
+
})
|
|
143
|
+
: null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* A path item (OpenAPI 3.2 §4.8.9): its `parameters`, one member per HTTP method, then `query` and
|
|
148
|
+
* `additionalOperations` when the path item declares them (ADR-020).
|
|
149
|
+
*/
|
|
150
|
+
export function pathItemType(
|
|
151
|
+
pathItem: PathItemObject,
|
|
152
|
+
location: SchemaLocation,
|
|
153
|
+
context: TransformContext,
|
|
154
|
+
): IrType {
|
|
155
|
+
const parametersLocation = { ...location, path: createRef([location.path, "parameters"]) };
|
|
156
|
+
const members: IrMember[] = [
|
|
157
|
+
parametersMember(pathItem.parameters ?? [], parametersLocation, context),
|
|
158
|
+
...HTTP_METHODS.map((method) => methodMember(method, pathItem, location, context)),
|
|
159
|
+
];
|
|
160
|
+
if (pathItem[QUERY_METHOD] !== undefined) {
|
|
161
|
+
members.push(methodMember(QUERY_METHOD, pathItem, location, context));
|
|
162
|
+
}
|
|
163
|
+
const additionalOperations = additionalOperationsMember(pathItem, location, context);
|
|
164
|
+
if (additionalOperations) {
|
|
165
|
+
members.push(additionalOperations);
|
|
166
|
+
}
|
|
167
|
+
return irObject(members);
|
|
168
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `--path-params-as-types` overlaps (roadmap R10.2, backlog 28). A path key with parameters is an
|
|
3
|
+
* index signature over a template literal type, such as `` `/apps/${string}` ``. `${string}` also
|
|
4
|
+
* matches `/`, so that signature covers `/apps/regions` and `` `/apps/${string}/restart` `` as
|
|
5
|
+
* well, and TypeScript requires the covered keys' types to be assignable to its type (TS2411,
|
|
6
|
+
* TS2413). These functions find the signatures that cover another key the checker rejects.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** A placeholder of a template literal type, by the type it stands for. */
|
|
10
|
+
export type PathPlaceholder = "string" | "number" | "boolean";
|
|
11
|
+
|
|
12
|
+
/** One part of a path key: text, or a placeholder. */
|
|
13
|
+
export type PathKeyPart =
|
|
14
|
+
| { readonly kind: "text"; readonly text: string }
|
|
15
|
+
| { readonly kind: "placeholder"; readonly type: PathPlaceholder };
|
|
16
|
+
|
|
17
|
+
/** A path key: a URL written as a property, or a template literal type of an index signature. */
|
|
18
|
+
export type PathKey =
|
|
19
|
+
| { readonly kind: "literal"; readonly url: string }
|
|
20
|
+
| { readonly kind: "template"; readonly parts: readonly PathKeyPart[] };
|
|
21
|
+
|
|
22
|
+
const BOOLEAN_TEXTS: readonly string[] = ["true", "false"];
|
|
23
|
+
|
|
24
|
+
/** The text one placeholder stands for in a sample of a template key. */
|
|
25
|
+
const SAMPLE_TEXTS: Readonly<Record<PathPlaceholder, string>> = {
|
|
26
|
+
string: "",
|
|
27
|
+
number: "0",
|
|
28
|
+
boolean: "true",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** TypeScript's rule for `${number}`: a text that converts to a finite number. */
|
|
32
|
+
function isNumberText(text: string): boolean {
|
|
33
|
+
return text !== "" && Number.isFinite(Number(text));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isPlaceholderText(type: PathPlaceholder, text: string): boolean {
|
|
37
|
+
if (type === "number") {
|
|
38
|
+
return isNumberText(text);
|
|
39
|
+
}
|
|
40
|
+
return type === "boolean" ? BOOLEAN_TEXTS.includes(text) : true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Whether `text` from `start` on is one of the strings the parts from `index` on describe. */
|
|
44
|
+
function matchesFrom(
|
|
45
|
+
text: string,
|
|
46
|
+
start: number,
|
|
47
|
+
parts: readonly PathKeyPart[],
|
|
48
|
+
index: number,
|
|
49
|
+
): boolean {
|
|
50
|
+
const part = parts[index];
|
|
51
|
+
if (part === undefined) {
|
|
52
|
+
return start === text.length;
|
|
53
|
+
}
|
|
54
|
+
if (part.kind === "text") {
|
|
55
|
+
return (
|
|
56
|
+
text.startsWith(part.text, start) &&
|
|
57
|
+
matchesFrom(text, start + part.text.length, parts, index + 1)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
for (let end = start; end <= text.length; end += 1) {
|
|
61
|
+
if (
|
|
62
|
+
isPlaceholderText(part.type, text.slice(start, end)) &&
|
|
63
|
+
matchesFrom(text, end, parts, index + 1)
|
|
64
|
+
) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* One string of the key. If a template key is covered, every string of it is, so a sample that is
|
|
73
|
+
* not covered proves the key is not; a sample that is covered may over-report, which only moves a
|
|
74
|
+
* signature that did not need it (the types stay the same, see `pathsObjectType`).
|
|
75
|
+
*/
|
|
76
|
+
function sampleOf(key: PathKey): string {
|
|
77
|
+
if (key.kind === "literal") {
|
|
78
|
+
return key.url;
|
|
79
|
+
}
|
|
80
|
+
return key.parts
|
|
81
|
+
.map((part) => (part.kind === "text" ? part.text : SAMPLE_TEXTS[part.type]))
|
|
82
|
+
.join("");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Whether TypeScript rejects the key at `covered` for the signature at `covering`. */
|
|
86
|
+
export type CoverRejection = (covering: number, covered: number) => boolean;
|
|
87
|
+
|
|
88
|
+
/** Without type information every covered key counts. */
|
|
89
|
+
const EVERY_COVER_REJECTED: CoverRejection = () => true;
|
|
90
|
+
|
|
91
|
+
/** The indexes of the template keys that cover another key of the list, where it is rejected. */
|
|
92
|
+
export function coveringTemplateKeys(
|
|
93
|
+
keys: readonly PathKey[],
|
|
94
|
+
isRejected: CoverRejection = EVERY_COVER_REJECTED,
|
|
95
|
+
): ReadonlySet<number> {
|
|
96
|
+
const covering = new Set<number>();
|
|
97
|
+
keys.forEach((key, index) => {
|
|
98
|
+
if (key.kind !== "template") {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const isCovering = keys.some(
|
|
102
|
+
(other, otherIndex) =>
|
|
103
|
+
otherIndex !== index &&
|
|
104
|
+
matchesFrom(sampleOf(other), 0, key.parts, 0) &&
|
|
105
|
+
isRejected(index, otherIndex),
|
|
106
|
+
);
|
|
107
|
+
if (isCovering) {
|
|
108
|
+
covering.add(index);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return covering;
|
|
112
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { IrEnumDeclaration } from "../../../domain/ir/nodes.js";
|
|
2
|
+
import type { OperationObject } from "../../../domain/openapi/operation-object.js";
|
|
3
|
+
import {
|
|
4
|
+
ADDITIONAL_OPERATIONS_KEY,
|
|
5
|
+
HTTP_METHODS,
|
|
6
|
+
type PathItemMethod,
|
|
7
|
+
type PathsObject,
|
|
8
|
+
QUERY_METHOD,
|
|
9
|
+
} from "../../../domain/openapi/path-item-object.js";
|
|
10
|
+
import { EnumNaming, enumDeclaration } from "../footer/enum-naming.js";
|
|
11
|
+
import { withNumberedRepeats } from "../numbered-names.js";
|
|
12
|
+
import type { EnumMemberMetadata } from "../schema/schema-context.js";
|
|
13
|
+
|
|
14
|
+
/** A path segment that is one parameter: `{user_id}` or `:user_id`. */
|
|
15
|
+
const PARAMETER_SEGMENT_RE = /^(?:{(.+)}|:(.+))$/;
|
|
16
|
+
/** Characters not allowed in an enum key, or a `{param}` / `:param` part (first match only). */
|
|
17
|
+
const INVALID_KEY_PART_RE = /{.*}|:.*|[^a-zA-Z\d_]+/;
|
|
18
|
+
const API_PATHS_NAME = "ApiPaths";
|
|
19
|
+
const METHODS: ReadonlySet<string> = new Set<PathItemMethod>([...HTTP_METHODS, QUERY_METHOD]);
|
|
20
|
+
|
|
21
|
+
/** The members of the `ApiPaths` enum (`--make-paths-enum`). */
|
|
22
|
+
export interface ApiPathsEnum {
|
|
23
|
+
readonly values: readonly string[];
|
|
24
|
+
readonly metadata: readonly EnumMemberMetadata[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** `getUsersById` style key from the method and URL, when the operation has no ID. */
|
|
28
|
+
function keyFromUrl(method: string, url: string): string {
|
|
29
|
+
return `${method}${url}`
|
|
30
|
+
.split("/")
|
|
31
|
+
.map((part) => {
|
|
32
|
+
const capitalized = part.charAt(0).toUpperCase() + part.slice(1);
|
|
33
|
+
return capitalized.replace(INVALID_KEY_PART_RE, "");
|
|
34
|
+
})
|
|
35
|
+
.join("");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** `user_id` and `order-id` as `UserId` and `OrderId`. */
|
|
39
|
+
function parameterWord(name: string): string {
|
|
40
|
+
return name
|
|
41
|
+
.split(/[^a-zA-Z\d]+/)
|
|
42
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
43
|
+
.join("");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The key with parameters named, `GetUserByUserId`, for keys that collide without them. */
|
|
47
|
+
function keyWithParameters(method: string, url: string): string {
|
|
48
|
+
const parts = url.split("/").map((part) => {
|
|
49
|
+
const parameter = PARAMETER_SEGMENT_RE.exec(part);
|
|
50
|
+
const name = parameter?.[1] ?? parameter?.[2];
|
|
51
|
+
return name === undefined ? part : `By${parameterWord(name)}`;
|
|
52
|
+
});
|
|
53
|
+
return keyFromUrl(method, parts.join("/"));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface PathOperation {
|
|
57
|
+
readonly url: string;
|
|
58
|
+
readonly method: string;
|
|
59
|
+
readonly operationId: string | undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The operations of one path item in document order; `additionalOperations` (OpenAPI 3.2) adds
|
|
64
|
+
* its methods where the key stands.
|
|
65
|
+
*/
|
|
66
|
+
function pathItemEntries(pathItem: object): [string, unknown][] {
|
|
67
|
+
return Object.entries(pathItem).flatMap(([key, value]): [string, unknown][] => {
|
|
68
|
+
if (key === ADDITIONAL_OPERATIONS_KEY) {
|
|
69
|
+
return typeof value === "object" && value !== null ? Object.entries(value) : [];
|
|
70
|
+
}
|
|
71
|
+
return METHODS.has(key) ? [[key, value]] : [];
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function pathOperations(paths: PathsObject): PathOperation[] {
|
|
76
|
+
return Object.entries(paths).flatMap(([url, pathItem]) =>
|
|
77
|
+
pathItemEntries(pathItem).map(([method, operation]) => {
|
|
78
|
+
const operationId = (operation as OperationObject).operationId || undefined;
|
|
79
|
+
return { url, method, operationId };
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function countOf(names: readonly string[]): Map<string, number> {
|
|
85
|
+
const counts = new Map<string, number>();
|
|
86
|
+
for (const name of names) {
|
|
87
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
88
|
+
}
|
|
89
|
+
return counts;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Names that are unique, so the enum compiles (upstream #2194). A URL key that collides names
|
|
94
|
+
* its parameters; a name that still collides gets 2, 3… after its first use.
|
|
95
|
+
*/
|
|
96
|
+
function uniqueNames(operations: readonly PathOperation[]): string[] {
|
|
97
|
+
const keys = operations.map((op) => op.operationId ?? keyFromUrl(op.method, op.url));
|
|
98
|
+
const counts = countOf(keys);
|
|
99
|
+
const named = operations.map((op, index) => {
|
|
100
|
+
const isCollidingUrlKey =
|
|
101
|
+
op.operationId === undefined && (counts.get(keys[index] as string) ?? 0) > 1;
|
|
102
|
+
return isCollidingUrlKey ? keyWithParameters(op.method, op.url) : (keys[index] as string);
|
|
103
|
+
});
|
|
104
|
+
return withNumberedRepeats(named, (name, count) => `${name}${count}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* One enum member per operation: the URL as the value, the operation ID (or a key built from the
|
|
109
|
+
* method and URL) as the name. Paths are in document order; `--alphabetize` does not apply.
|
|
110
|
+
*/
|
|
111
|
+
export function apiPathsEnum(paths: PathsObject): ApiPathsEnum {
|
|
112
|
+
const operations = pathOperations(paths);
|
|
113
|
+
const names = uniqueNames(operations);
|
|
114
|
+
return {
|
|
115
|
+
values: operations.map((operation) => operation.url),
|
|
116
|
+
metadata: names.map((name) => ({ name, description: undefined })),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The `ApiPaths` enum declaration. Its own naming state is equivalent to the run's: the name is a
|
|
122
|
+
* valid identifier, and member names only reset the state, never read it.
|
|
123
|
+
*/
|
|
124
|
+
export function apiPathsEnumDeclaration(paths: PathsObject): IrEnumDeclaration {
|
|
125
|
+
const naming = new EnumNaming();
|
|
126
|
+
return enumDeclaration(naming.enumName(API_PATHS_NAME), apiPathsEnum(paths), naming);
|
|
127
|
+
}
|