openapi-typesafe 1.0.0-rc.5 → 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.
Files changed (148) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/dist/adapters/redocly-loader/query-document-names.cjs +50 -0
  3. package/dist/adapters/redocly-loader/query-document-names.cjs.map +1 -0
  4. package/dist/adapters/redocly-loader/query-document-names.mjs +48 -0
  5. package/dist/adapters/redocly-loader/query-document-names.mjs.map +1 -0
  6. package/dist/adapters/redocly-loader/query-named-components.cjs +29 -37
  7. package/dist/adapters/redocly-loader/query-named-components.cjs.map +1 -1
  8. package/dist/adapters/redocly-loader/query-named-components.mjs +29 -37
  9. package/dist/adapters/redocly-loader/query-named-components.mjs.map +1 -1
  10. package/dist/adapters/redocly-loader/redocly-config-source.cjs +3 -0
  11. package/dist/adapters/redocly-loader/redocly-config-source.cjs.map +1 -1
  12. package/dist/adapters/redocly-loader/redocly-config-source.mjs +4 -1
  13. package/dist/adapters/redocly-loader/redocly-config-source.mjs.map +1 -1
  14. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +16 -7
  15. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
  16. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +17 -8
  17. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
  18. package/dist/adapters/redocly-loader/ref-access.cjs +9 -1
  19. package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
  20. package/dist/adapters/redocly-loader/ref-access.mjs +10 -2
  21. package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
  22. package/dist/adapters/redocly-loader/remote-fetch.cjs +16 -1
  23. package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
  24. package/dist/adapters/redocly-loader/remote-fetch.mjs +16 -2
  25. package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
  26. package/dist/api/cwd-option.cjs +58 -0
  27. package/dist/api/cwd-option.cjs.map +1 -0
  28. package/dist/api/cwd-option.mjs +52 -0
  29. package/dist/api/cwd-option.mjs.map +1 -0
  30. package/dist/api/default-ports.cjs +15 -7
  31. package/dist/api/default-ports.cjs.map +1 -1
  32. package/dist/api/default-ports.mjs +14 -8
  33. package/dist/api/default-ports.mjs.map +1 -1
  34. package/dist/api/document-run.cjs +2 -16
  35. package/dist/api/document-run.cjs.map +1 -1
  36. package/dist/api/document-run.mjs +2 -12
  37. package/dist/api/document-run.mjs.map +1 -1
  38. package/dist/api/legacy-utils.cjs +1 -1
  39. package/dist/api/legacy-utils.cjs.map +1 -1
  40. package/dist/api/legacy-utils.mjs +1 -1
  41. package/dist/api/legacy-utils.mjs.map +1 -1
  42. package/dist/api/openapi-ts.cjs.map +1 -1
  43. package/dist/api/openapi-ts.mjs.map +1 -1
  44. package/dist/api/option-errors.cjs +24 -0
  45. package/dist/api/option-errors.cjs.map +1 -0
  46. package/dist/api/option-errors.mjs +21 -0
  47. package/dist/api/option-errors.mjs.map +1 -0
  48. package/dist/api/ref-limit-options.cjs +19 -24
  49. package/dist/api/ref-limit-options.cjs.map +1 -1
  50. package/dist/api/ref-limit-options.mjs +15 -20
  51. package/dist/api/ref-limit-options.mjs.map +1 -1
  52. package/dist/application/transform/document/path-template-refs.cjs +12 -2
  53. package/dist/application/transform/document/path-template-refs.cjs.map +1 -1
  54. package/dist/application/transform/document/path-template-refs.mjs +12 -2
  55. package/dist/application/transform/document/path-template-refs.mjs.map +1 -1
  56. package/dist/application/transform/ref-pointer/generated-shape.cjs +28 -10
  57. package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -1
  58. package/dist/application/transform/ref-pointer/generated-shape.mjs +29 -11
  59. package/dist/application/transform/ref-pointer/generated-shape.mjs.map +1 -1
  60. package/dist/application/transform/ref-pointer/original-index.cjs +1 -1
  61. package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -1
  62. package/dist/application/transform/ref-pointer/original-index.mjs +1 -1
  63. package/dist/application/transform/ref-pointer/original-index.mjs.map +1 -1
  64. package/dist/application/transform/ref-pointer/property-shape.cjs +5 -0
  65. package/dist/application/transform/ref-pointer/property-shape.cjs.map +1 -1
  66. package/dist/application/transform/ref-pointer/property-shape.mjs +5 -1
  67. package/dist/application/transform/ref-pointer/property-shape.mjs.map +1 -1
  68. package/dist/application/transform/ref-pointer/typed-walk.cjs +11 -1
  69. package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -1
  70. package/dist/application/transform/ref-pointer/typed-walk.mjs +12 -2
  71. package/dist/application/transform/ref-pointer/typed-walk.mjs.map +1 -1
  72. package/dist/cli/api-settings.cjs +3 -2
  73. package/dist/cli/api-settings.cjs.map +1 -1
  74. package/dist/cli/api-settings.mjs +2 -1
  75. package/dist/cli/api-settings.mjs.map +1 -1
  76. package/dist/cli/api-writes.cjs +7 -1
  77. package/dist/cli/api-writes.cjs.map +1 -1
  78. package/dist/cli/api-writes.mjs +7 -1
  79. package/dist/cli/api-writes.mjs.map +1 -1
  80. package/dist/cli/cli-arguments.cjs +25 -107
  81. package/dist/cli/cli-arguments.cjs.map +1 -1
  82. package/dist/cli/cli-arguments.mjs +18 -100
  83. package/dist/cli/cli-arguments.mjs.map +1 -1
  84. package/dist/cli/cli-errors.cjs +1 -0
  85. package/dist/cli/cli-errors.cjs.map +1 -1
  86. package/dist/cli/cli-errors.mjs +1 -0
  87. package/dist/cli/cli-errors.mjs.map +1 -1
  88. package/dist/cli/cli-flag-names.cjs +77 -0
  89. package/dist/cli/cli-flag-names.cjs.map +1 -0
  90. package/dist/cli/cli-flag-names.mjs +64 -0
  91. package/dist/cli/cli-flag-names.mjs.map +1 -0
  92. package/dist/cli/cli-output.cjs +7 -2
  93. package/dist/cli/cli-output.cjs.map +1 -1
  94. package/dist/cli/cli-output.mjs +7 -2
  95. package/dist/cli/cli-output.mjs.map +1 -1
  96. package/dist/cli/main.cjs +1 -1
  97. package/dist/cli/main.cjs.map +1 -1
  98. package/dist/cli/main.mjs +1 -1
  99. package/dist/cli/main.mjs.map +1 -1
  100. package/dist/cli/redocly-apis.cjs +14 -4
  101. package/dist/cli/redocly-apis.cjs.map +1 -1
  102. package/dist/cli/redocly-apis.mjs +14 -4
  103. package/dist/cli/redocly-apis.mjs.map +1 -1
  104. package/dist/cli/written-flags.cjs +83 -0
  105. package/dist/cli/written-flags.cjs.map +1 -0
  106. package/dist/cli/written-flags.mjs +77 -0
  107. package/dist/cli/written-flags.mjs.map +1 -0
  108. package/dist/domain/errors.cjs +1 -0
  109. package/dist/domain/errors.cjs.map +1 -1
  110. package/dist/domain/errors.mjs +1 -0
  111. package/dist/domain/errors.mjs.map +1 -1
  112. package/dist/domain/location-text.cjs +7 -1
  113. package/dist/domain/location-text.cjs.map +1 -1
  114. package/dist/domain/location-text.mjs +7 -1
  115. package/dist/domain/location-text.mjs.map +1 -1
  116. package/dist/index.d.cts +3 -0
  117. package/dist/index.d.mts +3 -0
  118. package/dist/index.d.ts +3 -0
  119. package/package.json +1 -1
  120. package/src/adapters/redocly-loader/query-document-names.ts +79 -0
  121. package/src/adapters/redocly-loader/query-named-components.ts +48 -49
  122. package/src/adapters/redocly-loader/redocly-config-source.ts +11 -1
  123. package/src/adapters/redocly-loader/redocly-schema-loader.ts +20 -6
  124. package/src/adapters/redocly-loader/ref-access.ts +16 -2
  125. package/src/adapters/redocly-loader/remote-fetch.ts +26 -0
  126. package/src/api/cwd-option.ts +76 -0
  127. package/src/api/default-ports.ts +33 -10
  128. package/src/api/document-run.ts +2 -17
  129. package/src/api/legacy-utils.ts +1 -1
  130. package/src/api/openapi-ts.ts +14 -1
  131. package/src/api/option-errors.ts +22 -0
  132. package/src/api/ref-limit-options.ts +17 -24
  133. package/src/application/ports/redocly-config-source.ts +5 -0
  134. package/src/application/transform/document/path-template-refs.ts +28 -7
  135. package/src/application/transform/ref-pointer/generated-shape.ts +57 -14
  136. package/src/application/transform/ref-pointer/original-index.ts +6 -3
  137. package/src/application/transform/ref-pointer/property-shape.ts +9 -0
  138. package/src/application/transform/ref-pointer/typed-walk.ts +26 -4
  139. package/src/cli/api-writes.ts +11 -3
  140. package/src/cli/cli-arguments.ts +42 -153
  141. package/src/cli/cli-errors.ts +1 -0
  142. package/src/cli/cli-flag-names.ts +99 -0
  143. package/src/cli/cli-output.ts +20 -6
  144. package/src/cli/main.ts +2 -1
  145. package/src/cli/redocly-apis.ts +21 -5
  146. package/src/cli/written-flags.ts +131 -0
  147. package/src/domain/errors.ts +1 -0
  148. package/src/domain/location-text.ts +17 -2
@@ -23,6 +23,10 @@ function isExcludedProperty(property, options, refs) {
23
23
  const resolved = locatedNode.followRefs(property, refs);
24
24
  return options.excludeDeprecated && locatedNode.isJsonObject(resolved) && Boolean(resolved.deprecated);
25
25
  }
