openapi-typesafe 1.0.0-rc.4 → 1.0.0-rc.6
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 +214 -0
- package/dist/adapters/node-file-system/node-file-system.cjs +7 -0
- package/dist/adapters/node-file-system/node-file-system.cjs.map +1 -1
- package/dist/adapters/node-file-system/node-file-system.mjs +7 -0
- 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 +5 -32
- package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs.map +1 -1
- package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs +6 -33
- package/dist/adapters/redocly-loader/bundled-mapping-copies.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/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-document-names.cjs +50 -0
- package/dist/adapters/redocly-loader/query-document-names.cjs.map +1 -0
- package/dist/adapters/redocly-loader/query-document-names.mjs +48 -0
- package/dist/adapters/redocly-loader/query-document-names.mjs.map +1 -0
- package/dist/adapters/redocly-loader/query-named-components.cjs +129 -0
- package/dist/adapters/redocly-loader/query-named-components.cjs.map +1 -0
- package/dist/adapters/redocly-loader/query-named-components.mjs +126 -0
- package/dist/adapters/redocly-loader/query-named-components.mjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-config-source.cjs +3 -0
- package/dist/adapters/redocly-loader/redocly-config-source.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-config-source.mjs +4 -1
- package/dist/adapters/redocly-loader/redocly-config-source.mjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +39 -18
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +40 -19
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.cjs +25 -4
- package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.mjs +26 -5
- 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 +52 -11
- package/dist/adapters/redocly-loader/ref-holders.mjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-fetch.cjs +20 -3
- package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-fetch.mjs +20 -4
- package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-node-limit.cjs +17 -3
- package/dist/adapters/redocly-loader/remote-node-limit.cjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-node-limit.mjs +17 -3
- package/dist/adapters/redocly-loader/remote-node-limit.mjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-source.cjs +7 -2
- package/dist/adapters/redocly-loader/schema-source.cjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-source.mjs +8 -3
- package/dist/adapters/redocly-loader/schema-source.mjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.cjs +7 -3
- package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.mjs +7 -3
- package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
- package/dist/api/cwd-option.cjs +58 -0
- package/dist/api/cwd-option.cjs.map +1 -0
- package/dist/api/cwd-option.mjs +52 -0
- package/dist/api/cwd-option.mjs.map +1 -0
- package/dist/api/default-ports.cjs +15 -7
- package/dist/api/default-ports.cjs.map +1 -1
- package/dist/api/default-ports.mjs +14 -8
- package/dist/api/default-ports.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 -26
- package/dist/api/document-run.cjs.map +1 -1
- package/dist/api/document-run.mjs +5 -21
- package/dist/api/document-run.mjs.map +1 -1
- package/dist/api/legacy-utils.cjs +1 -1
- package/dist/api/legacy-utils.cjs.map +1 -1
- package/dist/api/legacy-utils.mjs +1 -1
- package/dist/api/legacy-utils.mjs.map +1 -1
- package/dist/api/openapi-ts.cjs +1 -2
- package/dist/api/openapi-ts.cjs.map +1 -1
- package/dist/api/openapi-ts.mjs +2 -3
- package/dist/api/openapi-ts.mjs.map +1 -1
- package/dist/api/option-errors.cjs +24 -0
- package/dist/api/option-errors.cjs.map +1 -0
- package/dist/api/option-errors.mjs +21 -0
- package/dist/api/option-errors.mjs.map +1 -0
- package/dist/api/ref-limit-options.cjs +58 -0
- package/dist/api/ref-limit-options.cjs.map +1 -0
- package/dist/api/ref-limit-options.mjs +52 -0
- package/dist/api/ref-limit-options.mjs.map +1 -0
- package/dist/api/transform-schema.cjs +12 -5
- package/dist/api/transform-schema.cjs.map +1 -1
- package/dist/api/transform-schema.mjs +12 -5
- package/dist/api/transform-schema.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/document.cjs +3 -1
- package/dist/application/transform/document/document.cjs.map +1 -1
- package/dist/application/transform/document/document.mjs +3 -1
- package/dist/application/transform/document/document.mjs.map +1 -1
- 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/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/parameter.cjs +1 -1
- package/dist/application/transform/document/parameter.cjs.map +1 -1
- package/dist/application/transform/document/parameter.mjs +1 -1
- package/dist/application/transform/document/parameter.mjs.map +1 -1
- package/dist/application/transform/document/parameters.cjs +23 -5
- package/dist/application/transform/document/parameters.cjs.map +1 -1
- package/dist/application/transform/document/parameters.mjs +23 -5
- package/dist/application/transform/document/parameters.mjs.map +1 -1
- package/dist/application/transform/document/path-item.cjs +4 -3
- package/dist/application/transform/document/path-item.cjs.map +1 -1
- package/dist/application/transform/document/path-item.mjs +4 -4
- 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 +80 -0
- package/dist/application/transform/document/path-template-refs.cjs.map +1 -0
- package/dist/application/transform/document/path-template-refs.mjs +77 -0
- package/dist/application/transform/document/path-template-refs.mjs.map +1 -0
- package/dist/application/transform/document/paths-enum.cjs +7 -6
- package/dist/application/transform/document/paths-enum.cjs.map +1 -1
- package/dist/application/transform/document/paths-enum.mjs +7 -6
- package/dist/application/transform/document/paths-enum.mjs.map +1 -1
- package/dist/application/transform/document/paths.cjs +38 -66
- package/dist/application/transform/document/paths.cjs.map +1 -1
- package/dist/application/transform/document/paths.mjs +36 -66
- package/dist/application/transform/document/paths.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 +9 -2
- package/dist/application/transform/document/webhooks.mjs.map +1 -1
- package/dist/application/transform/footer/document-footer.cjs +6 -3
- package/dist/application/transform/footer/document-footer.cjs.map +1 -1
- package/dist/application/transform/footer/document-footer.mjs +6 -3
- package/dist/application/transform/footer/document-footer.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/ref-pointer/generated-location.cjs +4 -4
- package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/generated-location.mjs +1 -1
- package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -1
- package/dist/application/transform/ref-pointer/generated-shape.cjs +63 -64
- package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/generated-shape.mjs +57 -53
- 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 +69 -14
- package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/original-index.mjs +71 -16
- 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 +57 -0
- package/dist/application/transform/ref-pointer/property-shape.cjs.map +1 -0
- package/dist/application/transform/ref-pointer/property-shape.mjs +49 -0
- package/dist/application/transform/ref-pointer/property-shape.mjs.map +1 -0
- package/dist/application/transform/ref-pointer/typed-walk.cjs +90 -22
- package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -1
- package/dist/application/transform/ref-pointer/typed-walk.mjs +87 -19
- package/dist/application/transform/ref-pointer/typed-walk.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/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 +15 -5
- package/dist/application/transform/schema/object-type.cjs.map +1 -1
- package/dist/application/transform/schema/object-type.mjs +15 -5
- package/dist/application/transform/schema/object-type.mjs.map +1 -1
- package/dist/application/transform/schema/schema-transform.cjs +2 -1
- package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
- package/dist/application/transform/schema/schema-transform.mjs +2 -1
- 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/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 +10 -17
- package/dist/cli/api-settings.cjs.map +1 -1
- package/dist/cli/api-settings.mjs +10 -17
- package/dist/cli/api-settings.mjs.map +1 -1
- package/dist/cli/api-writes.cjs +7 -1
- package/dist/cli/api-writes.cjs.map +1 -1
- package/dist/cli/api-writes.mjs +7 -1
- package/dist/cli/api-writes.mjs.map +1 -1
- package/dist/cli/cli-arguments.cjs +32 -74
- package/dist/cli/cli-arguments.cjs.map +1 -1
- package/dist/cli/cli-arguments.mjs +28 -70
- package/dist/cli/cli-arguments.mjs.map +1 -1
- package/dist/cli/cli-errors.cjs +18 -0
- package/dist/cli/cli-errors.cjs.map +1 -1
- package/dist/cli/cli-errors.mjs +18 -1
- package/dist/cli/cli-errors.mjs.map +1 -1
- package/dist/cli/cli-flag-names.cjs +77 -0
- package/dist/cli/cli-flag-names.cjs.map +1 -0
- package/dist/cli/cli-flag-names.mjs +64 -0
- package/dist/cli/cli-flag-names.mjs.map +1 -0
- package/dist/cli/cli-output.cjs +13 -6
- package/dist/cli/cli-output.cjs.map +1 -1
- package/dist/cli/cli-output.mjs +14 -7
- package/dist/cli/cli-output.mjs.map +1 -1
- package/dist/cli/main.cjs +11 -5
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.mjs +11 -5
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/redocly-apis.cjs +33 -12
- package/dist/cli/redocly-apis.cjs.map +1 -1
- package/dist/cli/redocly-apis.mjs +35 -14
- 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 +24 -7
- package/dist/cli/run-cli.cjs.map +1 -1
- package/dist/cli/run-cli.mjs +25 -8
- package/dist/cli/run-cli.mjs.map +1 -1
- package/dist/cli/written-flags.cjs +83 -0
- package/dist/cli/written-flags.cjs.map +1 -0
- package/dist/cli/written-flags.mjs +77 -0
- package/dist/cli/written-flags.mjs.map +1 -0
- package/dist/domain/cause-secrets.cjs +31 -16
- package/dist/domain/cause-secrets.cjs.map +1 -1
- package/dist/domain/cause-secrets.mjs +31 -16
- package/dist/domain/cause-secrets.mjs.map +1 -1
- package/dist/domain/errors.cjs +3 -0
- package/dist/domain/errors.cjs.map +1 -1
- package/dist/domain/errors.mjs +3 -0
- package/dist/domain/errors.mjs.map +1 -1
- package/dist/domain/location-text.cjs +15 -0
- package/dist/domain/location-text.cjs.map +1 -0
- package/dist/domain/location-text.mjs +13 -0
- package/dist/domain/location-text.mjs.map +1 -0
- 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/output-fixes.cjs +8 -2
- package/dist/domain/output-fixes.cjs.map +1 -1
- package/dist/domain/output-fixes.mjs +8 -2
- 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/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 +29 -18
- package/dist/index.d.mts +29 -18
- package/dist/index.d.ts +29 -18
- package/package.json +1 -1
- package/src/adapters/node-file-system/node-file-system.ts +14 -1
- package/src/adapters/pipe-safe-writer/pipe-safe-writer.ts +29 -0
- package/src/adapters/redocly-loader/bundled-mapping-copies.ts +7 -42
- package/src/adapters/redocly-loader/component-schemas.ts +19 -0
- package/src/adapters/redocly-loader/mapping-schema-names.ts +25 -0
- package/src/adapters/redocly-loader/query-document-names.ts +79 -0
- package/src/adapters/redocly-loader/query-named-components.ts +200 -0
- package/src/adapters/redocly-loader/redocly-config-source.ts +11 -1
- package/src/adapters/redocly-loader/redocly-schema-loader.ts +63 -17
- package/src/adapters/redocly-loader/ref-access.ts +32 -5
- package/src/adapters/redocly-loader/ref-holders.ts +75 -14
- package/src/adapters/redocly-loader/remote-fetch.ts +37 -2
- package/src/adapters/redocly-loader/remote-node-limit.ts +44 -4
- package/src/adapters/redocly-loader/schema-source.ts +15 -3
- package/src/adapters/terminal-logger/terminal-logger.ts +10 -4
- package/src/api/cwd-option.ts +76 -0
- package/src/api/default-ports.ts +33 -10
- package/src/api/document-refs.ts +29 -1
- package/src/api/document-run.ts +7 -32
- package/src/api/legacy-utils.ts +1 -1
- package/src/api/openapi-ts.ts +20 -4
- package/src/api/option-errors.ts +22 -0
- package/src/api/ref-limit-options.ts +69 -0
- package/src/api/transform-schema.ts +20 -5
- package/src/application/ports/file-system.ts +8 -0
- package/src/application/ports/redocly-config-source.ts +5 -0
- package/src/application/transform/declared-value-types.ts +42 -0
- package/src/application/transform/document/document.ts +4 -2
- package/src/application/transform/document/exploded-query-values.ts +88 -0
- package/src/application/transform/document/header.ts +25 -5
- package/src/application/transform/document/parameter.ts +4 -4
- package/src/application/transform/document/parameters.ts +45 -10
- package/src/application/transform/document/path-item.ts +3 -3
- package/src/application/transform/document/path-template-key.ts +152 -0
- package/src/application/transform/document/path-template-refs.ts +127 -0
- package/src/application/transform/document/paths-enum.ts +23 -9
- package/src/application/transform/document/paths.ts +53 -123
- package/src/application/transform/document/webhooks.ts +18 -5
- package/src/application/transform/footer/document-footer.ts +18 -8
- package/src/application/transform/helper-types.ts +4 -4
- package/src/application/transform/ref-pointer/generated-location.ts +1 -1
- package/src/application/transform/ref-pointer/generated-shape.ts +115 -83
- 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 +106 -20
- 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 +106 -0
- package/src/application/transform/ref-pointer/typed-walk.ts +143 -29
- package/src/application/transform/schema/access-flags.ts +5 -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 +18 -8
- package/src/application/transform/schema/schema-transform.ts +2 -1
- package/src/application/transform/schema/unevaluated-properties.ts +4 -44
- package/src/cli/api-logger.ts +17 -0
- package/src/cli/api-settings.ts +12 -20
- package/src/cli/api-writes.ts +11 -3
- package/src/cli/cli-arguments.ts +57 -92
- package/src/cli/cli-dependencies.ts +7 -2
- package/src/cli/cli-errors.ts +23 -0
- package/src/cli/cli-flag-names.ts +99 -0
- package/src/cli/cli-output.ts +31 -16
- package/src/cli/main.ts +12 -5
- package/src/cli/redocly-apis.ts +56 -20
- package/src/cli/ref-limits.ts +21 -2
- package/src/cli/run-cli.ts +39 -7
- package/src/cli/written-flags.ts +131 -0
- package/src/domain/cause-secrets.ts +59 -25
- package/src/domain/errors.ts +3 -0
- package/src/domain/location-text.ts +27 -0
- package/src/domain/openapi/document-places.ts +78 -0
- package/src/domain/output-fixes.ts +9 -2
- package/src/domain/terminal-text.ts +44 -0
- package/src/domain/warnings.ts +1 -0
package/src/cli/api-settings.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { kebabCase } from "scule";
|
|
2
|
-
import { isOpenAPITypesafeError, OpenAPITypesafeError } from "../domain/errors.js";
|
|
3
2
|
import type { OutputFixName } from "../domain/output-fixes.js";
|
|
4
3
|
import { WARNING_CODES, warningText } from "../domain/warnings.js";
|
|
5
4
|
import { GENERATOR_FLAGS, type GeneratorFlags, hostList } from "./cli-arguments.js";
|
|
6
|
-
import { cliError } from "./cli-errors.js";
|
|
7
|
-
import { resolveLocationUrl } from "./cli-output.js";
|
|
5
|
+
import { ApiFailure, cliError } from "./cli-errors.js";
|
|
8
6
|
import { fixNamesOf } from "./fix-option.js";
|
|
9
|
-
import type
|
|
7
|
+
import { localRootUrl, type RefLimitOptions } from "./ref-limits.js";
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name
|
|
@@ -23,6 +21,7 @@ export const OUTPUT_SETTING = "output";
|
|
|
23
21
|
export const FIX_SETTING = "fix";
|
|
24
22
|
|
|
25
23
|
const LOCAL_REF_ROOT_SETTING = "localRefRoot";
|
|
24
|
+
const LOCAL_ROOT_EXPECTED = "a directory path or a file: URL";
|
|
26
25
|
const REMOTE_REF_HOSTS_SETTING = "remoteRefHosts";
|
|
27
26
|
|
|
28
27
|
/** `--content-never` is accepted and has no effect, as on the command line. */
|
|
@@ -127,31 +126,24 @@ export function apiFixNames(
|
|
|
127
126
|
try {
|
|
128
127
|
return fixNamesOf(entries);
|
|
129
128
|
} catch (error) {
|
|
130
|
-
throw
|
|
129
|
+
throw new ApiFailure(apiName, error);
|
|
131
130
|
}
|
|
132
131
|
}
|
|
133
132
|
|
|
134
|
-
/**
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
code,
|
|
139
|
-
message: `API ${apiName}: ${error.message}`,
|
|
140
|
-
details,
|
|
141
|
-
cause,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** `local-ref-root: dir`, relative to the config file; empty means the config file's directory. */
|
|
133
|
+
/**
|
|
134
|
+
* `local-ref-root: dir`, relative to the config file; empty means the config file's directory. A
|
|
135
|
+
* value that is no text or a URL of another protocol fails with `CLI_CONFIG_INVALID`.
|
|
136
|
+
*/
|
|
146
137
|
function localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {
|
|
147
138
|
if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {
|
|
148
139
|
return {};
|
|
149
140
|
}
|
|
150
141
|
const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? "";
|
|
151
|
-
|
|
152
|
-
|
|
142
|
+
const localRoot = typeof value === "string" ? localRootUrl(value, configRoot) : undefined;
|
|
143
|
+
if (localRoot === undefined) {
|
|
144
|
+
throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, LOCAL_ROOT_EXPECTED);
|
|
153
145
|
}
|
|
154
|
-
return { localRefRoot:
|
|
146
|
+
return { localRefRoot: localRoot };
|
|
155
147
|
}
|
|
156
148
|
|
|
157
149
|
/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */
|
package/src/cli/api-writes.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ClaimedFile } from "../application/ports/file-system.js";
|
|
2
2
|
import type { GeneratedTypes } from "./cli-dependencies.js";
|
|
3
|
+
import { ApiFailure } from "./cli-errors.js";
|
|
3
4
|
import {
|
|
4
5
|
type CliRun,
|
|
5
6
|
duplicateOutputError,
|
|
@@ -84,10 +85,17 @@ function writeClaimed(run: CliRun, { api, claim }: ClaimedApi): unknown[] {
|
|
|
84
85
|
: failures;
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
/** The failures with the name of their API, which the CLI prints before each message. */
|
|
89
|
+
function namedFailures(failures: ApiFailures): ApiFailures {
|
|
90
|
+
return new Map(
|
|
91
|
+
[...failures].map(([name, list]) => [name, list.map((cause) => new ApiFailure(name, cause))]),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
87
95
|
/**
|
|
88
96
|
* Write (or `--check`) every API unless its output is a file the run read or the file of another
|
|
89
|
-
* API. Returns the failures by API name
|
|
90
|
-
* one claim created is empty by the time it is removed.
|
|
97
|
+
* API. Returns the failures by API name, each an `ApiFailure`. Claims are released in reverse
|
|
98
|
+
* order, so a directory one claim created is empty by the time it is removed.
|
|
91
99
|
*/
|
|
92
100
|
export function writeGeneratedApis(
|
|
93
101
|
run: CliRun,
|
|
@@ -113,5 +121,5 @@ export function writeGeneratedApis(
|
|
|
113
121
|
for (const entry of claimed.filter(({ api }) => !shared.has(api.name))) {
|
|
114
122
|
failures.set(entry.api.name, writeClaimed(run, entry));
|
|
115
123
|
}
|
|
116
|
-
return failures;
|
|
124
|
+
return namedFailures(failures);
|
|
117
125
|
}
|
package/src/cli/cli-arguments.ts
CHANGED
|
@@ -2,51 +2,28 @@ import { kebabCase } from "scule";
|
|
|
2
2
|
import parser from "yargs-parser";
|
|
3
3
|
import type { OutputFixName } from "../domain/output-fixes.js";
|
|
4
4
|
import { cliError } from "./cli-errors.js";
|
|
5
|
+
import {
|
|
6
|
+
ALIASES,
|
|
7
|
+
BOOLEAN_FLAGS,
|
|
8
|
+
GENERATOR_FLAGS,
|
|
9
|
+
type GeneratorFlag,
|
|
10
|
+
type GeneratorFlags,
|
|
11
|
+
KNOWN_FLAGS,
|
|
12
|
+
STRING_FLAGS,
|
|
13
|
+
} from "./cli-flag-names.js";
|
|
14
|
+
import { MULTIPLE_SCHEMAS_DOCS_URL } from "./docs-links.js";
|
|
5
15
|
import { fixNamesOf } from "./fix-option.js";
|
|
16
|
+
import {
|
|
17
|
+
rejectInvalidBooleans,
|
|
18
|
+
rejectNegatedValueFlags,
|
|
19
|
+
rejectRemovedFlags,
|
|
20
|
+
unknownFlagNames,
|
|
21
|
+
writtenFlags,
|
|
22
|
+
} from "./written-flags.js";
|
|
6
23
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** Boolean flags that become generator options (camelCase; yargs also accepts kebab-case). */
|
|
10
|
-
export const GENERATOR_FLAGS = [
|
|
11
|
-
"additionalProperties",
|
|
12
|
-
"alphabetize",
|
|
13
|
-
"arrayLength",
|
|
14
|
-
"binaryAsBlob",
|
|
15
|
-
"conditionalEnums",
|
|
16
|
-
"dedupeEnums",
|
|
17
|
-
"defaultNonNullable",
|
|
18
|
-
"emptyObjectsUnknown",
|
|
19
|
-
"enum",
|
|
20
|
-
"enumValues",
|
|
21
|
-
"excludeDeprecated",
|
|
22
|
-
"exportType",
|
|
23
|
-
"generatePathParams",
|
|
24
|
-
"immutable",
|
|
25
|
-
"lint",
|
|
26
|
-
"makePathsEnum",
|
|
27
|
-
"pathParamsAsTypes",
|
|
28
|
-
"propertiesRequiredByDefault",
|
|
29
|
-
"readWriteMarkers",
|
|
30
|
-
"rootTypes",
|
|
31
|
-
"rootTypesKeepCasing",
|
|
32
|
-
"rootTypesNoSchemaPrefix",
|
|
33
|
-
] as const;
|
|
34
|
-
|
|
35
|
-
export type GeneratorFlag = (typeof GENERATOR_FLAGS)[number];
|
|
24
|
+
export { GENERATOR_FLAGS, type GeneratorFlag, type GeneratorFlags } from "./cli-flag-names.js";
|
|
36
25
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// `contentNever` was a boolean flag of the original CLI that no code reads; it stays in the list
|
|
40
|
-
// so that `--content-never <input>` keeps parsing as a flag and an input.
|
|
41
|
-
const CAMEL_CASE_BOOLEAN_FLAGS = [...GENERATOR_FLAGS, "check", "contentNever", "help"];
|
|
42
|
-
|
|
43
|
-
// yargs-parser matches the `boolean` list by the exact spelling of the flag: with camelCase names
|
|
44
|
-
// only, `--root-types schema.yaml` took the path as the flag's value (upstream #2523). Both
|
|
45
|
-
// spellings are listed.
|
|
46
|
-
const BOOLEAN_FLAGS = [
|
|
47
|
-
...CAMEL_CASE_BOOLEAN_FLAGS,
|
|
48
|
-
...CAMEL_CASE_BOOLEAN_FLAGS.map((flag) => kebabCase(flag)),
|
|
49
|
-
];
|
|
26
|
+
/** The CLI's arguments, parsed as the original CLI parsed them (yargs-parser). */
|
|
50
27
|
|
|
51
28
|
/** The `$ref` limits as the user wrote them; unset flags are absent. */
|
|
52
29
|
export interface CliRefLimits {
|
|
@@ -70,36 +47,16 @@ export interface CliArguments {
|
|
|
70
47
|
readonly unknownFlags: readonly string[];
|
|
71
48
|
}
|
|
72
49
|
|
|
73
|
-
/** Flags of older versions that were removed or renamed, with the message for each. */
|
|
74
|
-
const REMOVED_FLAGS: readonly (readonly [string, string])[] = [
|
|
75
|
-
["-ap", `The -ap alias has been deprecated. Use "--additional-properties" instead.`],
|
|
76
|
-
["--immutable-types", `The --immutable-types flag has been renamed to "--immutable".`],
|
|
77
|
-
[
|
|
78
|
-
"--support-array-length",
|
|
79
|
-
`The --support-array-length flag has been renamed to "--array-length".`,
|
|
80
|
-
],
|
|
81
|
-
["-it", `The -it alias has been deprecated. Use "--immutable" instead.`],
|
|
82
|
-
["--redoc", `The --redoc config flag has been renamed to "--redocly" (or -c as shorthand).`],
|
|
83
|
-
];
|
|
84
|
-
|
|
85
50
|
/** Flags that only work together with `--root-types`. */
|
|
86
|
-
const ROOT_TYPES_FLAGS = ["
|
|
87
|
-
|
|
88
|
-
function rejectRemovedFlags(argv: readonly string[]): void {
|
|
89
|
-
for (const [flag, message] of REMOVED_FLAGS) {
|
|
90
|
-
if (argv.includes(flag)) {
|
|
91
|
-
throw cliError("CLI_FLAG_REMOVED", message);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
51
|
+
const ROOT_TYPES_FLAGS = ["rootTypesNoSchemaPrefix", "rootTypesKeepCasing"] as const;
|
|
95
52
|
|
|
96
53
|
/** Notices for flags that have no effect in this combination, printed before the run. */
|
|
97
|
-
export function ineffectiveFlagNotices(
|
|
98
|
-
if (
|
|
54
|
+
export function ineffectiveFlagNotices(flags: GeneratorFlags): string[] {
|
|
55
|
+
if (flags.rootTypes === true) {
|
|
99
56
|
return [];
|
|
100
57
|
}
|
|
101
|
-
return ROOT_TYPES_FLAGS.filter((flag) =>
|
|
102
|
-
(flag) =>
|
|
58
|
+
return ROOT_TYPES_FLAGS.filter((flag) => flags[flag] === true).map(
|
|
59
|
+
(flag) => `--${kebabCase(flag)} has no effect without --root-types flag`,
|
|
103
60
|
);
|
|
104
61
|
}
|
|
105
62
|
|
|
@@ -117,7 +74,10 @@ function optionalString(value: unknown): string | undefined {
|
|
|
117
74
|
return value === undefined ? undefined : String(value);
|
|
118
75
|
}
|
|
119
76
|
|
|
120
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* The last value of a flag that takes one value: given twice, the last one wins, as for the
|
|
79
|
+
* boolean flags (yargs-parser gives a list of every value).
|
|
80
|
+
*/
|
|
121
81
|
function lastString(value: unknown): string | undefined {
|
|
122
82
|
return optionalString(Array.isArray(value) ? value.at(-1) : value);
|
|
123
83
|
}
|
|
@@ -146,24 +106,6 @@ function refLimitsOf(parsed: parser.Arguments): CliRefLimits {
|
|
|
146
106
|
};
|
|
147
107
|
}
|
|
148
108
|
|
|
149
|
-
/** String flags, in both spellings, so that a value such as `8080` is not read as a number. */
|
|
150
|
-
const STRING_FLAGS = [
|
|
151
|
-
"output",
|
|
152
|
-
"redocly",
|
|
153
|
-
"fix",
|
|
154
|
-
...["localRefRoot", "remoteRefHosts"].flatMap((flag) => [flag, kebabCase(flag)]),
|
|
155
|
-
];
|
|
156
|
-
|
|
157
|
-
const ALIASES = { redocly: ["c"], exportType: ["t"], output: ["o"] };
|
|
158
|
-
|
|
159
|
-
/** Every name yargs-parser can return for a flag this CLI reads. */
|
|
160
|
-
const KNOWN_FLAGS = new Set<string>([
|
|
161
|
-
...BOOLEAN_FLAGS,
|
|
162
|
-
...STRING_FLAGS,
|
|
163
|
-
...Object.values(ALIASES).flat(),
|
|
164
|
-
"version",
|
|
165
|
-
]);
|
|
166
|
-
|
|
167
109
|
/**
|
|
168
110
|
* Flags that no code reads. The original CLI ignored them silently, so a typo such as
|
|
169
111
|
* `--alphabetise` gave other output with no hint; they still do not fail the run.
|
|
@@ -186,20 +128,43 @@ function writtenFlagName(key: string, argv: readonly string[]): string {
|
|
|
186
128
|
}
|
|
187
129
|
|
|
188
130
|
/**
|
|
189
|
-
*
|
|
131
|
+
* The one schema argument. More than one fails with `CLI_INPUT_EXTRA`: the original CLI read the
|
|
132
|
+
* first and dropped the rest, so a glob the shell expanded (`g/*.yaml`) generated one schema.
|
|
133
|
+
*/
|
|
134
|
+
function inputOf(positionals: readonly (string | number)[]): string | undefined {
|
|
135
|
+
if (positionals.length > 1) {
|
|
136
|
+
throw cliError(
|
|
137
|
+
"CLI_INPUT_EXTRA",
|
|
138
|
+
`Only one schema argument is allowed, but ${positionals.length} were given: ` +
|
|
139
|
+
`${positionals.join(" ")}. A shell expands an unquoted *; to generate several ` +
|
|
140
|
+
`schemas, list them under \`apis\` in redocly.yaml. See ${MULTIPLE_SCHEMAS_DOCS_URL}`,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
return optionalString(positionals[0]);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Parse the arguments after `node cli.js`. Fails with `CLI_FLAG_REMOVED` for an old flag, with
|
|
148
|
+
* `CLI_FLAG_INVALID` for a boolean flag with another value than true or false or a `--no-` form
|
|
149
|
+
* of a flag that takes a value, with `CLI_INPUT_EXTRA` for a second schema argument, and with
|
|
190
150
|
* `OPTION_FIX_UNKNOWN` for an unknown `--fix` name.
|
|
191
151
|
*/
|
|
192
152
|
export function parseCliArguments(argv: readonly string[]): CliArguments {
|
|
193
|
-
|
|
153
|
+
const flags = writtenFlags(argv);
|
|
154
|
+
rejectRemovedFlags(flags);
|
|
155
|
+
rejectInvalidBooleans(flags);
|
|
156
|
+
rejectNegatedValueFlags(flags);
|
|
194
157
|
const parsed = parser([...argv], {
|
|
195
|
-
boolean: BOOLEAN_FLAGS,
|
|
158
|
+
boolean: [...BOOLEAN_FLAGS, ...unknownFlagNames(flags)],
|
|
196
159
|
string: STRING_FLAGS,
|
|
197
160
|
alias: ALIASES,
|
|
161
|
+
// A schema path is a file name: `1.10` is not the number 1.1.
|
|
162
|
+
configuration: { "parse-positional-numbers": false },
|
|
198
163
|
});
|
|
199
164
|
return {
|
|
200
|
-
input:
|
|
201
|
-
output:
|
|
202
|
-
redocly:
|
|
165
|
+
input: inputOf(parsed._),
|
|
166
|
+
output: lastString(parsed.output),
|
|
167
|
+
redocly: lastString(parsed.redocly),
|
|
203
168
|
isCheck: parsed.check === true,
|
|
204
169
|
isHelp: "help" in parsed,
|
|
205
170
|
isVersion: "version" in parsed,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Readable } from "node:stream";
|
|
2
2
|
import type {
|
|
3
3
|
DirectoryCheck,
|
|
4
|
+
FileCheck,
|
|
4
5
|
FileClaims,
|
|
5
6
|
FileIdentity,
|
|
6
7
|
FileReader,
|
|
@@ -33,10 +34,14 @@ export interface GeneratedTypes {
|
|
|
33
34
|
readonly localFiles: readonly URL[];
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Generate the types of one schema. With `apiName`, an API of `redocly.yaml`, every line the
|
|
39
|
+
* generation logs names that API.
|
|
40
|
+
*/
|
|
37
41
|
export type GenerateTypes = (
|
|
38
42
|
source: SchemaSource,
|
|
39
43
|
options: GeneratorOptions,
|
|
44
|
+
apiName?: string,
|
|
40
45
|
) => Promise<GeneratedTypes>;
|
|
41
46
|
|
|
42
47
|
export interface CliDependencies {
|
|
@@ -55,7 +60,7 @@ export interface CliDependencies {
|
|
|
55
60
|
* input with no prompt, which looks like a hang (upstream #1905).
|
|
56
61
|
*/
|
|
57
62
|
readonly isStdinTerminal: () => boolean;
|
|
58
|
-
readonly files: FileReader & FileWriter & FileIdentity & DirectoryCheck & FileClaims;
|
|
63
|
+
readonly files: FileReader & FileWriter & FileIdentity & DirectoryCheck & FileCheck & FileClaims;
|
|
59
64
|
readonly redoclyConfigs: RedoclyConfigSource;
|
|
60
65
|
readonly generate: GenerateTypes;
|
|
61
66
|
/** A monotonic time in milliseconds, for the time printed after each output. */
|
package/src/cli/cli-errors.ts
CHANGED
|
@@ -99,14 +99,17 @@ const CLI_ERROR_REPORTS: Readonly<Record<ErrorCode, CliErrorReport>> = {
|
|
|
99
99
|
ENUM_NAME_EMPTY: { exitCode: EXIT_CODES.SCHEMA },
|
|
100
100
|
CALLBACK_RESULT_UNREADABLE: { exitCode: EXIT_CODES.USAGE },
|
|
101
101
|
OPTION_FIX_UNKNOWN: { exitCode: EXIT_CODES.USAGE },
|
|
102
|
+
OPTION_INVALID: { exitCode: EXIT_CODES.USAGE },
|
|
102
103
|
TYPESCRIPT_NOT_FOUND: { exitCode: EXIT_CODES.USAGE },
|
|
103
104
|
CLI_FLAG_REMOVED: { exitCode: EXIT_CODES.USAGE },
|
|
105
|
+
CLI_FLAG_INVALID: { exitCode: EXIT_CODES.USAGE },
|
|
104
106
|
CLI_GLOB_UNSUPPORTED: { exitCode: EXIT_CODES.USAGE },
|
|
105
107
|
CLI_CONFIG_NOT_FOUND: { exitCode: EXIT_CODES.USAGE },
|
|
106
108
|
CLI_CONFIG_INVALID: { exitCode: EXIT_CODES.USAGE },
|
|
107
109
|
CLI_CONFIG_OUTPUT_MISSING: { exitCode: EXIT_CODES.USAGE },
|
|
108
110
|
CLI_CHECK_OUTPUT_MISSING: { exitCode: EXIT_CODES.USAGE },
|
|
109
111
|
CLI_INPUT_MISSING: { exitCode: EXIT_CODES.USAGE },
|
|
112
|
+
CLI_INPUT_EXTRA: { exitCode: EXIT_CODES.USAGE },
|
|
110
113
|
CLI_OUTPUT_IS_INPUT: { exitCode: EXIT_CODES.USAGE },
|
|
111
114
|
CLI_OUTPUT_DUPLICATE: { exitCode: EXIT_CODES.USAGE },
|
|
112
115
|
CLI_OUTPUT_INVALID: { exitCode: EXIT_CODES.USAGE },
|
|
@@ -127,6 +130,10 @@ export interface CliFailure {
|
|
|
127
130
|
* else is a bug and prints its stack, so it can be reported.
|
|
128
131
|
*/
|
|
129
132
|
export function describeCliFailure(error: unknown): CliFailure {
|
|
133
|
+
if (error instanceof ApiFailure) {
|
|
134
|
+
const failure = describeCliFailure(error.cause);
|
|
135
|
+
return { ...failure, message: `API ${error.apiName}: ${failure.message}` };
|
|
136
|
+
}
|
|
130
137
|
if (!isOpenAPITypesafeError(error)) {
|
|
131
138
|
const text = error instanceof Error ? (error.stack ?? error.message) : String(error);
|
|
132
139
|
return { exitCode: EXIT_CODES.INTERNAL, message: `Unexpected error: ${text}` };
|
|
@@ -136,6 +143,22 @@ export function describeCliFailure(error: unknown): CliFailure {
|
|
|
136
143
|
return { exitCode: report.exitCode, message: `${message} (${error.code})` };
|
|
137
144
|
}
|
|
138
145
|
|
|
146
|
+
/**
|
|
147
|
+
* A failure of one API of a Redocly config. The CLI reports its cause with the API named first,
|
|
148
|
+
* as the config errors of an API are; the cause keeps its code and so its exit code.
|
|
149
|
+
*/
|
|
150
|
+
export class ApiFailure extends Error {
|
|
151
|
+
override readonly name = "ApiFailure";
|
|
152
|
+
override readonly cause: unknown;
|
|
153
|
+
readonly apiName: string;
|
|
154
|
+
|
|
155
|
+
constructor(apiName: string, cause: unknown) {
|
|
156
|
+
super(`API ${apiName} failed`, { cause });
|
|
157
|
+
this.apiName = apiName;
|
|
158
|
+
this.cause = cause;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
139
162
|
/** Errors of the CLI itself; its messages are the original CLI's messages. */
|
|
140
163
|
export function cliError(
|
|
141
164
|
code: Extract<ErrorCode, `CLI_${string}` | `OUTPUT_${string}`>,
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { kebabCase } from "scule";
|
|
2
|
+
|
|
3
|
+
/** The names of the CLI's flags, in the spellings yargs-parser is told about. */
|
|
4
|
+
|
|
5
|
+
/** Boolean flags that become generator options (camelCase; yargs also accepts kebab-case). */
|
|
6
|
+
export const GENERATOR_FLAGS = [
|
|
7
|
+
"additionalProperties",
|
|
8
|
+
"alphabetize",
|
|
9
|
+
"arrayLength",
|
|
10
|
+
"binaryAsBlob",
|
|
11
|
+
"conditionalEnums",
|
|
12
|
+
"dedupeEnums",
|
|
13
|
+
"defaultNonNullable",
|
|
14
|
+
"emptyObjectsUnknown",
|
|
15
|
+
"enum",
|
|
16
|
+
"enumValues",
|
|
17
|
+
"excludeDeprecated",
|
|
18
|
+
"exportType",
|
|
19
|
+
"generatePathParams",
|
|
20
|
+
"immutable",
|
|
21
|
+
"lint",
|
|
22
|
+
"makePathsEnum",
|
|
23
|
+
"pathParamsAsTypes",
|
|
24
|
+
"propertiesRequiredByDefault",
|
|
25
|
+
"readWriteMarkers",
|
|
26
|
+
"rootTypes",
|
|
27
|
+
"rootTypesKeepCasing",
|
|
28
|
+
"rootTypesNoSchemaPrefix",
|
|
29
|
+
] as const;
|
|
30
|
+
|
|
31
|
+
export type GeneratorFlag = (typeof GENERATOR_FLAGS)[number];
|
|
32
|
+
|
|
33
|
+
export type GeneratorFlags = Readonly<Partial<Record<GeneratorFlag, boolean>>>;
|
|
34
|
+
|
|
35
|
+
// `contentNever` was a boolean flag of the original CLI that no code reads; it stays in the list
|
|
36
|
+
// so that `--content-never <input>` keeps parsing as a flag and an input.
|
|
37
|
+
const CAMEL_CASE_BOOLEAN_FLAGS = [...GENERATOR_FLAGS, "check", "contentNever", "help"];
|
|
38
|
+
|
|
39
|
+
// yargs-parser matches the `boolean` list by the exact spelling of the flag: with camelCase names
|
|
40
|
+
// only, `--root-types schema.yaml` took the path as the flag's value (upstream #2523). Both
|
|
41
|
+
// spellings are listed.
|
|
42
|
+
export const BOOLEAN_FLAGS = [
|
|
43
|
+
...CAMEL_CASE_BOOLEAN_FLAGS,
|
|
44
|
+
...CAMEL_CASE_BOOLEAN_FLAGS.map((flag) => kebabCase(flag)),
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
export const ALIASES = { redocly: ["c"], exportType: ["t"], output: ["o"] };
|
|
48
|
+
|
|
49
|
+
const CAMEL_CASE_STRING_FLAGS = ["output", "redocly", "fix", "localRefRoot", "remoteRefHosts"];
|
|
50
|
+
|
|
51
|
+
/** String flags, in both spellings, so that a value such as `8080` is not read as a number. */
|
|
52
|
+
export const STRING_FLAGS = [
|
|
53
|
+
...CAMEL_CASE_STRING_FLAGS,
|
|
54
|
+
...CAMEL_CASE_STRING_FLAGS.map((flag) => kebabCase(flag)),
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
/** Every name yargs-parser can return for a flag this CLI reads. */
|
|
58
|
+
export const KNOWN_FLAGS: ReadonlySet<string> = new Set<string>([
|
|
59
|
+
...BOOLEAN_FLAGS,
|
|
60
|
+
...STRING_FLAGS,
|
|
61
|
+
...Object.values(ALIASES).flat(),
|
|
62
|
+
"version",
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
export const LONG_PREFIX = "--";
|
|
66
|
+
export const SHORT_PREFIX = "-";
|
|
67
|
+
export const NEGATION_PREFIX = "--no-";
|
|
68
|
+
|
|
69
|
+
/** The short aliases of `flags`, as written on the command line (`-t`). */
|
|
70
|
+
function aliasesOf(flags: readonly string[]): string[] {
|
|
71
|
+
return Object.entries(ALIASES)
|
|
72
|
+
.filter(([flag]) => flags.includes(flag))
|
|
73
|
+
.flatMap(([, aliases]) => aliases.map((alias) => `${SHORT_PREFIX}${alias}`));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The boolean flags as written, `--` and `-` included; they take `=true` or `=false`. */
|
|
77
|
+
export const BOOLEAN_FLAG_NAMES: ReadonlySet<string> = new Set([
|
|
78
|
+
...BOOLEAN_FLAGS.map((flag) => `${LONG_PREFIX}${flag}`),
|
|
79
|
+
...aliasesOf(CAMEL_CASE_BOOLEAN_FLAGS),
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The flags that take a value, as `canonicalFlagName` gives them: kebab-case, and the short
|
|
84
|
+
* aliases with `--`, since yargs-parser reads `--no-o` as the negation of `-o`.
|
|
85
|
+
*/
|
|
86
|
+
export const VALUE_FLAG_NAMES: ReadonlySet<string> = new Set([
|
|
87
|
+
...CAMEL_CASE_STRING_FLAGS.map((flag) => `${LONG_PREFIX}${kebabCase(flag)}`),
|
|
88
|
+
...aliasesOf(CAMEL_CASE_STRING_FLAGS).map((alias) => `${SHORT_PREFIX}${alias}`),
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
/** The long flags this CLI reads, as `canonicalFlagName` gives them. */
|
|
92
|
+
export const KNOWN_LONG_FLAG_NAMES: ReadonlySet<string> = new Set(
|
|
93
|
+
[...KNOWN_FLAGS]
|
|
94
|
+
.filter((flag) => flag.length > 1)
|
|
95
|
+
.map((flag) => `${LONG_PREFIX}${kebabCase(flag)}`),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
/** The short flags this CLI reads, without the `-`. */
|
|
99
|
+
export const KNOWN_SHORT_FLAGS: ReadonlySet<string> = new Set(Object.values(ALIASES).flat());
|
package/src/cli/cli-output.ts
CHANGED
|
@@ -2,7 +2,9 @@ import path from "node:path";
|
|
|
2
2
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
import { formatDuration } from "../adapters/terminal-logger/terminal-logger.js";
|
|
4
4
|
import type { RedoclyConfig } from "../application/ports/redocly-config-source.js";
|
|
5
|
-
import {
|
|
5
|
+
import { hasUrlScheme } from "../domain/location-text.js";
|
|
6
|
+
import { terminalSafeText } from "../domain/terminal-text.js";
|
|
7
|
+
import { redactUnparsedUrl, redactUrlSecrets } from "../domain/url-secrets.js";
|
|
6
8
|
import type { CliArguments } from "./cli-arguments.js";
|
|
7
9
|
import type { CliDependencies, GeneratedTypes } from "./cli-dependencies.js";
|
|
8
10
|
import { cliError } from "./cli-errors.js";
|
|
@@ -27,12 +29,6 @@ export interface OutputFile extends NamedOutput {
|
|
|
27
29
|
readonly file: URL;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
/**
|
|
31
|
-
* A scheme of two or more characters (`https:`, `file:`). One letter is a Windows drive (`C:`), so
|
|
32
|
-
* `C:\\specs\\api.yaml` stays a path.
|
|
33
|
-
*/
|
|
34
|
-
const URL_SCHEME = /^[a-z][a-z\d+.-]+:/i;
|
|
35
|
-
|
|
36
32
|
/**
|
|
37
33
|
* The URL of a location the user wrote: a URL, else a file path, absolute or relative to the
|
|
38
34
|
* directory of `base` (a directory or file URL). A relative `file:` URL (`file:api.yaml`) resolves
|
|
@@ -41,7 +37,7 @@ const URL_SCHEME = /^[a-z][a-z\d+.-]+:/i;
|
|
|
41
37
|
* (`http://[::1/x`) fails with `CLI_LOCATION_INVALID`.
|
|
42
38
|
*/
|
|
43
39
|
export function resolveLocationUrl(location: string, base: URL): URL {
|
|
44
|
-
if (
|
|
40
|
+
if (hasUrlScheme(location)) {
|
|
45
41
|
const url = URL.parse(location, base.href);
|
|
46
42
|
if (url === null) {
|
|
47
43
|
const shown = redactUnparsedUrl(location);
|
|
@@ -191,37 +187,56 @@ export function ensureOutputIsOwn(
|
|
|
191
187
|
}
|
|
192
188
|
}
|
|
193
189
|
|
|
194
|
-
/**
|
|
190
|
+
/**
|
|
191
|
+
* `CLI_OUTPUT_DUPLICATE` for `output`, which is also the output of the `others` (named). Only
|
|
192
|
+
* APIs share outputs, and the CLI names the API before the message (`ApiFailure`).
|
|
193
|
+
*/
|
|
195
194
|
export function duplicateOutputError(output: NamedOutput, others: readonly string[]): Error {
|
|
196
195
|
return cliError(
|
|
197
196
|
"CLI_OUTPUT_DUPLICATE",
|
|
198
|
-
`The output ${output.output}
|
|
199
|
-
|
|
197
|
+
`The output ${output.output} is also the output of ${others.join(", ")}: they would ` +
|
|
198
|
+
"overwrite each other. Give each API its own output file.",
|
|
200
199
|
);
|
|
201
200
|
}
|
|
202
201
|
|
|
203
202
|
/** As `resolveLocationUrl`, but undefined for a URL that does not parse instead of a throw. */
|
|
204
203
|
export function parseLocationUrl(location: string, base: URL): URL | undefined {
|
|
205
|
-
if (
|
|
204
|
+
if (hasUrlScheme(location)) {
|
|
206
205
|
return URL.parse(location, base.href) ?? undefined;
|
|
207
206
|
}
|
|
208
207
|
return resolveLocationUrl(location, base);
|
|
209
208
|
}
|
|
210
209
|
|
|
210
|
+
/**
|
|
211
|
+
* The line for a written file. It goes to the job log, so a source URL shows no secrets, and a
|
|
212
|
+
* line break or escape sequence in a name cannot start a forged line.
|
|
213
|
+
*/
|
|
211
214
|
function printDone(run: CliRun, output: OutputFile): void {
|
|
212
215
|
const { style, now } = run.deps;
|
|
213
|
-
const
|
|
216
|
+
const source = terminalSafeText(redactUrlSecrets(output.source));
|
|
217
|
+
const target = style.green(`${source} → ${style.bold(terminalSafeText(output.output))}`);
|
|
214
218
|
const duration = style.dim(`[${formatDuration(now() - run.startedAt)}]`);
|
|
215
219
|
run.deps.console.info(`🚀 ${target} ${duration}`);
|
|
216
220
|
}
|
|
217
221
|
|
|
222
|
+
const CRLF = /\r\n/g;
|
|
223
|
+
const LF = "\n";
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* The text with LF line ends. Git with `core.autocrlf` checks a committed file out with CRLF on
|
|
227
|
+
* Windows, so `--check` compares lines, not line ends.
|
|
228
|
+
*/
|
|
229
|
+
function withLfLineEnds(text: string): string {
|
|
230
|
+
return text.replace(CRLF, LF);
|
|
231
|
+
}
|
|
232
|
+
|
|
218
233
|
/**
|
|
219
|
-
* With `--check`, fail with `OUTPUT_STALE` when the file differs from `contents`
|
|
220
|
-
* alone otherwise. Without it, write the file and print where it went.
|
|
234
|
+
* With `--check`, fail with `OUTPUT_STALE` when the file differs from `contents` (line ends
|
|
235
|
+
* aside) and leave it alone otherwise. Without it, write the file and print where it went.
|
|
221
236
|
*/
|
|
222
237
|
export function emitOutput(run: CliRun, output: OutputFile, contents: string): void {
|
|
223
238
|
if (run.args.isCheck) {
|
|
224
|
-
if (run.deps.files.readText(output.file) !== contents) {
|
|
239
|
+
if (withLfLineEnds(run.deps.files.readText(output.file)) !== withLfLineEnds(contents)) {
|
|
225
240
|
// The original message, then the file: with several APIs it tells which one is stale.
|
|
226
241
|
throw cliError(
|
|
227
242
|
"OUTPUT_STALE",
|
package/src/cli/main.ts
CHANGED
|
@@ -3,11 +3,14 @@ import { isatty } from "node:tty";
|
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
import colors from "ansi-colors";
|
|
5
5
|
import { createNodeFileSystem } from "../adapters/node-file-system/node-file-system.js";
|
|
6
|
+
import { createPipeSafeWriter } from "../adapters/pipe-safe-writer/pipe-safe-writer.js";
|
|
6
7
|
import { createRedoclyConfigSource } from "../adapters/redocly-loader/redocly-config-source.js";
|
|
7
8
|
import { astToString } from "../api/ast-to-string.js";
|
|
8
9
|
import { COMMENT_HEADER } from "../api/comment-header.js";
|
|
9
10
|
import { defaultLogger, monotonicNow, terminalSupportsColor } from "../api/default-ports.js";
|
|
10
11
|
import { defaultGeneratorPorts, generateDocument } from "../api/openapi-ts.js";
|
|
12
|
+
import { terminalSafeText } from "../domain/terminal-text.js";
|
|
13
|
+
import { apiLogger } from "./api-logger.js";
|
|
11
14
|
import type { CliConsole, CliDependencies, GenerateTypes, TextStyle } from "./cli-dependencies.js";
|
|
12
15
|
import { runCli } from "./run-cli.js";
|
|
13
16
|
|
|
@@ -24,9 +27,10 @@ function readVersion(): string {
|
|
|
24
27
|
return packageJson.version;
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
/** The style of the CLI's own lines, which go to stdout. */
|
|
27
31
|
function terminalStyle(): TextStyle {
|
|
28
32
|
const palette = colors.create();
|
|
29
|
-
palette.enabled = terminalSupportsColor();
|
|
33
|
+
palette.enabled = terminalSupportsColor("stdout");
|
|
30
34
|
return {
|
|
31
35
|
bold: (text) => palette.bold(text),
|
|
32
36
|
green: (text) => palette.green(text),
|
|
@@ -36,8 +40,10 @@ function terminalStyle(): TextStyle {
|
|
|
36
40
|
|
|
37
41
|
const STDIN_DESCRIPTOR = 0;
|
|
38
42
|
|
|
39
|
-
const generateTypes: GenerateTypes = async (source, options) => {
|
|
40
|
-
const
|
|
43
|
+
const generateTypes: GenerateTypes = async (source, options, apiName) => {
|
|
44
|
+
const terminalLogger = defaultLogger(options.silent ?? false);
|
|
45
|
+
const logger = apiName === undefined ? terminalLogger : apiLogger(terminalLogger, apiName);
|
|
46
|
+
const ports = await defaultGeneratorPorts(options, logger);
|
|
41
47
|
const { declarations, localFiles } = await generateDocument(source, options, ports);
|
|
42
48
|
return { contents: `${COMMENT_HEADER}${astToString(declarations)}`, localFiles };
|
|
43
49
|
};
|
|
@@ -46,8 +52,9 @@ function terminalConsole(): CliConsole {
|
|
|
46
52
|
return {
|
|
47
53
|
// biome-ignore lint/suspicious/noConsole: the CLI's own output lines
|
|
48
54
|
info: (text) => console.info(text),
|
|
55
|
+
// A notice names flags and API names as written, so it is shown as one plain line.
|
|
49
56
|
// biome-ignore lint/suspicious/noConsole: the CLI's own notices
|
|
50
|
-
notice: (text) => console.warn(text),
|
|
57
|
+
notice: (text) => console.warn(terminalSafeText(text)),
|
|
51
58
|
};
|
|
52
59
|
}
|
|
53
60
|
|
|
@@ -58,7 +65,7 @@ function processDependencies(): CliDependencies {
|
|
|
58
65
|
version: readVersion(),
|
|
59
66
|
logger: defaultLogger(false),
|
|
60
67
|
console: terminalConsole(),
|
|
61
|
-
writeStdout: (
|
|
68
|
+
writeStdout: createPipeSafeWriter(process.stdout),
|
|
62
69
|
stdin: () => process.stdin,
|
|
63
70
|
// `isatty` reads the descriptor without opening `process.stdin`, which would keep the
|
|
64
71
|
// process alive.
|