26
+ function hasKeptProperties(node, options, refs) {
27
+ const properties = locatedNode.isJsonObject(node.properties) ? node.properties : {};
28
+ return Object.values(properties).some((value) => !isExcludedProperty(value, options, refs));
29
+ }
26
30
  function isMarkedProperty(value, options, refs) {
27
31
  if (!options.readWriteMarkers || !locatedNode.isJsonObject(value)) {
28
32
  return false;
@@ -43,6 +47,7 @@ function propertyPresence(schema, key, options, refs) {
43
47
  return isOptionalProperty({ ...owner, node }, key, options) ? "absent" : schemaPresence(properties[key], refs);
44
48
  }
45
49
 
50
+ exports.hasKeptProperties = hasKeptProperties;
46
51
  exports.isExcludedProperty = isExcludedProperty;
47
52
  exports.isMarkedProperty = isMarkedProperty;
48
53
  exports.isNullableSchema = isNullableSchema;
@@ -1 +1 @@
1
- {"version":3,"file":"property-shape.cjs","sources":["../../../../src/application/transform/ref-pointer/property-shape.ts"],"sourcesContent":["import type { Schema } from \"../../../domain/openapi/schema-object.js\";\nimport { propertyAccessFlags } from \"../schema/access-flags.js\";\nimport { isInputLocation } from \"../schema/input-location.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport {\n followLocated,\n followRefs,\n isJsonObject,\n type JsonObject,\n type LocatedNode,\n} from \"./located-node.js\";\n\n/**\n * What the generated type of an object schema makes of one of its properties: optional, left\n * out, wrapped in a read or write marker, or a value that may be `undefined` or `null`.\n */\n\n/** `nullable: true` or a `type` list with `null`: the generated type includes `null`. */\nexport function isNullableSchema(node: unknown): boolean {\n if (!isJsonObject(node)) {\n return false;\n }\n return node.nullable === true || (Array.isArray(node.type) && node.type.includes(\"null\"));\n}\n\n/**\n * Whether the generated type has the property as optional, as `objectType` decides: a `default`\n * makes a property required except in an input location, where the client may leave it out.\n */\nexport function isOptionalProperty(\n owner: LocatedNode & { node: JsonObject },\n key: string,\n options: SchemaOptions,\n): boolean {\n const { node } = owner;\n const required = Array.isArray(node.required) ? node.required : undefined;\n const property = (node.properties as JsonObject)[key];\n const hasDefault = isJsonObject(property) && property.default !== undefined;\n const isDefaultRequired =\n hasDefault && options.defaultNonNullable && !isInputLocation(owner.location, options.fixes);\n const isRequired =\n required?.includes(key) === true ||\n (required === undefined && options.propertiesRequiredByDefault) ||\n isDefaultRequired;\n return !isRequired;\n}\n\n/**\n * Whether `--exclude-deprecated` leaves the property out: its object, or the one its `$ref`\n * names, is deprecated (`objectType`). The key is then not in the generated type at all.\n */\nexport function isExcludedProperty(\n property: unknown,\n options: SchemaOptions,\n refs: RefResolver,\n): boolean {\n const resolved = followRefs(property, refs);\n return options.excludeDeprecated && isJsonObject(resolved) && Boolean(resolved.deprecated);\n}\n\n/**\n * Whether `--read-write-markers` wraps the type of a property or `$defs` member: one that is only\n * `readOnly` or only `writeOnly` is `$Read<T>` or `$Write<T>` (object-type.ts).\n */\nexport function isMarkedProperty(value: unknown, options: SchemaOptions, refs: RefResolver) {\n if (!options.readWriteMarkers || !isJsonObject(value)) {\n return false;\n }\n const flags = propertyAccessFlags(value as Schema, { options, refs });\n return flags.isReadOnly !== flags.isWriteOnly;\n}\n\n/** Whether a value is there: `present`, `absent` (may be `undefined` or `null`) or `unknown`. */\nexport type Presence = \"present\" | \"absent\" | \"unknown\";\n\n/** The presence of a value of `schema` itself: `absent` when its type includes `null`. */\nexport function schemaPresence(schema: unknown, refs: RefResolver): Presence {\n return isNullableSchema(followRefs(schema, refs)) ? \"absent\" : \"present\";\n}\n\n/** The presence of property `key` of `schema`: optional or nullable is `absent`. */\nexport function propertyPresence(\n schema: LocatedNode,\n key: string,\n options: SchemaOptions,\n refs: RefResolver,\n): Presence {\n const owner = followLocated(schema, refs);\n const { node } = owner;\n const properties = isJsonObject(node) && isJsonObject(node.properties) ? node.properties : {};\n if (!isJsonObject(node) || !Object.hasOwn(properties, key)) {\n return \"unknown\";\n }\n return isOptionalProperty({ ...owner, node }, key, options)\n ? \"absent\"\n : schemaPresence(properties[key], refs);\n}\n"],"names":["isJsonObject","isInputLocation","followRefs","propertyAccessFlags","followLocated"],"mappings":";;;;;;AAkBO,SAAS,iBAAiB,IAAA,EAAwB;AACvD,EAAA,IAAI,CAACA,wBAAA,CAAa,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,CAAK,QAAA,KAAa,IAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,IAAK,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AACzF;AAMO,SAAS,kBAAA,CACd,KAAA,EACA,GAAA,EACA,OAAA,EACS;AACT,EAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,EAAA,MAAM,WAAW,KAAA,CAAM,OAAA,CAAQ,KAAK,QAAQ,CAAA,GAAI,KAAK,QAAA,GAAW,MAAA;AAChE,EAAA,MAAM,QAAA,GAAY,IAAA,CAAK,UAAA,CAA0B,GAAG,CAAA;AACpD,EAAA,MAAM,UAAA,GAAaA,wBAAA,CAAa,QAAQ,CAAA,IAAK,SAAS,OAAA,KAAY,MAAA;AAClE,EAAA,MAAM,iBAAA,GACJ,cAAc,OAAA,CAAQ,kBAAA,IAAsB,CAACC,6BAAA,CAAgB,KAAA,CAAM,QAAA,EAAU,OAAA,CAAQ,KAAK,CAAA;AAC5F,EAAA,MAAM,UAAA,GACJ,UAAU,QAAA,CAAS,GAAG,MAAM,IAAA,IAC3B,QAAA,KAAa,MAAA,IAAa,OAAA,CAAQ,2BAAA,IACnC,iBAAA;AACF,EAAA,OAAO,CAAC,UAAA;AACV;AAMO,SAAS,kBAAA,CACd,QAAA,EACA,OAAA,EACA,IAAA,EACS;AACT,EAAA,MAAM,QAAA,GAAWC,sBAAA,CAAW,QAAA,EAAU,IAAI,CAAA;AAC1C,EAAA,OAAO,QAAQ,iBAAA,IAAqBF,wBAAA,CAAa,QAAQ,CAAA,IAAK,OAAA,CAAQ,SAAS,UAAU,CAAA;AAC3F;AAMO,SAAS,gBAAA,CAAiB,KAAA,EAAgB,OAAA,EAAwB,IAAA,EAAmB;AAC1F,EAAA,IAAI,CAAC,OAAA,CAAQ,gBAAA,IAAoB,CAACA,wBAAA,CAAa,KAAK,CAAA,EAAG;AACrD,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAQG,+BAAA,CAAoB,KAAA,EAAiB,EAAE,OAAA,EAAS,MAAM,CAAA;AACpE,EAAA,OAAO,KAAA,CAAM,eAAe,KAAA,CAAM,WAAA;AACpC;AAMO,SAAS,cAAA,CAAe,QAAiB,IAAA,EAA6B;AAC3E,EAAA,OAAO,iBAAiBD,sBAAA,CAAW,MAAA,EAAQ,IAAI,CAAC,IAAI,QAAA,GAAW,SAAA;AACjE;AAGO,SAAS,gBAAA,CACd,MAAA,EACA,GAAA,EACA,OAAA,EACA,IAAA,EACU;AACV,EAAA,MAAM,KAAA,GAAQE,yBAAA,CAAc,MAAA,EAAQ,IAAI,CAAA;AACxC,EAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,EAAA,MAAM,UAAA,GAAaJ,wBAAA,CAAa,IAAI,CAAA,IAAKA,wBAAA,CAAa,KAAK,UAAU,CAAA,GAAI,IAAA,CAAK,UAAA,GAAa,EAAC;AAC5F,EAAA,IAAI,CAACA,yBAAa,IAAI,CAAA,IAAK,CAAC,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,GAAG,CAAA,EAAG;AAC1D,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,OAAO,kBAAA,CAAmB,EAAE,GAAG,KAAA,EAAO,MAAK,EAAG,GAAA,EAAK,OAAO,CAAA,GACtD,QAAA,GACA,cAAA,CAAe,UAAA,CAAW,GAAG,GAAG,IAAI,CAAA;AAC1C;;;;;;;"}
1
+ {"version":3,"file":"property-shape.cjs","sources":["../../../../src/application/transform/ref-pointer/property-shape.ts"],"sourcesContent":["import type { Schema } from \"../../../domain/openapi/schema-object.js\";\nimport { propertyAccessFlags } from \"../schema/access-flags.js\";\nimport { isInputLocation } from \"../schema/input-location.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport {\n followLocated,\n followRefs,\n isJsonObject,\n type JsonObject,\n type LocatedNode,\n} from \"./located-node.js\";\n\n/**\n * What the generated type of an object schema makes of one of its properties: optional, left\n * out, wrapped in a read or write marker, or a value that may be `undefined` or `null`.\n */\n\n/** `nullable: true` or a `type` list with `null`: the generated type includes `null`. */\nexport function isNullableSchema(node: unknown): boolean {\n if (!isJsonObject(node)) {\n return false;\n }\n return node.nullable === true || (Array.isArray(node.type) && node.type.includes(\"null\"));\n}\n\n/**\n * Whether the generated type has the property as optional, as `objectType` decides: a `default`\n * makes a property required except in an input location, where the client may leave it out.\n */\nexport function isOptionalProperty(\n owner: LocatedNode & { node: JsonObject },\n key: string,\n options: SchemaOptions,\n): boolean {\n const { node } = owner;\n const required = Array.isArray(node.required) ? node.required : undefined;\n const property = (node.properties as JsonObject)[key];\n const hasDefault = isJsonObject(property) && property.default !== undefined;\n const isDefaultRequired =\n hasDefault && options.defaultNonNullable && !isInputLocation(owner.location, options.fixes);\n const isRequired =\n required?.includes(key) === true ||\n (required === undefined && options.propertiesRequiredByDefault) ||\n isDefaultRequired;\n return !isRequired;\n}\n\n/**\n * Whether `--exclude-deprecated` leaves the property out: its object, or the one its `$ref`\n * names, is deprecated (`objectType`). The key is then not in the generated type at all.\n */\nexport function isExcludedProperty(\n property: unknown,\n options: SchemaOptions,\n refs: RefResolver,\n): boolean {\n const resolved = followRefs(property, refs);\n return options.excludeDeprecated && isJsonObject(resolved) && Boolean(resolved.deprecated);\n}\n\n/**\n * Whether the generated type keeps one of the schema's properties. The index signature next to\n * them then holds their types too (`withPropertyTypes`), so it is not its value schema's type.\n */\nexport function hasKeptProperties(node: JsonObject, options: SchemaOptions, refs: RefResolver) {\n const properties = isJsonObject(node.properties) ? node.properties : {};\n return Object.values(properties).some((value) => !isExcludedProperty(value, options, refs));\n}\n\n/**\n * Whether `--read-write-markers` wraps the type of a property or `$defs` member: one that is only\n * `readOnly` or only `writeOnly` is `$Read<T>` or `$Write<T>` (object-type.ts).\n */\nexport function isMarkedProperty(value: unknown, options: SchemaOptions, refs: RefResolver) {\n if (!options.readWriteMarkers || !isJsonObject(value)) {\n return false;\n }\n const flags = propertyAccessFlags(value as Schema, { options, refs });\n return flags.isReadOnly !== flags.isWriteOnly;\n}\n\n/** Whether a value is there: `present`, `absent` (may be `undefined` or `null`) or `unknown`. */\nexport type Presence = \"present\" | \"absent\" | \"unknown\";\n\n/** The presence of a value of `schema` itself: `absent` when its type includes `null`. */\nexport function schemaPresence(schema: unknown, refs: RefResolver): Presence {\n return isNullableSchema(followRefs(schema, refs)) ? \"absent\" : \"present\";\n}\n\n/** The presence of property `key` of `schema`: optional or nullable is `absent`. */\nexport function propertyPresence(\n schema: LocatedNode,\n key: string,\n options: SchemaOptions,\n refs: RefResolver,\n): Presence {\n const owner = followLocated(schema, refs);\n const { node } = owner;\n const properties = isJsonObject(node) && isJsonObject(node.properties) ? node.properties : {};\n if (!isJsonObject(node) || !Object.hasOwn(properties, key)) {\n return \"unknown\";\n }\n return isOptionalProperty({ ...owner, node }, key, options)\n ? \"absent\"\n : schemaPresence(properties[key], refs);\n}\n"],"names":["isJsonObject","isInputLocation","followRefs","propertyAccessFlags","followLocated"],"mappings":"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"}
@@ -21,6 +21,10 @@ function isExcludedProperty(property, options, refs) {
21
21
  const resolved = followRefs(property, refs);
22
22
  return options.excludeDeprecated && isJsonObject(resolved) && Boolean(resolved.deprecated);
23
23
  }
24
+ function hasKeptProperties(node, options, refs) {
25
+ const properties = isJsonObject(node.properties) ? node.properties : {};
26
+ return Object.values(properties).some((value) => !isExcludedProperty(value, options, refs));
27
+ }
24
28
  function isMarkedProperty(value, options, refs) {
25
29
  if (!options.readWriteMarkers || !isJsonObject(value)) {
26
30
  return false;
@@ -41,5 +45,5 @@ function propertyPresence(schema, key, options, refs) {
41
45
  return isOptionalProperty({ ...owner, node }, key, options) ? "absent" : schemaPresence(properties[key], refs);
42
46
  }
43
47
 
44
- export { isExcludedProperty, isMarkedProperty, isNullableSchema, isOptionalProperty, propertyPresence, schemaPresence };
48
+ export { hasKeptProperties, isExcludedProperty, isMarkedProperty, isNullableSchema, isOptionalProperty, propertyPresence, schemaPresence };
45
49
  //# sourceMappingURL=property-shape.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"property-shape.mjs","sources":["../../../../src/application/transform/ref-pointer/property-shape.ts"],"sourcesContent":["import type { Schema } from \"../../../domain/openapi/schema-object.js\";\nimport { propertyAccessFlags } from \"../schema/access-flags.js\";\nimport { isInputLocation } from \"../schema/input-location.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport {\n followLocated,\n followRefs,\n isJsonObject,\n type JsonObject,\n type LocatedNode,\n} from \"./located-node.js\";\n\n/**\n * What the generated type of an object schema makes of one of its properties: optional, left\n * out, wrapped in a read or write marker, or a value that may be `undefined` or `null`.\n */\n\n/** `nullable: true` or a `type` list with `null`: the generated type includes `null`. */\nexport function isNullableSchema(node: unknown): boolean {\n if (!isJsonObject(node)) {\n return false;\n }\n return node.nullable === true || (Array.isArray(node.type) && node.type.includes(\"null\"));\n}\n\n/**\n * Whether the generated type has the property as optional, as `objectType` decides: a `default`\n * makes a property required except in an input location, where the client may leave it out.\n */\nexport function isOptionalProperty(\n owner: LocatedNode & { node: JsonObject },\n key: string,\n options: SchemaOptions,\n): boolean {\n const { node } = owner;\n const required = Array.isArray(node.required) ? node.required : undefined;\n const property = (node.properties as JsonObject)[key];\n const hasDefault = isJsonObject(property) && property.default !== undefined;\n const isDefaultRequired =\n hasDefault && options.defaultNonNullable && !isInputLocation(owner.location, options.fixes);\n const isRequired =\n required?.includes(key) === true ||\n (required === undefined && options.propertiesRequiredByDefault) ||\n isDefaultRequired;\n return !isRequired;\n}\n\n/**\n * Whether `--exclude-deprecated` leaves the property out: its object, or the one its `$ref`\n * names, is deprecated (`objectType`). The key is then not in the generated type at all.\n */\nexport function isExcludedProperty(\n property: unknown,\n options: SchemaOptions,\n refs: RefResolver,\n): boolean {\n const resolved = followRefs(property, refs);\n return options.excludeDeprecated && isJsonObject(resolved) && Boolean(resolved.deprecated);\n}\n\n/**\n * Whether `--read-write-markers` wraps the type of a property or `$defs` member: one that is only\n * `readOnly` or only `writeOnly` is `$Read<T>` or `$Write<T>` (object-type.ts).\n */\nexport function isMarkedProperty(value: unknown, options: SchemaOptions, refs: RefResolver) {\n if (!options.readWriteMarkers || !isJsonObject(value)) {\n return false;\n }\n const flags = propertyAccessFlags(value as Schema, { options, refs });\n return flags.isReadOnly !== flags.isWriteOnly;\n}\n\n/** Whether a value is there: `present`, `absent` (may be `undefined` or `null`) or `unknown`. */\nexport type Presence = \"present\" | \"absent\" | \"unknown\";\n\n/** The presence of a value of `schema` itself: `absent` when its type includes `null`. */\nexport function schemaPresence(schema: unknown, refs: RefResolver): Presence {\n return isNullableSchema(followRefs(schema, refs)) ? \"absent\" : \"present\";\n}\n\n/** The presence of property `key` of `schema`: optional or nullable is `absent`. */\nexport function propertyPresence(\n schema: LocatedNode,\n key: string,\n options: SchemaOptions,\n refs: RefResolver,\n): Presence {\n const owner = followLocated(schema, refs);\n const { node } = owner;\n const properties = isJsonObject(node) && isJsonObject(node.properties) ? node.properties : {};\n if (!isJsonObject(node) || !Object.hasOwn(properties, key)) {\n return \"unknown\";\n }\n return isOptionalProperty({ ...owner, node }, key, options)\n ? \"absent\"\n : schemaPresence(properties[key], refs);\n}\n"],"names":[],"mappings":";;;;AAkBO,SAAS,iBAAiB,IAAA,EAAwB;AACvD,EAAA,IAAI,CAAC,YAAA,CAAa,IAAI,CAAA,EAAG;AACvB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,CAAK,QAAA,KAAa,IAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,IAAK,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AACzF;AAMO,SAAS,kBAAA,CACd,KAAA,EACA,GAAA,EACA,OAAA,EACS;AACT,EAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,EAAA,MAAM,WAAW,KAAA,CAAM,OAAA,CAAQ,KAAK,QAAQ,CAAA,GAAI,KAAK,QAAA,GAAW,MAAA;AAChE,EAAA,MAAM,QAAA,GAAY,IAAA,CAAK,UAAA,CAA0B,GAAG,CAAA;AACpD,EAAA,MAAM,UAAA,GAAa,YAAA,CAAa,QAAQ,CAAA,IAAK,SAAS,OAAA,KAAY,MAAA;AAClE,EAAA,MAAM,iBAAA,GACJ,cAAc,OAAA,CAAQ,kBAAA,IAAsB,CAAC,eAAA,CAAgB,KAAA,CAAM,QAAA,EAAU,OAAA,CAAQ,KAAK,CAAA;AAC5F,EAAA,MAAM,UAAA,GACJ,UAAU,QAAA,CAAS,GAAG,MAAM,IAAA,IAC3B,QAAA,KAAa,MAAA,IAAa,OAAA,CAAQ,2BAAA,IACnC,iBAAA;AACF,EAAA,OAAO,CAAC,UAAA;AACV;AAMO,SAAS,kBAAA,CACd,QAAA,EACA,OAAA,EACA,IAAA,EACS;AACT,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,QAAA,EAAU,IAAI,CAAA;AAC1C,EAAA,OAAO,QAAQ,iBAAA,IAAqB,YAAA,CAAa,QAAQ,CAAA,IAAK,OAAA,CAAQ,SAAS,UAAU,CAAA;AAC3F;AAMO,SAAS,gBAAA,CAAiB,KAAA,EAAgB,OAAA,EAAwB,IAAA,EAAmB;AAC1F,EAAA,IAAI,CAAC,OAAA,CAAQ,gBAAA,IAAoB,CAAC,YAAA,CAAa,KAAK,CAAA,EAAG;AACrD,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAQ,mBAAA,CAAoB,KAAA,EAAiB,EAAE,OAAA,EAAS,MAAM,CAAA;AACpE,EAAA,OAAO,KAAA,CAAM,eAAe,KAAA,CAAM,WAAA;AACpC;AAMO,SAAS,cAAA,CAAe,QAAiB,IAAA,EAA6B;AAC3E,EAAA,OAAO,iBAAiB,UAAA,CAAW,MAAA,EAAQ,IAAI,CAAC,IAAI,QAAA,GAAW,SAAA;AACjE;AAGO,SAAS,gBAAA,CACd,MAAA,EACA,GAAA,EACA,OAAA,EACA,IAAA,EACU;AACV,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,MAAA,EAAQ,IAAI,CAAA;AACxC,EAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,EAAA,MAAM,UAAA,GAAa,YAAA,CAAa,IAAI,CAAA,IAAK,YAAA,CAAa,KAAK,UAAU,CAAA,GAAI,IAAA,CAAK,UAAA,GAAa,EAAC;AAC5F,EAAA,IAAI,CAAC,aAAa,IAAI,CAAA,IAAK,CAAC,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,GAAG,CAAA,EAAG;AAC1D,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,OAAO,kBAAA,CAAmB,EAAE,GAAG,KAAA,EAAO,MAAK,EAAG,GAAA,EAAK,OAAO,CAAA,GACtD,QAAA,GACA,cAAA,CAAe,UAAA,CAAW,GAAG,GAAG,IAAI,CAAA;AAC1C;;"}
1
+ {"version":3,"file":"property-shape.mjs","sources":["../../../../src/application/transform/ref-pointer/property-shape.ts"],"sourcesContent":["import type { Schema } from \"../../../domain/openapi/schema-object.js\";\nimport { propertyAccessFlags } from \"../schema/access-flags.js\";\nimport { isInputLocation } from \"../schema/input-location.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport {\n followLocated,\n followRefs,\n isJsonObject,\n type JsonObject,\n type LocatedNode,\n} from \"./located-node.js\";\n\n/**\n * What the generated type of an object schema makes of one of its properties: optional, left\n * out, wrapped in a read or write marker, or a value that may be `undefined` or `null`.\n */\n\n/** `nullable: true` or a `type` list with `null`: the generated type includes `null`. */\nexport function isNullableSchema(node: unknown): boolean {\n if (!isJsonObject(node)) {\n return false;\n }\n return node.nullable === true || (Array.isArray(node.type) && node.type.includes(\"null\"));\n}\n\n/**\n * Whether the generated type has the property as optional, as `objectType` decides: a `default`\n * makes a property required except in an input location, where the client may leave it out.\n */\nexport function isOptionalProperty(\n owner: LocatedNode & { node: JsonObject },\n key: string,\n options: SchemaOptions,\n): boolean {\n const { node } = owner;\n const required = Array.isArray(node.required) ? node.required : undefined;\n const property = (node.properties as JsonObject)[key];\n const hasDefault = isJsonObject(property) && property.default !== undefined;\n const isDefaultRequired =\n hasDefault && options.defaultNonNullable && !isInputLocation(owner.location, options.fixes);\n const isRequired =\n required?.includes(key) === true ||\n (required === undefined && options.propertiesRequiredByDefault) ||\n isDefaultRequired;\n return !isRequired;\n}\n\n/**\n * Whether `--exclude-deprecated` leaves the property out: its object, or the one its `$ref`\n * names, is deprecated (`objectType`). The key is then not in the generated type at all.\n */\nexport function isExcludedProperty(\n property: unknown,\n options: SchemaOptions,\n refs: RefResolver,\n): boolean {\n const resolved = followRefs(property, refs);\n return options.excludeDeprecated && isJsonObject(resolved) && Boolean(resolved.deprecated);\n}\n\n/**\n * Whether the generated type keeps one of the schema's properties. The index signature next to\n * them then holds their types too (`withPropertyTypes`), so it is not its value schema's type.\n */\nexport function hasKeptProperties(node: JsonObject, options: SchemaOptions, refs: RefResolver) {\n const properties = isJsonObject(node.properties) ? node.properties : {};\n return Object.values(properties).some((value) => !isExcludedProperty(value, options, refs));\n}\n\n/**\n * Whether `--read-write-markers` wraps the type of a property or `$defs` member: one that is only\n * `readOnly` or only `writeOnly` is `$Read<T>` or `$Write<T>` (object-type.ts).\n */\nexport function isMarkedProperty(value: unknown, options: SchemaOptions, refs: RefResolver) {\n if (!options.readWriteMarkers || !isJsonObject(value)) {\n return false;\n }\n const flags = propertyAccessFlags(value as Schema, { options, refs });\n return flags.isReadOnly !== flags.isWriteOnly;\n}\n\n/** Whether a value is there: `present`, `absent` (may be `undefined` or `null`) or `unknown`. */\nexport type Presence = \"present\" | \"absent\" | \"unknown\";\n\n/** The presence of a value of `schema` itself: `absent` when its type includes `null`. */\nexport function schemaPresence(schema: unknown, refs: RefResolver): Presence {\n return isNullableSchema(followRefs(schema, refs)) ? \"absent\" : \"present\";\n}\n\n/** The presence of property `key` of `schema`: optional or nullable is `absent`. */\nexport function propertyPresence(\n schema: LocatedNode,\n key: string,\n options: SchemaOptions,\n refs: RefResolver,\n): Presence {\n const owner = followLocated(schema, refs);\n const { node } = owner;\n const properties = isJsonObject(node) && isJsonObject(node.properties) ? node.properties : {};\n if (!isJsonObject(node) || !Object.hasOwn(properties, key)) {\n return \"unknown\";\n }\n return isOptionalProperty({ ...owner, node }, key, options)\n ? \"absent\"\n : schemaPresence(properties[key], refs);\n}\n"],"names":[],"mappings":"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"}
@@ -57,6 +57,7 @@ function defsStep(walk, owner, isLast) {
57
57
  presence: "present"
58
58
  };
59
59
  }
60
+ const COMPOSITION_KEYWORDS = ["allOf", "anyOf", "oneOf"];
60
61
  const SHAPED_KEYWORDS = /* @__PURE__ */ new Set([
61
62
  "properties",
62
63
  "items",
@@ -68,6 +69,15 @@ function hasKeywordMember(owner, segment) {
68
69
  }
69
70
  return segment === "items" ? generatedShape.isArrayShape(owner) : generatedShape.isObjectShape(owner);
70
71
  }
72
+ function isIndexedByValue(owner, input) {
73
+ if (!locatedNode.isJsonObject(owner)) {
74
+ return true;
75
+ }
76
+ const patterns = owner.patternProperties;
77
+ const hasPatterns = locatedNode.isJsonObject(patterns) && Object.keys(patterns).length > 0;
78
+ const isComposed = COMPOSITION_KEYWORDS.some((keyword) => keyword in owner);
79
+ return !hasPatterns && !isComposed && !propertyShape.hasKeptProperties(owner, input.options, input.refs);
80
+ }
71
81
  function keywordStep(walk, segment, isLast, input) {
72
82
  const owner = locatedNode.followLocated(walk, input.refs);
73
83
  if (!hasKeywordMember(owner.node, segment)) {
@@ -79,7 +89,7 @@ function keywordStep(walk, segment, isLast, input) {
79
89
  case "items":
80
90
  return indexEntries(walk, "number", "items", input.refs);
81
91
  case "additionalProperties":
82
- return indexEntries(walk, "string", "additionalProperties", input.refs);
92
+ return isIndexedByValue(owner.node, input) ? indexEntries(walk, "string", "additionalProperties", input.refs) : null;
83
93
  case DEFS_KEYWORD:
84
94
  return defsStep(walk, owner, isLast);
85
95
  default:
@@ -1 +1 @@
1
- {"version":3,"file":"typed-walk.cjs","sources":["../../../../src/application/transform/ref-pointer/typed-walk.ts"],"sourcesContent":["import { irIndexedAccess, irKeyword, irReference } from \"../../../domain/ir/constructors.js\";\nimport type { IrKeyword, IrType } from \"../../../domain/ir/nodes.js\";\nimport { indexBy, indexKeyword, rootType } from \"../ref-type.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport { isArrayShape, isObjectShape } from \"./generated-shape.js\";\nimport {\n childLocation,\n followLocated,\n followRefs,\n isJsonObject,\n type LocatedNode,\n} from \"./located-node.js\";\nimport {\n type ContentForm,\n headerParameterContentForm,\n isExcludedOperation,\n isOptionalHeader,\n isOptionalRequestBody,\n isParameterList,\n isTypedAsSchema,\n leadingLocated,\n leadingSegmentsOf,\n type RefPointer,\n startsInSchema,\n} from \"./pointer-walk.js\";\nimport {\n isExcludedProperty,\n isMarkedProperty,\n type Presence,\n propertyPresence,\n schemaPresence,\n} from \"./property-shape.js\";\n\n/**\n * The type of a `$ref` pointer as the generated types have it: the `schema` of a media type,\n * header or component parameter is its type, `items` is indexed by `number`,\n * `additionalProperties` by `string`, and a value that may be `undefined` or `null` is wrapped in\n * `NonNullable` before it is indexed. The walk stops at a segment with no type of its own\n * (`allOf/0`, `definitions/A`, operation `parameters/0`): the caller types the target itself.\n */\n\nconst DEFS_KEYWORD = \"$defs\";\n\nexport interface TypedWalk {\n readonly type: IrType;\n /** The document node the type stands for (not followed through a `$ref`). */\n readonly node: unknown;\n /** The node's JSON Pointer, where the generator writes its type (`LocatedNode`). */\n readonly location: string | undefined;\n readonly isSchema: boolean;\n /** The segment is a property or `$defs` name, not a keyword. */\n readonly isName: boolean;\n /** The location of the map of names (`properties` or `$defs`) when `isName`. */\n readonly namesLocation?: string | undefined;\n /**\n * The node is the `content` of a header or parameter typed as its first media type, so the\n * next segment must name that media type and adds no member.\n */\n readonly isFirstMediaType?: boolean;\n readonly presence: Presence;\n}\n\nexport interface TypedWalkInput {\n readonly pointer: RefPointer;\n readonly options: SchemaOptions;\n readonly refs: RefResolver;\n}\n\n/** The walk result: a type, or the index of the first segment that has no type. */\nexport type TypedWalkResult =\n | { readonly kind: \"typed\"; readonly walk: TypedWalk }\n | { readonly kind: \"untyped\"; readonly index: number };\n\nfunction present(walk: TypedWalk): IrType {\n return walk.presence === \"present\" ? walk.type : irReference(\"NonNullable\", [walk.type]);\n}\n\nfunction indexEntries(walk: TypedWalk, key: IrKeyword, keyword: string, refs: RefResolver) {\n const owner = followLocated(walk, refs);\n const child = isJsonObject(owner.node) ? owner.node[keyword] : undefined;\n return {\n ...walk,\n type: irIndexedAccess(present(walk), irKeyword(key)),\n node: child,\n location: childLocation(owner.location, keyword),\n presence: schemaPresence(child, refs),\n };\n}\n\n/**\n * A property `--exclude-deprecated` left out has no member to index, and the `$Read<T>` or\n * `$Write<T>` of a marked property has no member but the marker's: such a pointer is typed in\n * place.\n */\nfunction nameStep(walk: TypedWalk, name: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followLocated(walk, input.refs);\n const { node } = owner;\n const properties = isJsonObject(node) && isJsonObject(node.properties) ? node.properties : {};\n const value = properties[name];\n const { options, refs } = input;\n const isMarkedOnTheWay = !isLast && isMarkedProperty(value, options, refs);\n if (isExcludedProperty(value, options, refs) || isMarkedOnTheWay) {\n return null;\n }\n const type =\n walk.presence === \"present\"\n ? indexKeyword(walk.type, name, isLast)\n : indexBy(present(walk), name);\n return {\n ...walk,\n type,\n node: value,\n location: childLocation(walk.namesLocation, name),\n isName: false,\n presence: propertyPresence(walk, name, input.options, input.refs),\n };\n}\n\n/** `$defs` is optional (`NonNullable` when more follows); its members are present. */\nfunction defsStep(walk: TypedWalk, owner: LocatedNode, isLast: boolean): TypedWalk {\n const { node } = owner;\n const defs = isJsonObject(node) && isJsonObject(node[DEFS_KEYWORD]) ? node[DEFS_KEYWORD] : {};\n const namesLocation = childLocation(owner.location, DEFS_KEYWORD);\n return {\n ...walk,\n type: indexKeyword(present(walk), DEFS_KEYWORD, isLast),\n // A node of its own, not in the document: its properties are the definitions.\n node: { properties: defs, required: Object.keys(defs) },\n location: namesLocation,\n namesLocation,\n isName: true,\n presence: \"present\",\n };\n}\n\nconst SHAPED_KEYWORDS: ReadonlySet<string> = new Set([\n \"properties\",\n \"items\",\n \"additionalProperties\",\n]);\n\n/**\n * Whether the keyword gives the owner's generated type a member: `items` only an array,\n * `properties` and `additionalProperties` only an object (`type: string` ignores them). A node\n * that is not in the document is indexed as the keyword says.\n */\nfunction hasKeywordMember(owner: unknown, segment: string): boolean {\n if (!SHAPED_KEYWORDS.has(segment) || !isJsonObject(owner)) {\n return true;\n }\n return segment === \"items\" ? isArrayShape(owner) : isObjectShape(owner);\n}\n\nfunction keywordStep(walk: TypedWalk, segment: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followLocated(walk, input.refs);\n if (!hasKeywordMember(owner.node, segment)) {\n return null;\n }\n switch (segment) {\n case \"properties\":\n return { ...walk, isName: true, namesLocation: childLocation(owner.location, segment) };\n case \"items\":\n return indexEntries(walk, \"number\", \"items\", input.refs);\n case \"additionalProperties\":\n return indexEntries(walk, \"string\", \"additionalProperties\", input.refs);\n case DEFS_KEYWORD:\n return defsStep(walk, owner, isLast);\n default:\n return null;\n }\n}\n\nfunction containerStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk {\n const segment = input.pointer.segments[index] as string;\n const owner = followRefs(walk.node, input.refs);\n const isOptional =\n (segment === \"requestBody\" && isOptionalRequestBody(owner, input.refs)) ||\n isOptionalHeader(input.pointer, index, owner);\n return {\n ...walk,\n type: indexBy(present(walk), segment),\n node: isJsonObject(owner) ? owner[segment] : undefined,\n location: childLocation(followLocated(walk, input.refs).location, segment),\n presence: isOptional ? \"absent\" : \"present\",\n };\n}\n\n/**\n * The `content` of a header or parameter: no member of its own, since the type holds its media\n * types (or the first one's type). Untyped where the type is `string` or a `schema`'s, and as the\n * last segment of the first media type form, whose type is not the map's.\n */\nfunction contentStep(walk: TypedWalk, form: ContentForm, isLast: boolean, refs: RefResolver) {\n const isMapTyped = form === \"media-type-members\" || (form === \"first-media-type\" && !isLast);\n if (!isMapTyped) {\n return null;\n }\n const owner = followLocated(walk, refs);\n return {\n ...walk,\n node: isJsonObject(owner.node) ? owner.node.content : undefined,\n location: childLocation(owner.location, \"content\"),\n isFirstMediaType: form === \"first-media-type\",\n };\n}\n\n/** The first media type of such a `content` is the type itself; another one has no type. */\nfunction firstMediaTypeStep(walk: TypedWalk, segment: string): TypedWalk | null {\n const content = isJsonObject(walk.node) ? walk.node : {};\n if (Object.keys(content)[0] !== segment) {\n return null;\n }\n const location = childLocation(walk.location, segment);\n return { ...walk, node: content[segment], location, isFirstMediaType: false };\n}\n\nfunction schemaStep(walk: TypedWalk, refs: RefResolver): TypedWalk {\n const owner = followLocated(walk, refs);\n const schema = isJsonObject(owner.node) ? owner.node.schema : undefined;\n const location = childLocation(owner.location, \"schema\");\n // The container's type is its schema's type: an optional header stays optional.\n const presence = walk.presence === \"absent\" ? \"absent\" : schemaPresence(schema, refs);\n return { ...walk, node: schema, location, isSchema: true, presence };\n}\n\nfunction documentStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const owner = followRefs(walk.node, input.refs);\n const form = headerParameterContentForm(input.pointer, index, owner, input.options);\n if (form !== null) {\n const isLast = index === input.pointer.segments.length - 1;\n return contentStep(walk, form, isLast, input.refs);\n }\n if (\n isParameterList(input.pointer, index) ||\n isExcludedOperation(input.pointer, index, owner, input)\n ) {\n return null;\n }\n return containerStep(walk, index, input);\n}\n\nfunction step(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const { segments } = input.pointer;\n const segment = segments[index] as string;\n const isLast = index === segments.length - 1;\n if (walk.isSchema) {\n return walk.isName\n ? nameStep(walk, segment, isLast, input)\n : keywordStep(walk, segment, isLast, input);\n }\n if (walk.isFirstMediaType) {\n return firstMediaTypeStep(walk, segment);\n }\n if (segment === \"schema\" && isTypedAsSchema(input.pointer, index)) {\n return schemaStep(walk, input.refs);\n }\n return documentStep(walk, index, input);\n}\n\n/** Walk the whole pointer; see the module comment. */\nexport function typedWalk(input: TypedWalkInput): TypedWalkResult {\n const { pointer } = input;\n const { node, location } = leadingLocated(pointer, input.refs);\n const isSchema = startsInSchema(pointer);\n let walk: TypedWalk = {\n type: indexBy(\n rootType(pointer.rootSegment, false),\n ...pointer.segments.slice(0, leadingSegmentsOf(pointer)),\n ),\n node,\n location,\n isSchema,\n isName: false,\n presence: isSchema ? schemaPresence(node, input.refs) : \"present\",\n };\n for (let index = leadingSegmentsOf(pointer); index < pointer.segments.length; index++) {\n const next = step(walk, index, input);\n if (next === null) {\n return { kind: \"untyped\", index };\n }\n walk = next;\n }\n return { kind: \"typed\", walk };\n}\n"],"names":["irReference","followLocated","isJsonObject","irIndexedAccess","irKeyword","childLocation","schemaPresence","isMarkedProperty","isExcludedProperty","indexKeyword","indexBy","propertyPresence","isArrayShape","isObjectShape","followRefs","isOptionalRequestBody","isOptionalHeader","headerParameterContentForm","isParameterList","isExcludedOperation","isTypedAsSchema","leadingLocated","startsInSchema","rootType","leadingSegmentsOf"],"mappings":"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"}
1
+ {"version":3,"file":"typed-walk.cjs","sources":["../../../../src/application/transform/ref-pointer/typed-walk.ts"],"sourcesContent":["import { irIndexedAccess, irKeyword, irReference } from \"../../../domain/ir/constructors.js\";\nimport type { IrKeyword, IrType } from \"../../../domain/ir/nodes.js\";\nimport { indexBy, indexKeyword, rootType } from \"../ref-type.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport { isArrayShape, isObjectShape } from \"./generated-shape.js\";\nimport {\n childLocation,\n followLocated,\n followRefs,\n isJsonObject,\n type LocatedNode,\n} from \"./located-node.js\";\nimport {\n type ContentForm,\n headerParameterContentForm,\n isExcludedOperation,\n isOptionalHeader,\n isOptionalRequestBody,\n isParameterList,\n isTypedAsSchema,\n leadingLocated,\n leadingSegmentsOf,\n type RefPointer,\n startsInSchema,\n} from \"./pointer-walk.js\";\nimport {\n hasKeptProperties,\n isExcludedProperty,\n isMarkedProperty,\n type Presence,\n propertyPresence,\n schemaPresence,\n} from \"./property-shape.js\";\n\n/**\n * The type of a `$ref` pointer as the generated types have it: the `schema` of a media type,\n * header or component parameter is its type, `items` is indexed by `number`,\n * `additionalProperties` by `string` where the index signature is its type alone, and a value\n * that may be `undefined` or `null` is wrapped in `NonNullable` before it is indexed. The walk\n * stops at a segment with no type of its own (`allOf/0`, `definitions/A`, operation\n * `parameters/0`): the caller types the target itself.\n */\n\nconst DEFS_KEYWORD = \"$defs\";\n\nexport interface TypedWalk {\n readonly type: IrType;\n /** The document node the type stands for (not followed through a `$ref`). */\n readonly node: unknown;\n /** The node's JSON Pointer, where the generator writes its type (`LocatedNode`). */\n readonly location: string | undefined;\n readonly isSchema: boolean;\n /** The segment is a property or `$defs` name, not a keyword. */\n readonly isName: boolean;\n /** The location of the map of names (`properties` or `$defs`) when `isName`. */\n readonly namesLocation?: string | undefined;\n /**\n * The node is the `content` of a header or parameter typed as its first media type, so the\n * next segment must name that media type and adds no member.\n */\n readonly isFirstMediaType?: boolean;\n readonly presence: Presence;\n}\n\nexport interface TypedWalkInput {\n readonly pointer: RefPointer;\n readonly options: SchemaOptions;\n readonly refs: RefResolver;\n}\n\n/** The walk result: a type, or the index of the first segment that has no type. */\nexport type TypedWalkResult =\n | { readonly kind: \"typed\"; readonly walk: TypedWalk }\n | { readonly kind: \"untyped\"; readonly index: number };\n\nfunction present(walk: TypedWalk): IrType {\n return walk.presence === \"present\" ? walk.type : irReference(\"NonNullable\", [walk.type]);\n}\n\nfunction indexEntries(walk: TypedWalk, key: IrKeyword, keyword: string, refs: RefResolver) {\n const owner = followLocated(walk, refs);\n const child = isJsonObject(owner.node) ? owner.node[keyword] : undefined;\n return {\n ...walk,\n type: irIndexedAccess(present(walk), irKeyword(key)),\n node: child,\n location: childLocation(owner.location, keyword),\n presence: schemaPresence(child, refs),\n };\n}\n\n/**\n * A property `--exclude-deprecated` left out has no member to index, and the `$Read<T>` or\n * `$Write<T>` of a marked property has no member but the marker's: such a pointer is typed in\n * place.\n */\nfunction nameStep(walk: TypedWalk, name: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followLocated(walk, input.refs);\n const { node } = owner;\n const properties = isJsonObject(node) && isJsonObject(node.properties) ? node.properties : {};\n const value = properties[name];\n const { options, refs } = input;\n const isMarkedOnTheWay = !isLast && isMarkedProperty(value, options, refs);\n if (isExcludedProperty(value, options, refs) || isMarkedOnTheWay) {\n return null;\n }\n const type =\n walk.presence === \"present\"\n ? indexKeyword(walk.type, name, isLast)\n : indexBy(present(walk), name);\n return {\n ...walk,\n type,\n node: value,\n location: childLocation(walk.namesLocation, name),\n isName: false,\n presence: propertyPresence(walk, name, input.options, input.refs),\n };\n}\n\n/** `$defs` is optional (`NonNullable` when more follows); its members are present. */\nfunction defsStep(walk: TypedWalk, owner: LocatedNode, isLast: boolean): TypedWalk {\n const { node } = owner;\n const defs = isJsonObject(node) && isJsonObject(node[DEFS_KEYWORD]) ? node[DEFS_KEYWORD] : {};\n const namesLocation = childLocation(owner.location, DEFS_KEYWORD);\n return {\n ...walk,\n type: indexKeyword(present(walk), DEFS_KEYWORD, isLast),\n // A node of its own, not in the document: its properties are the definitions.\n node: { properties: defs, required: Object.keys(defs) },\n location: namesLocation,\n namesLocation,\n isName: true,\n presence: \"present\",\n };\n}\n\nconst COMPOSITION_KEYWORDS = [\"allOf\", \"anyOf\", \"oneOf\"] as const;\n\nconst SHAPED_KEYWORDS: ReadonlySet<string> = new Set([\n \"properties\",\n \"items\",\n \"additionalProperties\",\n]);\n\n/**\n * Whether the keyword gives the owner's generated type a member: `items` only an array,\n * `properties` and `additionalProperties` only an object (`type: string` ignores them). A node\n * that is not in the document is indexed as the keyword says.\n */\nfunction hasKeywordMember(owner: unknown, segment: string): boolean {\n if (!SHAPED_KEYWORDS.has(segment) || !isJsonObject(owner)) {\n return true;\n }\n return segment === \"items\" ? isArrayShape(owner) : isObjectShape(owner);\n}\n\n/**\n * Whether `[string]` of the owner's type is its `additionalProperties` type. Not where the index\n * signature also holds pattern or property types (`withPropertyTypes`), nor next to `allOf` /\n * `anyOf` / `oneOf`, whose members may add an index signature or an inherited discriminator.\n */\nfunction isIndexedByValue(owner: unknown, input: TypedWalkInput): boolean {\n if (!isJsonObject(owner)) {\n return true;\n }\n const patterns = owner.patternProperties;\n const hasPatterns = isJsonObject(patterns) && Object.keys(patterns).length > 0;\n const isComposed = COMPOSITION_KEYWORDS.some((keyword) => keyword in owner);\n return !hasPatterns && !isComposed && !hasKeptProperties(owner, input.options, input.refs);\n}\n\nfunction keywordStep(walk: TypedWalk, segment: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followLocated(walk, input.refs);\n if (!hasKeywordMember(owner.node, segment)) {\n return null;\n }\n switch (segment) {\n case \"properties\":\n return { ...walk, isName: true, namesLocation: childLocation(owner.location, segment) };\n case \"items\":\n return indexEntries(walk, \"number\", \"items\", input.refs);\n case \"additionalProperties\":\n // Otherwise the walk stops, and the target is typed in place.\n return isIndexedByValue(owner.node, input)\n ? indexEntries(walk, \"string\", \"additionalProperties\", input.refs)\n : null;\n case DEFS_KEYWORD:\n return defsStep(walk, owner, isLast);\n default:\n return null;\n }\n}\n\nfunction containerStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk {\n const segment = input.pointer.segments[index] as string;\n const owner = followRefs(walk.node, input.refs);\n const isOptional =\n (segment === \"requestBody\" && isOptionalRequestBody(owner, input.refs)) ||\n isOptionalHeader(input.pointer, index, owner);\n return {\n ...walk,\n type: indexBy(present(walk), segment),\n node: isJsonObject(owner) ? owner[segment] : undefined,\n location: childLocation(followLocated(walk, input.refs).location, segment),\n presence: isOptional ? \"absent\" : \"present\",\n };\n}\n\n/**\n * The `content` of a header or parameter: no member of its own, since the type holds its media\n * types (or the first one's type). Untyped where the type is `string` or a `schema`'s, and as the\n * last segment of the first media type form, whose type is not the map's.\n */\nfunction contentStep(walk: TypedWalk, form: ContentForm, isLast: boolean, refs: RefResolver) {\n const isMapTyped = form === \"media-type-members\" || (form === \"first-media-type\" && !isLast);\n if (!isMapTyped) {\n return null;\n }\n const owner = followLocated(walk, refs);\n return {\n ...walk,\n node: isJsonObject(owner.node) ? owner.node.content : undefined,\n location: childLocation(owner.location, \"content\"),\n isFirstMediaType: form === \"first-media-type\",\n };\n}\n\n/** The first media type of such a `content` is the type itself; another one has no type. */\nfunction firstMediaTypeStep(walk: TypedWalk, segment: string): TypedWalk | null {\n const content = isJsonObject(walk.node) ? walk.node : {};\n if (Object.keys(content)[0] !== segment) {\n return null;\n }\n const location = childLocation(walk.location, segment);\n return { ...walk, node: content[segment], location, isFirstMediaType: false };\n}\n\nfunction schemaStep(walk: TypedWalk, refs: RefResolver): TypedWalk {\n const owner = followLocated(walk, refs);\n const schema = isJsonObject(owner.node) ? owner.node.schema : undefined;\n const location = childLocation(owner.location, \"schema\");\n // The container's type is its schema's type: an optional header stays optional.\n const presence = walk.presence === \"absent\" ? \"absent\" : schemaPresence(schema, refs);\n return { ...walk, node: schema, location, isSchema: true, presence };\n}\n\nfunction documentStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const owner = followRefs(walk.node, input.refs);\n const form = headerParameterContentForm(input.pointer, index, owner, input.options);\n if (form !== null) {\n const isLast = index === input.pointer.segments.length - 1;\n return contentStep(walk, form, isLast, input.refs);\n }\n if (\n isParameterList(input.pointer, index) ||\n isExcludedOperation(input.pointer, index, owner, input)\n ) {\n return null;\n }\n return containerStep(walk, index, input);\n}\n\nfunction step(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const { segments } = input.pointer;\n const segment = segments[index] as string;\n const isLast = index === segments.length - 1;\n if (walk.isSchema) {\n return walk.isName\n ? nameStep(walk, segment, isLast, input)\n : keywordStep(walk, segment, isLast, input);\n }\n if (walk.isFirstMediaType) {\n return firstMediaTypeStep(walk, segment);\n }\n if (segment === \"schema\" && isTypedAsSchema(input.pointer, index)) {\n return schemaStep(walk, input.refs);\n }\n return documentStep(walk, index, input);\n}\n\n/** Walk the whole pointer; see the module comment. */\nexport function typedWalk(input: TypedWalkInput): TypedWalkResult {\n const { pointer } = input;\n const { node, location } = leadingLocated(pointer, input.refs);\n const isSchema = startsInSchema(pointer);\n let walk: TypedWalk = {\n type: indexBy(\n rootType(pointer.rootSegment, false),\n ...pointer.segments.slice(0, leadingSegmentsOf(pointer)),\n ),\n node,\n location,\n isSchema,\n isName: false,\n presence: isSchema ? schemaPresence(node, input.refs) : \"present\",\n };\n for (let index = leadingSegmentsOf(pointer); index < pointer.segments.length; index++) {\n const next = step(walk, index, input);\n if (next === null) {\n return { kind: \"untyped\", index };\n }\n walk = next;\n }\n return { kind: \"typed\", walk };\n}\n"],"names":["irReference","followLocated","isJsonObject","irIndexedAccess","irKeyword","childLocation","schemaPresence","isMarkedProperty","isExcludedProperty","indexKeyword","indexBy","propertyPresence","isArrayShape","isObjectShape","hasKeptProperties","followRefs","isOptionalRequestBody","isOptionalHeader","headerParameterContentForm","isParameterList","isExcludedOperation","isTypedAsSchema","leadingLocated","startsInSchema","rootType","leadingSegmentsOf"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { indexBy, rootType, indexKeyword } from '../ref-type.mjs';
3
3
  import { isArrayShape, isObjectShape } from './generated-shape.mjs';
4
4
  import { followLocated, isJsonObject, childLocation, followRefs } from './located-node.mjs';
5
5
  import { leadingLocated, startsInSchema, leadingSegmentsOf, isTypedAsSchema, headerParameterContentForm, isParameterList, isExcludedOperation, isOptionalRequestBody, isOptionalHeader } from './pointer-walk.mjs';
6
- import { schemaPresence, isMarkedProperty, isExcludedProperty, propertyPresence } from './property-shape.mjs';
6
+ import { schemaPresence, isMarkedProperty, isExcludedProperty, propertyPresence, hasKeptProperties } from './property-shape.mjs';
7
7
 
8
8
  const DEFS_KEYWORD = "$defs";
9
9
  function present(walk) {
@@ -55,6 +55,7 @@ function defsStep(walk, owner, isLast) {
55
55
  presence: "present"
56
56
  };
57
57
  }
58
+ const COMPOSITION_KEYWORDS = ["allOf", "anyOf", "oneOf"];
58
59
  const SHAPED_KEYWORDS = /* @__PURE__ */ new Set([
59
60
  "properties",
60
61
  "items",
@@ -66,6 +67,15 @@ function hasKeywordMember(owner, segment) {
66
67
  }
67
68
  return segment === "items" ? isArrayShape(owner) : isObjectShape(owner);
68
69
  }
70
+ function isIndexedByValue(owner, input) {
71
+ if (!isJsonObject(owner)) {
72
+ return true;
73
+ }
74
+ const patterns = owner.patternProperties;
75
+ const hasPatterns = isJsonObject(patterns) && Object.keys(patterns).length > 0;
76
+ const isComposed = COMPOSITION_KEYWORDS.some((keyword) => keyword in owner);
77
+ return !hasPatterns && !isComposed && !hasKeptProperties(owner, input.options, input.refs);
78
+ }
69
79
  function keywordStep(walk, segment, isLast, input) {
70
80
  const owner = followLocated(walk, input.refs);
71
81
  if (!hasKeywordMember(owner.node, segment)) {
@@ -77,7 +87,7 @@ function keywordStep(walk, segment, isLast, input) {
77
87
  case "items":
78
88
  return indexEntries(walk, "number", "items", input.refs);
79
89
  case "additionalProperties":
80
- return indexEntries(walk, "string", "additionalProperties", input.refs);
90
+ return isIndexedByValue(owner.node, input) ? indexEntries(walk, "string", "additionalProperties", input.refs) : null;
81
91
  case DEFS_KEYWORD:
82
92
  return defsStep(walk, owner, isLast);
83
93
  default:
@@ -1 +1 @@
1
- {"version":3,"file":"typed-walk.mjs","sources":["../../../../src/application/transform/ref-pointer/typed-walk.ts"],"sourcesContent":["import { irIndexedAccess, irKeyword, irReference } from \"../../../domain/ir/constructors.js\";\nimport type { IrKeyword, IrType } from \"../../../domain/ir/nodes.js\";\nimport { indexBy, indexKeyword, rootType } from \"../ref-type.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport { isArrayShape, isObjectShape } from \"./generated-shape.js\";\nimport {\n childLocation,\n followLocated,\n followRefs,\n isJsonObject,\n type LocatedNode,\n} from \"./located-node.js\";\nimport {\n type ContentForm,\n headerParameterContentForm,\n isExcludedOperation,\n isOptionalHeader,\n isOptionalRequestBody,\n isParameterList,\n isTypedAsSchema,\n leadingLocated,\n leadingSegmentsOf,\n type RefPointer,\n startsInSchema,\n} from \"./pointer-walk.js\";\nimport {\n isExcludedProperty,\n isMarkedProperty,\n type Presence,\n propertyPresence,\n schemaPresence,\n} from \"./property-shape.js\";\n\n/**\n * The type of a `$ref` pointer as the generated types have it: the `schema` of a media type,\n * header or component parameter is its type, `items` is indexed by `number`,\n * `additionalProperties` by `string`, and a value that may be `undefined` or `null` is wrapped in\n * `NonNullable` before it is indexed. The walk stops at a segment with no type of its own\n * (`allOf/0`, `definitions/A`, operation `parameters/0`): the caller types the target itself.\n */\n\nconst DEFS_KEYWORD = \"$defs\";\n\nexport interface TypedWalk {\n readonly type: IrType;\n /** The document node the type stands for (not followed through a `$ref`). */\n readonly node: unknown;\n /** The node's JSON Pointer, where the generator writes its type (`LocatedNode`). */\n readonly location: string | undefined;\n readonly isSchema: boolean;\n /** The segment is a property or `$defs` name, not a keyword. */\n readonly isName: boolean;\n /** The location of the map of names (`properties` or `$defs`) when `isName`. */\n readonly namesLocation?: string | undefined;\n /**\n * The node is the `content` of a header or parameter typed as its first media type, so the\n * next segment must name that media type and adds no member.\n */\n readonly isFirstMediaType?: boolean;\n readonly presence: Presence;\n}\n\nexport interface TypedWalkInput {\n readonly pointer: RefPointer;\n readonly options: SchemaOptions;\n readonly refs: RefResolver;\n}\n\n/** The walk result: a type, or the index of the first segment that has no type. */\nexport type TypedWalkResult =\n | { readonly kind: \"typed\"; readonly walk: TypedWalk }\n | { readonly kind: \"untyped\"; readonly index: number };\n\nfunction present(walk: TypedWalk): IrType {\n return walk.presence === \"present\" ? walk.type : irReference(\"NonNullable\", [walk.type]);\n}\n\nfunction indexEntries(walk: TypedWalk, key: IrKeyword, keyword: string, refs: RefResolver) {\n const owner = followLocated(walk, refs);\n const child = isJsonObject(owner.node) ? owner.node[keyword] : undefined;\n return {\n ...walk,\n type: irIndexedAccess(present(walk), irKeyword(key)),\n node: child,\n location: childLocation(owner.location, keyword),\n presence: schemaPresence(child, refs),\n };\n}\n\n/**\n * A property `--exclude-deprecated` left out has no member to index, and the `$Read<T>` or\n * `$Write<T>` of a marked property has no member but the marker's: such a pointer is typed in\n * place.\n */\nfunction nameStep(walk: TypedWalk, name: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followLocated(walk, input.refs);\n const { node } = owner;\n const properties = isJsonObject(node) && isJsonObject(node.properties) ? node.properties : {};\n const value = properties[name];\n const { options, refs } = input;\n const isMarkedOnTheWay = !isLast && isMarkedProperty(value, options, refs);\n if (isExcludedProperty(value, options, refs) || isMarkedOnTheWay) {\n return null;\n }\n const type =\n walk.presence === \"present\"\n ? indexKeyword(walk.type, name, isLast)\n : indexBy(present(walk), name);\n return {\n ...walk,\n type,\n node: value,\n location: childLocation(walk.namesLocation, name),\n isName: false,\n presence: propertyPresence(walk, name, input.options, input.refs),\n };\n}\n\n/** `$defs` is optional (`NonNullable` when more follows); its members are present. */\nfunction defsStep(walk: TypedWalk, owner: LocatedNode, isLast: boolean): TypedWalk {\n const { node } = owner;\n const defs = isJsonObject(node) && isJsonObject(node[DEFS_KEYWORD]) ? node[DEFS_KEYWORD] : {};\n const namesLocation = childLocation(owner.location, DEFS_KEYWORD);\n return {\n ...walk,\n type: indexKeyword(present(walk), DEFS_KEYWORD, isLast),\n // A node of its own, not in the document: its properties are the definitions.\n node: { properties: defs, required: Object.keys(defs) },\n location: namesLocation,\n namesLocation,\n isName: true,\n presence: \"present\",\n };\n}\n\nconst SHAPED_KEYWORDS: ReadonlySet<string> = new Set([\n \"properties\",\n \"items\",\n \"additionalProperties\",\n]);\n\n/**\n * Whether the keyword gives the owner's generated type a member: `items` only an array,\n * `properties` and `additionalProperties` only an object (`type: string` ignores them). A node\n * that is not in the document is indexed as the keyword says.\n */\nfunction hasKeywordMember(owner: unknown, segment: string): boolean {\n if (!SHAPED_KEYWORDS.has(segment) || !isJsonObject(owner)) {\n return true;\n }\n return segment === \"items\" ? isArrayShape(owner) : isObjectShape(owner);\n}\n\nfunction keywordStep(walk: TypedWalk, segment: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followLocated(walk, input.refs);\n if (!hasKeywordMember(owner.node, segment)) {\n return null;\n }\n switch (segment) {\n case \"properties\":\n return { ...walk, isName: true, namesLocation: childLocation(owner.location, segment) };\n case \"items\":\n return indexEntries(walk, \"number\", \"items\", input.refs);\n case \"additionalProperties\":\n return indexEntries(walk, \"string\", \"additionalProperties\", input.refs);\n case DEFS_KEYWORD:\n return defsStep(walk, owner, isLast);\n default:\n return null;\n }\n}\n\nfunction containerStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk {\n const segment = input.pointer.segments[index] as string;\n const owner = followRefs(walk.node, input.refs);\n const isOptional =\n (segment === \"requestBody\" && isOptionalRequestBody(owner, input.refs)) ||\n isOptionalHeader(input.pointer, index, owner);\n return {\n ...walk,\n type: indexBy(present(walk), segment),\n node: isJsonObject(owner) ? owner[segment] : undefined,\n location: childLocation(followLocated(walk, input.refs).location, segment),\n presence: isOptional ? \"absent\" : \"present\",\n };\n}\n\n/**\n * The `content` of a header or parameter: no member of its own, since the type holds its media\n * types (or the first one's type). Untyped where the type is `string` or a `schema`'s, and as the\n * last segment of the first media type form, whose type is not the map's.\n */\nfunction contentStep(walk: TypedWalk, form: ContentForm, isLast: boolean, refs: RefResolver) {\n const isMapTyped = form === \"media-type-members\" || (form === \"first-media-type\" && !isLast);\n if (!isMapTyped) {\n return null;\n }\n const owner = followLocated(walk, refs);\n return {\n ...walk,\n node: isJsonObject(owner.node) ? owner.node.content : undefined,\n location: childLocation(owner.location, \"content\"),\n isFirstMediaType: form === \"first-media-type\",\n };\n}\n\n/** The first media type of such a `content` is the type itself; another one has no type. */\nfunction firstMediaTypeStep(walk: TypedWalk, segment: string): TypedWalk | null {\n const content = isJsonObject(walk.node) ? walk.node : {};\n if (Object.keys(content)[0] !== segment) {\n return null;\n }\n const location = childLocation(walk.location, segment);\n return { ...walk, node: content[segment], location, isFirstMediaType: false };\n}\n\nfunction schemaStep(walk: TypedWalk, refs: RefResolver): TypedWalk {\n const owner = followLocated(walk, refs);\n const schema = isJsonObject(owner.node) ? owner.node.schema : undefined;\n const location = childLocation(owner.location, \"schema\");\n // The container's type is its schema's type: an optional header stays optional.\n const presence = walk.presence === \"absent\" ? \"absent\" : schemaPresence(schema, refs);\n return { ...walk, node: schema, location, isSchema: true, presence };\n}\n\nfunction documentStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const owner = followRefs(walk.node, input.refs);\n const form = headerParameterContentForm(input.pointer, index, owner, input.options);\n if (form !== null) {\n const isLast = index === input.pointer.segments.length - 1;\n return contentStep(walk, form, isLast, input.refs);\n }\n if (\n isParameterList(input.pointer, index) ||\n isExcludedOperation(input.pointer, index, owner, input)\n ) {\n return null;\n }\n return containerStep(walk, index, input);\n}\n\nfunction step(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const { segments } = input.pointer;\n const segment = segments[index] as string;\n const isLast = index === segments.length - 1;\n if (walk.isSchema) {\n return walk.isName\n ? nameStep(walk, segment, isLast, input)\n : keywordStep(walk, segment, isLast, input);\n }\n if (walk.isFirstMediaType) {\n return firstMediaTypeStep(walk, segment);\n }\n if (segment === \"schema\" && isTypedAsSchema(input.pointer, index)) {\n return schemaStep(walk, input.refs);\n }\n return documentStep(walk, index, input);\n}\n\n/** Walk the whole pointer; see the module comment. */\nexport function typedWalk(input: TypedWalkInput): TypedWalkResult {\n const { pointer } = input;\n const { node, location } = leadingLocated(pointer, input.refs);\n const isSchema = startsInSchema(pointer);\n let walk: TypedWalk = {\n type: indexBy(\n rootType(pointer.rootSegment, false),\n ...pointer.segments.slice(0, leadingSegmentsOf(pointer)),\n ),\n node,\n location,\n isSchema,\n isName: false,\n presence: isSchema ? schemaPresence(node, input.refs) : \"present\",\n };\n for (let index = leadingSegmentsOf(pointer); index < pointer.segments.length; index++) {\n const next = step(walk, index, input);\n if (next === null) {\n return { kind: \"untyped\", index };\n }\n walk = next;\n }\n return { kind: \"typed\", walk };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"typed-walk.mjs","sources":["../../../../src/application/transform/ref-pointer/typed-walk.ts"],"sourcesContent":["import { irIndexedAccess, irKeyword, irReference } from \"../../../domain/ir/constructors.js\";\nimport type { IrKeyword, IrType } from \"../../../domain/ir/nodes.js\";\nimport { indexBy, indexKeyword, rootType } from \"../ref-type.js\";\nimport type { RefResolver, SchemaOptions } from \"../schema/schema-context.js\";\nimport { isArrayShape, isObjectShape } from \"./generated-shape.js\";\nimport {\n childLocation,\n followLocated,\n followRefs,\n isJsonObject,\n type LocatedNode,\n} from \"./located-node.js\";\nimport {\n type ContentForm,\n headerParameterContentForm,\n isExcludedOperation,\n isOptionalHeader,\n isOptionalRequestBody,\n isParameterList,\n isTypedAsSchema,\n leadingLocated,\n leadingSegmentsOf,\n type RefPointer,\n startsInSchema,\n} from \"./pointer-walk.js\";\nimport {\n hasKeptProperties,\n isExcludedProperty,\n isMarkedProperty,\n type Presence,\n propertyPresence,\n schemaPresence,\n} from \"./property-shape.js\";\n\n/**\n * The type of a `$ref` pointer as the generated types have it: the `schema` of a media type,\n * header or component parameter is its type, `items` is indexed by `number`,\n * `additionalProperties` by `string` where the index signature is its type alone, and a value\n * that may be `undefined` or `null` is wrapped in `NonNullable` before it is indexed. The walk\n * stops at a segment with no type of its own (`allOf/0`, `definitions/A`, operation\n * `parameters/0`): the caller types the target itself.\n */\n\nconst DEFS_KEYWORD = \"$defs\";\n\nexport interface TypedWalk {\n readonly type: IrType;\n /** The document node the type stands for (not followed through a `$ref`). */\n readonly node: unknown;\n /** The node's JSON Pointer, where the generator writes its type (`LocatedNode`). */\n readonly location: string | undefined;\n readonly isSchema: boolean;\n /** The segment is a property or `$defs` name, not a keyword. */\n readonly isName: boolean;\n /** The location of the map of names (`properties` or `$defs`) when `isName`. */\n readonly namesLocation?: string | undefined;\n /**\n * The node is the `content` of a header or parameter typed as its first media type, so the\n * next segment must name that media type and adds no member.\n */\n readonly isFirstMediaType?: boolean;\n readonly presence: Presence;\n}\n\nexport interface TypedWalkInput {\n readonly pointer: RefPointer;\n readonly options: SchemaOptions;\n readonly refs: RefResolver;\n}\n\n/** The walk result: a type, or the index of the first segment that has no type. */\nexport type TypedWalkResult =\n | { readonly kind: \"typed\"; readonly walk: TypedWalk }\n | { readonly kind: \"untyped\"; readonly index: number };\n\nfunction present(walk: TypedWalk): IrType {\n return walk.presence === \"present\" ? walk.type : irReference(\"NonNullable\", [walk.type]);\n}\n\nfunction indexEntries(walk: TypedWalk, key: IrKeyword, keyword: string, refs: RefResolver) {\n const owner = followLocated(walk, refs);\n const child = isJsonObject(owner.node) ? owner.node[keyword] : undefined;\n return {\n ...walk,\n type: irIndexedAccess(present(walk), irKeyword(key)),\n node: child,\n location: childLocation(owner.location, keyword),\n presence: schemaPresence(child, refs),\n };\n}\n\n/**\n * A property `--exclude-deprecated` left out has no member to index, and the `$Read<T>` or\n * `$Write<T>` of a marked property has no member but the marker's: such a pointer is typed in\n * place.\n */\nfunction nameStep(walk: TypedWalk, name: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followLocated(walk, input.refs);\n const { node } = owner;\n const properties = isJsonObject(node) && isJsonObject(node.properties) ? node.properties : {};\n const value = properties[name];\n const { options, refs } = input;\n const isMarkedOnTheWay = !isLast && isMarkedProperty(value, options, refs);\n if (isExcludedProperty(value, options, refs) || isMarkedOnTheWay) {\n return null;\n }\n const type =\n walk.presence === \"present\"\n ? indexKeyword(walk.type, name, isLast)\n : indexBy(present(walk), name);\n return {\n ...walk,\n type,\n node: value,\n location: childLocation(walk.namesLocation, name),\n isName: false,\n presence: propertyPresence(walk, name, input.options, input.refs),\n };\n}\n\n/** `$defs` is optional (`NonNullable` when more follows); its members are present. */\nfunction defsStep(walk: TypedWalk, owner: LocatedNode, isLast: boolean): TypedWalk {\n const { node } = owner;\n const defs = isJsonObject(node) && isJsonObject(node[DEFS_KEYWORD]) ? node[DEFS_KEYWORD] : {};\n const namesLocation = childLocation(owner.location, DEFS_KEYWORD);\n return {\n ...walk,\n type: indexKeyword(present(walk), DEFS_KEYWORD, isLast),\n // A node of its own, not in the document: its properties are the definitions.\n node: { properties: defs, required: Object.keys(defs) },\n location: namesLocation,\n namesLocation,\n isName: true,\n presence: \"present\",\n };\n}\n\nconst COMPOSITION_KEYWORDS = [\"allOf\", \"anyOf\", \"oneOf\"] as const;\n\nconst SHAPED_KEYWORDS: ReadonlySet<string> = new Set([\n \"properties\",\n \"items\",\n \"additionalProperties\",\n]);\n\n/**\n * Whether the keyword gives the owner's generated type a member: `items` only an array,\n * `properties` and `additionalProperties` only an object (`type: string` ignores them). A node\n * that is not in the document is indexed as the keyword says.\n */\nfunction hasKeywordMember(owner: unknown, segment: string): boolean {\n if (!SHAPED_KEYWORDS.has(segment) || !isJsonObject(owner)) {\n return true;\n }\n return segment === \"items\" ? isArrayShape(owner) : isObjectShape(owner);\n}\n\n/**\n * Whether `[string]` of the owner's type is its `additionalProperties` type. Not where the index\n * signature also holds pattern or property types (`withPropertyTypes`), nor next to `allOf` /\n * `anyOf` / `oneOf`, whose members may add an index signature or an inherited discriminator.\n */\nfunction isIndexedByValue(owner: unknown, input: TypedWalkInput): boolean {\n if (!isJsonObject(owner)) {\n return true;\n }\n const patterns = owner.patternProperties;\n const hasPatterns = isJsonObject(patterns) && Object.keys(patterns).length > 0;\n const isComposed = COMPOSITION_KEYWORDS.some((keyword) => keyword in owner);\n return !hasPatterns && !isComposed && !hasKeptProperties(owner, input.options, input.refs);\n}\n\nfunction keywordStep(walk: TypedWalk, segment: string, isLast: boolean, input: TypedWalkInput) {\n const owner = followLocated(walk, input.refs);\n if (!hasKeywordMember(owner.node, segment)) {\n return null;\n }\n switch (segment) {\n case \"properties\":\n return { ...walk, isName: true, namesLocation: childLocation(owner.location, segment) };\n case \"items\":\n return indexEntries(walk, \"number\", \"items\", input.refs);\n case \"additionalProperties\":\n // Otherwise the walk stops, and the target is typed in place.\n return isIndexedByValue(owner.node, input)\n ? indexEntries(walk, \"string\", \"additionalProperties\", input.refs)\n : null;\n case DEFS_KEYWORD:\n return defsStep(walk, owner, isLast);\n default:\n return null;\n }\n}\n\nfunction containerStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk {\n const segment = input.pointer.segments[index] as string;\n const owner = followRefs(walk.node, input.refs);\n const isOptional =\n (segment === \"requestBody\" && isOptionalRequestBody(owner, input.refs)) ||\n isOptionalHeader(input.pointer, index, owner);\n return {\n ...walk,\n type: indexBy(present(walk), segment),\n node: isJsonObject(owner) ? owner[segment] : undefined,\n location: childLocation(followLocated(walk, input.refs).location, segment),\n presence: isOptional ? \"absent\" : \"present\",\n };\n}\n\n/**\n * The `content` of a header or parameter: no member of its own, since the type holds its media\n * types (or the first one's type). Untyped where the type is `string` or a `schema`'s, and as the\n * last segment of the first media type form, whose type is not the map's.\n */\nfunction contentStep(walk: TypedWalk, form: ContentForm, isLast: boolean, refs: RefResolver) {\n const isMapTyped = form === \"media-type-members\" || (form === \"first-media-type\" && !isLast);\n if (!isMapTyped) {\n return null;\n }\n const owner = followLocated(walk, refs);\n return {\n ...walk,\n node: isJsonObject(owner.node) ? owner.node.content : undefined,\n location: childLocation(owner.location, \"content\"),\n isFirstMediaType: form === \"first-media-type\",\n };\n}\n\n/** The first media type of such a `content` is the type itself; another one has no type. */\nfunction firstMediaTypeStep(walk: TypedWalk, segment: string): TypedWalk | null {\n const content = isJsonObject(walk.node) ? walk.node : {};\n if (Object.keys(content)[0] !== segment) {\n return null;\n }\n const location = childLocation(walk.location, segment);\n return { ...walk, node: content[segment], location, isFirstMediaType: false };\n}\n\nfunction schemaStep(walk: TypedWalk, refs: RefResolver): TypedWalk {\n const owner = followLocated(walk, refs);\n const schema = isJsonObject(owner.node) ? owner.node.schema : undefined;\n const location = childLocation(owner.location, \"schema\");\n // The container's type is its schema's type: an optional header stays optional.\n const presence = walk.presence === \"absent\" ? \"absent\" : schemaPresence(schema, refs);\n return { ...walk, node: schema, location, isSchema: true, presence };\n}\n\nfunction documentStep(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const owner = followRefs(walk.node, input.refs);\n const form = headerParameterContentForm(input.pointer, index, owner, input.options);\n if (form !== null) {\n const isLast = index === input.pointer.segments.length - 1;\n return contentStep(walk, form, isLast, input.refs);\n }\n if (\n isParameterList(input.pointer, index) ||\n isExcludedOperation(input.pointer, index, owner, input)\n ) {\n return null;\n }\n return containerStep(walk, index, input);\n}\n\nfunction step(walk: TypedWalk, index: number, input: TypedWalkInput): TypedWalk | null {\n const { segments } = input.pointer;\n const segment = segments[index] as string;\n const isLast = index === segments.length - 1;\n if (walk.isSchema) {\n return walk.isName\n ? nameStep(walk, segment, isLast, input)\n : keywordStep(walk, segment, isLast, input);\n }\n if (walk.isFirstMediaType) {\n return firstMediaTypeStep(walk, segment);\n }\n if (segment === \"schema\" && isTypedAsSchema(input.pointer, index)) {\n return schemaStep(walk, input.refs);\n }\n return documentStep(walk, index, input);\n}\n\n/** Walk the whole pointer; see the module comment. */\nexport function typedWalk(input: TypedWalkInput): TypedWalkResult {\n const { pointer } = input;\n const { node, location } = leadingLocated(pointer, input.refs);\n const isSchema = startsInSchema(pointer);\n let walk: TypedWalk = {\n type: indexBy(\n rootType(pointer.rootSegment, false),\n ...pointer.segments.slice(0, leadingSegmentsOf(pointer)),\n ),\n node,\n location,\n isSchema,\n isName: false,\n presence: isSchema ? schemaPresence(node, input.refs) : \"present\",\n };\n for (let index = leadingSegmentsOf(pointer); index < pointer.segments.length; index++) {\n const next = step(walk, index, input);\n if (next === null) {\n return { kind: \"untyped\", index };\n }\n walk = next;\n }\n return { kind: \"typed\", walk };\n}\n"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ const cliArguments = require('./cli-arguments.cjs');
6
6
  const cliErrors = require('./cli-errors.cjs');
7
7
  const fixOption = require('./fix-option.cjs');
8
8
  const refLimits = require('./ref-limits.cjs');
9
+ const cliFlagNames = require('./cli-flag-names.cjs');
9
10
 
10
11
  const OUTPUT_SETTING = "output";
11
12
  const FIX_SETTING = "fix";
@@ -18,7 +19,7 @@ const CAMEL_CASE_SETTINGS = [
18
19
  FIX_SETTING,
19
20
  LOCAL_REF_ROOT_SETTING,
20
21
  REMOTE_REF_HOSTS_SETTING,
21
- ...cliArguments.GENERATOR_FLAGS,
22
+ ...cliFlagNames.GENERATOR_FLAGS,
22
23
  ...IGNORED_SETTINGS
23
24
  ];
24
25
  const KNOWN_SETTINGS = /* @__PURE__ */ new Set([
@@ -56,7 +57,7 @@ function invalidSetting(apiName, settings, name, expected) {
56
57
  }
57
58
  function apiFlags(apiName, settings) {
58
59
  const flags = {};
59
- for (const name of cliArguments.GENERATOR_FLAGS) {
60
+ for (const name of cliFlagNames.GENERATOR_FLAGS) {
60
61
  const value = settingValue(settings, name);
61
62
  if (typeof value === "boolean") {
62
63
  flags[name] = value;
@@ -1 +1 @@
1
- {"version":3,"file":"api-settings.cjs","sources":["../../src/cli/api-settings.ts"],"sourcesContent":["import { kebabCase } from \"scule\";\nimport type { OutputFixName } from \"../domain/output-fixes.js\";\nimport { WARNING_CODES, warningText } from \"../domain/warnings.js\";\nimport { GENERATOR_FLAGS, type GeneratorFlags, hostList } from \"./cli-arguments.js\";\nimport { ApiFailure, cliError } from \"./cli-errors.js\";\nimport { fixNamesOf } from \"./fix-option.js\";\nimport { localRootUrl, type RefLimitOptions } from \"./ref-limits.js\";\n\n/**\n * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name\n * of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not\n * read gets a warning, as an unknown flag gets a notice.\n */\n\nexport type ApiSettings = Readonly<Record<string, unknown>>;\n\n/** The setting that names the output file. */\nexport const OUTPUT_SETTING = \"output\";\n\n/** The setting that lists the API's output fixes. */\nexport const FIX_SETTING = \"fix\";\n\nconst LOCAL_REF_ROOT_SETTING = \"localRefRoot\";\nconst LOCAL_ROOT_EXPECTED = \"a directory path or a file: URL\";\nconst REMOTE_REF_HOSTS_SETTING = \"remoteRefHosts\";\n\n/** `--content-never` is accepted and has no effect, as on the command line. */\nconst IGNORED_SETTINGS = [\"contentNever\"] as const;\n\nconst CAMEL_CASE_SETTINGS = [\n OUTPUT_SETTING,\n FIX_SETTING,\n LOCAL_REF_ROOT_SETTING,\n REMOTE_REF_HOSTS_SETTING,\n ...GENERATOR_FLAGS,\n ...IGNORED_SETTINGS,\n];\n\nconst KNOWN_SETTINGS = new Set<string>([\n ...CAMEL_CASE_SETTINGS,\n ...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),\n]);\n\n/** The warning for each setting of an API that no code reads. */\nexport function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {\n return Object.keys(settings)\n .filter((key) => !KNOWN_SETTINGS.has(key))\n .map((key) =>\n warningText(\n `API ${apiName}: the setting \\`${key}\\` is not an openapi-typesafe option and is ignored`,\n WARNING_CODES.CONFIG_SETTING_UNKNOWN,\n ),\n );\n}\n\n/** The key a setting is written with: camelCase, else kebab-case; undefined when it is absent. */\nfunction settingKey(settings: ApiSettings, name: string): string | undefined {\n if (name in settings) {\n return name;\n }\n const kebabName = kebabCase(name);\n return kebabName in settings ? kebabName : undefined;\n}\n\n/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */\nfunction settingValue(settings: ApiSettings, name: string): unknown {\n const key = settingKey(settings, name);\n return key === undefined ? undefined : settings[key];\n}\n\nfunction hasSetting(settings: ApiSettings, name: string): boolean {\n return settingKey(settings, name) !== undefined;\n}\n\n/** `CLI_CONFIG_INVALID` for the setting `name` of an API, named as the user wrote it. */\nfunction invalidSetting(apiName: string, settings: ApiSettings, name: string, expected: string) {\n const key = settingKey(settings, name) ?? kebabCase(name);\n return cliError(\n \"CLI_CONFIG_INVALID\",\n `API ${apiName}: \\`${key}\\` in x-openapi-ts must be ${expected}`,\n );\n}\n\n/**\n * The boolean flags an API sets, in camelCase or kebab-case; they win over the CLI's flags. A\n * value of another type (`root-types: \"true\"`) fails with `CLI_CONFIG_INVALID`: ignoring it\n * would generate other types than the config asks for, without a word.\n */\nexport function apiFlags(apiName: string, settings: ApiSettings): GeneratorFlags {\n const flags: Partial<Record<(typeof GENERATOR_FLAGS)[number], boolean>> = {};\n for (const name of GENERATOR_FLAGS) {\n const value = settingValue(settings, name);\n if (typeof value === \"boolean\") {\n flags[name] = value;\n } else if (hasSetting(settings, name)) {\n throw invalidSetting(apiName, settings, name, \"true or false\");\n }\n }\n return flags;\n}\n\n/** The API's `output` file as written; fails with `CLI_CONFIG_INVALID` when it is not text. */\nexport function apiOutputOf(apiName: string, settings: ApiSettings): string {\n const output = settings[OUTPUT_SETTING];\n if (typeof output !== \"string\") {\n throw invalidSetting(apiName, settings, OUTPUT_SETTING, \"a file path\");\n }\n return output;\n}\n\n/**\n * The API's `fix` names, which replace the CLI's `--fix` (ADR-021). An entry that is not text\n * fails with `CLI_CONFIG_INVALID`; an unknown name with `OPTION_FIX_UNKNOWN`, naming the API.\n */\nexport function apiFixNames(\n apiName: string,\n settings: ApiSettings,\n): readonly OutputFixName[] | undefined {\n if (!hasSetting(settings, FIX_SETTING)) {\n return undefined;\n }\n const entries = [settingValue(settings, FIX_SETTING)].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, FIX_SETTING, \"a list of fix names or a comma list\");\n }\n try {\n return fixNamesOf(entries);\n } catch (error) {\n throw new ApiFailure(apiName, error);\n }\n}\n\n/**\n * `local-ref-root: dir`, relative to the config file; empty means the config file's directory. A\n * value that is no text or a URL of another protocol fails with `CLI_CONFIG_INVALID`.\n */\nfunction localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {\n if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {\n return {};\n }\n const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? \"\";\n const localRoot = typeof value === \"string\" ? localRootUrl(value, configRoot) : undefined;\n if (localRoot === undefined) {\n throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, LOCAL_ROOT_EXPECTED);\n }\n return { localRefRoot: localRoot };\n}\n\n/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */\nfunction remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {\n if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {\n return {};\n }\n const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];\n const entries = [value].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, REMOTE_REF_HOSTS_SETTING, \"a host list\");\n }\n return { remoteRefHosts: hostList(entries) ?? [] };\n}\n\n/**\n * The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same\n * name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a\n * value of another type.\n */\nexport function apiRefLimitOptions(\n apiName: string,\n settings: ApiSettings,\n configRoot: URL,\n): RefLimitOptions {\n return {\n ...localRefRootOf(apiName, settings, configRoot),\n ...remoteRefHostsOf(apiName, settings),\n };\n}\n"],"names":["GENERATOR_FLAGS","kebabCase","warningText","WARNING_CODES","cliError","fixNamesOf","ApiFailure","localRootUrl","hostList"],"mappings":"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"}
1
+ {"version":3,"file":"api-settings.cjs","sources":["../../src/cli/api-settings.ts"],"sourcesContent":["import { kebabCase } from \"scule\";\nimport type { OutputFixName } from \"../domain/output-fixes.js\";\nimport { WARNING_CODES, warningText } from \"../domain/warnings.js\";\nimport { GENERATOR_FLAGS, type GeneratorFlags, hostList } from \"./cli-arguments.js\";\nimport { ApiFailure, cliError } from \"./cli-errors.js\";\nimport { fixNamesOf } from \"./fix-option.js\";\nimport { localRootUrl, type RefLimitOptions } from \"./ref-limits.js\";\n\n/**\n * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name\n * of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not\n * read gets a warning, as an unknown flag gets a notice.\n */\n\nexport type ApiSettings = Readonly<Record<string, unknown>>;\n\n/** The setting that names the output file. */\nexport const OUTPUT_SETTING = \"output\";\n\n/** The setting that lists the API's output fixes. */\nexport const FIX_SETTING = \"fix\";\n\nconst LOCAL_REF_ROOT_SETTING = \"localRefRoot\";\nconst LOCAL_ROOT_EXPECTED = \"a directory path or a file: URL\";\nconst REMOTE_REF_HOSTS_SETTING = \"remoteRefHosts\";\n\n/** `--content-never` is accepted and has no effect, as on the command line. */\nconst IGNORED_SETTINGS = [\"contentNever\"] as const;\n\nconst CAMEL_CASE_SETTINGS = [\n OUTPUT_SETTING,\n FIX_SETTING,\n LOCAL_REF_ROOT_SETTING,\n REMOTE_REF_HOSTS_SETTING,\n ...GENERATOR_FLAGS,\n ...IGNORED_SETTINGS,\n];\n\nconst KNOWN_SETTINGS = new Set<string>([\n ...CAMEL_CASE_SETTINGS,\n ...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),\n]);\n\n/** The warning for each setting of an API that no code reads. */\nexport function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {\n return Object.keys(settings)\n .filter((key) => !KNOWN_SETTINGS.has(key))\n .map((key) =>\n warningText(\n `API ${apiName}: the setting \\`${key}\\` is not an openapi-typesafe option and is ignored`,\n WARNING_CODES.CONFIG_SETTING_UNKNOWN,\n ),\n );\n}\n\n/** The key a setting is written with: camelCase, else kebab-case; undefined when it is absent. */\nfunction settingKey(settings: ApiSettings, name: string): string | undefined {\n if (name in settings) {\n return name;\n }\n const kebabName = kebabCase(name);\n return kebabName in settings ? kebabName : undefined;\n}\n\n/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */\nfunction settingValue(settings: ApiSettings, name: string): unknown {\n const key = settingKey(settings, name);\n return key === undefined ? undefined : settings[key];\n}\n\nfunction hasSetting(settings: ApiSettings, name: string): boolean {\n return settingKey(settings, name) !== undefined;\n}\n\n/** `CLI_CONFIG_INVALID` for the setting `name` of an API, named as the user wrote it. */\nfunction invalidSetting(apiName: string, settings: ApiSettings, name: string, expected: string) {\n const key = settingKey(settings, name) ?? kebabCase(name);\n return cliError(\n \"CLI_CONFIG_INVALID\",\n `API ${apiName}: \\`${key}\\` in x-openapi-ts must be ${expected}`,\n );\n}\n\n/**\n * The boolean flags an API sets, in camelCase or kebab-case; they win over the CLI's flags. A\n * value of another type (`root-types: \"true\"`) fails with `CLI_CONFIG_INVALID`: ignoring it\n * would generate other types than the config asks for, without a word.\n */\nexport function apiFlags(apiName: string, settings: ApiSettings): GeneratorFlags {\n const flags: Partial<Record<(typeof GENERATOR_FLAGS)[number], boolean>> = {};\n for (const name of GENERATOR_FLAGS) {\n const value = settingValue(settings, name);\n if (typeof value === \"boolean\") {\n flags[name] = value;\n } else if (hasSetting(settings, name)) {\n throw invalidSetting(apiName, settings, name, \"true or false\");\n }\n }\n return flags;\n}\n\n/** The API's `output` file as written; fails with `CLI_CONFIG_INVALID` when it is not text. */\nexport function apiOutputOf(apiName: string, settings: ApiSettings): string {\n const output = settings[OUTPUT_SETTING];\n if (typeof output !== \"string\") {\n throw invalidSetting(apiName, settings, OUTPUT_SETTING, \"a file path\");\n }\n return output;\n}\n\n/**\n * The API's `fix` names, which replace the CLI's `--fix` (ADR-021). An entry that is not text\n * fails with `CLI_CONFIG_INVALID`; an unknown name with `OPTION_FIX_UNKNOWN`, naming the API.\n */\nexport function apiFixNames(\n apiName: string,\n settings: ApiSettings,\n): readonly OutputFixName[] | undefined {\n if (!hasSetting(settings, FIX_SETTING)) {\n return undefined;\n }\n const entries = [settingValue(settings, FIX_SETTING)].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, FIX_SETTING, \"a list of fix names or a comma list\");\n }\n try {\n return fixNamesOf(entries);\n } catch (error) {\n throw new ApiFailure(apiName, error);\n }\n}\n\n/**\n * `local-ref-root: dir`, relative to the config file; empty means the config file's directory. A\n * value that is no text or a URL of another protocol fails with `CLI_CONFIG_INVALID`.\n */\nfunction localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {\n if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {\n return {};\n }\n const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? \"\";\n const localRoot = typeof value === \"string\" ? localRootUrl(value, configRoot) : undefined;\n if (localRoot === undefined) {\n throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, LOCAL_ROOT_EXPECTED);\n }\n return { localRefRoot: localRoot };\n}\n\n/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */\nfunction remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {\n if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {\n return {};\n }\n const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];\n const entries = [value].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, REMOTE_REF_HOSTS_SETTING, \"a host list\");\n }\n return { remoteRefHosts: hostList(entries) ?? [] };\n}\n\n/**\n * The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same\n * name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a\n * value of another type.\n */\nexport function apiRefLimitOptions(\n apiName: string,\n settings: ApiSettings,\n configRoot: URL,\n): RefLimitOptions {\n return {\n ...localRefRootOf(apiName, settings, configRoot),\n ...remoteRefHostsOf(apiName, settings),\n };\n}\n"],"names":["GENERATOR_FLAGS","kebabCase","warningText","WARNING_CODES","cliError","fixNamesOf","ApiFailure","localRootUrl","hostList"],"mappings":";;;;;;;;;;AAiBO,MAAM,cAAA,GAAiB;AAGvB,MAAM,WAAA,GAAc;AAE3B,MAAM,sBAAA,GAAyB,cAAA;AAC/B,MAAM,mBAAA,GAAsB,iCAAA;AAC5B,MAAM,wBAAA,GAA2B,gBAAA;AAGjC,MAAM,gBAAA,GAAmB,CAAC,cAAc,CAAA;AAExC,MAAM,mBAAA,GAAsB;AAAA,EAC1B,cAAA;AAAA,EACA,WAAA;AAAA,EACA,sBAAA;AAAA,EACA,wBAAA;AAAA,EACA,GAAGA,4BAAA;AAAA,EACH,GAAG;AACL,CAAA;AAEA,MAAM,cAAA,uBAAqB,GAAA,CAAY;AAAA,EACrC,GAAG,mBAAA;AAAA,EACH,GAAG,mBAAA,CAAoB,GAAA,CAAI,CAAC,IAAA,KAASC,eAAA,CAAU,IAAI,CAAC;AACtD,CAAC,CAAA;AAGM,SAAS,sBAAA,CAAuB,SAAiB,QAAA,EAAiC;AACvF,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA,CACxB,MAAA,CAAO,CAAC,GAAA,KAAQ,CAAC,cAAA,CAAe,GAAA,CAAI,GAAG,CAAC,CAAA,CACxC,GAAA;AAAA,IAAI,CAAC,GAAA,KACJC,oBAAA;AAAA,MACE,CAAA,IAAA,EAAO,OAAO,CAAA,gBAAA,EAAmB,GAAG,CAAA,mDAAA,CAAA;AAAA,MACpCC,sBAAA,CAAc;AAAA;AAChB,GACF;AACJ;AAGA,SAAS,UAAA,CAAW,UAAuB,IAAA,EAAkC;AAC3E,EAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAYF,gBAAU,IAAI,CAAA;AAChC,EAAA,OAAO,SAAA,IAAa,WAAW,SAAA,GAAY,MAAA;AAC7C;AAGA,SAAS,YAAA,CAAa,UAAuB,IAAA,EAAuB;AAClE,EAAA,MAAM,GAAA,GAAM,UAAA,CAAW,QAAA,EAAU,IAAI,CAAA;AACrC,EAAA,OAAO,GAAA,KAAQ,MAAA,GAAY,MAAA,GAAY,QAAA,CAAS,GAAG,CAAA;AACrD;AAEA,SAAS,UAAA,CAAW,UAAuB,IAAA,EAAuB;AAChE,EAAA,OAAO,UAAA,CAAW,QAAA,EAAU,IAAI,CAAA,KAAM,MAAA;AACxC;AAGA,SAAS,cAAA,CAAe,OAAA,EAAiB,QAAA,EAAuB,IAAA,EAAc,QAAA,EAAkB;AAC9F,EAAA,MAAM,MAAM,UAAA,CAAW,QAAA,EAAU,IAAI,CAAA,IAAKA,gBAAU,IAAI,CAAA;AACxD,EAAA,OAAOG,kBAAA;AAAA,IACL,oBAAA;AAAA,IACA,CAAA,IAAA,EAAO,OAAO,CAAA,IAAA,EAAO,GAAG,8BAA8B,QAAQ,CAAA;AAAA,GAChE;AACF;AAOO,SAAS,QAAA,CAAS,SAAiB,QAAA,EAAuC;AAC/E,EAAA,MAAM,QAAoE,EAAC;AAC3E,EAAA,KAAA,MAAW,QAAQJ,4BAAA,EAAiB;AAClC,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,QAAA,EAAU,IAAI,CAAA;AACzC,IAAA,IAAI,OAAO,UAAU,SAAA,EAAW;AAC9B,MAAA,KAAA,CAAM,IAAI,CAAA,GAAI,KAAA;AAAA,IAChB,CAAA,MAAA,IAAW,UAAA,CAAW,QAAA,EAAU,IAAI,CAAA,EAAG;AACrC,MAAA,MAAM,cAAA,CAAe,OAAA,EAAS,QAAA,EAAU,IAAA,EAAM,eAAe,CAAA;AAAA,IAC/D;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,WAAA,CAAY,SAAiB,QAAA,EAA+B;AAC1E,EAAA,MAAM,MAAA,GAAS,SAAS,cAAc,CAAA;AACtC,EAAA,IAAI,OAAO,WAAW,QAAA,EAAU;AAC9B,IAAA,MAAM,cAAA,CAAe,OAAA,EAAS,QAAA,EAAU,cAAA,EAAgB,aAAa,CAAA;AAAA,EACvE;AACA,EAAA,OAAO,MAAA;AACT;AAMO,SAAS,WAAA,CACd,SACA,QAAA,EACsC;AACtC,EAAA,IAAI,CAAC,UAAA,CAAW,QAAA,EAAU,WAAW,CAAA,EAAG;AACtC,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,UAAU,CAAC,YAAA,CAAa,UAAU,WAAW,CAAC,EAAE,IAAA,EAAK;AAC3D,EAAA,IAAI,QAAQ,IAAA,CAAK,CAAC,UAAU,OAAO,KAAA,KAAU,QAAQ,CAAA,EAAG;AACtD,IAAA,MAAM,cAAA,CAAe,OAAA,EAAS,QAAA,EAAU,WAAA,EAAa,qCAAqC,CAAA;AAAA,EAC5F;AACA,EAAA,IAAI;AACF,IAAA,OAAOK,qBAAW,OAAO,CAAA;AAAA,EAC3B,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAIC,oBAAA,CAAW,OAAA,EAAS,KAAK,CAAA;AAAA,EACrC;AACF;AAMA,SAAS,cAAA,CAAe,OAAA,EAAiB,QAAA,EAAuB,UAAA,EAAkC;AAChG,EAAA,IAAI,CAAC,UAAA,CAAW,QAAA,EAAU,sBAAsB,CAAA,EAAG;AACjD,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,QAAA,EAAU,sBAAsB,CAAA,IAAK,EAAA;AAChE,EAAA,MAAM,YAAY,OAAO,KAAA,KAAU,WAAWC,sBAAA,CAAa,KAAA,EAAO,UAAU,CAAA,GAAI,MAAA;AAChF,EAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,IAAA,MAAM,cAAA,CAAe,OAAA,EAAS,QAAA,EAAU,sBAAA,EAAwB,mBAAmB,CAAA;AAAA,EACrF;AACA,EAAA,OAAO,EAAE,cAAc,SAAA,EAAU;AACnC;AAGA,SAAS,gBAAA,CAAiB,SAAiB,QAAA,EAAwC;AACjF,EAAA,IAAI,CAAC,UAAA,CAAW,QAAA,EAAU,wBAAwB,CAAA,EAAG;AACnD,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,QAAA,EAAU,wBAAwB,KAAK,EAAC;AACnE,EAAA,MAAM,OAAA,GAAU,CAAC,KAAK,CAAA,CAAE,IAAA,EAAK;AAC7B,EAAA,IAAI,QAAQ,IAAA,CAAK,CAAC,UAAU,OAAO,KAAA,KAAU,QAAQ,CAAA,EAAG;AACtD,IAAA,MAAM,cAAA,CAAe,OAAA,EAAS,QAAA,EAAU,wBAAA,EAA0B,aAAa,CAAA;AAAA,EACjF;AACA,EAAA,OAAO,EAAE,cAAA,EAAgBC,qBAAA,CAAS,OAAO,CAAA,IAAK,EAAC,EAAE;AACnD;AAOO,SAAS,kBAAA,CACd,OAAA,EACA,QAAA,EACA,UAAA,EACiB;AACjB,EAAA,OAAO;AAAA,IACL,GAAG,cAAA,CAAe,OAAA,EAAS,QAAA,EAAU,UAAU,CAAA;AAAA,IAC/C,GAAG,gBAAA,CAAiB,OAAA,EAAS,QAAQ;AAAA,GACvC;AACF;;;;;;;;"}
@@ -1,9 +1,10 @@
1
1
  import { kebabCase } from 'scule';
2
2
  import { warningText, WARNING_CODES } from '../domain/warnings.mjs';
3
- import { GENERATOR_FLAGS, hostList } from './cli-arguments.mjs';
3
+ import { hostList } from './cli-arguments.mjs';
4
4
  import { cliError, ApiFailure } from './cli-errors.mjs';
5
5
  import { fixNamesOf } from './fix-option.mjs';
6
6
  import { localRootUrl } from './ref-limits.mjs';
7
+ import { GENERATOR_FLAGS } from './cli-flag-names.mjs';
7
8
 
8
9
  const OUTPUT_SETTING = "output";
9
10
  const FIX_SETTING = "fix";
@@ -1 +1 @@
1
- {"version":3,"file":"api-settings.mjs","sources":["../../src/cli/api-settings.ts"],"sourcesContent":["import { kebabCase } from \"scule\";\nimport type { OutputFixName } from \"../domain/output-fixes.js\";\nimport { WARNING_CODES, warningText } from \"../domain/warnings.js\";\nimport { GENERATOR_FLAGS, type GeneratorFlags, hostList } from \"./cli-arguments.js\";\nimport { ApiFailure, cliError } from \"./cli-errors.js\";\nimport { fixNamesOf } from \"./fix-option.js\";\nimport { localRootUrl, type RefLimitOptions } from \"./ref-limits.js\";\n\n/**\n * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name\n * of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not\n * read gets a warning, as an unknown flag gets a notice.\n */\n\nexport type ApiSettings = Readonly<Record<string, unknown>>;\n\n/** The setting that names the output file. */\nexport const OUTPUT_SETTING = \"output\";\n\n/** The setting that lists the API's output fixes. */\nexport const FIX_SETTING = \"fix\";\n\nconst LOCAL_REF_ROOT_SETTING = \"localRefRoot\";\nconst LOCAL_ROOT_EXPECTED = \"a directory path or a file: URL\";\nconst REMOTE_REF_HOSTS_SETTING = \"remoteRefHosts\";\n\n/** `--content-never` is accepted and has no effect, as on the command line. */\nconst IGNORED_SETTINGS = [\"contentNever\"] as const;\n\nconst CAMEL_CASE_SETTINGS = [\n OUTPUT_SETTING,\n FIX_SETTING,\n LOCAL_REF_ROOT_SETTING,\n REMOTE_REF_HOSTS_SETTING,\n ...GENERATOR_FLAGS,\n ...IGNORED_SETTINGS,\n];\n\nconst KNOWN_SETTINGS = new Set<string>([\n ...CAMEL_CASE_SETTINGS,\n ...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),\n]);\n\n/** The warning for each setting of an API that no code reads. */\nexport function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {\n return Object.keys(settings)\n .filter((key) => !KNOWN_SETTINGS.has(key))\n .map((key) =>\n warningText(\n `API ${apiName}: the setting \\`${key}\\` is not an openapi-typesafe option and is ignored`,\n WARNING_CODES.CONFIG_SETTING_UNKNOWN,\n ),\n );\n}\n\n/** The key a setting is written with: camelCase, else kebab-case; undefined when it is absent. */\nfunction settingKey(settings: ApiSettings, name: string): string | undefined {\n if (name in settings) {\n return name;\n }\n const kebabName = kebabCase(name);\n return kebabName in settings ? kebabName : undefined;\n}\n\n/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */\nfunction settingValue(settings: ApiSettings, name: string): unknown {\n const key = settingKey(settings, name);\n return key === undefined ? undefined : settings[key];\n}\n\nfunction hasSetting(settings: ApiSettings, name: string): boolean {\n return settingKey(settings, name) !== undefined;\n}\n\n/** `CLI_CONFIG_INVALID` for the setting `name` of an API, named as the user wrote it. */\nfunction invalidSetting(apiName: string, settings: ApiSettings, name: string, expected: string) {\n const key = settingKey(settings, name) ?? kebabCase(name);\n return cliError(\n \"CLI_CONFIG_INVALID\",\n `API ${apiName}: \\`${key}\\` in x-openapi-ts must be ${expected}`,\n );\n}\n\n/**\n * The boolean flags an API sets, in camelCase or kebab-case; they win over the CLI's flags. A\n * value of another type (`root-types: \"true\"`) fails with `CLI_CONFIG_INVALID`: ignoring it\n * would generate other types than the config asks for, without a word.\n */\nexport function apiFlags(apiName: string, settings: ApiSettings): GeneratorFlags {\n const flags: Partial<Record<(typeof GENERATOR_FLAGS)[number], boolean>> = {};\n for (const name of GENERATOR_FLAGS) {\n const value = settingValue(settings, name);\n if (typeof value === \"boolean\") {\n flags[name] = value;\n } else if (hasSetting(settings, name)) {\n throw invalidSetting(apiName, settings, name, \"true or false\");\n }\n }\n return flags;\n}\n\n/** The API's `output` file as written; fails with `CLI_CONFIG_INVALID` when it is not text. */\nexport function apiOutputOf(apiName: string, settings: ApiSettings): string {\n const output = settings[OUTPUT_SETTING];\n if (typeof output !== \"string\") {\n throw invalidSetting(apiName, settings, OUTPUT_SETTING, \"a file path\");\n }\n return output;\n}\n\n/**\n * The API's `fix` names, which replace the CLI's `--fix` (ADR-021). An entry that is not text\n * fails with `CLI_CONFIG_INVALID`; an unknown name with `OPTION_FIX_UNKNOWN`, naming the API.\n */\nexport function apiFixNames(\n apiName: string,\n settings: ApiSettings,\n): readonly OutputFixName[] | undefined {\n if (!hasSetting(settings, FIX_SETTING)) {\n return undefined;\n }\n const entries = [settingValue(settings, FIX_SETTING)].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, FIX_SETTING, \"a list of fix names or a comma list\");\n }\n try {\n return fixNamesOf(entries);\n } catch (error) {\n throw new ApiFailure(apiName, error);\n }\n}\n\n/**\n * `local-ref-root: dir`, relative to the config file; empty means the config file's directory. A\n * value that is no text or a URL of another protocol fails with `CLI_CONFIG_INVALID`.\n */\nfunction localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {\n if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {\n return {};\n }\n const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? \"\";\n const localRoot = typeof value === \"string\" ? localRootUrl(value, configRoot) : undefined;\n if (localRoot === undefined) {\n throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, LOCAL_ROOT_EXPECTED);\n }\n return { localRefRoot: localRoot };\n}\n\n/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */\nfunction remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {\n if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {\n return {};\n }\n const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];\n const entries = [value].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, REMOTE_REF_HOSTS_SETTING, \"a host list\");\n }\n return { remoteRefHosts: hostList(entries) ?? [] };\n}\n\n/**\n * The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same\n * name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a\n * value of another type.\n */\nexport function apiRefLimitOptions(\n apiName: string,\n settings: ApiSettings,\n configRoot: URL,\n): RefLimitOptions {\n return {\n ...localRefRootOf(apiName, settings, configRoot),\n ...remoteRefHostsOf(apiName, settings),\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-settings.mjs","sources":["../../src/cli/api-settings.ts"],"sourcesContent":["import { kebabCase } from \"scule\";\nimport type { OutputFixName } from \"../domain/output-fixes.js\";\nimport { WARNING_CODES, warningText } from \"../domain/warnings.js\";\nimport { GENERATOR_FLAGS, type GeneratorFlags, hostList } from \"./cli-arguments.js\";\nimport { ApiFailure, cliError } from \"./cli-errors.js\";\nimport { fixNamesOf } from \"./fix-option.js\";\nimport { localRootUrl, type RefLimitOptions } from \"./ref-limits.js\";\n\n/**\n * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name\n * of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not\n * read gets a warning, as an unknown flag gets a notice.\n */\n\nexport type ApiSettings = Readonly<Record<string, unknown>>;\n\n/** The setting that names the output file. */\nexport const OUTPUT_SETTING = \"output\";\n\n/** The setting that lists the API's output fixes. */\nexport const FIX_SETTING = \"fix\";\n\nconst LOCAL_REF_ROOT_SETTING = \"localRefRoot\";\nconst LOCAL_ROOT_EXPECTED = \"a directory path or a file: URL\";\nconst REMOTE_REF_HOSTS_SETTING = \"remoteRefHosts\";\n\n/** `--content-never` is accepted and has no effect, as on the command line. */\nconst IGNORED_SETTINGS = [\"contentNever\"] as const;\n\nconst CAMEL_CASE_SETTINGS = [\n OUTPUT_SETTING,\n FIX_SETTING,\n LOCAL_REF_ROOT_SETTING,\n REMOTE_REF_HOSTS_SETTING,\n ...GENERATOR_FLAGS,\n ...IGNORED_SETTINGS,\n];\n\nconst KNOWN_SETTINGS = new Set<string>([\n ...CAMEL_CASE_SETTINGS,\n ...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),\n]);\n\n/** The warning for each setting of an API that no code reads. */\nexport function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {\n return Object.keys(settings)\n .filter((key) => !KNOWN_SETTINGS.has(key))\n .map((key) =>\n warningText(\n `API ${apiName}: the setting \\`${key}\\` is not an openapi-typesafe option and is ignored`,\n WARNING_CODES.CONFIG_SETTING_UNKNOWN,\n ),\n );\n}\n\n/** The key a setting is written with: camelCase, else kebab-case; undefined when it is absent. */\nfunction settingKey(settings: ApiSettings, name: string): string | undefined {\n if (name in settings) {\n return name;\n }\n const kebabName = kebabCase(name);\n return kebabName in settings ? kebabName : undefined;\n}\n\n/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */\nfunction settingValue(settings: ApiSettings, name: string): unknown {\n const key = settingKey(settings, name);\n return key === undefined ? undefined : settings[key];\n}\n\nfunction hasSetting(settings: ApiSettings, name: string): boolean {\n return settingKey(settings, name) !== undefined;\n}\n\n/** `CLI_CONFIG_INVALID` for the setting `name` of an API, named as the user wrote it. */\nfunction invalidSetting(apiName: string, settings: ApiSettings, name: string, expected: string) {\n const key = settingKey(settings, name) ?? kebabCase(name);\n return cliError(\n \"CLI_CONFIG_INVALID\",\n `API ${apiName}: \\`${key}\\` in x-openapi-ts must be ${expected}`,\n );\n}\n\n/**\n * The boolean flags an API sets, in camelCase or kebab-case; they win over the CLI's flags. A\n * value of another type (`root-types: \"true\"`) fails with `CLI_CONFIG_INVALID`: ignoring it\n * would generate other types than the config asks for, without a word.\n */\nexport function apiFlags(apiName: string, settings: ApiSettings): GeneratorFlags {\n const flags: Partial<Record<(typeof GENERATOR_FLAGS)[number], boolean>> = {};\n for (const name of GENERATOR_FLAGS) {\n const value = settingValue(settings, name);\n if (typeof value === \"boolean\") {\n flags[name] = value;\n } else if (hasSetting(settings, name)) {\n throw invalidSetting(apiName, settings, name, \"true or false\");\n }\n }\n return flags;\n}\n\n/** The API's `output` file as written; fails with `CLI_CONFIG_INVALID` when it is not text. */\nexport function apiOutputOf(apiName: string, settings: ApiSettings): string {\n const output = settings[OUTPUT_SETTING];\n if (typeof output !== \"string\") {\n throw invalidSetting(apiName, settings, OUTPUT_SETTING, \"a file path\");\n }\n return output;\n}\n\n/**\n * The API's `fix` names, which replace the CLI's `--fix` (ADR-021). An entry that is not text\n * fails with `CLI_CONFIG_INVALID`; an unknown name with `OPTION_FIX_UNKNOWN`, naming the API.\n */\nexport function apiFixNames(\n apiName: string,\n settings: ApiSettings,\n): readonly OutputFixName[] | undefined {\n if (!hasSetting(settings, FIX_SETTING)) {\n return undefined;\n }\n const entries = [settingValue(settings, FIX_SETTING)].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, FIX_SETTING, \"a list of fix names or a comma list\");\n }\n try {\n return fixNamesOf(entries);\n } catch (error) {\n throw new ApiFailure(apiName, error);\n }\n}\n\n/**\n * `local-ref-root: dir`, relative to the config file; empty means the config file's directory. A\n * value that is no text or a URL of another protocol fails with `CLI_CONFIG_INVALID`.\n */\nfunction localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {\n if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {\n return {};\n }\n const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? \"\";\n const localRoot = typeof value === \"string\" ? localRootUrl(value, configRoot) : undefined;\n if (localRoot === undefined) {\n throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, LOCAL_ROOT_EXPECTED);\n }\n return { localRefRoot: localRoot };\n}\n\n/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */\nfunction remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {\n if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {\n return {};\n }\n const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];\n const entries = [value].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, REMOTE_REF_HOSTS_SETTING, \"a host list\");\n }\n return { remoteRefHosts: hostList(entries) ?? [] };\n}\n\n/**\n * The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same\n * name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a\n * value of another type.\n */\nexport function apiRefLimitOptions(\n apiName: string,\n settings: ApiSettings,\n configRoot: URL,\n): RefLimitOptions {\n return {\n ...localRefRootOf(apiName, settings, configRoot),\n ...remoteRefHostsOf(apiName, settings),\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const cliErrors = require('./cli-errors.cjs');
3
4
  const cliOutput = require('./cli-output.cjs');
4
5
 
5
6
  function failuresOf(step) {
@@ -44,6 +45,11 @@ function writeClaimed(run, { api, claim }) {
44
45
  const failures = failuresOf(() => cliOutput.emitOutput(run, api.outputFile, api.types.contents));
45
46
  return failures.length > 0 && claim ? [...failures, ...failuresOf(() => claim.release())] : failures;
46
47
  }
48
+ function namedFailures(failures) {
49
+ return new Map(
50
+ [...failures].map(([name, list]) => [name, list.map((cause) => new cliErrors.ApiFailure(name, cause))])
51
+ );
52
+ }
47
53
  function writeGeneratedApis(run, apis, readFiles) {
48
54
  const failures = /* @__PURE__ */ new Map();
49
55
  const ownOutputs = apis.filter((api) => {
@@ -64,7 +70,7 @@ function writeGeneratedApis(run, apis, readFiles) {
64
70
  for (const entry of claimed.filter(({ api }) => !shared.has(api.name))) {
65
71
  failures.set(entry.api.name, writeClaimed(run, entry));
66
72
  }
67
- return failures;
73
+ return namedFailures(failures);
68
74
  }
69
75
 
70
76
  exports.failuresOf = failuresOf;
@@ -1 +1 @@
1
- {"version":3,"file":"api-writes.cjs","sources":["../../src/cli/api-writes.ts"],"sourcesContent":["import type { ClaimedFile } from \"../application/ports/file-system.js\";\nimport type { GeneratedTypes } from \"./cli-dependencies.js\";\nimport {\n type CliRun,\n duplicateOutputError,\n emitOutput,\n ensureOutputIsNotSchema,\n type NamedFile,\n type OutputFile,\n} from \"./cli-output.js\";\n\n/**\n * Writing the generated APIs of a Redocly config. Before the first byte is written, every output\n * is claimed: a missing one is created empty, so the file system gives it its own identity. Two\n * APIs whose files then have one identity fail with `CLI_OUTPUT_DUPLICATE` and write nothing,\n * also when their names looked different (ADR-043, decision 1).\n */\n\n/** An API whose types are generated and not written yet. */\nexport interface GeneratedApi {\n readonly name: string;\n readonly outputFile: OutputFile;\n readonly types: GeneratedTypes;\n}\n\n/** An API whose output is claimed; `claim` is undefined with `--check`, which writes nothing. */\ninterface ClaimedApi {\n readonly api: GeneratedApi;\n readonly claim: ClaimedFile | undefined;\n}\n\n/** The failures of the API an API name maps to; an API without failures was written. */\ntype ApiFailures = Map<string, unknown[]>;\n\n/** The failure of a step, as a list: empty when it succeeded. */\nexport function failuresOf(step: () => void): unknown[] {\n try {\n step();\n return [];\n } catch (failure) {\n return [failure];\n }\n}\n\n/** Claim the output of each API; an API whose claim fails gets that failure instead. */\nfunction claimOutputs(run: CliRun, apis: readonly GeneratedApi[], failures: ApiFailures) {\n const claimed: ClaimedApi[] = [];\n for (const api of apis) {\n try {\n const claim = run.args.isCheck ? undefined : run.deps.files.claimFile(api.outputFile.file);\n claimed.push({ api, claim });\n } catch (failure) {\n failures.set(api.name, [failure]);\n }\n }\n return claimed;\n}\n\n/** The APIs that share their claimed file with another, by API name, with the other names. */\nfunction sharedOutputs(claimed: readonly ClaimedApi[]): Map<string, string[]> {\n const byIdentity = new Map<string, string[]>();\n for (const { api, claim } of claimed) {\n if (claim) {\n byIdentity.set(claim.identity, [...(byIdentity.get(claim.identity) ?? []), api.name]);\n }\n }\n const shared = new Map<string, string[]>();\n for (const names of byIdentity.values()) {\n for (const name of names.length > 1 ? names : []) {\n shared.set(\n name,\n names.filter((other) => other !== name).map((other) => `API ${other}`),\n );\n }\n }\n return shared;\n}\n\n/** Write one claimed API; a failed write releases the claim, so no empty file is left. */\nfunction writeClaimed(run: CliRun, { api, claim }: ClaimedApi): unknown[] {\n const failures = failuresOf(() => emitOutput(run, api.outputFile, api.types.contents));\n return failures.length > 0 && claim\n ? [...failures, ...failuresOf(() => claim.release())]\n : failures;\n}\n\n/**\n * Write (or `--check`) every API unless its output is a file the run read or the file of another\n * API. Returns the failures by API name. Claims are released in reverse order, so a directory\n * one claim created is empty by the time it is removed.\n */\nexport function writeGeneratedApis(\n run: CliRun,\n apis: readonly GeneratedApi[],\n readFiles: readonly NamedFile[],\n): ApiFailures {\n const failures: ApiFailures = new Map();\n const ownOutputs = apis.filter((api) => {\n const failure = failuresOf(() => ensureOutputIsNotSchema(run, api.outputFile, readFiles));\n failures.set(api.name, failure);\n return failure.length === 0;\n });\n const claimed = claimOutputs(run, ownOutputs, failures);\n const shared = sharedOutputs(claimed);\n for (const entry of [...claimed].reverse()) {\n const { api, claim } = entry;\n const others = shared.get(api.name);\n if (others) {\n const release = claim ? failuresOf(() => claim.release()) : [];\n failures.set(api.name, [duplicateOutputError(api.outputFile, others), ...release]);\n }\n }\n for (const entry of claimed.filter(({ api }) => !shared.has(api.name))) {\n failures.set(entry.api.name, writeClaimed(run, entry));\n }\n return failures;\n}\n"],"names":["emitOutput","ensureOutputIsNotSchema","duplicateOutputError"],"mappings":"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"}
1
+ {"version":3,"file":"api-writes.cjs","sources":["../../src/cli/api-writes.ts"],"sourcesContent":["import type { ClaimedFile } from \"../application/ports/file-system.js\";\nimport type { GeneratedTypes } from \"./cli-dependencies.js\";\nimport { ApiFailure } from \"./cli-errors.js\";\nimport {\n type CliRun,\n duplicateOutputError,\n emitOutput,\n ensureOutputIsNotSchema,\n type NamedFile,\n type OutputFile,\n} from \"./cli-output.js\";\n\n/**\n * Writing the generated APIs of a Redocly config. Before the first byte is written, every output\n * is claimed: a missing one is created empty, so the file system gives it its own identity. Two\n * APIs whose files then have one identity fail with `CLI_OUTPUT_DUPLICATE` and write nothing,\n * also when their names looked different (ADR-043, decision 1).\n */\n\n/** An API whose types are generated and not written yet. */\nexport interface GeneratedApi {\n readonly name: string;\n readonly outputFile: OutputFile;\n readonly types: GeneratedTypes;\n}\n\n/** An API whose output is claimed; `claim` is undefined with `--check`, which writes nothing. */\ninterface ClaimedApi {\n readonly api: GeneratedApi;\n readonly claim: ClaimedFile | undefined;\n}\n\n/** The failures of the API an API name maps to; an API without failures was written. */\ntype ApiFailures = Map<string, unknown[]>;\n\n/** The failure of a step, as a list: empty when it succeeded. */\nexport function failuresOf(step: () => void): unknown[] {\n try {\n step();\n return [];\n } catch (failure) {\n return [failure];\n }\n}\n\n/** Claim the output of each API; an API whose claim fails gets that failure instead. */\nfunction claimOutputs(run: CliRun, apis: readonly GeneratedApi[], failures: ApiFailures) {\n const claimed: ClaimedApi[] = [];\n for (const api of apis) {\n try {\n const claim = run.args.isCheck ? undefined : run.deps.files.claimFile(api.outputFile.file);\n claimed.push({ api, claim });\n } catch (failure) {\n failures.set(api.name, [failure]);\n }\n }\n return claimed;\n}\n\n/** The APIs that share their claimed file with another, by API name, with the other names. */\nfunction sharedOutputs(claimed: readonly ClaimedApi[]): Map<string, string[]> {\n const byIdentity = new Map<string, string[]>();\n for (const { api, claim } of claimed) {\n if (claim) {\n byIdentity.set(claim.identity, [...(byIdentity.get(claim.identity) ?? []), api.name]);\n }\n }\n const shared = new Map<string, string[]>();\n for (const names of byIdentity.values()) {\n for (const name of names.length > 1 ? names : []) {\n shared.set(\n name,\n names.filter((other) => other !== name).map((other) => `API ${other}`),\n );\n }\n }\n return shared;\n}\n\n/** Write one claimed API; a failed write releases the claim, so no empty file is left. */\nfunction writeClaimed(run: CliRun, { api, claim }: ClaimedApi): unknown[] {\n const failures = failuresOf(() => emitOutput(run, api.outputFile, api.types.contents));\n return failures.length > 0 && claim\n ? [...failures, ...failuresOf(() => claim.release())]\n : failures;\n}\n\n/** The failures with the name of their API, which the CLI prints before each message. */\nfunction namedFailures(failures: ApiFailures): ApiFailures {\n return new Map(\n [...failures].map(([name, list]) => [name, list.map((cause) => new ApiFailure(name, cause))]),\n );\n}\n\n/**\n * Write (or `--check`) every API unless its output is a file the run read or the file of another\n * API. Returns the failures by API name, each an `ApiFailure`. Claims are released in reverse\n * order, so a directory one claim created is empty by the time it is removed.\n */\nexport function writeGeneratedApis(\n run: CliRun,\n apis: readonly GeneratedApi[],\n readFiles: readonly NamedFile[],\n): ApiFailures {\n const failures: ApiFailures = new Map();\n const ownOutputs = apis.filter((api) => {\n const failure = failuresOf(() => ensureOutputIsNotSchema(run, api.outputFile, readFiles));\n failures.set(api.name, failure);\n return failure.length === 0;\n });\n const claimed = claimOutputs(run, ownOutputs, failures);\n const shared = sharedOutputs(claimed);\n for (const entry of [...claimed].reverse()) {\n const { api, claim } = entry;\n const others = shared.get(api.name);\n if (others) {\n const release = claim ? failuresOf(() => claim.release()) : [];\n failures.set(api.name, [duplicateOutputError(api.outputFile, others), ...release]);\n }\n }\n for (const entry of claimed.filter(({ api }) => !shared.has(api.name))) {\n failures.set(entry.api.name, writeClaimed(run, entry));\n }\n return namedFailures(failures);\n}\n"],"names":["emitOutput","ApiFailure","ensureOutputIsNotSchema","duplicateOutputError"],"mappings":"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"}