openapi-typesafe 1.0.0-rc.2 → 1.0.0-rc.3

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 (139) hide show
  1. package/dist/adapters/node-deprecations/node-deprecations.cjs +14 -0
  2. package/dist/adapters/node-deprecations/node-deprecations.cjs.map +1 -0
  3. package/dist/adapters/node-deprecations/node-deprecations.mjs +12 -0
  4. package/dist/adapters/node-deprecations/node-deprecations.mjs.map +1 -0
  5. package/dist/api/default-ports.cjs +5 -0
  6. package/dist/api/default-ports.cjs.map +1 -1
  7. package/dist/api/default-ports.mjs +5 -1
  8. package/dist/api/default-ports.mjs.map +1 -1
  9. package/dist/api/discriminator-conflict-warnings.cjs +1 -1
  10. package/dist/api/discriminator-conflict-warnings.cjs.map +1 -1
  11. package/dist/api/discriminator-conflict-warnings.mjs +2 -2
  12. package/dist/api/discriminator-conflict-warnings.mjs.map +1 -1
  13. package/dist/api/discriminator-patch.cjs +3 -3
  14. package/dist/api/discriminator-patch.cjs.map +1 -1
  15. package/dist/api/discriminator-patch.mjs +4 -4
  16. package/dist/api/discriminator-patch.mjs.map +1 -1
  17. package/dist/api/discriminator-scan.cjs +2 -2
  18. package/dist/api/discriminator-scan.cjs.map +1 -1
  19. package/dist/api/discriminator-scan.mjs +3 -3
  20. package/dist/api/discriminator-scan.mjs.map +1 -1
  21. package/dist/api/document-run.cjs +2 -1
  22. package/dist/api/document-run.cjs.map +1 -1
  23. package/dist/api/document-run.mjs +2 -1
  24. package/dist/api/document-run.mjs.map +1 -1
  25. package/dist/api/legacy-callback-warning.cjs +7 -4
  26. package/dist/api/legacy-callback-warning.cjs.map +1 -1
  27. package/dist/api/legacy-callback-warning.mjs +8 -5
  28. package/dist/api/legacy-callback-warning.mjs.map +1 -1
  29. package/dist/api/openapi-ts.cjs +1 -1
  30. package/dist/api/openapi-ts.cjs.map +1 -1
  31. package/dist/api/openapi-ts.mjs +2 -2
  32. package/dist/api/openapi-ts.mjs.map +1 -1
  33. package/dist/api/string-to-ast.cjs +7 -9
  34. package/dist/api/string-to-ast.cjs.map +1 -1
  35. package/dist/api/string-to-ast.mjs +8 -9
  36. package/dist/api/string-to-ast.mjs.map +1 -1
  37. package/dist/api/transform-schema.cjs +2 -2
  38. package/dist/api/transform-schema.cjs.map +1 -1
  39. package/dist/api/transform-schema.mjs +3 -3
  40. package/dist/api/transform-schema.mjs.map +1 -1
  41. package/dist/application/transform/document/components.cjs +1 -1
  42. package/dist/application/transform/document/components.cjs.map +1 -1
  43. package/dist/application/transform/document/components.mjs +2 -2
  44. package/dist/application/transform/document/components.mjs.map +1 -1
  45. package/dist/application/transform/document/parameters.cjs +1 -1
  46. package/dist/application/transform/document/parameters.cjs.map +1 -1
  47. package/dist/application/transform/document/parameters.mjs +2 -2
  48. package/dist/application/transform/document/parameters.mjs.map +1 -1
  49. package/dist/application/transform/document/paths.cjs +1 -1
  50. package/dist/application/transform/document/paths.cjs.map +1 -1
  51. package/dist/application/transform/document/paths.mjs +2 -2
  52. package/dist/application/transform/document/paths.mjs.map +1 -1
  53. package/dist/application/transform/ref-pointer/pointer-type.cjs +1 -1
  54. package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -1
  55. package/dist/application/transform/ref-pointer/pointer-type.mjs +2 -2
  56. package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -1
  57. package/dist/application/transform/schema/access-flags.cjs +1 -1
  58. package/dist/application/transform/schema/access-flags.cjs.map +1 -1
  59. package/dist/application/transform/schema/access-flags.mjs +2 -2
  60. package/dist/application/transform/schema/access-flags.mjs.map +1 -1
  61. package/dist/application/transform/schema/array-type.cjs +2 -2
  62. package/dist/application/transform/schema/array-type.cjs.map +1 -1
  63. package/dist/application/transform/schema/array-type.mjs +3 -3
  64. package/dist/application/transform/schema/array-type.mjs.map +1 -1
  65. package/dist/application/transform/schema/composition-type.cjs +3 -3
  66. package/dist/application/transform/schema/composition-type.cjs.map +1 -1
  67. package/dist/application/transform/schema/composition-type.mjs +4 -4
  68. package/dist/application/transform/schema/composition-type.mjs.map +1 -1
  69. package/dist/application/transform/schema/enum-rule.cjs +3 -5
  70. package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
  71. package/dist/application/transform/schema/enum-rule.mjs +4 -6
  72. package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
  73. package/dist/application/transform/schema/presence-members.cjs +1 -1
  74. package/dist/application/transform/schema/presence-members.cjs.map +1 -1
  75. package/dist/application/transform/schema/presence-members.mjs +2 -2
  76. package/dist/application/transform/schema/presence-members.mjs.map +1 -1
  77. package/dist/application/transform/schema/required-variants.cjs +2 -2
  78. package/dist/application/transform/schema/required-variants.cjs.map +1 -1
  79. package/dist/application/transform/schema/required-variants.mjs +3 -3
  80. package/dist/application/transform/schema/required-variants.mjs.map +1 -1
  81. package/dist/application/transform/schema/unevaluated-properties.cjs +1 -1
  82. package/dist/application/transform/schema/unevaluated-properties.cjs.map +1 -1
  83. package/dist/application/transform/schema/unevaluated-properties.mjs +2 -2
  84. package/dist/application/transform/schema/unevaluated-properties.mjs.map +1 -1
  85. package/dist/application/transform/schema-comment.cjs +1 -1
  86. package/dist/application/transform/schema-comment.cjs.map +1 -1
  87. package/dist/application/transform/schema-comment.mjs +2 -2
  88. package/dist/application/transform/schema-comment.mjs.map +1 -1
  89. package/dist/domain/deprecations.cjs +11 -0
  90. package/dist/domain/deprecations.cjs.map +1 -0
  91. package/dist/domain/deprecations.mjs +9 -0
  92. package/dist/domain/deprecations.mjs.map +1 -0
  93. package/dist/domain/errors.cjs.map +1 -1
  94. package/dist/domain/errors.mjs.map +1 -1
  95. package/dist/domain/output-fixes.cjs +11 -14
  96. package/dist/domain/output-fixes.cjs.map +1 -1
  97. package/dist/domain/output-fixes.mjs +11 -13
  98. package/dist/domain/output-fixes.mjs.map +1 -1
  99. package/dist/domain/warnings.cjs +0 -1
  100. package/dist/domain/warnings.cjs.map +1 -1
  101. package/dist/domain/warnings.mjs +0 -1
  102. package/dist/domain/warnings.mjs.map +1 -1
  103. package/dist/index.cjs +2 -3
  104. package/dist/index.cjs.map +1 -1
  105. package/dist/index.d.cts +35 -16
  106. package/dist/index.d.mts +35 -16
  107. package/dist/index.d.ts +35 -16
  108. package/dist/index.mjs +3 -2
  109. package/dist/index.mjs.map +1 -1
  110. package/package.json +2 -2
  111. package/src/adapters/node-deprecations/node-deprecations.ts +14 -0
  112. package/src/api/default-ports.ts +7 -0
  113. package/src/api/discriminator-conflict-warnings.ts +2 -2
  114. package/src/api/discriminator-patch.ts +4 -5
  115. package/src/api/discriminator-scan.ts +3 -3
  116. package/src/api/document-run.ts +5 -0
  117. package/src/api/legacy-callback-warning.ts +13 -6
  118. package/src/api/openapi-ts.ts +6 -2
  119. package/src/api/run-context.ts +3 -0
  120. package/src/api/string-to-ast.ts +11 -15
  121. package/src/api/transform-schema.ts +3 -3
  122. package/src/application/ports/deprecation-reporter.ts +9 -0
  123. package/src/application/transform/document/components.ts +2 -2
  124. package/src/application/transform/document/parameters.ts +2 -2
  125. package/src/application/transform/document/paths.ts +2 -2
  126. package/src/application/transform/ref-pointer/pointer-type.ts +2 -4
  127. package/src/application/transform/schema/access-flags.ts +2 -2
  128. package/src/application/transform/schema/array-type.ts +3 -5
  129. package/src/application/transform/schema/composition-type.ts +4 -4
  130. package/src/application/transform/schema/enum-rule.ts +4 -6
  131. package/src/application/transform/schema/presence-members.ts +2 -2
  132. package/src/application/transform/schema/required-variants.ts +3 -3
  133. package/src/application/transform/schema/unevaluated-properties.ts +2 -2
  134. package/src/application/transform/schema-comment.ts +2 -2
  135. package/src/domain/deprecations.ts +15 -0
  136. package/src/domain/errors.ts +8 -2
  137. package/src/domain/output-fixes.ts +16 -16
  138. package/src/domain/warnings.ts +0 -1
  139. package/src/index.ts +2 -6
@@ -1 +1 @@
1
- {"version":3,"file":"enum-rule.cjs","sources":["../../../../src/application/transform/schema/enum-rule.ts"],"sourcesContent":["import {\n irIndexedAccess,\n irKeyword,\n irObject,\n irReference,\n irString,\n} from \"../../../domain/ir/constructors.js\";\nimport type { IrType } from \"../../../domain/ir/nodes.js\";\nimport { createRef, parseRefPointer } from \"../../../domain/openapi/json-pointer.js\";\nimport type { SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { OutputFix } from \"../../../domain/output-fixes.js\";\nimport { literalType } from \"../literal-type.js\";\nimport { refType } from \"../ref-type.js\";\nimport { intersectionOf, unionOf } from \"../type-combinators.js\";\nimport type {\n DiscriminatorEnumParent,\n EnumDeclarationRequest,\n EnumMemberMetadata,\n SchemaOptions,\n} from \"./schema-context.js\";\nimport type { SchemaRequest, SchemaRule } from \"./schema-rule.js\";\n\n/** Removed from generated names, so `#/components/schemas/Status` gives `Status`. */\nconst COMPONENT_SCHEMAS_PREFIX = \"components/schemas\";\nconst UNION_KEYWORDS: ReadonlySet<string> = new Set([\"anyOf\", \"oneOf\"]);\nconst INDEX_RE = /^\\d+$/;\n\nfunction hasAdditionalProperties(schema: SchemaObject): boolean {\n return \"additionalProperties\" in schema && Boolean(schema.additionalProperties);\n}\n\n/** A name from the schema's pointer: `#/components/schemas/Pet/status` → `/Pet/status`. */\nfunction nameFromPath(path: string | undefined): string {\n return parseRefPointer(path ?? \"\")\n .join(\"/\")\n .replace(COMPONENT_SCHEMAS_PREFIX, \"\");\n}\n\n/** `#/components/schemas/Name`, and no deeper pointer. */\nconst COMPONENT_SCHEMA_RE = /^#\\/components\\/schemas\\/[^/]+$/;\n\nfunction hasEnumMetadata(schema: SchemaObject): boolean {\n return [\n schema[\"x-enum-varnames\"],\n schema[\"x-enumNames\"],\n schema[\"x-enum-descriptions\"],\n schema[\"x-enumDescriptions\"],\n ].some(Array.isArray);\n}\n\n/**\n * The values a TypeScript enum declares, with their positions in `enum`. With the\n * `nullable-enums` fix a `null` value is left out (upstream #1872): an enum member cannot be\n * `null`, so the type adds it as `| null` instead (`tsEnumType`).\n */\nfunction tsEnumEntries(schema: SchemaObject, options: SchemaOptions): [unknown, number][] {\n const entries = (schema.enum ?? []).map((value, index): [unknown, number] => [value, index]);\n return options.fixes.has(OutputFix.NULLABLE_ENUMS)\n ? entries.filter(([value]) => value !== null)\n : entries;\n}\n\n/**\n * `--enum`: string and number enums become TypeScript enums. The original meant to allow `null`\n * too, but tested `typeof value` against `null`, so an enum containing null stays a union; the\n * `nullable-enums` fix declares its other values.\n */\nfunction isTsEnum(schema: SchemaObject, options: SchemaOptions): boolean {\n if (!options.enum || !schema.enum) {\n return false;\n }\n const entries = tsEnumEntries(schema, options);\n // An empty `enum` stays an empty TypeScript enum, as the original made it; an enum of only\n // `null` has no member left once the fix drops `null`, so it stays a union.\n const isOnlyNull = entries.length === 0 && schema.enum.length > 0;\n const isSupported =\n !isOnlyNull && entries.every(([value]) => [\"string\", \"number\"].includes(typeof value));\n // `--conditional-enums` converts only enums that carry x-enum-* metadata.\n return isSupported && (!options.conditionalEnums || hasEnumMetadata(schema));\n}\n\nfunction enumMetadata(\n schema: SchemaObject,\n entries: readonly [unknown, number][],\n): EnumMemberMetadata[] {\n return entries.map(([, index]) => ({\n name: schema[\"x-enum-varnames\"]?.[index] ?? schema[\"x-enumNames\"]?.[index],\n description: schema[\"x-enum-descriptions\"]?.[index] ?? schema[\"x-enumDescriptions\"]?.[index],\n }));\n}\n\n/**\n * Whether `null` is a valid value: it is in `enum` and the schema's type admits it (`type`\n * absent or listing `\"null\"`, or OpenAPI 3.0 `nullable: true`). Both keywords must pass.\n */\nfunction isNullAllowed(schema: SchemaObject): boolean {\n const { type } = schema;\n const isTypeNullable =\n type === undefined ||\n (Array.isArray(type) && type.includes(\"null\")) ||\n Boolean(schema.nullable);\n return (schema.enum ?? []).includes(null) && isTypeNullable;\n}\n\n/**\n * `additionalProperties: true` on a string enum keeps other strings allowed but still offers the\n * listed values in editors: `\"a\" | \"b\" | (string & {})`.\n */\nfunction withOtherStrings(type: IrType, schema: SchemaObject): IrType {\n if (!hasAdditionalProperties(schema) || schema.type !== \"string\") {\n return type;\n }\n return unionOf([type, intersectionOf([irKeyword(\"string\"), irObject([])])]);\n}\n\n/** The enum declaration of `schema` typed at `path`; its values are strings and numbers. */\nfunction enumRequest(\n schema: SchemaObject,\n path: string | undefined,\n options: SchemaOptions,\n): EnumDeclarationRequest {\n const entries = tsEnumEntries(schema, options);\n return {\n name: nameFromPath(path),\n isComponentSchema: COMPONENT_SCHEMA_RE.test(path ?? \"\"),\n values: entries.map(([value]) => value as string | number),\n metadata: enumMetadata(schema, entries),\n };\n}\n\n/** One member's type; a quoted member cannot follow a dot, `typeof E[\"+\"]` is the same type. */\nfunction enumMemberType(enumName: string, member: string): IrType {\n return member.startsWith('\"')\n ? irIndexedAccess(irReference(`typeof ${enumName}`), irString(JSON.parse(member), \"escaped\"))\n : irReference(`${enumName}.${member}`);\n}\n\n/**\n * The `discriminator-values` fix: a member's discriminator value is typed with members of\n * the owner's enum (`PetType.Cat`), so the member is one of the owner's type (#1700). `key` is the\n * enum the scan added or the inherited discriminator object. Null when the fix is off, or the\n * owner's property is no TypeScript enum with every value.\n */\nexport function ownerEnumMembersType(\n key: object,\n values: readonly unknown[],\n request: SchemaRequest,\n): IrType | null {\n const { options, discriminators, footer } = request.context;\n const parent: DiscriminatorEnumParent | undefined = options.fixes.has(\n OutputFix.DISCRIMINATOR_VALUES,\n )\n ? discriminators.enumParentOf(key)\n : undefined;\n if (parent === undefined || !isTsEnum(parent.schema, options)) {\n return null;\n }\n const reference = { ...enumRequest(parent.schema, parent.path, options), isOwnerReference: true };\n const name = footer.addEnum(reference);\n const members = footer.enumMembers(name);\n const names = values.map((value) => members.get(value as string | number));\n if (names.length === 0 || names.some((member) => member === undefined)) {\n return null;\n }\n return unionOf(names.map((member) => enumMemberType(name, member as string)));\n}\n\nfunction tsEnumType(schema: SchemaObject, request: SchemaRequest): IrType {\n const { options, footer } = request.context;\n // `isTsEnum` admits only strings and numbers, and the fix leaves `null` out of the members.\n const values = tsEnumEntries(schema, options).map(([value]) => value);\n const type =\n ownerEnumMembersType(schema, values, request) ??\n withOtherStrings(\n irReference(footer.addEnum(enumRequest(schema, request.location.path, options))),\n schema,\n );\n return options.fixes.has(OutputFix.NULLABLE_ENUMS) && isNullAllowed(schema)\n ? unionOf([type, irKeyword(\"null\")])\n : type;\n}\n\nfunction isUnionPosition(pointer: readonly string[], index: number): boolean {\n const next = pointer[index + 1];\n return UNION_KEYWORDS.has(pointer[index] as string) && next !== undefined && INDEX_RE.test(next);\n}\n\nconst PARAMETERS = \"parameters\";\n\n/** Where the `parameters` of a path item sit in its pointer: `paths/<key>/…`, `components/…`. */\nfunction pathItemParametersIndex(pointer: readonly string[]): number | null {\n if (pointer[0] === \"paths\" || pointer[0] === \"webhooks\") {\n return 2;\n }\n return pointer[0] === \"components\" && pointer[1] === \"pathItems\" ? 3 : null;\n}\n\n/**\n * The location of a path item parameter repeats `parameters` (`paths/~1a/parameters/parameters/\n * path/id`), which keeps the generated names as they were. The generated type has the segment\n * once: `paths[\"/a\"][\"parameters\"][\"path\"][\"id\"]`.\n */\nfunction withSingleParametersSegment(pointer: readonly string[]): readonly string[] {\n const index = pathItemParametersIndex(pointer);\n const isRepeated =\n index !== null && pointer[index] === PARAMETERS && pointer[index + 1] === PARAMETERS;\n return isRepeated ? [...pointer.slice(0, index), ...pointer.slice(index + 1)] : pointer;\n}\n\n/**\n * The pointer of `--enum-values` arrays without union positions (`anyOf/0`), so names stay\n * stable. Every property after the first union position is narrowed with `Extract`: a no-op where\n * all variants have it, and the needed narrowing where only some do.\n */\nfunction enumValuesPointer(path: string | undefined): { ref: string; extract: string[] } {\n const pointer = withSingleParametersSegment(parseRefPointer(path ?? \"\"));\n const kept: string[] = [];\n let firstVariantStart: number | null = null;\n for (let index = 0; index < pointer.length; index++) {\n if (isUnionPosition(pointer, index)) {\n firstVariantStart ??= index + 2;\n index++;\n continue;\n }\n kept.push(pointer[index] as string);\n }\n const extract =\n firstVariantStart === null\n ? []\n : pointer\n .slice(firstVariantStart)\n .filter((segment) => !UNION_KEYWORDS.has(segment) && !INDEX_RE.test(segment));\n return { ref: createRef(kept), extract };\n}\n\nfunction addEnumValues(schema: SchemaObject, request: SchemaRequest): void {\n const { ref, extract } = enumValuesPointer(request.location.path);\n const valuesType = refType(ref, { isDeep: true, extractProperties: extract });\n request.context.footer.addEnumValues({\n name: `${nameFromPath(request.location.path)}Values`,\n // A record value (`additionalProperties`) is reached by indexing with `string`.\n type: request.isFromAdditionalProperties\n ? irIndexedAccess(valuesType, irReference(\"string\"))\n : valuesType,\n values: (schema.enum ?? []) as (string | number)[],\n });\n}\n\nfunction literalEnumType(schema: SchemaObject, request: SchemaRequest): IrType {\n const values = schema.enum ?? [];\n const isNullable =\n (Array.isArray(schema.type) && schema.type.includes(\"null\")) || Boolean(schema.nullable);\n const literals = [...values.map(literalType), ...(isNullable ? [irKeyword(\"null\")] : [])];\n const type = withOtherStrings(unionOf(literals), schema);\n const isListable = values.every(\n (value) => typeof value === \"string\" || typeof value === \"number\",\n );\n if (request.context.options.enumValues && isListable) {\n addEnumValues(schema, request);\n }\n return type;\n}\n\n/**\n * `enum` on anything but an object (object enums are handled as `oneOf`). With\n * `additionalProperties`, only string enums are handled here; others fall through to composition.\n */\nexport const enumRule: SchemaRule = {\n name: \"enum\",\n matches(schema) {\n const isCandidate =\n Array.isArray(schema.enum) && schema.type !== \"object\" && !(\"properties\" in schema);\n return isCandidate && (!hasAdditionalProperties(schema) || schema.type === \"string\");\n },\n transform(schema, request) {\n return isTsEnum(schema, request.context.options)\n ? tsEnumType(schema, request)\n : literalEnumType(schema, request);\n },\n};\n"],"names":["parseRefPointer","OutputFix","unionOf","intersectionOf","irKeyword","irObject","irIndexedAccess","irReference","irString","createRef","refType","literalType"],"mappings":";;;;;;;;;AAuBA,MAAM,wBAAA,GAA2B,oBAAA;AACjC,MAAM,iCAAsC,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,OAAO,CAAC,CAAA;AACtE,MAAM,QAAA,GAAW,OAAA;AAEjB,SAAS,wBAAwB,MAAA,EAA+B;AAC9D,EAAA,OAAO,sBAAA,IAA0B,MAAA,IAAU,OAAA,CAAQ,MAAA,CAAO,oBAAoB,CAAA;AAChF;AAGA,SAAS,aAAa,IAAA,EAAkC;AACtD,EAAA,OAAOA,2BAAA,CAAgB,QAAQ,EAAE,CAAA,CAC9B,KAAK,GAAG,CAAA,CACR,OAAA,CAAQ,wBAAA,EAA0B,EAAE,CAAA;AACzC;AAGA,MAAM,mBAAA,GAAsB,iCAAA;AAE5B,SAAS,gBAAgB,MAAA,EAA+B;AACtD,EAAA,OAAO;AAAA,IACL,OAAO,iBAAiB,CAAA;AAAA,IACxB,OAAO,aAAa,CAAA;AAAA,IACpB,OAAO,qBAAqB,CAAA;AAAA,IAC5B,OAAO,oBAAoB;AAAA,GAC7B,CAAE,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AACtB;AAOA,SAAS,aAAA,CAAc,QAAsB,OAAA,EAA6C;AACxF,EAAA,MAAM,OAAA,GAAA,CAAW,MAAA,CAAO,IAAA,IAAQ,EAAC,EAAG,GAAA,CAAI,CAAC,KAAA,EAAO,KAAA,KAA6B,CAAC,KAAA,EAAO,KAAK,CAAC,CAAA;AAC3F,EAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,GAAA,CAAIC,qBAAA,CAAU,cAAc,CAAA,GAC7C,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAC,KAAK,CAAA,KAAM,KAAA,KAAU,IAAI,CAAA,GAC1C,OAAA;AACN;AAOA,SAAS,QAAA,CAAS,QAAsB,OAAA,EAAiC;AACvE,EAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,IAAQ,CAAC,OAAO,IAAA,EAAM;AACjC,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,OAAA,GAAU,aAAA,CAAc,MAAA,EAAQ,OAAO,CAAA;AAG7C,EAAA,MAAM,aAAa,OAAA,CAAQ,MAAA,KAAW,CAAA,IAAK,MAAA,CAAO,KAAK,MAAA,GAAS,CAAA;AAChE,EAAA,MAAM,cACJ,CAAC,UAAA,IAAc,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAC,KAAK,CAAA,KAAM,CAAC,UAAU,QAAQ,CAAA,CAAE,QAAA,CAAS,OAAO,KAAK,CAAC,CAAA;AAEvF,EAAA,OAAO,WAAA,KAAgB,CAAC,OAAA,CAAQ,gBAAA,IAAoB,gBAAgB,MAAM,CAAA,CAAA;AAC5E;AAEA,SAAS,YAAA,CACP,QACA,OAAA,EACsB;AACtB,EAAA,OAAO,QAAQ,GAAA,CAAI,CAAC,GAAG,KAAK,CAAA,MAAO;AAAA,IACjC,IAAA,EAAM,OAAO,iBAAiB,CAAA,GAAI,KAAK,CAAA,IAAK,MAAA,CAAO,aAAa,CAAA,GAAI,KAAK,CAAA;AAAA,IACzE,WAAA,EAAa,OAAO,qBAAqB,CAAA,GAAI,KAAK,CAAA,IAAK,MAAA,CAAO,oBAAoB,CAAA,GAAI,KAAK;AAAA,GAC7F,CAAE,CAAA;AACJ;AAMA,SAAS,cAAc,MAAA,EAA+B;AACpD,EAAA,MAAM,EAAE,MAAK,GAAI,MAAA;AACjB,EAAA,MAAM,cAAA,GACJ,IAAA,KAAS,MAAA,IACR,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,IAC5C,OAAA,CAAQ,OAAO,QAAQ,CAAA;AACzB,EAAA,OAAA,CAAQ,OAAO,IAAA,IAAQ,EAAC,EAAG,QAAA,CAAS,IAAI,CAAA,IAAK,cAAA;AAC/C;AAMA,SAAS,gBAAA,CAAiB,MAAc,MAAA,EAA8B;AACpE,EAAA,IAAI,CAAC,uBAAA,CAAwB,MAAM,CAAA,IAAK,MAAA,CAAO,SAAS,QAAA,EAAU;AAChE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAOC,uBAAA,CAAQ,CAAC,IAAA,EAAMC,8BAAA,CAAe,CAACC,sBAAA,CAAU,QAAQ,CAAA,EAAGC,qBAAA,CAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;AAC5E;AAGA,SAAS,WAAA,CACP,MAAA,EACA,IAAA,EACA,OAAA,EACwB;AACxB,EAAA,MAAM,OAAA,GAAU,aAAA,CAAc,MAAA,EAAQ,OAAO,CAAA;AAC7C,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAa,IAAI,CAAA;AAAA,IACvB,iBAAA,EAAmB,mBAAA,CAAoB,IAAA,CAAK,IAAA,IAAQ,EAAE,CAAA;AAAA,IACtD,QAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAC,KAAK,MAAM,KAAwB,CAAA;AAAA,IACzD,QAAA,EAAU,YAAA,CAAa,MAAA,EAAQ,OAAO;AAAA,GACxC;AACF;AAGA,SAAS,cAAA,CAAe,UAAkB,MAAA,EAAwB;AAChE,EAAA,OAAO,MAAA,CAAO,WAAW,GAAG,CAAA,GACxBC,6BAAgBC,wBAAA,CAAY,CAAA,OAAA,EAAU,QAAQ,CAAA,CAAE,CAAA,EAAGC,qBAAA,CAAS,KAAK,KAAA,CAAM,MAAM,CAAA,EAAG,SAAS,CAAC,CAAA,GAC1FD,yBAAY,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE,CAAA;AACzC;AAQO,SAAS,oBAAA,CACd,GAAA,EACA,MAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,EAAE,OAAA,EAAS,cAAA,EAAgB,MAAA,KAAW,OAAA,CAAQ,OAAA;AACpD,EAAA,MAAM,MAAA,GAA8C,QAAQ,KAAA,CAAM,GAAA;AAAA,IAChEN,qBAAA,CAAU;AAAA,GACZ,GACI,cAAA,CAAe,YAAA,CAAa,GAAG,CAAA,GAC/B,MAAA;AACJ,EAAA,IAAI,WAAW,MAAA,IAAa,CAAC,SAAS,MAAA,CAAO,MAAA,EAAQ,OAAO,CAAA,EAAG;AAC7D,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,EAAE,GAAG,WAAA,CAAY,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,EAAM,OAAO,CAAA,EAAG,gBAAA,EAAkB,IAAA,EAAK;AAChG,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA;AACrC,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,WAAA,CAAY,IAAI,CAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,OAAO,GAAA,CAAI,CAAC,UAAU,OAAA,CAAQ,GAAA,CAAI,KAAwB,CAAC,CAAA;AACzE,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,IAAK,KAAA,CAAM,KAAK,CAAC,MAAA,KAAW,MAAA,KAAW,MAAS,CAAA,EAAG;AACtE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAOC,uBAAA,CAAQ,MAAM,GAAA,CAAI,CAAC,WAAW,cAAA,CAAe,IAAA,EAAM,MAAgB,CAAC,CAAC,CAAA;AAC9E;AAEA,SAAS,UAAA,CAAW,QAAsB,OAAA,EAAgC;AACxE,EAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAO,GAAI,OAAA,CAAQ,OAAA;AAEpC,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,MAAA,EAAQ,OAAO,CAAA,CAAE,IAAI,CAAC,CAAC,KAAK,CAAA,KAAM,KAAK,CAAA;AACpE,EAAA,MAAM,IAAA,GACJ,oBAAA,CAAqB,MAAA,EAAQ,MAAA,EAAQ,OAAO,CAAA,IAC5C,gBAAA;AAAA,IACEK,wBAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,WAAA,CAAY,MAAA,EAAQ,QAAQ,QAAA,CAAS,IAAA,EAAM,OAAO,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,GACF;AACF,EAAA,OAAO,QAAQ,KAAA,CAAM,GAAA,CAAIN,qBAAA,CAAU,cAAc,KAAK,aAAA,CAAc,MAAM,CAAA,GACtEC,uBAAA,CAAQ,CAAC,IAAA,EAAME,sBAAA,CAAU,MAAM,CAAC,CAAC,CAAA,GACjC,IAAA;AACN;AAEA,SAAS,eAAA,CAAgB,SAA4B,KAAA,EAAwB;AAC3E,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,GAAQ,CAAC,CAAA;AAC9B,EAAA,OAAO,cAAA,CAAe,GAAA,CAAI,OAAA,CAAQ,KAAK,CAAW,KAAK,IAAA,KAAS,MAAA,IAAa,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA;AACjG;AAEA,MAAM,UAAA,GAAa,YAAA;AAGnB,SAAS,wBAAwB,OAAA,EAA2C;AAC1E,EAAA,IAAI,QAAQ,CAAC,CAAA,KAAM,WAAW,OAAA,CAAQ,CAAC,MAAM,UAAA,EAAY;AACvD,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAA,CAAQ,CAAC,CAAA,KAAM,YAAA,IAAgB,QAAQ,CAAC,CAAA,KAAM,cAAc,CAAA,GAAI,IAAA;AACzE;AAOA,SAAS,4BAA4B,OAAA,EAA+C;AAClF,EAAA,MAAM,KAAA,GAAQ,wBAAwB,OAAO,CAAA;AAC7C,EAAA,MAAM,UAAA,GACJ,KAAA,KAAU,IAAA,IAAQ,OAAA,CAAQ,KAAK,MAAM,UAAA,IAAc,OAAA,CAAQ,KAAA,GAAQ,CAAC,CAAA,KAAM,UAAA;AAC5E,EAAA,OAAO,UAAA,GAAa,CAAC,GAAG,OAAA,CAAQ,MAAM,CAAA,EAAG,KAAK,CAAA,EAAG,GAAG,OAAA,CAAQ,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAC,CAAA,GAAI,OAAA;AAClF;AAOA,SAAS,kBAAkB,IAAA,EAA8D;AACvF,EAAA,MAAM,OAAA,GAAU,2BAAA,CAA4BJ,2BAAA,CAAgB,IAAA,IAAQ,EAAE,CAAC,CAAA;AACvE,EAAA,MAAM,OAAiB,EAAC;AACxB,EAAA,IAAI,iBAAA,GAAmC,IAAA;AACvC,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,OAAA,CAAQ,QAAQ,KAAA,EAAA,EAAS;AACnD,IAAA,IAAI,eAAA,CAAgB,OAAA,EAAS,KAAK,CAAA,EAAG;AACnC,MAAA,iBAAA,KAAsB,KAAA,GAAQ,CAAA;AAC9B,MAAA,KAAA,EAAA;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,KAAK,CAAW,CAAA;AAAA,EACpC;AACA,EAAA,MAAM,OAAA,GACJ,sBAAsB,IAAA,GAClB,KACA,OAAA,CACG,KAAA,CAAM,iBAAiB,CAAA,CACvB,MAAA,CAAO,CAAC,OAAA,KAAY,CAAC,eAAe,GAAA,CAAI,OAAO,KAAK,CAAC,QAAA,CAAS,IAAA,CAAK,OAAO,CAAC,CAAA;AACpF,EAAA,OAAO,EAAE,GAAA,EAAKS,qBAAA,CAAU,IAAI,GAAG,OAAA,EAAQ;AACzC;AAEA,SAAS,aAAA,CAAc,QAAsB,OAAA,EAA8B;AACzE,EAAA,MAAM,EAAE,GAAA,EAAK,OAAA,KAAY,iBAAA,CAAkB,OAAA,CAAQ,SAAS,IAAI,CAAA;AAChE,EAAA,MAAM,UAAA,GAAaC,gBAAQ,GAAA,EAAK,EAAE,QAAQ,IAAA,EAAM,iBAAA,EAAmB,SAAS,CAAA;AAC5E,EAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,aAAA,CAAc;AAAA,IACnC,MAAM,CAAA,EAAG,YAAA,CAAa,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAC,CAAA,MAAA,CAAA;AAAA;AAAA,IAE5C,IAAA,EAAM,QAAQ,0BAAA,GACVJ,4BAAA,CAAgB,YAAYC,wBAAA,CAAY,QAAQ,CAAC,CAAA,GACjD,UAAA;AAAA,IACJ,MAAA,EAAS,MAAA,CAAO,IAAA,IAAQ;AAAC,GAC1B,CAAA;AACH;AAEA,SAAS,eAAA,CAAgB,QAAsB,OAAA,EAAgC;AAC7E,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,IAAA,IAAQ,EAAC;AAC/B,EAAA,MAAM,UAAA,GACH,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,IAAK,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,IAAM,OAAA,CAAQ,OAAO,QAAQ,CAAA;AACzF,EAAA,MAAM,QAAA,GAAW,CAAC,GAAG,MAAA,CAAO,IAAII,uBAAW,CAAA,EAAG,GAAI,UAAA,GAAa,CAACP,sBAAA,CAAU,MAAM,CAAC,CAAA,GAAI,EAAG,CAAA;AACxF,EAAA,MAAM,IAAA,GAAO,gBAAA,CAAiBF,uBAAA,CAAQ,QAAQ,GAAG,MAAM,CAAA;AACvD,EAAA,MAAM,aAAa,MAAA,CAAO,KAAA;AAAA,IACxB,CAAC,KAAA,KAAU,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,KAAA,KAAU;AAAA,GAC3D;AACA,EAAA,IAAI,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,UAAA,IAAc,UAAA,EAAY;AACpD,IAAA,aAAA,CAAc,QAAQ,OAAO,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,IAAA;AACT;AAMO,MAAM,QAAA,GAAuB;AAAA,EAClC,IAAA,EAAM,MAAA;AAAA,EACN,QAAQ,MAAA,EAAQ;AACd,IAAA,MAAM,WAAA,GACJ,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,KAAK,MAAA,CAAO,IAAA,KAAS,QAAA,IAAY,EAAE,YAAA,IAAgB,MAAA,CAAA;AAC9E,IAAA,OAAO,gBAAgB,CAAC,uBAAA,CAAwB,MAAM,CAAA,IAAK,OAAO,IAAA,KAAS,QAAA,CAAA;AAAA,EAC7E,CAAA;AAAA,EACA,SAAA,CAAU,QAAQ,OAAA,EAAS;AACzB,IAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,OAAA,CAAQ,OAAA,CAAQ,OAAO,CAAA,GAC3C,UAAA,CAAW,MAAA,EAAQ,OAAO,CAAA,GAC1B,eAAA,CAAgB,MAAA,EAAQ,OAAO,CAAA;AAAA,EACrC;AACF;;;"}
1
+ {"version":3,"file":"enum-rule.cjs","sources":["../../../../src/application/transform/schema/enum-rule.ts"],"sourcesContent":["import {\n irIndexedAccess,\n irKeyword,\n irObject,\n irReference,\n irString,\n} from \"../../../domain/ir/constructors.js\";\nimport type { IrType } from \"../../../domain/ir/nodes.js\";\nimport { createRef, parseRefPointer } from \"../../../domain/openapi/json-pointer.js\";\nimport type { SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { FIX } from \"../../../domain/output-fixes.js\";\nimport { literalType } from \"../literal-type.js\";\nimport { refType } from \"../ref-type.js\";\nimport { intersectionOf, unionOf } from \"../type-combinators.js\";\nimport type {\n DiscriminatorEnumParent,\n EnumDeclarationRequest,\n EnumMemberMetadata,\n SchemaOptions,\n} from \"./schema-context.js\";\nimport type { SchemaRequest, SchemaRule } from \"./schema-rule.js\";\n\n/** Removed from generated names, so `#/components/schemas/Status` gives `Status`. */\nconst COMPONENT_SCHEMAS_PREFIX = \"components/schemas\";\nconst UNION_KEYWORDS: ReadonlySet<string> = new Set([\"anyOf\", \"oneOf\"]);\nconst INDEX_RE = /^\\d+$/;\n\nfunction hasAdditionalProperties(schema: SchemaObject): boolean {\n return \"additionalProperties\" in schema && Boolean(schema.additionalProperties);\n}\n\n/** A name from the schema's pointer: `#/components/schemas/Pet/status` → `/Pet/status`. */\nfunction nameFromPath(path: string | undefined): string {\n return parseRefPointer(path ?? \"\")\n .join(\"/\")\n .replace(COMPONENT_SCHEMAS_PREFIX, \"\");\n}\n\n/** `#/components/schemas/Name`, and no deeper pointer. */\nconst COMPONENT_SCHEMA_RE = /^#\\/components\\/schemas\\/[^/]+$/;\n\nfunction hasEnumMetadata(schema: SchemaObject): boolean {\n return [\n schema[\"x-enum-varnames\"],\n schema[\"x-enumNames\"],\n schema[\"x-enum-descriptions\"],\n schema[\"x-enumDescriptions\"],\n ].some(Array.isArray);\n}\n\n/**\n * The values a TypeScript enum declares, with their positions in `enum`. With the\n * `nullable-enums` fix a `null` value is left out (upstream #1872): an enum member cannot be\n * `null`, so the type adds it as `| null` instead (`tsEnumType`).\n */\nfunction tsEnumEntries(schema: SchemaObject, options: SchemaOptions): [unknown, number][] {\n const entries = (schema.enum ?? []).map((value, index): [unknown, number] => [value, index]);\n return options.fixes.has(FIX.NULLABLE_ENUMS)\n ? entries.filter(([value]) => value !== null)\n : entries;\n}\n\n/**\n * `--enum`: string and number enums become TypeScript enums. The original meant to allow `null`\n * too, but tested `typeof value` against `null`, so an enum containing null stays a union; the\n * `nullable-enums` fix declares its other values.\n */\nfunction isTsEnum(schema: SchemaObject, options: SchemaOptions): boolean {\n if (!options.enum || !schema.enum) {\n return false;\n }\n const entries = tsEnumEntries(schema, options);\n // An empty `enum` stays an empty TypeScript enum, as the original made it; an enum of only\n // `null` has no member left once the fix drops `null`, so it stays a union.\n const isOnlyNull = entries.length === 0 && schema.enum.length > 0;\n const isSupported =\n !isOnlyNull && entries.every(([value]) => [\"string\", \"number\"].includes(typeof value));\n // `--conditional-enums` converts only enums that carry x-enum-* metadata.\n return isSupported && (!options.conditionalEnums || hasEnumMetadata(schema));\n}\n\nfunction enumMetadata(\n schema: SchemaObject,\n entries: readonly [unknown, number][],\n): EnumMemberMetadata[] {\n return entries.map(([, index]) => ({\n name: schema[\"x-enum-varnames\"]?.[index] ?? schema[\"x-enumNames\"]?.[index],\n description: schema[\"x-enum-descriptions\"]?.[index] ?? schema[\"x-enumDescriptions\"]?.[index],\n }));\n}\n\n/**\n * Whether `null` is a valid value: it is in `enum` and the schema's type admits it (`type`\n * absent or listing `\"null\"`, or OpenAPI 3.0 `nullable: true`). Both keywords must pass.\n */\nfunction isNullAllowed(schema: SchemaObject): boolean {\n const { type } = schema;\n const isTypeNullable =\n type === undefined ||\n (Array.isArray(type) && type.includes(\"null\")) ||\n Boolean(schema.nullable);\n return (schema.enum ?? []).includes(null) && isTypeNullable;\n}\n\n/**\n * `additionalProperties: true` on a string enum keeps other strings allowed but still offers the\n * listed values in editors: `\"a\" | \"b\" | (string & {})`.\n */\nfunction withOtherStrings(type: IrType, schema: SchemaObject): IrType {\n if (!hasAdditionalProperties(schema) || schema.type !== \"string\") {\n return type;\n }\n return unionOf([type, intersectionOf([irKeyword(\"string\"), irObject([])])]);\n}\n\n/** The enum declaration of `schema` typed at `path`; its values are strings and numbers. */\nfunction enumRequest(\n schema: SchemaObject,\n path: string | undefined,\n options: SchemaOptions,\n): EnumDeclarationRequest {\n const entries = tsEnumEntries(schema, options);\n return {\n name: nameFromPath(path),\n isComponentSchema: COMPONENT_SCHEMA_RE.test(path ?? \"\"),\n values: entries.map(([value]) => value as string | number),\n metadata: enumMetadata(schema, entries),\n };\n}\n\n/** One member's type; a quoted member cannot follow a dot, `typeof E[\"+\"]` is the same type. */\nfunction enumMemberType(enumName: string, member: string): IrType {\n return member.startsWith('\"')\n ? irIndexedAccess(irReference(`typeof ${enumName}`), irString(JSON.parse(member), \"escaped\"))\n : irReference(`${enumName}.${member}`);\n}\n\n/**\n * The `discriminator-values` fix: a member's discriminator value is typed with members of\n * the owner's enum (`PetType.Cat`), so the member is one of the owner's type (#1700). `key` is the\n * enum the scan added or the inherited discriminator object. Null when the fix is off, or the\n * owner's property is no TypeScript enum with every value.\n */\nexport function ownerEnumMembersType(\n key: object,\n values: readonly unknown[],\n request: SchemaRequest,\n): IrType | null {\n const { options, discriminators, footer } = request.context;\n const parent: DiscriminatorEnumParent | undefined = options.fixes.has(FIX.DISCRIMINATOR_VALUES)\n ? discriminators.enumParentOf(key)\n : undefined;\n if (parent === undefined || !isTsEnum(parent.schema, options)) {\n return null;\n }\n const reference = { ...enumRequest(parent.schema, parent.path, options), isOwnerReference: true };\n const name = footer.addEnum(reference);\n const members = footer.enumMembers(name);\n const names = values.map((value) => members.get(value as string | number));\n if (names.length === 0 || names.some((member) => member === undefined)) {\n return null;\n }\n return unionOf(names.map((member) => enumMemberType(name, member as string)));\n}\n\nfunction tsEnumType(schema: SchemaObject, request: SchemaRequest): IrType {\n const { options, footer } = request.context;\n // `isTsEnum` admits only strings and numbers, and the fix leaves `null` out of the members.\n const values = tsEnumEntries(schema, options).map(([value]) => value);\n const type =\n ownerEnumMembersType(schema, values, request) ??\n withOtherStrings(\n irReference(footer.addEnum(enumRequest(schema, request.location.path, options))),\n schema,\n );\n return options.fixes.has(FIX.NULLABLE_ENUMS) && isNullAllowed(schema)\n ? unionOf([type, irKeyword(\"null\")])\n : type;\n}\n\nfunction isUnionPosition(pointer: readonly string[], index: number): boolean {\n const next = pointer[index + 1];\n return UNION_KEYWORDS.has(pointer[index] as string) && next !== undefined && INDEX_RE.test(next);\n}\n\nconst PARAMETERS = \"parameters\";\n\n/** Where the `parameters` of a path item sit in its pointer: `paths/<key>/…`, `components/…`. */\nfunction pathItemParametersIndex(pointer: readonly string[]): number | null {\n if (pointer[0] === \"paths\" || pointer[0] === \"webhooks\") {\n return 2;\n }\n return pointer[0] === \"components\" && pointer[1] === \"pathItems\" ? 3 : null;\n}\n\n/**\n * The location of a path item parameter repeats `parameters` (`paths/~1a/parameters/parameters/\n * path/id`), which keeps the generated names as they were. The generated type has the segment\n * once: `paths[\"/a\"][\"parameters\"][\"path\"][\"id\"]`.\n */\nfunction withSingleParametersSegment(pointer: readonly string[]): readonly string[] {\n const index = pathItemParametersIndex(pointer);\n const isRepeated =\n index !== null && pointer[index] === PARAMETERS && pointer[index + 1] === PARAMETERS;\n return isRepeated ? [...pointer.slice(0, index), ...pointer.slice(index + 1)] : pointer;\n}\n\n/**\n * The pointer of `--enum-values` arrays without union positions (`anyOf/0`), so names stay\n * stable. Every property after the first union position is narrowed with `Extract`: a no-op where\n * all variants have it, and the needed narrowing where only some do.\n */\nfunction enumValuesPointer(path: string | undefined): { ref: string; extract: string[] } {\n const pointer = withSingleParametersSegment(parseRefPointer(path ?? \"\"));\n const kept: string[] = [];\n let firstVariantStart: number | null = null;\n for (let index = 0; index < pointer.length; index++) {\n if (isUnionPosition(pointer, index)) {\n firstVariantStart ??= index + 2;\n index++;\n continue;\n }\n kept.push(pointer[index] as string);\n }\n const extract =\n firstVariantStart === null\n ? []\n : pointer\n .slice(firstVariantStart)\n .filter((segment) => !UNION_KEYWORDS.has(segment) && !INDEX_RE.test(segment));\n return { ref: createRef(kept), extract };\n}\n\nfunction addEnumValues(schema: SchemaObject, request: SchemaRequest): void {\n const { ref, extract } = enumValuesPointer(request.location.path);\n const valuesType = refType(ref, { isDeep: true, extractProperties: extract });\n request.context.footer.addEnumValues({\n name: `${nameFromPath(request.location.path)}Values`,\n // A record value (`additionalProperties`) is reached by indexing with `string`.\n type: request.isFromAdditionalProperties\n ? irIndexedAccess(valuesType, irReference(\"string\"))\n : valuesType,\n values: (schema.enum ?? []) as (string | number)[],\n });\n}\n\nfunction literalEnumType(schema: SchemaObject, request: SchemaRequest): IrType {\n const values = schema.enum ?? [];\n const isNullable =\n (Array.isArray(schema.type) && schema.type.includes(\"null\")) || Boolean(schema.nullable);\n const literals = [...values.map(literalType), ...(isNullable ? [irKeyword(\"null\")] : [])];\n const type = withOtherStrings(unionOf(literals), schema);\n const isListable = values.every(\n (value) => typeof value === \"string\" || typeof value === \"number\",\n );\n if (request.context.options.enumValues && isListable) {\n addEnumValues(schema, request);\n }\n return type;\n}\n\n/**\n * `enum` on anything but an object (object enums are handled as `oneOf`). With\n * `additionalProperties`, only string enums are handled here; others fall through to composition.\n */\nexport const enumRule: SchemaRule = {\n name: \"enum\",\n matches(schema) {\n const isCandidate =\n Array.isArray(schema.enum) && schema.type !== \"object\" && !(\"properties\" in schema);\n return isCandidate && (!hasAdditionalProperties(schema) || schema.type === \"string\");\n },\n transform(schema, request) {\n return isTsEnum(schema, request.context.options)\n ? tsEnumType(schema, request)\n : literalEnumType(schema, request);\n },\n};\n"],"names":["parseRefPointer","FIX","unionOf","intersectionOf","irKeyword","irObject","irIndexedAccess","irReference","irString","createRef","refType","literalType"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { irReference, irKeyword, irIndexedAccess, irString, irObject } from '../../../domain/ir/constructors.mjs';
2
2
  import { parseRefPointer, createRef } from '../../../domain/openapi/json-pointer.mjs';
3
- import { OutputFix } from '../../../domain/output-fixes.mjs';
3
+ import { FIX } from '../../../domain/output-fixes.mjs';
4
4
  import { literalType } from '../literal-type.mjs';
5
5
  import { refType } from '../ref-type.mjs';
6
6
  import { unionOf, intersectionOf } from '../type-combinators.mjs';
@@ -25,7 +25,7 @@ function hasEnumMetadata(schema) {
25
25
  }
26
26
  function tsEnumEntries(schema, options) {
27
27
  const entries = (schema.enum ?? []).map((value, index) => [value, index]);
28
- return options.fixes.has(OutputFix.NULLABLE_ENUMS) ? entries.filter(([value]) => value !== null) : entries;
28
+ return options.fixes.has(FIX.NULLABLE_ENUMS) ? entries.filter(([value]) => value !== null) : entries;
29
29
  }
30
30
  function isTsEnum(schema, options) {
31
31
  if (!options.enum || !schema.enum) {
@@ -67,9 +67,7 @@ function enumMemberType(enumName, member) {
67
67
  }
68
68
  function ownerEnumMembersType(key, values, request) {
69
69
  const { options, discriminators, footer } = request.context;
70
- const parent = options.fixes.has(
71
- OutputFix.DISCRIMINATOR_VALUES
72
- ) ? discriminators.enumParentOf(key) : void 0;
70
+ const parent = options.fixes.has(FIX.DISCRIMINATOR_VALUES) ? discriminators.enumParentOf(key) : void 0;
73
71
  if (parent === void 0 || !isTsEnum(parent.schema, options)) {
74
72
  return null;
75
73
  }
@@ -89,7 +87,7 @@ function tsEnumType(schema, request) {
89
87
  irReference(footer.addEnum(enumRequest(schema, request.location.path, options))),
90
88
  schema
91
89
  );
92
- return options.fixes.has(OutputFix.NULLABLE_ENUMS) && isNullAllowed(schema) ? unionOf([type, irKeyword("null")]) : type;
90
+ return options.fixes.has(FIX.NULLABLE_ENUMS) && isNullAllowed(schema) ? unionOf([type, irKeyword("null")]) : type;
93
91
  }
94
92
  function isUnionPosition(pointer, index) {
95
93
  const next = pointer[index + 1];
@@ -1 +1 @@
1
- {"version":3,"file":"enum-rule.mjs","sources":["../../../../src/application/transform/schema/enum-rule.ts"],"sourcesContent":["import {\n irIndexedAccess,\n irKeyword,\n irObject,\n irReference,\n irString,\n} from \"../../../domain/ir/constructors.js\";\nimport type { IrType } from \"../../../domain/ir/nodes.js\";\nimport { createRef, parseRefPointer } from \"../../../domain/openapi/json-pointer.js\";\nimport type { SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { OutputFix } from \"../../../domain/output-fixes.js\";\nimport { literalType } from \"../literal-type.js\";\nimport { refType } from \"../ref-type.js\";\nimport { intersectionOf, unionOf } from \"../type-combinators.js\";\nimport type {\n DiscriminatorEnumParent,\n EnumDeclarationRequest,\n EnumMemberMetadata,\n SchemaOptions,\n} from \"./schema-context.js\";\nimport type { SchemaRequest, SchemaRule } from \"./schema-rule.js\";\n\n/** Removed from generated names, so `#/components/schemas/Status` gives `Status`. */\nconst COMPONENT_SCHEMAS_PREFIX = \"components/schemas\";\nconst UNION_KEYWORDS: ReadonlySet<string> = new Set([\"anyOf\", \"oneOf\"]);\nconst INDEX_RE = /^\\d+$/;\n\nfunction hasAdditionalProperties(schema: SchemaObject): boolean {\n return \"additionalProperties\" in schema && Boolean(schema.additionalProperties);\n}\n\n/** A name from the schema's pointer: `#/components/schemas/Pet/status` → `/Pet/status`. */\nfunction nameFromPath(path: string | undefined): string {\n return parseRefPointer(path ?? \"\")\n .join(\"/\")\n .replace(COMPONENT_SCHEMAS_PREFIX, \"\");\n}\n\n/** `#/components/schemas/Name`, and no deeper pointer. */\nconst COMPONENT_SCHEMA_RE = /^#\\/components\\/schemas\\/[^/]+$/;\n\nfunction hasEnumMetadata(schema: SchemaObject): boolean {\n return [\n schema[\"x-enum-varnames\"],\n schema[\"x-enumNames\"],\n schema[\"x-enum-descriptions\"],\n schema[\"x-enumDescriptions\"],\n ].some(Array.isArray);\n}\n\n/**\n * The values a TypeScript enum declares, with their positions in `enum`. With the\n * `nullable-enums` fix a `null` value is left out (upstream #1872): an enum member cannot be\n * `null`, so the type adds it as `| null` instead (`tsEnumType`).\n */\nfunction tsEnumEntries(schema: SchemaObject, options: SchemaOptions): [unknown, number][] {\n const entries = (schema.enum ?? []).map((value, index): [unknown, number] => [value, index]);\n return options.fixes.has(OutputFix.NULLABLE_ENUMS)\n ? entries.filter(([value]) => value !== null)\n : entries;\n}\n\n/**\n * `--enum`: string and number enums become TypeScript enums. The original meant to allow `null`\n * too, but tested `typeof value` against `null`, so an enum containing null stays a union; the\n * `nullable-enums` fix declares its other values.\n */\nfunction isTsEnum(schema: SchemaObject, options: SchemaOptions): boolean {\n if (!options.enum || !schema.enum) {\n return false;\n }\n const entries = tsEnumEntries(schema, options);\n // An empty `enum` stays an empty TypeScript enum, as the original made it; an enum of only\n // `null` has no member left once the fix drops `null`, so it stays a union.\n const isOnlyNull = entries.length === 0 && schema.enum.length > 0;\n const isSupported =\n !isOnlyNull && entries.every(([value]) => [\"string\", \"number\"].includes(typeof value));\n // `--conditional-enums` converts only enums that carry x-enum-* metadata.\n return isSupported && (!options.conditionalEnums || hasEnumMetadata(schema));\n}\n\nfunction enumMetadata(\n schema: SchemaObject,\n entries: readonly [unknown, number][],\n): EnumMemberMetadata[] {\n return entries.map(([, index]) => ({\n name: schema[\"x-enum-varnames\"]?.[index] ?? schema[\"x-enumNames\"]?.[index],\n description: schema[\"x-enum-descriptions\"]?.[index] ?? schema[\"x-enumDescriptions\"]?.[index],\n }));\n}\n\n/**\n * Whether `null` is a valid value: it is in `enum` and the schema's type admits it (`type`\n * absent or listing `\"null\"`, or OpenAPI 3.0 `nullable: true`). Both keywords must pass.\n */\nfunction isNullAllowed(schema: SchemaObject): boolean {\n const { type } = schema;\n const isTypeNullable =\n type === undefined ||\n (Array.isArray(type) && type.includes(\"null\")) ||\n Boolean(schema.nullable);\n return (schema.enum ?? []).includes(null) && isTypeNullable;\n}\n\n/**\n * `additionalProperties: true` on a string enum keeps other strings allowed but still offers the\n * listed values in editors: `\"a\" | \"b\" | (string & {})`.\n */\nfunction withOtherStrings(type: IrType, schema: SchemaObject): IrType {\n if (!hasAdditionalProperties(schema) || schema.type !== \"string\") {\n return type;\n }\n return unionOf([type, intersectionOf([irKeyword(\"string\"), irObject([])])]);\n}\n\n/** The enum declaration of `schema` typed at `path`; its values are strings and numbers. */\nfunction enumRequest(\n schema: SchemaObject,\n path: string | undefined,\n options: SchemaOptions,\n): EnumDeclarationRequest {\n const entries = tsEnumEntries(schema, options);\n return {\n name: nameFromPath(path),\n isComponentSchema: COMPONENT_SCHEMA_RE.test(path ?? \"\"),\n values: entries.map(([value]) => value as string | number),\n metadata: enumMetadata(schema, entries),\n };\n}\n\n/** One member's type; a quoted member cannot follow a dot, `typeof E[\"+\"]` is the same type. */\nfunction enumMemberType(enumName: string, member: string): IrType {\n return member.startsWith('\"')\n ? irIndexedAccess(irReference(`typeof ${enumName}`), irString(JSON.parse(member), \"escaped\"))\n : irReference(`${enumName}.${member}`);\n}\n\n/**\n * The `discriminator-values` fix: a member's discriminator value is typed with members of\n * the owner's enum (`PetType.Cat`), so the member is one of the owner's type (#1700). `key` is the\n * enum the scan added or the inherited discriminator object. Null when the fix is off, or the\n * owner's property is no TypeScript enum with every value.\n */\nexport function ownerEnumMembersType(\n key: object,\n values: readonly unknown[],\n request: SchemaRequest,\n): IrType | null {\n const { options, discriminators, footer } = request.context;\n const parent: DiscriminatorEnumParent | undefined = options.fixes.has(\n OutputFix.DISCRIMINATOR_VALUES,\n )\n ? discriminators.enumParentOf(key)\n : undefined;\n if (parent === undefined || !isTsEnum(parent.schema, options)) {\n return null;\n }\n const reference = { ...enumRequest(parent.schema, parent.path, options), isOwnerReference: true };\n const name = footer.addEnum(reference);\n const members = footer.enumMembers(name);\n const names = values.map((value) => members.get(value as string | number));\n if (names.length === 0 || names.some((member) => member === undefined)) {\n return null;\n }\n return unionOf(names.map((member) => enumMemberType(name, member as string)));\n}\n\nfunction tsEnumType(schema: SchemaObject, request: SchemaRequest): IrType {\n const { options, footer } = request.context;\n // `isTsEnum` admits only strings and numbers, and the fix leaves `null` out of the members.\n const values = tsEnumEntries(schema, options).map(([value]) => value);\n const type =\n ownerEnumMembersType(schema, values, request) ??\n withOtherStrings(\n irReference(footer.addEnum(enumRequest(schema, request.location.path, options))),\n schema,\n );\n return options.fixes.has(OutputFix.NULLABLE_ENUMS) && isNullAllowed(schema)\n ? unionOf([type, irKeyword(\"null\")])\n : type;\n}\n\nfunction isUnionPosition(pointer: readonly string[], index: number): boolean {\n const next = pointer[index + 1];\n return UNION_KEYWORDS.has(pointer[index] as string) && next !== undefined && INDEX_RE.test(next);\n}\n\nconst PARAMETERS = \"parameters\";\n\n/** Where the `parameters` of a path item sit in its pointer: `paths/<key>/…`, `components/…`. */\nfunction pathItemParametersIndex(pointer: readonly string[]): number | null {\n if (pointer[0] === \"paths\" || pointer[0] === \"webhooks\") {\n return 2;\n }\n return pointer[0] === \"components\" && pointer[1] === \"pathItems\" ? 3 : null;\n}\n\n/**\n * The location of a path item parameter repeats `parameters` (`paths/~1a/parameters/parameters/\n * path/id`), which keeps the generated names as they were. The generated type has the segment\n * once: `paths[\"/a\"][\"parameters\"][\"path\"][\"id\"]`.\n */\nfunction withSingleParametersSegment(pointer: readonly string[]): readonly string[] {\n const index = pathItemParametersIndex(pointer);\n const isRepeated =\n index !== null && pointer[index] === PARAMETERS && pointer[index + 1] === PARAMETERS;\n return isRepeated ? [...pointer.slice(0, index), ...pointer.slice(index + 1)] : pointer;\n}\n\n/**\n * The pointer of `--enum-values` arrays without union positions (`anyOf/0`), so names stay\n * stable. Every property after the first union position is narrowed with `Extract`: a no-op where\n * all variants have it, and the needed narrowing where only some do.\n */\nfunction enumValuesPointer(path: string | undefined): { ref: string; extract: string[] } {\n const pointer = withSingleParametersSegment(parseRefPointer(path ?? \"\"));\n const kept: string[] = [];\n let firstVariantStart: number | null = null;\n for (let index = 0; index < pointer.length; index++) {\n if (isUnionPosition(pointer, index)) {\n firstVariantStart ??= index + 2;\n index++;\n continue;\n }\n kept.push(pointer[index] as string);\n }\n const extract =\n firstVariantStart === null\n ? []\n : pointer\n .slice(firstVariantStart)\n .filter((segment) => !UNION_KEYWORDS.has(segment) && !INDEX_RE.test(segment));\n return { ref: createRef(kept), extract };\n}\n\nfunction addEnumValues(schema: SchemaObject, request: SchemaRequest): void {\n const { ref, extract } = enumValuesPointer(request.location.path);\n const valuesType = refType(ref, { isDeep: true, extractProperties: extract });\n request.context.footer.addEnumValues({\n name: `${nameFromPath(request.location.path)}Values`,\n // A record value (`additionalProperties`) is reached by indexing with `string`.\n type: request.isFromAdditionalProperties\n ? irIndexedAccess(valuesType, irReference(\"string\"))\n : valuesType,\n values: (schema.enum ?? []) as (string | number)[],\n });\n}\n\nfunction literalEnumType(schema: SchemaObject, request: SchemaRequest): IrType {\n const values = schema.enum ?? [];\n const isNullable =\n (Array.isArray(schema.type) && schema.type.includes(\"null\")) || Boolean(schema.nullable);\n const literals = [...values.map(literalType), ...(isNullable ? [irKeyword(\"null\")] : [])];\n const type = withOtherStrings(unionOf(literals), schema);\n const isListable = values.every(\n (value) => typeof value === \"string\" || typeof value === \"number\",\n );\n if (request.context.options.enumValues && isListable) {\n addEnumValues(schema, request);\n }\n return type;\n}\n\n/**\n * `enum` on anything but an object (object enums are handled as `oneOf`). With\n * `additionalProperties`, only string enums are handled here; others fall through to composition.\n */\nexport const enumRule: SchemaRule = {\n name: \"enum\",\n matches(schema) {\n const isCandidate =\n Array.isArray(schema.enum) && schema.type !== \"object\" && !(\"properties\" in schema);\n return isCandidate && (!hasAdditionalProperties(schema) || schema.type === \"string\");\n },\n transform(schema, request) {\n return isTsEnum(schema, request.context.options)\n ? tsEnumType(schema, request)\n : literalEnumType(schema, request);\n },\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"enum-rule.mjs","sources":["../../../../src/application/transform/schema/enum-rule.ts"],"sourcesContent":["import {\n irIndexedAccess,\n irKeyword,\n irObject,\n irReference,\n irString,\n} from \"../../../domain/ir/constructors.js\";\nimport type { IrType } from \"../../../domain/ir/nodes.js\";\nimport { createRef, parseRefPointer } from \"../../../domain/openapi/json-pointer.js\";\nimport type { SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { FIX } from \"../../../domain/output-fixes.js\";\nimport { literalType } from \"../literal-type.js\";\nimport { refType } from \"../ref-type.js\";\nimport { intersectionOf, unionOf } from \"../type-combinators.js\";\nimport type {\n DiscriminatorEnumParent,\n EnumDeclarationRequest,\n EnumMemberMetadata,\n SchemaOptions,\n} from \"./schema-context.js\";\nimport type { SchemaRequest, SchemaRule } from \"./schema-rule.js\";\n\n/** Removed from generated names, so `#/components/schemas/Status` gives `Status`. */\nconst COMPONENT_SCHEMAS_PREFIX = \"components/schemas\";\nconst UNION_KEYWORDS: ReadonlySet<string> = new Set([\"anyOf\", \"oneOf\"]);\nconst INDEX_RE = /^\\d+$/;\n\nfunction hasAdditionalProperties(schema: SchemaObject): boolean {\n return \"additionalProperties\" in schema && Boolean(schema.additionalProperties);\n}\n\n/** A name from the schema's pointer: `#/components/schemas/Pet/status` → `/Pet/status`. */\nfunction nameFromPath(path: string | undefined): string {\n return parseRefPointer(path ?? \"\")\n .join(\"/\")\n .replace(COMPONENT_SCHEMAS_PREFIX, \"\");\n}\n\n/** `#/components/schemas/Name`, and no deeper pointer. */\nconst COMPONENT_SCHEMA_RE = /^#\\/components\\/schemas\\/[^/]+$/;\n\nfunction hasEnumMetadata(schema: SchemaObject): boolean {\n return [\n schema[\"x-enum-varnames\"],\n schema[\"x-enumNames\"],\n schema[\"x-enum-descriptions\"],\n schema[\"x-enumDescriptions\"],\n ].some(Array.isArray);\n}\n\n/**\n * The values a TypeScript enum declares, with their positions in `enum`. With the\n * `nullable-enums` fix a `null` value is left out (upstream #1872): an enum member cannot be\n * `null`, so the type adds it as `| null` instead (`tsEnumType`).\n */\nfunction tsEnumEntries(schema: SchemaObject, options: SchemaOptions): [unknown, number][] {\n const entries = (schema.enum ?? []).map((value, index): [unknown, number] => [value, index]);\n return options.fixes.has(FIX.NULLABLE_ENUMS)\n ? entries.filter(([value]) => value !== null)\n : entries;\n}\n\n/**\n * `--enum`: string and number enums become TypeScript enums. The original meant to allow `null`\n * too, but tested `typeof value` against `null`, so an enum containing null stays a union; the\n * `nullable-enums` fix declares its other values.\n */\nfunction isTsEnum(schema: SchemaObject, options: SchemaOptions): boolean {\n if (!options.enum || !schema.enum) {\n return false;\n }\n const entries = tsEnumEntries(schema, options);\n // An empty `enum` stays an empty TypeScript enum, as the original made it; an enum of only\n // `null` has no member left once the fix drops `null`, so it stays a union.\n const isOnlyNull = entries.length === 0 && schema.enum.length > 0;\n const isSupported =\n !isOnlyNull && entries.every(([value]) => [\"string\", \"number\"].includes(typeof value));\n // `--conditional-enums` converts only enums that carry x-enum-* metadata.\n return isSupported && (!options.conditionalEnums || hasEnumMetadata(schema));\n}\n\nfunction enumMetadata(\n schema: SchemaObject,\n entries: readonly [unknown, number][],\n): EnumMemberMetadata[] {\n return entries.map(([, index]) => ({\n name: schema[\"x-enum-varnames\"]?.[index] ?? schema[\"x-enumNames\"]?.[index],\n description: schema[\"x-enum-descriptions\"]?.[index] ?? schema[\"x-enumDescriptions\"]?.[index],\n }));\n}\n\n/**\n * Whether `null` is a valid value: it is in `enum` and the schema's type admits it (`type`\n * absent or listing `\"null\"`, or OpenAPI 3.0 `nullable: true`). Both keywords must pass.\n */\nfunction isNullAllowed(schema: SchemaObject): boolean {\n const { type } = schema;\n const isTypeNullable =\n type === undefined ||\n (Array.isArray(type) && type.includes(\"null\")) ||\n Boolean(schema.nullable);\n return (schema.enum ?? []).includes(null) && isTypeNullable;\n}\n\n/**\n * `additionalProperties: true` on a string enum keeps other strings allowed but still offers the\n * listed values in editors: `\"a\" | \"b\" | (string & {})`.\n */\nfunction withOtherStrings(type: IrType, schema: SchemaObject): IrType {\n if (!hasAdditionalProperties(schema) || schema.type !== \"string\") {\n return type;\n }\n return unionOf([type, intersectionOf([irKeyword(\"string\"), irObject([])])]);\n}\n\n/** The enum declaration of `schema` typed at `path`; its values are strings and numbers. */\nfunction enumRequest(\n schema: SchemaObject,\n path: string | undefined,\n options: SchemaOptions,\n): EnumDeclarationRequest {\n const entries = tsEnumEntries(schema, options);\n return {\n name: nameFromPath(path),\n isComponentSchema: COMPONENT_SCHEMA_RE.test(path ?? \"\"),\n values: entries.map(([value]) => value as string | number),\n metadata: enumMetadata(schema, entries),\n };\n}\n\n/** One member's type; a quoted member cannot follow a dot, `typeof E[\"+\"]` is the same type. */\nfunction enumMemberType(enumName: string, member: string): IrType {\n return member.startsWith('\"')\n ? irIndexedAccess(irReference(`typeof ${enumName}`), irString(JSON.parse(member), \"escaped\"))\n : irReference(`${enumName}.${member}`);\n}\n\n/**\n * The `discriminator-values` fix: a member's discriminator value is typed with members of\n * the owner's enum (`PetType.Cat`), so the member is one of the owner's type (#1700). `key` is the\n * enum the scan added or the inherited discriminator object. Null when the fix is off, or the\n * owner's property is no TypeScript enum with every value.\n */\nexport function ownerEnumMembersType(\n key: object,\n values: readonly unknown[],\n request: SchemaRequest,\n): IrType | null {\n const { options, discriminators, footer } = request.context;\n const parent: DiscriminatorEnumParent | undefined = options.fixes.has(FIX.DISCRIMINATOR_VALUES)\n ? discriminators.enumParentOf(key)\n : undefined;\n if (parent === undefined || !isTsEnum(parent.schema, options)) {\n return null;\n }\n const reference = { ...enumRequest(parent.schema, parent.path, options), isOwnerReference: true };\n const name = footer.addEnum(reference);\n const members = footer.enumMembers(name);\n const names = values.map((value) => members.get(value as string | number));\n if (names.length === 0 || names.some((member) => member === undefined)) {\n return null;\n }\n return unionOf(names.map((member) => enumMemberType(name, member as string)));\n}\n\nfunction tsEnumType(schema: SchemaObject, request: SchemaRequest): IrType {\n const { options, footer } = request.context;\n // `isTsEnum` admits only strings and numbers, and the fix leaves `null` out of the members.\n const values = tsEnumEntries(schema, options).map(([value]) => value);\n const type =\n ownerEnumMembersType(schema, values, request) ??\n withOtherStrings(\n irReference(footer.addEnum(enumRequest(schema, request.location.path, options))),\n schema,\n );\n return options.fixes.has(FIX.NULLABLE_ENUMS) && isNullAllowed(schema)\n ? unionOf([type, irKeyword(\"null\")])\n : type;\n}\n\nfunction isUnionPosition(pointer: readonly string[], index: number): boolean {\n const next = pointer[index + 1];\n return UNION_KEYWORDS.has(pointer[index] as string) && next !== undefined && INDEX_RE.test(next);\n}\n\nconst PARAMETERS = \"parameters\";\n\n/** Where the `parameters` of a path item sit in its pointer: `paths/<key>/…`, `components/…`. */\nfunction pathItemParametersIndex(pointer: readonly string[]): number | null {\n if (pointer[0] === \"paths\" || pointer[0] === \"webhooks\") {\n return 2;\n }\n return pointer[0] === \"components\" && pointer[1] === \"pathItems\" ? 3 : null;\n}\n\n/**\n * The location of a path item parameter repeats `parameters` (`paths/~1a/parameters/parameters/\n * path/id`), which keeps the generated names as they were. The generated type has the segment\n * once: `paths[\"/a\"][\"parameters\"][\"path\"][\"id\"]`.\n */\nfunction withSingleParametersSegment(pointer: readonly string[]): readonly string[] {\n const index = pathItemParametersIndex(pointer);\n const isRepeated =\n index !== null && pointer[index] === PARAMETERS && pointer[index + 1] === PARAMETERS;\n return isRepeated ? [...pointer.slice(0, index), ...pointer.slice(index + 1)] : pointer;\n}\n\n/**\n * The pointer of `--enum-values` arrays without union positions (`anyOf/0`), so names stay\n * stable. Every property after the first union position is narrowed with `Extract`: a no-op where\n * all variants have it, and the needed narrowing where only some do.\n */\nfunction enumValuesPointer(path: string | undefined): { ref: string; extract: string[] } {\n const pointer = withSingleParametersSegment(parseRefPointer(path ?? \"\"));\n const kept: string[] = [];\n let firstVariantStart: number | null = null;\n for (let index = 0; index < pointer.length; index++) {\n if (isUnionPosition(pointer, index)) {\n firstVariantStart ??= index + 2;\n index++;\n continue;\n }\n kept.push(pointer[index] as string);\n }\n const extract =\n firstVariantStart === null\n ? []\n : pointer\n .slice(firstVariantStart)\n .filter((segment) => !UNION_KEYWORDS.has(segment) && !INDEX_RE.test(segment));\n return { ref: createRef(kept), extract };\n}\n\nfunction addEnumValues(schema: SchemaObject, request: SchemaRequest): void {\n const { ref, extract } = enumValuesPointer(request.location.path);\n const valuesType = refType(ref, { isDeep: true, extractProperties: extract });\n request.context.footer.addEnumValues({\n name: `${nameFromPath(request.location.path)}Values`,\n // A record value (`additionalProperties`) is reached by indexing with `string`.\n type: request.isFromAdditionalProperties\n ? irIndexedAccess(valuesType, irReference(\"string\"))\n : valuesType,\n values: (schema.enum ?? []) as (string | number)[],\n });\n}\n\nfunction literalEnumType(schema: SchemaObject, request: SchemaRequest): IrType {\n const values = schema.enum ?? [];\n const isNullable =\n (Array.isArray(schema.type) && schema.type.includes(\"null\")) || Boolean(schema.nullable);\n const literals = [...values.map(literalType), ...(isNullable ? [irKeyword(\"null\")] : [])];\n const type = withOtherStrings(unionOf(literals), schema);\n const isListable = values.every(\n (value) => typeof value === \"string\" || typeof value === \"number\",\n );\n if (request.context.options.enumValues && isListable) {\n addEnumValues(schema, request);\n }\n return type;\n}\n\n/**\n * `enum` on anything but an object (object enums are handled as `oneOf`). With\n * `additionalProperties`, only string enums are handled here; others fall through to composition.\n */\nexport const enumRule: SchemaRule = {\n name: \"enum\",\n matches(schema) {\n const isCandidate =\n Array.isArray(schema.enum) && schema.type !== \"object\" && !(\"properties\" in schema);\n return isCandidate && (!hasAdditionalProperties(schema) || schema.type === \"string\");\n },\n transform(schema, request) {\n return isTsEnum(schema, request.context.options)\n ? tsEnumType(schema, request)\n : literalEnumType(schema, request);\n },\n};\n"],"names":[],"mappings":"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"}
@@ -41,7 +41,7 @@ function memberSchema(member, request) {
41
41
  }
42
42
  function allOfMembers(members, request) {
43
43
  const unchanged = { members, required: [] };
44
- if (!request.context.options.fixes.has(outputFixes.OutputFix.ALLOF_REQUIRED)) {
44
+ if (!request.context.options.fixes.has(outputFixes.FIX.ALLOF_REQUIRED)) {
45
45
  return unchanged;
46
46
  }
47
47
  const schemas = members.map((member) => memberSchema(member, request));
@@ -1 +1 @@
1
- {"version":3,"file":"presence-members.cjs","sources":["../../../../src/application/transform/schema/presence-members.ts"],"sourcesContent":["import type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { OutputFix } from \"../../../domain/output-fixes.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `allof-required` fix (ADR-021, roadmap R6). An `allOf` member such as `{ required: [name] }`\n * or `{ type: object }` says nothing about the shape of the object; it only asks that keys are\n * present. Typed as an object of its own, it adds `& Record<string, never>` or `& unknown`. With\n * the fix, such members are left out and their keys are made required in the other members, the\n * same way the parent's `required` is (upstream #1474, #1520, #2165).\n */\n\n/**\n * Keywords that do not change the shape: `type: object`, `required`, and annotations that the\n * generator does not read on an `allOf` member. `default`, `readOnly` and `writeOnly` are left out:\n * they change types elsewhere.\n */\nconst PRESENCE_KEYWORDS: ReadonlySet<string> = new Set([\n \"$comment\",\n \"deprecated\",\n \"description\",\n \"example\",\n \"examples\",\n \"required\",\n \"title\",\n \"type\",\n]);\n\nconst EXTENSION_PREFIX = \"x-\";\nconst OBJECT_TYPE = \"object\";\n\nfunction isStringList(value: unknown): value is readonly string[] {\n return Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\nfunction isPresenceKeyword([key, value]: readonly [string, unknown]): boolean {\n if (key === \"type\") {\n return value === OBJECT_TYPE;\n }\n if (key === \"required\") {\n return isStringList(value);\n }\n return PRESENCE_KEYWORDS.has(key) || key.startsWith(EXTENSION_PREFIX);\n}\n\nfunction isPresenceObject(schema: unknown): schema is SchemaObject {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n !Array.isArray(schema) &&\n !(\"$ref\" in schema) &&\n Object.entries(schema).every(isPresenceKeyword)\n );\n}\n\n/**\n * The schema a member stands for: itself, or the target of a `$ref` with no sibling keywords. The\n * discriminator scan has already added the discriminator property to a mapped target, so such a\n * target is never presence-only.\n */\nfunction memberSchema(member: Schema, request: SchemaRequest): unknown {\n if (typeof member !== \"object\" || member === null || !(\"$ref\" in member)) {\n return member;\n }\n const ref = (member as { readonly $ref: unknown }).$ref;\n if (typeof ref !== \"string\" || Object.keys(member).length !== 1) {\n return undefined;\n }\n return request.context.refs.resolve(ref);\n}\n\n/** The `allOf` members to type, and the keys the left-out members make required. */\nexport interface AllOfMembers {\n readonly members: readonly Schema[];\n readonly required: readonly string[];\n}\n\n/**\n * The members of `allOf` with presence-only ones left out, when the fix is on and another member\n * is left to carry the keys; otherwise the members as they are.\n */\nexport function allOfMembers(members: readonly Schema[], request: SchemaRequest): AllOfMembers {\n const unchanged = { members, required: [] };\n if (!request.context.options.fixes.has(OutputFix.ALLOF_REQUIRED)) {\n return unchanged;\n }\n const schemas = members.map((member) => memberSchema(member, request));\n const kept = members.filter((_, index) => !isPresenceObject(schemas[index]));\n if (kept.length === 0 || kept.length === members.length) {\n return unchanged;\n }\n const required = schemas.flatMap((schema) =>\n isPresenceObject(schema) ? (schema.required ?? []) : [],\n );\n return { members: kept, required };\n}\n"],"names":["OutputFix"],"mappings":";;;;AAiBA,MAAM,iBAAA,uBAA6C,GAAA,CAAI;AAAA,EACrD,UAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,MAAM,gBAAA,GAAmB,IAAA;AACzB,MAAM,WAAA,GAAc,QAAA;AAEpB,SAAS,aAAa,KAAA,EAA4C;AAChE,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,KAAA,CAAM,MAAM,CAAC,KAAA,KAAU,OAAO,KAAA,KAAU,QAAQ,CAAA;AACjF;AAEA,SAAS,iBAAA,CAAkB,CAAC,GAAA,EAAK,KAAK,CAAA,EAAwC;AAC5E,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,OAAO,KAAA,KAAU,WAAA;AAAA,EACnB;AACA,EAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,IAAA,OAAO,aAAa,KAAK,CAAA;AAAA,EAC3B;AACA,EAAA,OAAO,kBAAkB,GAAA,CAAI,GAAG,CAAA,IAAK,GAAA,CAAI,WAAW,gBAAgB,CAAA;AACtE;AAEA,SAAS,iBAAiB,MAAA,EAAyC;AACjE,EAAA,OACE,OAAO,MAAA,KAAW,QAAA,IAClB,WAAW,IAAA,IACX,CAAC,MAAM,OAAA,CAAQ,MAAM,CAAA,IACrB,EAAE,UAAU,MAAA,CAAA,IACZ,MAAA,CAAO,QAAQ,MAAM,CAAA,CAAE,MAAM,iBAAiB,CAAA;AAElD;AAOA,SAAS,YAAA,CAAa,QAAgB,OAAA,EAAiC;AACrE,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,WAAW,IAAA,IAAQ,EAAE,UAAU,MAAA,CAAA,EAAS;AACxE,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,MAAO,MAAA,CAAsC,IAAA;AACnD,EAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,MAAA,CAAO,KAAK,MAAM,CAAA,CAAE,WAAW,CAAA,EAAG;AAC/D,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AACzC;AAYO,SAAS,YAAA,CAAa,SAA4B,OAAA,EAAsC;AAC7F,EAAA,MAAM,SAAA,GAAY,EAAE,OAAA,EAAS,QAAA,EAAU,EAAC,EAAE;AAC1C,EAAA,IAAI,CAAC,QAAQ,OAAA,CAAQ,OAAA,CAAQ,MAAM,GAAA,CAAIA,qBAAA,CAAU,cAAc,CAAA,EAAG;AAChE,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,CAAI,CAAC,WAAW,YAAA,CAAa,MAAA,EAAQ,OAAO,CAAC,CAAA;AACrE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,EAAG,KAAA,KAAU,CAAC,gBAAA,CAAiB,OAAA,CAAQ,KAAK,CAAC,CAAC,CAAA;AAC3E,EAAA,IAAI,KAAK,MAAA,KAAW,CAAA,IAAK,IAAA,CAAK,MAAA,KAAW,QAAQ,MAAA,EAAQ;AACvD,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,WAAW,OAAA,CAAQ,OAAA;AAAA,IAAQ,CAAC,WAChC,gBAAA,CAAiB,MAAM,IAAK,MAAA,CAAO,QAAA,IAAY,EAAC,GAAK;AAAC,GACxD;AACA,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,QAAA,EAAS;AACnC;;"}
1
+ {"version":3,"file":"presence-members.cjs","sources":["../../../../src/application/transform/schema/presence-members.ts"],"sourcesContent":["import type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { FIX } from \"../../../domain/output-fixes.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `allof-required` fix (ADR-021, roadmap R6). An `allOf` member such as `{ required: [name] }`\n * or `{ type: object }` says nothing about the shape of the object; it only asks that keys are\n * present. Typed as an object of its own, it adds `& Record<string, never>` or `& unknown`. With\n * the fix, such members are left out and their keys are made required in the other members, the\n * same way the parent's `required` is (upstream #1474, #1520, #2165).\n */\n\n/**\n * Keywords that do not change the shape: `type: object`, `required`, and annotations that the\n * generator does not read on an `allOf` member. `default`, `readOnly` and `writeOnly` are left out:\n * they change types elsewhere.\n */\nconst PRESENCE_KEYWORDS: ReadonlySet<string> = new Set([\n \"$comment\",\n \"deprecated\",\n \"description\",\n \"example\",\n \"examples\",\n \"required\",\n \"title\",\n \"type\",\n]);\n\nconst EXTENSION_PREFIX = \"x-\";\nconst OBJECT_TYPE = \"object\";\n\nfunction isStringList(value: unknown): value is readonly string[] {\n return Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\nfunction isPresenceKeyword([key, value]: readonly [string, unknown]): boolean {\n if (key === \"type\") {\n return value === OBJECT_TYPE;\n }\n if (key === \"required\") {\n return isStringList(value);\n }\n return PRESENCE_KEYWORDS.has(key) || key.startsWith(EXTENSION_PREFIX);\n}\n\nfunction isPresenceObject(schema: unknown): schema is SchemaObject {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n !Array.isArray(schema) &&\n !(\"$ref\" in schema) &&\n Object.entries(schema).every(isPresenceKeyword)\n );\n}\n\n/**\n * The schema a member stands for: itself, or the target of a `$ref` with no sibling keywords. The\n * discriminator scan has already added the discriminator property to a mapped target, so such a\n * target is never presence-only.\n */\nfunction memberSchema(member: Schema, request: SchemaRequest): unknown {\n if (typeof member !== \"object\" || member === null || !(\"$ref\" in member)) {\n return member;\n }\n const ref = (member as { readonly $ref: unknown }).$ref;\n if (typeof ref !== \"string\" || Object.keys(member).length !== 1) {\n return undefined;\n }\n return request.context.refs.resolve(ref);\n}\n\n/** The `allOf` members to type, and the keys the left-out members make required. */\nexport interface AllOfMembers {\n readonly members: readonly Schema[];\n readonly required: readonly string[];\n}\n\n/**\n * The members of `allOf` with presence-only ones left out, when the fix is on and another member\n * is left to carry the keys; otherwise the members as they are.\n */\nexport function allOfMembers(members: readonly Schema[], request: SchemaRequest): AllOfMembers {\n const unchanged = { members, required: [] };\n if (!request.context.options.fixes.has(FIX.ALLOF_REQUIRED)) {\n return unchanged;\n }\n const schemas = members.map((member) => memberSchema(member, request));\n const kept = members.filter((_, index) => !isPresenceObject(schemas[index]));\n if (kept.length === 0 || kept.length === members.length) {\n return unchanged;\n }\n const required = schemas.flatMap((schema) =>\n isPresenceObject(schema) ? (schema.required ?? []) : [],\n );\n return { members: kept, required };\n}\n"],"names":["FIX"],"mappings":";;;;AAiBA,MAAM,iBAAA,uBAA6C,GAAA,CAAI;AAAA,EACrD,UAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,MAAM,gBAAA,GAAmB,IAAA;AACzB,MAAM,WAAA,GAAc,QAAA;AAEpB,SAAS,aAAa,KAAA,EAA4C;AAChE,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,KAAA,CAAM,MAAM,CAAC,KAAA,KAAU,OAAO,KAAA,KAAU,QAAQ,CAAA;AACjF;AAEA,SAAS,iBAAA,CAAkB,CAAC,GAAA,EAAK,KAAK,CAAA,EAAwC;AAC5E,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,OAAO,KAAA,KAAU,WAAA;AAAA,EACnB;AACA,EAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,IAAA,OAAO,aAAa,KAAK,CAAA;AAAA,EAC3B;AACA,EAAA,OAAO,kBAAkB,GAAA,CAAI,GAAG,CAAA,IAAK,GAAA,CAAI,WAAW,gBAAgB,CAAA;AACtE;AAEA,SAAS,iBAAiB,MAAA,EAAyC;AACjE,EAAA,OACE,OAAO,MAAA,KAAW,QAAA,IAClB,WAAW,IAAA,IACX,CAAC,MAAM,OAAA,CAAQ,MAAM,CAAA,IACrB,EAAE,UAAU,MAAA,CAAA,IACZ,MAAA,CAAO,QAAQ,MAAM,CAAA,CAAE,MAAM,iBAAiB,CAAA;AAElD;AAOA,SAAS,YAAA,CAAa,QAAgB,OAAA,EAAiC;AACrE,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,WAAW,IAAA,IAAQ,EAAE,UAAU,MAAA,CAAA,EAAS;AACxE,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,MAAO,MAAA,CAAsC,IAAA;AACnD,EAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,MAAA,CAAO,KAAK,MAAM,CAAA,CAAE,WAAW,CAAA,EAAG;AAC/D,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AACzC;AAYO,SAAS,YAAA,CAAa,SAA4B,OAAA,EAAsC;AAC7F,EAAA,MAAM,SAAA,GAAY,EAAE,OAAA,EAAS,QAAA,EAAU,EAAC,EAAE;AAC1C,EAAA,IAAI,CAAC,QAAQ,OAAA,CAAQ,OAAA,CAAQ,MAAM,GAAA,CAAIA,eAAA,CAAI,cAAc,CAAA,EAAG;AAC1D,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,CAAI,CAAC,WAAW,YAAA,CAAa,MAAA,EAAQ,OAAO,CAAC,CAAA;AACrE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,EAAG,KAAA,KAAU,CAAC,gBAAA,CAAiB,OAAA,CAAQ,KAAK,CAAC,CAAC,CAAA;AAC3E,EAAA,IAAI,KAAK,MAAA,KAAW,CAAA,IAAK,IAAA,CAAK,MAAA,KAAW,QAAQ,MAAA,EAAQ;AACvD,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,WAAW,OAAA,CAAQ,OAAA;AAAA,IAAQ,CAAC,WAChC,gBAAA,CAAiB,MAAM,IAAK,MAAA,CAAO,QAAA,IAAY,EAAC,GAAK;AAAC,GACxD;AACA,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,QAAA,EAAS;AACnC;;"}
@@ -1,4 +1,4 @@
1
- import { OutputFix } from '../../../domain/output-fixes.mjs';
1
+ import { FIX } from '../../../domain/output-fixes.mjs';
2
2
 
3
3
  const PRESENCE_KEYWORDS = /* @__PURE__ */ new Set([
4
4
  "$comment",
@@ -39,7 +39,7 @@ function memberSchema(member, request) {
39
39
  }
40
40
  function allOfMembers(members, request) {
41
41
  const unchanged = { members, required: [] };
42
- if (!request.context.options.fixes.has(OutputFix.ALLOF_REQUIRED)) {
42
+ if (!request.context.options.fixes.has(FIX.ALLOF_REQUIRED)) {
43
43
  return unchanged;
44
44
  }
45
45
  const schemas = members.map((member) => memberSchema(member, request));
@@ -1 +1 @@
1
- {"version":3,"file":"presence-members.mjs","sources":["../../../../src/application/transform/schema/presence-members.ts"],"sourcesContent":["import type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { OutputFix } from \"../../../domain/output-fixes.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `allof-required` fix (ADR-021, roadmap R6). An `allOf` member such as `{ required: [name] }`\n * or `{ type: object }` says nothing about the shape of the object; it only asks that keys are\n * present. Typed as an object of its own, it adds `& Record<string, never>` or `& unknown`. With\n * the fix, such members are left out and their keys are made required in the other members, the\n * same way the parent's `required` is (upstream #1474, #1520, #2165).\n */\n\n/**\n * Keywords that do not change the shape: `type: object`, `required`, and annotations that the\n * generator does not read on an `allOf` member. `default`, `readOnly` and `writeOnly` are left out:\n * they change types elsewhere.\n */\nconst PRESENCE_KEYWORDS: ReadonlySet<string> = new Set([\n \"$comment\",\n \"deprecated\",\n \"description\",\n \"example\",\n \"examples\",\n \"required\",\n \"title\",\n \"type\",\n]);\n\nconst EXTENSION_PREFIX = \"x-\";\nconst OBJECT_TYPE = \"object\";\n\nfunction isStringList(value: unknown): value is readonly string[] {\n return Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\nfunction isPresenceKeyword([key, value]: readonly [string, unknown]): boolean {\n if (key === \"type\") {\n return value === OBJECT_TYPE;\n }\n if (key === \"required\") {\n return isStringList(value);\n }\n return PRESENCE_KEYWORDS.has(key) || key.startsWith(EXTENSION_PREFIX);\n}\n\nfunction isPresenceObject(schema: unknown): schema is SchemaObject {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n !Array.isArray(schema) &&\n !(\"$ref\" in schema) &&\n Object.entries(schema).every(isPresenceKeyword)\n );\n}\n\n/**\n * The schema a member stands for: itself, or the target of a `$ref` with no sibling keywords. The\n * discriminator scan has already added the discriminator property to a mapped target, so such a\n * target is never presence-only.\n */\nfunction memberSchema(member: Schema, request: SchemaRequest): unknown {\n if (typeof member !== \"object\" || member === null || !(\"$ref\" in member)) {\n return member;\n }\n const ref = (member as { readonly $ref: unknown }).$ref;\n if (typeof ref !== \"string\" || Object.keys(member).length !== 1) {\n return undefined;\n }\n return request.context.refs.resolve(ref);\n}\n\n/** The `allOf` members to type, and the keys the left-out members make required. */\nexport interface AllOfMembers {\n readonly members: readonly Schema[];\n readonly required: readonly string[];\n}\n\n/**\n * The members of `allOf` with presence-only ones left out, when the fix is on and another member\n * is left to carry the keys; otherwise the members as they are.\n */\nexport function allOfMembers(members: readonly Schema[], request: SchemaRequest): AllOfMembers {\n const unchanged = { members, required: [] };\n if (!request.context.options.fixes.has(OutputFix.ALLOF_REQUIRED)) {\n return unchanged;\n }\n const schemas = members.map((member) => memberSchema(member, request));\n const kept = members.filter((_, index) => !isPresenceObject(schemas[index]));\n if (kept.length === 0 || kept.length === members.length) {\n return unchanged;\n }\n const required = schemas.flatMap((schema) =>\n isPresenceObject(schema) ? (schema.required ?? []) : [],\n );\n return { members: kept, required };\n}\n"],"names":[],"mappings":";;AAiBA,MAAM,iBAAA,uBAA6C,GAAA,CAAI;AAAA,EACrD,UAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,MAAM,gBAAA,GAAmB,IAAA;AACzB,MAAM,WAAA,GAAc,QAAA;AAEpB,SAAS,aAAa,KAAA,EAA4C;AAChE,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,KAAA,CAAM,MAAM,CAAC,KAAA,KAAU,OAAO,KAAA,KAAU,QAAQ,CAAA;AACjF;AAEA,SAAS,iBAAA,CAAkB,CAAC,GAAA,EAAK,KAAK,CAAA,EAAwC;AAC5E,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,OAAO,KAAA,KAAU,WAAA;AAAA,EACnB;AACA,EAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,IAAA,OAAO,aAAa,KAAK,CAAA;AAAA,EAC3B;AACA,EAAA,OAAO,kBAAkB,GAAA,CAAI,GAAG,CAAA,IAAK,GAAA,CAAI,WAAW,gBAAgB,CAAA;AACtE;AAEA,SAAS,iBAAiB,MAAA,EAAyC;AACjE,EAAA,OACE,OAAO,MAAA,KAAW,QAAA,IAClB,WAAW,IAAA,IACX,CAAC,MAAM,OAAA,CAAQ,MAAM,CAAA,IACrB,EAAE,UAAU,MAAA,CAAA,IACZ,MAAA,CAAO,QAAQ,MAAM,CAAA,CAAE,MAAM,iBAAiB,CAAA;AAElD;AAOA,SAAS,YAAA,CAAa,QAAgB,OAAA,EAAiC;AACrE,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,WAAW,IAAA,IAAQ,EAAE,UAAU,MAAA,CAAA,EAAS;AACxE,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,MAAO,MAAA,CAAsC,IAAA;AACnD,EAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,MAAA,CAAO,KAAK,MAAM,CAAA,CAAE,WAAW,CAAA,EAAG;AAC/D,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AACzC;AAYO,SAAS,YAAA,CAAa,SAA4B,OAAA,EAAsC;AAC7F,EAAA,MAAM,SAAA,GAAY,EAAE,OAAA,EAAS,QAAA,EAAU,EAAC,EAAE;AAC1C,EAAA,IAAI,CAAC,QAAQ,OAAA,CAAQ,OAAA,CAAQ,MAAM,GAAA,CAAI,SAAA,CAAU,cAAc,CAAA,EAAG;AAChE,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,CAAI,CAAC,WAAW,YAAA,CAAa,MAAA,EAAQ,OAAO,CAAC,CAAA;AACrE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,EAAG,KAAA,KAAU,CAAC,gBAAA,CAAiB,OAAA,CAAQ,KAAK,CAAC,CAAC,CAAA;AAC3E,EAAA,IAAI,KAAK,MAAA,KAAW,CAAA,IAAK,IAAA,CAAK,MAAA,KAAW,QAAQ,MAAA,EAAQ;AACvD,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,WAAW,OAAA,CAAQ,OAAA;AAAA,IAAQ,CAAC,WAChC,gBAAA,CAAiB,MAAM,IAAK,MAAA,CAAO,QAAA,IAAY,EAAC,GAAK;AAAC,GACxD;AACA,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,QAAA,EAAS;AACnC;;"}
1
+ {"version":3,"file":"presence-members.mjs","sources":["../../../../src/application/transform/schema/presence-members.ts"],"sourcesContent":["import type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { FIX } from \"../../../domain/output-fixes.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `allof-required` fix (ADR-021, roadmap R6). An `allOf` member such as `{ required: [name] }`\n * or `{ type: object }` says nothing about the shape of the object; it only asks that keys are\n * present. Typed as an object of its own, it adds `& Record<string, never>` or `& unknown`. With\n * the fix, such members are left out and their keys are made required in the other members, the\n * same way the parent's `required` is (upstream #1474, #1520, #2165).\n */\n\n/**\n * Keywords that do not change the shape: `type: object`, `required`, and annotations that the\n * generator does not read on an `allOf` member. `default`, `readOnly` and `writeOnly` are left out:\n * they change types elsewhere.\n */\nconst PRESENCE_KEYWORDS: ReadonlySet<string> = new Set([\n \"$comment\",\n \"deprecated\",\n \"description\",\n \"example\",\n \"examples\",\n \"required\",\n \"title\",\n \"type\",\n]);\n\nconst EXTENSION_PREFIX = \"x-\";\nconst OBJECT_TYPE = \"object\";\n\nfunction isStringList(value: unknown): value is readonly string[] {\n return Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\nfunction isPresenceKeyword([key, value]: readonly [string, unknown]): boolean {\n if (key === \"type\") {\n return value === OBJECT_TYPE;\n }\n if (key === \"required\") {\n return isStringList(value);\n }\n return PRESENCE_KEYWORDS.has(key) || key.startsWith(EXTENSION_PREFIX);\n}\n\nfunction isPresenceObject(schema: unknown): schema is SchemaObject {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n !Array.isArray(schema) &&\n !(\"$ref\" in schema) &&\n Object.entries(schema).every(isPresenceKeyword)\n );\n}\n\n/**\n * The schema a member stands for: itself, or the target of a `$ref` with no sibling keywords. The\n * discriminator scan has already added the discriminator property to a mapped target, so such a\n * target is never presence-only.\n */\nfunction memberSchema(member: Schema, request: SchemaRequest): unknown {\n if (typeof member !== \"object\" || member === null || !(\"$ref\" in member)) {\n return member;\n }\n const ref = (member as { readonly $ref: unknown }).$ref;\n if (typeof ref !== \"string\" || Object.keys(member).length !== 1) {\n return undefined;\n }\n return request.context.refs.resolve(ref);\n}\n\n/** The `allOf` members to type, and the keys the left-out members make required. */\nexport interface AllOfMembers {\n readonly members: readonly Schema[];\n readonly required: readonly string[];\n}\n\n/**\n * The members of `allOf` with presence-only ones left out, when the fix is on and another member\n * is left to carry the keys; otherwise the members as they are.\n */\nexport function allOfMembers(members: readonly Schema[], request: SchemaRequest): AllOfMembers {\n const unchanged = { members, required: [] };\n if (!request.context.options.fixes.has(FIX.ALLOF_REQUIRED)) {\n return unchanged;\n }\n const schemas = members.map((member) => memberSchema(member, request));\n const kept = members.filter((_, index) => !isPresenceObject(schemas[index]));\n if (kept.length === 0 || kept.length === members.length) {\n return unchanged;\n }\n const required = schemas.flatMap((schema) =>\n isPresenceObject(schema) ? (schema.required ?? []) : [],\n );\n return { members: kept, required };\n}\n"],"names":[],"mappings":";;AAiBA,MAAM,iBAAA,uBAA6C,GAAA,CAAI;AAAA,EACrD,UAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,MAAM,gBAAA,GAAmB,IAAA;AACzB,MAAM,WAAA,GAAc,QAAA;AAEpB,SAAS,aAAa,KAAA,EAA4C;AAChE,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,KAAA,CAAM,MAAM,CAAC,KAAA,KAAU,OAAO,KAAA,KAAU,QAAQ,CAAA;AACjF;AAEA,SAAS,iBAAA,CAAkB,CAAC,GAAA,EAAK,KAAK,CAAA,EAAwC;AAC5E,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,OAAO,KAAA,KAAU,WAAA;AAAA,EACnB;AACA,EAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,IAAA,OAAO,aAAa,KAAK,CAAA;AAAA,EAC3B;AACA,EAAA,OAAO,kBAAkB,GAAA,CAAI,GAAG,CAAA,IAAK,GAAA,CAAI,WAAW,gBAAgB,CAAA;AACtE;AAEA,SAAS,iBAAiB,MAAA,EAAyC;AACjE,EAAA,OACE,OAAO,MAAA,KAAW,QAAA,IAClB,WAAW,IAAA,IACX,CAAC,MAAM,OAAA,CAAQ,MAAM,CAAA,IACrB,EAAE,UAAU,MAAA,CAAA,IACZ,MAAA,CAAO,QAAQ,MAAM,CAAA,CAAE,MAAM,iBAAiB,CAAA;AAElD;AAOA,SAAS,YAAA,CAAa,QAAgB,OAAA,EAAiC;AACrE,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,WAAW,IAAA,IAAQ,EAAE,UAAU,MAAA,CAAA,EAAS;AACxE,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,MAAO,MAAA,CAAsC,IAAA;AACnD,EAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,MAAA,CAAO,KAAK,MAAM,CAAA,CAAE,WAAW,CAAA,EAAG;AAC/D,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AACzC;AAYO,SAAS,YAAA,CAAa,SAA4B,OAAA,EAAsC;AAC7F,EAAA,MAAM,SAAA,GAAY,EAAE,OAAA,EAAS,QAAA,EAAU,EAAC,EAAE;AAC1C,EAAA,IAAI,CAAC,QAAQ,OAAA,CAAQ,OAAA,CAAQ,MAAM,GAAA,CAAI,GAAA,CAAI,cAAc,CAAA,EAAG;AAC1D,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,CAAI,CAAC,WAAW,YAAA,CAAa,MAAA,EAAQ,OAAO,CAAC,CAAA;AACrE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,EAAG,KAAA,KAAU,CAAC,gBAAA,CAAiB,OAAA,CAAQ,KAAK,CAAC,CAAC,CAAA;AAC3E,EAAA,IAAI,KAAK,MAAA,KAAW,CAAA,IAAK,IAAA,CAAK,MAAA,KAAW,QAAQ,MAAA,EAAQ;AACvD,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,MAAM,WAAW,OAAA,CAAQ,OAAA;AAAA,IAAQ,CAAC,WAChC,gBAAA,CAAiB,MAAM,IAAK,MAAA,CAAO,QAAA,IAAY,EAAC,GAAK;AAAC,GACxD;AACA,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,QAAA,EAAS;AACnC;;"}
@@ -23,10 +23,10 @@ function requiredKeyLists(schema, variants, request) {
23
23
  return isApplicable ? keyLists : null;
24
24
  }
25
25
  function hasRequiredVariants(schema, variants, request) {
26
- return request.context.options.fixes.has(outputFixes.OutputFix.ANYOF_ONEOF_REQUIRED) && isObjectTyped(schema) && requiredKeyLists(schema, variants, request) !== null;
26
+ return request.context.options.fixes.has(outputFixes.FIX.ANYOF_ONEOF_REQUIRED) && isObjectTyped(schema) && requiredKeyLists(schema, variants, request) !== null;
27
27
  }
28
28
  function requiredVariantsType(previous, schema, variants, request) {
29
- if (!request.context.options.fixes.has(outputFixes.OutputFix.ANYOF_ONEOF_REQUIRED) || previous === null) {
29
+ if (!request.context.options.fixes.has(outputFixes.FIX.ANYOF_ONEOF_REQUIRED) || previous === null) {
30
30
  return null;
31
31
  }
32
32
  const keyLists = isObjectTyped(schema) ? requiredKeyLists(schema, variants, request) : null;
@@ -1 +1 @@
1
- {"version":3,"file":"required-variants.cjs","sources":["../../../../src/application/transform/schema/required-variants.ts"],"sourcesContent":["import type { IrType } from \"../../../domain/ir/nodes.js\";\nimport type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { OutputFix } from \"../../../domain/output-fixes.js\";\nimport { unionOf, withRequiredKeys } from \"../type-combinators.js\";\nimport { isKeptProperty } from \"./object-type.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `anyof-oneof-required` fix. `anyOf: [{ required: [a] }, { required: [b] }]` next to\n * `properties` says which of the properties must be there. Each such variant has no type of its\n * own (`unknown`), so the original gives `Props | unknown`, which is `unknown`. With the fix each\n * variant is the parent with its keys required:\n * `WithRequired<Props, \"a\"> | WithRequired<Props, \"b\">`.\n */\n\n/** Keywords that do not change a value's type: a variant of these and `required` counts. */\nconst ANNOTATION_KEYS: ReadonlySet<string> = new Set([\"required\", \"description\", \"title\"]);\n\n/** The `required` keys of a variant that has nothing else, or null for any other variant. */\nfunction requiredOnlyKeys(variant: Schema): readonly string[] | null {\n if (typeof variant !== \"object\" || variant === null || \"$ref\" in variant) {\n return null;\n }\n const { required } = variant as SchemaObject;\n const isRequiredOnly = Object.keys(variant).every((key) => ANNOTATION_KEYS.has(key));\n return isRequiredOnly && Array.isArray(required) && required.length > 0 ? required : null;\n}\n\n/** Whether the schema's type is an object: no `type`, `object`, or a list with `object`. */\nfunction isObjectTyped(schema: SchemaObject): boolean {\n const { type } = schema;\n return (\n type === undefined || type === \"object\" || (Array.isArray(type) && type.includes(\"object\"))\n );\n}\n\n/** The variants' key lists, or null unless each requires only properties the type keeps. */\nfunction requiredKeyLists(\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): (readonly string[])[] | null {\n const keyLists = variants.map(requiredOnlyKeys);\n // A key of a property the type leaves out (`--exclude-deprecated`) is no key of `WithRequired`.\n const isApplicable =\n keyLists.length > 0 &&\n keyLists.every((keys) => keys?.every((key) => isKeptProperty(schema, key, request)) === true);\n return isApplicable ? (keyLists as (readonly string[])[]) : null;\n}\n\n/** Whether the fix gives `variants` of the schema their keys of its properties. */\nexport function hasRequiredVariants(\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): boolean {\n return (\n request.context.options.fixes.has(OutputFix.ANYOF_ONEOF_REQUIRED) &&\n isObjectTyped(schema) &&\n requiredKeyLists(schema, variants, request) !== null\n );\n}\n\n/**\n * The union of the parent type with each variant's keys required, or null where the fix is off\n * or the variants are not all required-only ones over the parent's own, kept properties. Only an\n * object has the keys. For a `type` list, the `object` member has required them already\n * (`multipleTypes`), so the list is the whole type.\n */\nexport function requiredVariantsType(\n previous: IrType | null,\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): IrType | null {\n if (!request.context.options.fixes.has(OutputFix.ANYOF_ONEOF_REQUIRED) || previous === null) {\n return null;\n }\n const keyLists = isObjectTyped(schema) ? requiredKeyLists(schema, variants, request) : null;\n if (keyLists === null) {\n return null;\n }\n if (Array.isArray(schema.type)) {\n return previous;\n }\n request.context.footer.requireWithRequired();\n return unionOf(keyLists.map((keys) => withRequiredKeys(previous, keys)));\n}\n"],"names":["isKeptProperty","OutputFix","unionOf","withRequiredKeys"],"mappings":";;;;;;AAgBA,MAAM,kCAAuC,IAAI,GAAA,CAAI,CAAC,UAAA,EAAY,aAAA,EAAe,OAAO,CAAC,CAAA;AAGzF,SAAS,iBAAiB,OAAA,EAA2C;AACnE,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,IAAQ,UAAU,OAAA,EAAS;AACxE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AACrB,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ,eAAA,CAAgB,GAAA,CAAI,GAAG,CAAC,CAAA;AACnF,EAAA,OAAO,cAAA,IAAkB,MAAM,OAAA,CAAQ,QAAQ,KAAK,QAAA,CAAS,MAAA,GAAS,IAAI,QAAA,GAAW,IAAA;AACvF;AAGA,SAAS,cAAc,MAAA,EAA+B;AACpD,EAAA,MAAM,EAAE,MAAK,GAAI,MAAA;AACjB,EAAA,OACE,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,QAAA,IAAa,KAAA,CAAM,QAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AAE7F;AAGA,SAAS,gBAAA,CACP,MAAA,EACA,QAAA,EACA,OAAA,EAC8B;AAC9B,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,gBAAgB,CAAA;AAE9C,EAAA,MAAM,eACJ,QAAA,CAAS,MAAA,GAAS,KAClB,QAAA,CAAS,KAAA,CAAM,CAAC,IAAA,KAAS,IAAA,EAAM,KAAA,CAAM,CAAC,QAAQA,yBAAA,CAAe,MAAA,EAAQ,KAAK,OAAO,CAAC,MAAM,IAAI,CAAA;AAC9F,EAAA,OAAO,eAAgB,QAAA,GAAqC,IAAA;AAC9D;AAGO,SAAS,mBAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACS;AACT,EAAA,OACE,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAIC,qBAAA,CAAU,oBAAoB,CAAA,IAChE,aAAA,CAAc,MAAM,CAAA,IACpB,gBAAA,CAAiB,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA,KAAM,IAAA;AAEpD;AAQO,SAAS,oBAAA,CACd,QAAA,EACA,MAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,EAAA,IAAI,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAIA,qBAAA,CAAU,oBAAoB,CAAA,IAAK,QAAA,KAAa,IAAA,EAAM;AAC3F,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAW,cAAc,MAAM,CAAA,GAAI,iBAAiB,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA,GAAI,IAAA;AACvF,EAAA,IAAI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,EAAG;AAC9B,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,mBAAA,EAAoB;AAC3C,EAAA,OAAOC,uBAAA,CAAQ,SAAS,GAAA,CAAI,CAAC,SAASC,gCAAA,CAAiB,QAAA,EAAU,IAAI,CAAC,CAAC,CAAA;AACzE;;;"}
1
+ {"version":3,"file":"required-variants.cjs","sources":["../../../../src/application/transform/schema/required-variants.ts"],"sourcesContent":["import type { IrType } from \"../../../domain/ir/nodes.js\";\nimport type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { FIX } from \"../../../domain/output-fixes.js\";\nimport { unionOf, withRequiredKeys } from \"../type-combinators.js\";\nimport { isKeptProperty } from \"./object-type.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `anyof-oneof-required` fix. `anyOf: [{ required: [a] }, { required: [b] }]` next to\n * `properties` says which of the properties must be there. Each such variant has no type of its\n * own (`unknown`), so the original gives `Props | unknown`, which is `unknown`. With the fix each\n * variant is the parent with its keys required:\n * `WithRequired<Props, \"a\"> | WithRequired<Props, \"b\">`.\n */\n\n/** Keywords that do not change a value's type: a variant of these and `required` counts. */\nconst ANNOTATION_KEYS: ReadonlySet<string> = new Set([\"required\", \"description\", \"title\"]);\n\n/** The `required` keys of a variant that has nothing else, or null for any other variant. */\nfunction requiredOnlyKeys(variant: Schema): readonly string[] | null {\n if (typeof variant !== \"object\" || variant === null || \"$ref\" in variant) {\n return null;\n }\n const { required } = variant as SchemaObject;\n const isRequiredOnly = Object.keys(variant).every((key) => ANNOTATION_KEYS.has(key));\n return isRequiredOnly && Array.isArray(required) && required.length > 0 ? required : null;\n}\n\n/** Whether the schema's type is an object: no `type`, `object`, or a list with `object`. */\nfunction isObjectTyped(schema: SchemaObject): boolean {\n const { type } = schema;\n return (\n type === undefined || type === \"object\" || (Array.isArray(type) && type.includes(\"object\"))\n );\n}\n\n/** The variants' key lists, or null unless each requires only properties the type keeps. */\nfunction requiredKeyLists(\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): (readonly string[])[] | null {\n const keyLists = variants.map(requiredOnlyKeys);\n // A key of a property the type leaves out (`--exclude-deprecated`) is no key of `WithRequired`.\n const isApplicable =\n keyLists.length > 0 &&\n keyLists.every((keys) => keys?.every((key) => isKeptProperty(schema, key, request)) === true);\n return isApplicable ? (keyLists as (readonly string[])[]) : null;\n}\n\n/** Whether the fix gives `variants` of the schema their keys of its properties. */\nexport function hasRequiredVariants(\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): boolean {\n return (\n request.context.options.fixes.has(FIX.ANYOF_ONEOF_REQUIRED) &&\n isObjectTyped(schema) &&\n requiredKeyLists(schema, variants, request) !== null\n );\n}\n\n/**\n * The union of the parent type with each variant's keys required, or null where the fix is off\n * or the variants are not all required-only ones over the parent's own, kept properties. Only an\n * object has the keys. For a `type` list, the `object` member has required them already\n * (`multipleTypes`), so the list is the whole type.\n */\nexport function requiredVariantsType(\n previous: IrType | null,\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): IrType | null {\n if (!request.context.options.fixes.has(FIX.ANYOF_ONEOF_REQUIRED) || previous === null) {\n return null;\n }\n const keyLists = isObjectTyped(schema) ? requiredKeyLists(schema, variants, request) : null;\n if (keyLists === null) {\n return null;\n }\n if (Array.isArray(schema.type)) {\n return previous;\n }\n request.context.footer.requireWithRequired();\n return unionOf(keyLists.map((keys) => withRequiredKeys(previous, keys)));\n}\n"],"names":["isKeptProperty","FIX","unionOf","withRequiredKeys"],"mappings":";;;;;;AAgBA,MAAM,kCAAuC,IAAI,GAAA,CAAI,CAAC,UAAA,EAAY,aAAA,EAAe,OAAO,CAAC,CAAA;AAGzF,SAAS,iBAAiB,OAAA,EAA2C;AACnE,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,IAAQ,UAAU,OAAA,EAAS;AACxE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AACrB,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ,eAAA,CAAgB,GAAA,CAAI,GAAG,CAAC,CAAA;AACnF,EAAA,OAAO,cAAA,IAAkB,MAAM,OAAA,CAAQ,QAAQ,KAAK,QAAA,CAAS,MAAA,GAAS,IAAI,QAAA,GAAW,IAAA;AACvF;AAGA,SAAS,cAAc,MAAA,EAA+B;AACpD,EAAA,MAAM,EAAE,MAAK,GAAI,MAAA;AACjB,EAAA,OACE,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,QAAA,IAAa,KAAA,CAAM,QAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AAE7F;AAGA,SAAS,gBAAA,CACP,MAAA,EACA,QAAA,EACA,OAAA,EAC8B;AAC9B,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,gBAAgB,CAAA;AAE9C,EAAA,MAAM,eACJ,QAAA,CAAS,MAAA,GAAS,KAClB,QAAA,CAAS,KAAA,CAAM,CAAC,IAAA,KAAS,IAAA,EAAM,KAAA,CAAM,CAAC,QAAQA,yBAAA,CAAe,MAAA,EAAQ,KAAK,OAAO,CAAC,MAAM,IAAI,CAAA;AAC9F,EAAA,OAAO,eAAgB,QAAA,GAAqC,IAAA;AAC9D;AAGO,SAAS,mBAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACS;AACT,EAAA,OACE,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAIC,eAAA,CAAI,oBAAoB,CAAA,IAC1D,aAAA,CAAc,MAAM,CAAA,IACpB,gBAAA,CAAiB,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA,KAAM,IAAA;AAEpD;AAQO,SAAS,oBAAA,CACd,QAAA,EACA,MAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,EAAA,IAAI,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAIA,eAAA,CAAI,oBAAoB,CAAA,IAAK,QAAA,KAAa,IAAA,EAAM;AACrF,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAW,cAAc,MAAM,CAAA,GAAI,iBAAiB,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA,GAAI,IAAA;AACvF,EAAA,IAAI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,EAAG;AAC9B,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,mBAAA,EAAoB;AAC3C,EAAA,OAAOC,uBAAA,CAAQ,SAAS,GAAA,CAAI,CAAC,SAASC,gCAAA,CAAiB,QAAA,EAAU,IAAI,CAAC,CAAC,CAAA;AACzE;;;"}
@@ -1,4 +1,4 @@
1
- import { OutputFix } from '../../../domain/output-fixes.mjs';
1
+ import { FIX } from '../../../domain/output-fixes.mjs';
2
2
  import { unionOf, withRequiredKeys } from '../type-combinators.mjs';
3
3
  import { isKeptProperty } from './object-type.mjs';
4
4
 
@@ -21,10 +21,10 @@ function requiredKeyLists(schema, variants, request) {
21
21
  return isApplicable ? keyLists : null;
22
22
  }
23
23
  function hasRequiredVariants(schema, variants, request) {
24
- return request.context.options.fixes.has(OutputFix.ANYOF_ONEOF_REQUIRED) && isObjectTyped(schema) && requiredKeyLists(schema, variants, request) !== null;
24
+ return request.context.options.fixes.has(FIX.ANYOF_ONEOF_REQUIRED) && isObjectTyped(schema) && requiredKeyLists(schema, variants, request) !== null;
25
25
  }
26
26
  function requiredVariantsType(previous, schema, variants, request) {
27
- if (!request.context.options.fixes.has(OutputFix.ANYOF_ONEOF_REQUIRED) || previous === null) {
27
+ if (!request.context.options.fixes.has(FIX.ANYOF_ONEOF_REQUIRED) || previous === null) {
28
28
  return null;
29
29
  }
30
30
  const keyLists = isObjectTyped(schema) ? requiredKeyLists(schema, variants, request) : null;
@@ -1 +1 @@
1
- {"version":3,"file":"required-variants.mjs","sources":["../../../../src/application/transform/schema/required-variants.ts"],"sourcesContent":["import type { IrType } from \"../../../domain/ir/nodes.js\";\nimport type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { OutputFix } from \"../../../domain/output-fixes.js\";\nimport { unionOf, withRequiredKeys } from \"../type-combinators.js\";\nimport { isKeptProperty } from \"./object-type.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `anyof-oneof-required` fix. `anyOf: [{ required: [a] }, { required: [b] }]` next to\n * `properties` says which of the properties must be there. Each such variant has no type of its\n * own (`unknown`), so the original gives `Props | unknown`, which is `unknown`. With the fix each\n * variant is the parent with its keys required:\n * `WithRequired<Props, \"a\"> | WithRequired<Props, \"b\">`.\n */\n\n/** Keywords that do not change a value's type: a variant of these and `required` counts. */\nconst ANNOTATION_KEYS: ReadonlySet<string> = new Set([\"required\", \"description\", \"title\"]);\n\n/** The `required` keys of a variant that has nothing else, or null for any other variant. */\nfunction requiredOnlyKeys(variant: Schema): readonly string[] | null {\n if (typeof variant !== \"object\" || variant === null || \"$ref\" in variant) {\n return null;\n }\n const { required } = variant as SchemaObject;\n const isRequiredOnly = Object.keys(variant).every((key) => ANNOTATION_KEYS.has(key));\n return isRequiredOnly && Array.isArray(required) && required.length > 0 ? required : null;\n}\n\n/** Whether the schema's type is an object: no `type`, `object`, or a list with `object`. */\nfunction isObjectTyped(schema: SchemaObject): boolean {\n const { type } = schema;\n return (\n type === undefined || type === \"object\" || (Array.isArray(type) && type.includes(\"object\"))\n );\n}\n\n/** The variants' key lists, or null unless each requires only properties the type keeps. */\nfunction requiredKeyLists(\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): (readonly string[])[] | null {\n const keyLists = variants.map(requiredOnlyKeys);\n // A key of a property the type leaves out (`--exclude-deprecated`) is no key of `WithRequired`.\n const isApplicable =\n keyLists.length > 0 &&\n keyLists.every((keys) => keys?.every((key) => isKeptProperty(schema, key, request)) === true);\n return isApplicable ? (keyLists as (readonly string[])[]) : null;\n}\n\n/** Whether the fix gives `variants` of the schema their keys of its properties. */\nexport function hasRequiredVariants(\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): boolean {\n return (\n request.context.options.fixes.has(OutputFix.ANYOF_ONEOF_REQUIRED) &&\n isObjectTyped(schema) &&\n requiredKeyLists(schema, variants, request) !== null\n );\n}\n\n/**\n * The union of the parent type with each variant's keys required, or null where the fix is off\n * or the variants are not all required-only ones over the parent's own, kept properties. Only an\n * object has the keys. For a `type` list, the `object` member has required them already\n * (`multipleTypes`), so the list is the whole type.\n */\nexport function requiredVariantsType(\n previous: IrType | null,\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): IrType | null {\n if (!request.context.options.fixes.has(OutputFix.ANYOF_ONEOF_REQUIRED) || previous === null) {\n return null;\n }\n const keyLists = isObjectTyped(schema) ? requiredKeyLists(schema, variants, request) : null;\n if (keyLists === null) {\n return null;\n }\n if (Array.isArray(schema.type)) {\n return previous;\n }\n request.context.footer.requireWithRequired();\n return unionOf(keyLists.map((keys) => withRequiredKeys(previous, keys)));\n}\n"],"names":[],"mappings":";;;;AAgBA,MAAM,kCAAuC,IAAI,GAAA,CAAI,CAAC,UAAA,EAAY,aAAA,EAAe,OAAO,CAAC,CAAA;AAGzF,SAAS,iBAAiB,OAAA,EAA2C;AACnE,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,IAAQ,UAAU,OAAA,EAAS;AACxE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AACrB,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ,eAAA,CAAgB,GAAA,CAAI,GAAG,CAAC,CAAA;AACnF,EAAA,OAAO,cAAA,IAAkB,MAAM,OAAA,CAAQ,QAAQ,KAAK,QAAA,CAAS,MAAA,GAAS,IAAI,QAAA,GAAW,IAAA;AACvF;AAGA,SAAS,cAAc,MAAA,EAA+B;AACpD,EAAA,MAAM,EAAE,MAAK,GAAI,MAAA;AACjB,EAAA,OACE,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,QAAA,IAAa,KAAA,CAAM,QAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AAE7F;AAGA,SAAS,gBAAA,CACP,MAAA,EACA,QAAA,EACA,OAAA,EAC8B;AAC9B,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,gBAAgB,CAAA;AAE9C,EAAA,MAAM,eACJ,QAAA,CAAS,MAAA,GAAS,KAClB,QAAA,CAAS,KAAA,CAAM,CAAC,IAAA,KAAS,IAAA,EAAM,KAAA,CAAM,CAAC,QAAQ,cAAA,CAAe,MAAA,EAAQ,KAAK,OAAO,CAAC,MAAM,IAAI,CAAA;AAC9F,EAAA,OAAO,eAAgB,QAAA,GAAqC,IAAA;AAC9D;AAGO,SAAS,mBAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACS;AACT,EAAA,OACE,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,SAAA,CAAU,oBAAoB,CAAA,IAChE,aAAA,CAAc,MAAM,CAAA,IACpB,gBAAA,CAAiB,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA,KAAM,IAAA;AAEpD;AAQO,SAAS,oBAAA,CACd,QAAA,EACA,MAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,EAAA,IAAI,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,SAAA,CAAU,oBAAoB,CAAA,IAAK,QAAA,KAAa,IAAA,EAAM;AAC3F,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAW,cAAc,MAAM,CAAA,GAAI,iBAAiB,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA,GAAI,IAAA;AACvF,EAAA,IAAI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,EAAG;AAC9B,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,mBAAA,EAAoB;AAC3C,EAAA,OAAO,OAAA,CAAQ,SAAS,GAAA,CAAI,CAAC,SAAS,gBAAA,CAAiB,QAAA,EAAU,IAAI,CAAC,CAAC,CAAA;AACzE;;"}
1
+ {"version":3,"file":"required-variants.mjs","sources":["../../../../src/application/transform/schema/required-variants.ts"],"sourcesContent":["import type { IrType } from \"../../../domain/ir/nodes.js\";\nimport type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { FIX } from \"../../../domain/output-fixes.js\";\nimport { unionOf, withRequiredKeys } from \"../type-combinators.js\";\nimport { isKeptProperty } from \"./object-type.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `anyof-oneof-required` fix. `anyOf: [{ required: [a] }, { required: [b] }]` next to\n * `properties` says which of the properties must be there. Each such variant has no type of its\n * own (`unknown`), so the original gives `Props | unknown`, which is `unknown`. With the fix each\n * variant is the parent with its keys required:\n * `WithRequired<Props, \"a\"> | WithRequired<Props, \"b\">`.\n */\n\n/** Keywords that do not change a value's type: a variant of these and `required` counts. */\nconst ANNOTATION_KEYS: ReadonlySet<string> = new Set([\"required\", \"description\", \"title\"]);\n\n/** The `required` keys of a variant that has nothing else, or null for any other variant. */\nfunction requiredOnlyKeys(variant: Schema): readonly string[] | null {\n if (typeof variant !== \"object\" || variant === null || \"$ref\" in variant) {\n return null;\n }\n const { required } = variant as SchemaObject;\n const isRequiredOnly = Object.keys(variant).every((key) => ANNOTATION_KEYS.has(key));\n return isRequiredOnly && Array.isArray(required) && required.length > 0 ? required : null;\n}\n\n/** Whether the schema's type is an object: no `type`, `object`, or a list with `object`. */\nfunction isObjectTyped(schema: SchemaObject): boolean {\n const { type } = schema;\n return (\n type === undefined || type === \"object\" || (Array.isArray(type) && type.includes(\"object\"))\n );\n}\n\n/** The variants' key lists, or null unless each requires only properties the type keeps. */\nfunction requiredKeyLists(\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): (readonly string[])[] | null {\n const keyLists = variants.map(requiredOnlyKeys);\n // A key of a property the type leaves out (`--exclude-deprecated`) is no key of `WithRequired`.\n const isApplicable =\n keyLists.length > 0 &&\n keyLists.every((keys) => keys?.every((key) => isKeptProperty(schema, key, request)) === true);\n return isApplicable ? (keyLists as (readonly string[])[]) : null;\n}\n\n/** Whether the fix gives `variants` of the schema their keys of its properties. */\nexport function hasRequiredVariants(\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): boolean {\n return (\n request.context.options.fixes.has(FIX.ANYOF_ONEOF_REQUIRED) &&\n isObjectTyped(schema) &&\n requiredKeyLists(schema, variants, request) !== null\n );\n}\n\n/**\n * The union of the parent type with each variant's keys required, or null where the fix is off\n * or the variants are not all required-only ones over the parent's own, kept properties. Only an\n * object has the keys. For a `type` list, the `object` member has required them already\n * (`multipleTypes`), so the list is the whole type.\n */\nexport function requiredVariantsType(\n previous: IrType | null,\n schema: SchemaObject,\n variants: readonly Schema[],\n request: SchemaRequest,\n): IrType | null {\n if (!request.context.options.fixes.has(FIX.ANYOF_ONEOF_REQUIRED) || previous === null) {\n return null;\n }\n const keyLists = isObjectTyped(schema) ? requiredKeyLists(schema, variants, request) : null;\n if (keyLists === null) {\n return null;\n }\n if (Array.isArray(schema.type)) {\n return previous;\n }\n request.context.footer.requireWithRequired();\n return unionOf(keyLists.map((keys) => withRequiredKeys(previous, keys)));\n}\n"],"names":[],"mappings":";;;;AAgBA,MAAM,kCAAuC,IAAI,GAAA,CAAI,CAAC,UAAA,EAAY,aAAA,EAAe,OAAO,CAAC,CAAA;AAGzF,SAAS,iBAAiB,OAAA,EAA2C;AACnE,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,IAAQ,UAAU,OAAA,EAAS;AACxE,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AACrB,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ,eAAA,CAAgB,GAAA,CAAI,GAAG,CAAC,CAAA;AACnF,EAAA,OAAO,cAAA,IAAkB,MAAM,OAAA,CAAQ,QAAQ,KAAK,QAAA,CAAS,MAAA,GAAS,IAAI,QAAA,GAAW,IAAA;AACvF;AAGA,SAAS,cAAc,MAAA,EAA+B;AACpD,EAAA,MAAM,EAAE,MAAK,GAAI,MAAA;AACjB,EAAA,OACE,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,QAAA,IAAa,KAAA,CAAM,QAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AAE7F;AAGA,SAAS,gBAAA,CACP,MAAA,EACA,QAAA,EACA,OAAA,EAC8B;AAC9B,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,gBAAgB,CAAA;AAE9C,EAAA,MAAM,eACJ,QAAA,CAAS,MAAA,GAAS,KAClB,QAAA,CAAS,KAAA,CAAM,CAAC,IAAA,KAAS,IAAA,EAAM,KAAA,CAAM,CAAC,QAAQ,cAAA,CAAe,MAAA,EAAQ,KAAK,OAAO,CAAC,MAAM,IAAI,CAAA;AAC9F,EAAA,OAAO,eAAgB,QAAA,GAAqC,IAAA;AAC9D;AAGO,SAAS,mBAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACS;AACT,EAAA,OACE,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,GAAA,CAAI,oBAAoB,CAAA,IAC1D,aAAA,CAAc,MAAM,CAAA,IACpB,gBAAA,CAAiB,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA,KAAM,IAAA;AAEpD;AAQO,SAAS,oBAAA,CACd,QAAA,EACA,MAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,EAAA,IAAI,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,GAAA,CAAI,oBAAoB,CAAA,IAAK,QAAA,KAAa,IAAA,EAAM;AACrF,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAW,cAAc,MAAM,CAAA,GAAI,iBAAiB,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA,GAAI,IAAA;AACvF,EAAA,IAAI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,EAAG;AAC9B,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,mBAAA,EAAoB;AAC3C,EAAA,OAAO,OAAA,CAAQ,SAAS,GAAA,CAAI,CAAC,SAAS,gBAAA,CAAiB,QAAA,EAAU,IAAI,CAAC,CAAC,CAAA;AACzE;;"}
@@ -8,7 +8,7 @@ const typeCombinators = require('../type-combinators.cjs');
8
8
 
9
9
  function unevaluatedSchemaOf(schema, request) {
10
10
  const { unevaluatedProperties } = schema;
11
- if (!request.context.options.fixes.has(outputFixes.OutputFix.UNEVALUATED_PROPERTIES) || unevaluatedProperties === void 0 || unevaluatedProperties === false || schema.additionalProperties !== void 0) {
11
+ if (!request.context.options.fixes.has(outputFixes.FIX.UNEVALUATED_PROPERTIES) || unevaluatedProperties === void 0 || unevaluatedProperties === false || schema.additionalProperties !== void 0) {
12
12
  return null;
13
13
  }
14
14
  return schema.type === void 0 || schema.type === "object" ? unevaluatedProperties : null;
@@ -1 +1 @@
1
- {"version":3,"file":"unevaluated-properties.cjs","sources":["../../../../src/application/transform/schema/unevaluated-properties.ts"],"sourcesContent":["import {\n irKeyword,\n irObject,\n irReference,\n irStringIndexSignature,\n} from \"../../../domain/ir/constructors.js\";\nimport type { IrMember, IrType } from \"../../../domain/ir/nodes.js\";\nimport type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { OutputFix } from \"../../../domain/output-fixes.js\";\nimport { HELPER_TYPES } from \"../helper-types.js\";\nimport { UNKNOWN_TYPE } from \"../shared-types.js\";\nimport { unionOf } from \"../type-combinators.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `unevaluated-properties` fix (ADR-021, roadmap R11; upstream #2839, #2880). Without it\n * `unevaluatedProperties` is ignored, so its value type is lost and an object with only that\n * keyword is `Record<string, never>`. With it the composed type is intersected with an index\n * signature, as `additionalProperties` gives: every key that no other keyword declares has the\n * `unevaluatedProperties` type. TypeScript checks that index signature against every key of a\n * value, declared ones included, so its type also holds the types of the declared properties\n * (of this schema and of its `allOf`, `anyOf` and `oneOf` members); otherwise a valid value would\n * not be assignable. `false` adds nothing, like `additionalProperties: false`: TypeScript has no\n * closed object type.\n */\n\n/**\n * Whether `unevaluatedProperties` applies. It types the keys left over at this level, so it\n * does nothing next to `additionalProperties` (which already types them all), and only an object\n * schema has keys. A `type` list is typed one listed type at a time, so its object gets it.\n */\nfunction unevaluatedSchemaOf(schema: SchemaObject, request: SchemaRequest): Schema | null {\n const { unevaluatedProperties } = schema;\n if (\n !request.context.options.fixes.has(OutputFix.UNEVALUATED_PROPERTIES) ||\n unevaluatedProperties === undefined ||\n unevaluatedProperties === false ||\n schema.additionalProperties !== undefined\n ) {\n return null;\n }\n return schema.type === undefined || schema.type === \"object\" ? unevaluatedProperties : null;\n}\n\nfunction isAnySchema(schema: Schema): boolean {\n return schema === true || (typeof schema === \"object\" && Object.keys(schema).length === 0);\n}\n\nfunction memberValueTypes(member: IrMember): IrType[] {\n if (member.kind === \"indexSignature\") {\n return [member.type];\n }\n return member.isOptional ? [member.type, irKeyword(\"undefined\")] : [member.type];\n}\n\n/**\n * The value types a key of the composed type can have, read from its IR: the members of object\n * types, through unions and intersections. A reference (a `$ref`, `Omit`, `WithRequired`) or a raw\n * type is read with `PropertyValues`. Primitives, literals and arrays declare no keys.\n */\nfunction declaredValueTypes(type: IrType, request: SchemaRequest): IrType[] {\n switch (type.kind) {\n case \"object\":\n return type.members.flatMap(memberValueTypes);\n case \"union\":\n case \"intersection\":\n return type.types.flatMap((member) => declaredValueTypes(member, request));\n case \"reference\":\n case \"indexedAccess\":\n case \"raw\":\n request.context.footer.requirePropertyValues();\n return [irReference(HELPER_TYPES.propertyValues.name, [type])];\n case \"keyword\":\n case \"stringLiteral\":\n case \"numberLiteral\":\n case \"booleanLiteral\":\n case \"array\":\n case \"tuple\":\n case \"readonly\":\n return [];\n }\n}\n\n/**\n * The index signature object for `unevaluatedProperties`, given the composed type of the other\n * keywords (null when there is none). Null when the fix is off or the keyword does not apply.\n */\nexport function unevaluatedPropertiesType(\n schema: SchemaObject,\n composed: IrType | null,\n request: SchemaRequest,\n): IrType | null {\n const unevaluated = unevaluatedSchemaOf(schema, request);\n if (unevaluated === null) {\n return null;\n }\n const valueTypes = isAnySchema(unevaluated)\n ? [UNKNOWN_TYPE]\n : [\n request.transformNested(unevaluated, request.location, true),\n ...(composed === null ? [] : declaredValueTypes(composed, request)),\n ];\n const { immutable } = request.context.options;\n return irObject([irStringIndexSignature(\"key\", unionOf(valueTypes), immutable)]);\n}\n"],"names":["OutputFix","irKeyword","irReference","HELPER_TYPES","UNKNOWN_TYPE","irObject","irStringIndexSignature","unionOf"],"mappings":";;;;;;;;AA+BA,SAAS,mBAAA,CAAoB,QAAsB,OAAA,EAAuC;AACxF,EAAA,MAAM,EAAE,uBAAsB,GAAI,MAAA;AAClC,EAAA,IACE,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,MAAM,GAAA,CAAIA,qBAAA,CAAU,sBAAsB,CAAA,IACnE,0BAA0B,MAAA,IAC1B,qBAAA,KAA0B,KAAA,IAC1B,MAAA,CAAO,yBAAyB,MAAA,EAChC;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAO,IAAA,KAAS,MAAA,IAAa,MAAA,CAAO,IAAA,KAAS,WAAW,qBAAA,GAAwB,IAAA;AACzF;AAEA,SAAS,YAAY,MAAA,EAAyB;AAC5C,EAAA,OAAO,MAAA,KAAW,QAAS,OAAO,MAAA,KAAW,YAAY,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA;AAC1F;AAEA,SAAS,iBAAiB,MAAA,EAA4B;AACpD,EAAA,IAAI,MAAA,CAAO,SAAS,gBAAA,EAAkB;AACpC,IAAA,OAAO,CAAC,OAAO,IAAI,CAAA;AAAA,EACrB;AACA,EAAA,OAAO,MAAA,CAAO,UAAA,GAAa,CAAC,MAAA,CAAO,IAAA,EAAMC,sBAAA,CAAU,WAAW,CAAC,CAAA,GAAI,CAAC,MAAA,CAAO,IAAI,CAAA;AACjF;AAOA,SAAS,kBAAA,CAAmB,MAAc,OAAA,EAAkC;AAC1E,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,gBAAgB,CAAA;AAAA,IAC9C,KAAK,OAAA;AAAA,IACL,KAAK,cAAA;AACH,MAAA,OAAO,IAAA,CAAK,MAAM,OAAA,CAAQ,CAAC,WAAW,kBAAA,CAAmB,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,IAC3E,KAAK,WAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,KAAA;AACH,MAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,qBAAA,EAAsB;AAC7C,MAAA,OAAO,CAACC,yBAAYC,wBAAA,CAAa,cAAA,CAAe,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AAAA,IAC/D,KAAK,SAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,gBAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,EAAC;AAAA;AAEd;AAMO,SAAS,yBAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,WAAA,GAAc,mBAAA,CAAoB,MAAA,EAAQ,OAAO,CAAA;AACvD,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAa,WAAA,CAAY,WAAW,CAAA,GACtC,CAACC,wBAAY,CAAA,GACb;AAAA,IACE,OAAA,CAAQ,eAAA,CAAgB,WAAA,EAAa,OAAA,CAAQ,UAAU,IAAI,CAAA;AAAA,IAC3D,GAAI,QAAA,KAAa,IAAA,GAAO,EAAC,GAAI,kBAAA,CAAmB,UAAU,OAAO;AAAA,GACnE;AACJ,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,OAAA,CAAQ,OAAA,CAAQ,OAAA;AACtC,EAAA,OAAOC,qBAAA,CAAS,CAACC,mCAAA,CAAuB,KAAA,EAAOC,wBAAQ,UAAU,CAAA,EAAG,SAAS,CAAC,CAAC,CAAA;AACjF;;"}
1
+ {"version":3,"file":"unevaluated-properties.cjs","sources":["../../../../src/application/transform/schema/unevaluated-properties.ts"],"sourcesContent":["import {\n irKeyword,\n irObject,\n irReference,\n irStringIndexSignature,\n} from \"../../../domain/ir/constructors.js\";\nimport type { IrMember, IrType } from \"../../../domain/ir/nodes.js\";\nimport type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { FIX } from \"../../../domain/output-fixes.js\";\nimport { HELPER_TYPES } from \"../helper-types.js\";\nimport { UNKNOWN_TYPE } from \"../shared-types.js\";\nimport { unionOf } from \"../type-combinators.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `unevaluated-properties` fix (ADR-021, roadmap R11; upstream #2839, #2880). Without it\n * `unevaluatedProperties` is ignored, so its value type is lost and an object with only that\n * keyword is `Record<string, never>`. With it the composed type is intersected with an index\n * signature, as `additionalProperties` gives: every key that no other keyword declares has the\n * `unevaluatedProperties` type. TypeScript checks that index signature against every key of a\n * value, declared ones included, so its type also holds the types of the declared properties\n * (of this schema and of its `allOf`, `anyOf` and `oneOf` members); otherwise a valid value would\n * not be assignable. `false` adds nothing, like `additionalProperties: false`: TypeScript has no\n * closed object type.\n */\n\n/**\n * Whether `unevaluatedProperties` applies. It types the keys left over at this level, so it\n * does nothing next to `additionalProperties` (which already types them all), and only an object\n * schema has keys. A `type` list is typed one listed type at a time, so its object gets it.\n */\nfunction unevaluatedSchemaOf(schema: SchemaObject, request: SchemaRequest): Schema | null {\n const { unevaluatedProperties } = schema;\n if (\n !request.context.options.fixes.has(FIX.UNEVALUATED_PROPERTIES) ||\n unevaluatedProperties === undefined ||\n unevaluatedProperties === false ||\n schema.additionalProperties !== undefined\n ) {\n return null;\n }\n return schema.type === undefined || schema.type === \"object\" ? unevaluatedProperties : null;\n}\n\nfunction isAnySchema(schema: Schema): boolean {\n return schema === true || (typeof schema === \"object\" && Object.keys(schema).length === 0);\n}\n\nfunction memberValueTypes(member: IrMember): IrType[] {\n if (member.kind === \"indexSignature\") {\n return [member.type];\n }\n return member.isOptional ? [member.type, irKeyword(\"undefined\")] : [member.type];\n}\n\n/**\n * The value types a key of the composed type can have, read from its IR: the members of object\n * types, through unions and intersections. A reference (a `$ref`, `Omit`, `WithRequired`) or a raw\n * type is read with `PropertyValues`. Primitives, literals and arrays declare no keys.\n */\nfunction declaredValueTypes(type: IrType, request: SchemaRequest): IrType[] {\n switch (type.kind) {\n case \"object\":\n return type.members.flatMap(memberValueTypes);\n case \"union\":\n case \"intersection\":\n return type.types.flatMap((member) => declaredValueTypes(member, request));\n case \"reference\":\n case \"indexedAccess\":\n case \"raw\":\n request.context.footer.requirePropertyValues();\n return [irReference(HELPER_TYPES.propertyValues.name, [type])];\n case \"keyword\":\n case \"stringLiteral\":\n case \"numberLiteral\":\n case \"booleanLiteral\":\n case \"array\":\n case \"tuple\":\n case \"readonly\":\n return [];\n }\n}\n\n/**\n * The index signature object for `unevaluatedProperties`, given the composed type of the other\n * keywords (null when there is none). Null when the fix is off or the keyword does not apply.\n */\nexport function unevaluatedPropertiesType(\n schema: SchemaObject,\n composed: IrType | null,\n request: SchemaRequest,\n): IrType | null {\n const unevaluated = unevaluatedSchemaOf(schema, request);\n if (unevaluated === null) {\n return null;\n }\n const valueTypes = isAnySchema(unevaluated)\n ? [UNKNOWN_TYPE]\n : [\n request.transformNested(unevaluated, request.location, true),\n ...(composed === null ? [] : declaredValueTypes(composed, request)),\n ];\n const { immutable } = request.context.options;\n return irObject([irStringIndexSignature(\"key\", unionOf(valueTypes), immutable)]);\n}\n"],"names":["FIX","irKeyword","irReference","HELPER_TYPES","UNKNOWN_TYPE","irObject","irStringIndexSignature","unionOf"],"mappings":";;;;;;;;AA+BA,SAAS,mBAAA,CAAoB,QAAsB,OAAA,EAAuC;AACxF,EAAA,MAAM,EAAE,uBAAsB,GAAI,MAAA;AAClC,EAAA,IACE,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,MAAM,GAAA,CAAIA,eAAA,CAAI,sBAAsB,CAAA,IAC7D,0BAA0B,MAAA,IAC1B,qBAAA,KAA0B,KAAA,IAC1B,MAAA,CAAO,yBAAyB,MAAA,EAChC;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAO,IAAA,KAAS,MAAA,IAAa,MAAA,CAAO,IAAA,KAAS,WAAW,qBAAA,GAAwB,IAAA;AACzF;AAEA,SAAS,YAAY,MAAA,EAAyB;AAC5C,EAAA,OAAO,MAAA,KAAW,QAAS,OAAO,MAAA,KAAW,YAAY,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA;AAC1F;AAEA,SAAS,iBAAiB,MAAA,EAA4B;AACpD,EAAA,IAAI,MAAA,CAAO,SAAS,gBAAA,EAAkB;AACpC,IAAA,OAAO,CAAC,OAAO,IAAI,CAAA;AAAA,EACrB;AACA,EAAA,OAAO,MAAA,CAAO,UAAA,GAAa,CAAC,MAAA,CAAO,IAAA,EAAMC,sBAAA,CAAU,WAAW,CAAC,CAAA,GAAI,CAAC,MAAA,CAAO,IAAI,CAAA;AACjF;AAOA,SAAS,kBAAA,CAAmB,MAAc,OAAA,EAAkC;AAC1E,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,gBAAgB,CAAA;AAAA,IAC9C,KAAK,OAAA;AAAA,IACL,KAAK,cAAA;AACH,MAAA,OAAO,IAAA,CAAK,MAAM,OAAA,CAAQ,CAAC,WAAW,kBAAA,CAAmB,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,IAC3E,KAAK,WAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,KAAA;AACH,MAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,qBAAA,EAAsB;AAC7C,MAAA,OAAO,CAACC,yBAAYC,wBAAA,CAAa,cAAA,CAAe,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AAAA,IAC/D,KAAK,SAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,gBAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,EAAC;AAAA;AAEd;AAMO,SAAS,yBAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,WAAA,GAAc,mBAAA,CAAoB,MAAA,EAAQ,OAAO,CAAA;AACvD,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAa,WAAA,CAAY,WAAW,CAAA,GACtC,CAACC,wBAAY,CAAA,GACb;AAAA,IACE,OAAA,CAAQ,eAAA,CAAgB,WAAA,EAAa,OAAA,CAAQ,UAAU,IAAI,CAAA;AAAA,IAC3D,GAAI,QAAA,KAAa,IAAA,GAAO,EAAC,GAAI,kBAAA,CAAmB,UAAU,OAAO;AAAA,GACnE;AACJ,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,OAAA,CAAQ,OAAA,CAAQ,OAAA;AACtC,EAAA,OAAOC,qBAAA,CAAS,CAACC,mCAAA,CAAuB,KAAA,EAAOC,wBAAQ,UAAU,CAAA,EAAG,SAAS,CAAC,CAAC,CAAA;AACjF;;"}
@@ -1,12 +1,12 @@
1
1
  import { irObject, irStringIndexSignature, irReference, irKeyword } from '../../../domain/ir/constructors.mjs';
2
- import { OutputFix } from '../../../domain/output-fixes.mjs';
2
+ import { FIX } from '../../../domain/output-fixes.mjs';
3
3
  import { HELPER_TYPES } from '../helper-types.mjs';
4
4
  import { UNKNOWN_TYPE } from '../shared-types.mjs';
5
5
  import { unionOf } from '../type-combinators.mjs';
6
6
 
7
7
  function unevaluatedSchemaOf(schema, request) {
8
8
  const { unevaluatedProperties } = schema;
9
- if (!request.context.options.fixes.has(OutputFix.UNEVALUATED_PROPERTIES) || unevaluatedProperties === void 0 || unevaluatedProperties === false || schema.additionalProperties !== void 0) {
9
+ if (!request.context.options.fixes.has(FIX.UNEVALUATED_PROPERTIES) || unevaluatedProperties === void 0 || unevaluatedProperties === false || schema.additionalProperties !== void 0) {
10
10
  return null;
11
11
  }
12
12
  return schema.type === void 0 || schema.type === "object" ? unevaluatedProperties : null;
@@ -1 +1 @@
1
- {"version":3,"file":"unevaluated-properties.mjs","sources":["../../../../src/application/transform/schema/unevaluated-properties.ts"],"sourcesContent":["import {\n irKeyword,\n irObject,\n irReference,\n irStringIndexSignature,\n} from \"../../../domain/ir/constructors.js\";\nimport type { IrMember, IrType } from \"../../../domain/ir/nodes.js\";\nimport type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { OutputFix } from \"../../../domain/output-fixes.js\";\nimport { HELPER_TYPES } from \"../helper-types.js\";\nimport { UNKNOWN_TYPE } from \"../shared-types.js\";\nimport { unionOf } from \"../type-combinators.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `unevaluated-properties` fix (ADR-021, roadmap R11; upstream #2839, #2880). Without it\n * `unevaluatedProperties` is ignored, so its value type is lost and an object with only that\n * keyword is `Record<string, never>`. With it the composed type is intersected with an index\n * signature, as `additionalProperties` gives: every key that no other keyword declares has the\n * `unevaluatedProperties` type. TypeScript checks that index signature against every key of a\n * value, declared ones included, so its type also holds the types of the declared properties\n * (of this schema and of its `allOf`, `anyOf` and `oneOf` members); otherwise a valid value would\n * not be assignable. `false` adds nothing, like `additionalProperties: false`: TypeScript has no\n * closed object type.\n */\n\n/**\n * Whether `unevaluatedProperties` applies. It types the keys left over at this level, so it\n * does nothing next to `additionalProperties` (which already types them all), and only an object\n * schema has keys. A `type` list is typed one listed type at a time, so its object gets it.\n */\nfunction unevaluatedSchemaOf(schema: SchemaObject, request: SchemaRequest): Schema | null {\n const { unevaluatedProperties } = schema;\n if (\n !request.context.options.fixes.has(OutputFix.UNEVALUATED_PROPERTIES) ||\n unevaluatedProperties === undefined ||\n unevaluatedProperties === false ||\n schema.additionalProperties !== undefined\n ) {\n return null;\n }\n return schema.type === undefined || schema.type === \"object\" ? unevaluatedProperties : null;\n}\n\nfunction isAnySchema(schema: Schema): boolean {\n return schema === true || (typeof schema === \"object\" && Object.keys(schema).length === 0);\n}\n\nfunction memberValueTypes(member: IrMember): IrType[] {\n if (member.kind === \"indexSignature\") {\n return [member.type];\n }\n return member.isOptional ? [member.type, irKeyword(\"undefined\")] : [member.type];\n}\n\n/**\n * The value types a key of the composed type can have, read from its IR: the members of object\n * types, through unions and intersections. A reference (a `$ref`, `Omit`, `WithRequired`) or a raw\n * type is read with `PropertyValues`. Primitives, literals and arrays declare no keys.\n */\nfunction declaredValueTypes(type: IrType, request: SchemaRequest): IrType[] {\n switch (type.kind) {\n case \"object\":\n return type.members.flatMap(memberValueTypes);\n case \"union\":\n case \"intersection\":\n return type.types.flatMap((member) => declaredValueTypes(member, request));\n case \"reference\":\n case \"indexedAccess\":\n case \"raw\":\n request.context.footer.requirePropertyValues();\n return [irReference(HELPER_TYPES.propertyValues.name, [type])];\n case \"keyword\":\n case \"stringLiteral\":\n case \"numberLiteral\":\n case \"booleanLiteral\":\n case \"array\":\n case \"tuple\":\n case \"readonly\":\n return [];\n }\n}\n\n/**\n * The index signature object for `unevaluatedProperties`, given the composed type of the other\n * keywords (null when there is none). Null when the fix is off or the keyword does not apply.\n */\nexport function unevaluatedPropertiesType(\n schema: SchemaObject,\n composed: IrType | null,\n request: SchemaRequest,\n): IrType | null {\n const unevaluated = unevaluatedSchemaOf(schema, request);\n if (unevaluated === null) {\n return null;\n }\n const valueTypes = isAnySchema(unevaluated)\n ? [UNKNOWN_TYPE]\n : [\n request.transformNested(unevaluated, request.location, true),\n ...(composed === null ? [] : declaredValueTypes(composed, request)),\n ];\n const { immutable } = request.context.options;\n return irObject([irStringIndexSignature(\"key\", unionOf(valueTypes), immutable)]);\n}\n"],"names":[],"mappings":";;;;;;AA+BA,SAAS,mBAAA,CAAoB,QAAsB,OAAA,EAAuC;AACxF,EAAA,MAAM,EAAE,uBAAsB,GAAI,MAAA;AAClC,EAAA,IACE,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,MAAM,GAAA,CAAI,SAAA,CAAU,sBAAsB,CAAA,IACnE,0BAA0B,MAAA,IAC1B,qBAAA,KAA0B,KAAA,IAC1B,MAAA,CAAO,yBAAyB,MAAA,EAChC;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAO,IAAA,KAAS,MAAA,IAAa,MAAA,CAAO,IAAA,KAAS,WAAW,qBAAA,GAAwB,IAAA;AACzF;AAEA,SAAS,YAAY,MAAA,EAAyB;AAC5C,EAAA,OAAO,MAAA,KAAW,QAAS,OAAO,MAAA,KAAW,YAAY,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA;AAC1F;AAEA,SAAS,iBAAiB,MAAA,EAA4B;AACpD,EAAA,IAAI,MAAA,CAAO,SAAS,gBAAA,EAAkB;AACpC,IAAA,OAAO,CAAC,OAAO,IAAI,CAAA;AAAA,EACrB;AACA,EAAA,OAAO,MAAA,CAAO,UAAA,GAAa,CAAC,MAAA,CAAO,IAAA,EAAM,SAAA,CAAU,WAAW,CAAC,CAAA,GAAI,CAAC,MAAA,CAAO,IAAI,CAAA;AACjF;AAOA,SAAS,kBAAA,CAAmB,MAAc,OAAA,EAAkC;AAC1E,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,gBAAgB,CAAA;AAAA,IAC9C,KAAK,OAAA;AAAA,IACL,KAAK,cAAA;AACH,MAAA,OAAO,IAAA,CAAK,MAAM,OAAA,CAAQ,CAAC,WAAW,kBAAA,CAAmB,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,IAC3E,KAAK,WAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,KAAA;AACH,MAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,qBAAA,EAAsB;AAC7C,MAAA,OAAO,CAAC,YAAY,YAAA,CAAa,cAAA,CAAe,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AAAA,IAC/D,KAAK,SAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,gBAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,EAAC;AAAA;AAEd;AAMO,SAAS,yBAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,WAAA,GAAc,mBAAA,CAAoB,MAAA,EAAQ,OAAO,CAAA;AACvD,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAa,WAAA,CAAY,WAAW,CAAA,GACtC,CAAC,YAAY,CAAA,GACb;AAAA,IACE,OAAA,CAAQ,eAAA,CAAgB,WAAA,EAAa,OAAA,CAAQ,UAAU,IAAI,CAAA;AAAA,IAC3D,GAAI,QAAA,KAAa,IAAA,GAAO,EAAC,GAAI,kBAAA,CAAmB,UAAU,OAAO;AAAA,GACnE;AACJ,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,OAAA,CAAQ,OAAA,CAAQ,OAAA;AACtC,EAAA,OAAO,QAAA,CAAS,CAAC,sBAAA,CAAuB,KAAA,EAAO,QAAQ,UAAU,CAAA,EAAG,SAAS,CAAC,CAAC,CAAA;AACjF;;"}
1
+ {"version":3,"file":"unevaluated-properties.mjs","sources":["../../../../src/application/transform/schema/unevaluated-properties.ts"],"sourcesContent":["import {\n irKeyword,\n irObject,\n irReference,\n irStringIndexSignature,\n} from \"../../../domain/ir/constructors.js\";\nimport type { IrMember, IrType } from \"../../../domain/ir/nodes.js\";\nimport type { Schema, SchemaObject } from \"../../../domain/openapi/schema-object.js\";\nimport { FIX } from \"../../../domain/output-fixes.js\";\nimport { HELPER_TYPES } from \"../helper-types.js\";\nimport { UNKNOWN_TYPE } from \"../shared-types.js\";\nimport { unionOf } from \"../type-combinators.js\";\nimport type { SchemaRequest } from \"./schema-rule.js\";\n\n/**\n * The `unevaluated-properties` fix (ADR-021, roadmap R11; upstream #2839, #2880). Without it\n * `unevaluatedProperties` is ignored, so its value type is lost and an object with only that\n * keyword is `Record<string, never>`. With it the composed type is intersected with an index\n * signature, as `additionalProperties` gives: every key that no other keyword declares has the\n * `unevaluatedProperties` type. TypeScript checks that index signature against every key of a\n * value, declared ones included, so its type also holds the types of the declared properties\n * (of this schema and of its `allOf`, `anyOf` and `oneOf` members); otherwise a valid value would\n * not be assignable. `false` adds nothing, like `additionalProperties: false`: TypeScript has no\n * closed object type.\n */\n\n/**\n * Whether `unevaluatedProperties` applies. It types the keys left over at this level, so it\n * does nothing next to `additionalProperties` (which already types them all), and only an object\n * schema has keys. A `type` list is typed one listed type at a time, so its object gets it.\n */\nfunction unevaluatedSchemaOf(schema: SchemaObject, request: SchemaRequest): Schema | null {\n const { unevaluatedProperties } = schema;\n if (\n !request.context.options.fixes.has(FIX.UNEVALUATED_PROPERTIES) ||\n unevaluatedProperties === undefined ||\n unevaluatedProperties === false ||\n schema.additionalProperties !== undefined\n ) {\n return null;\n }\n return schema.type === undefined || schema.type === \"object\" ? unevaluatedProperties : null;\n}\n\nfunction isAnySchema(schema: Schema): boolean {\n return schema === true || (typeof schema === \"object\" && Object.keys(schema).length === 0);\n}\n\nfunction memberValueTypes(member: IrMember): IrType[] {\n if (member.kind === \"indexSignature\") {\n return [member.type];\n }\n return member.isOptional ? [member.type, irKeyword(\"undefined\")] : [member.type];\n}\n\n/**\n * The value types a key of the composed type can have, read from its IR: the members of object\n * types, through unions and intersections. A reference (a `$ref`, `Omit`, `WithRequired`) or a raw\n * type is read with `PropertyValues`. Primitives, literals and arrays declare no keys.\n */\nfunction declaredValueTypes(type: IrType, request: SchemaRequest): IrType[] {\n switch (type.kind) {\n case \"object\":\n return type.members.flatMap(memberValueTypes);\n case \"union\":\n case \"intersection\":\n return type.types.flatMap((member) => declaredValueTypes(member, request));\n case \"reference\":\n case \"indexedAccess\":\n case \"raw\":\n request.context.footer.requirePropertyValues();\n return [irReference(HELPER_TYPES.propertyValues.name, [type])];\n case \"keyword\":\n case \"stringLiteral\":\n case \"numberLiteral\":\n case \"booleanLiteral\":\n case \"array\":\n case \"tuple\":\n case \"readonly\":\n return [];\n }\n}\n\n/**\n * The index signature object for `unevaluatedProperties`, given the composed type of the other\n * keywords (null when there is none). Null when the fix is off or the keyword does not apply.\n */\nexport function unevaluatedPropertiesType(\n schema: SchemaObject,\n composed: IrType | null,\n request: SchemaRequest,\n): IrType | null {\n const unevaluated = unevaluatedSchemaOf(schema, request);\n if (unevaluated === null) {\n return null;\n }\n const valueTypes = isAnySchema(unevaluated)\n ? [UNKNOWN_TYPE]\n : [\n request.transformNested(unevaluated, request.location, true),\n ...(composed === null ? [] : declaredValueTypes(composed, request)),\n ];\n const { immutable } = request.context.options;\n return irObject([irStringIndexSignature(\"key\", unionOf(valueTypes), immutable)]);\n}\n"],"names":[],"mappings":";;;;;;AA+BA,SAAS,mBAAA,CAAoB,QAAsB,OAAA,EAAuC;AACxF,EAAA,MAAM,EAAE,uBAAsB,GAAI,MAAA;AAClC,EAAA,IACE,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,MAAM,GAAA,CAAI,GAAA,CAAI,sBAAsB,CAAA,IAC7D,0BAA0B,MAAA,IAC1B,qBAAA,KAA0B,KAAA,IAC1B,MAAA,CAAO,yBAAyB,MAAA,EAChC;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,OAAO,IAAA,KAAS,MAAA,IAAa,MAAA,CAAO,IAAA,KAAS,WAAW,qBAAA,GAAwB,IAAA;AACzF;AAEA,SAAS,YAAY,MAAA,EAAyB;AAC5C,EAAA,OAAO,MAAA,KAAW,QAAS,OAAO,MAAA,KAAW,YAAY,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,KAAW,CAAA;AAC1F;AAEA,SAAS,iBAAiB,MAAA,EAA4B;AACpD,EAAA,IAAI,MAAA,CAAO,SAAS,gBAAA,EAAkB;AACpC,IAAA,OAAO,CAAC,OAAO,IAAI,CAAA;AAAA,EACrB;AACA,EAAA,OAAO,MAAA,CAAO,UAAA,GAAa,CAAC,MAAA,CAAO,IAAA,EAAM,SAAA,CAAU,WAAW,CAAC,CAAA,GAAI,CAAC,MAAA,CAAO,IAAI,CAAA;AACjF;AAOA,SAAS,kBAAA,CAAmB,MAAc,OAAA,EAAkC;AAC1E,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,gBAAgB,CAAA;AAAA,IAC9C,KAAK,OAAA;AAAA,IACL,KAAK,cAAA;AACH,MAAA,OAAO,IAAA,CAAK,MAAM,OAAA,CAAQ,CAAC,WAAW,kBAAA,CAAmB,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,IAC3E,KAAK,WAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,KAAA;AACH,MAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,qBAAA,EAAsB;AAC7C,MAAA,OAAO,CAAC,YAAY,YAAA,CAAa,cAAA,CAAe,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AAAA,IAC/D,KAAK,SAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,eAAA;AAAA,IACL,KAAK,gBAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,EAAC;AAAA;AAEd;AAMO,SAAS,yBAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,WAAA,GAAc,mBAAA,CAAoB,MAAA,EAAQ,OAAO,CAAA;AACvD,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAa,WAAA,CAAY,WAAW,CAAA,GACtC,CAAC,YAAY,CAAA,GACb;AAAA,IACE,OAAA,CAAQ,eAAA,CAAgB,WAAA,EAAa,OAAA,CAAQ,UAAU,IAAI,CAAA;AAAA,IAC3D,GAAI,QAAA,KAAa,IAAA,GAAO,EAAC,GAAI,kBAAA,CAAmB,UAAU,OAAO;AAAA,GACnE;AACJ,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,OAAA,CAAQ,OAAA,CAAQ,OAAA;AACtC,EAAA,OAAO,QAAA,CAAS,CAAC,sBAAA,CAAuB,KAAA,EAAO,QAAQ,UAAU,CAAA,EAAG,SAAS,CAAC,CAAC,CAAA;AACjF;;"}
@@ -15,7 +15,7 @@ const MEMBER_LISTS = [
15
15
  const BULLET_CONTINUATION = "\n ";
16
16
  const ORIGINAL_SCHEMA_COMMENT = { hasMemberDescriptions: false };
17
17
  function schemaCommentOptionsOf(fixes) {
18
- return { hasMemberDescriptions: fixes.has(outputFixes.OutputFix.ANYOF_ONEOF_DESCRIPTIONS) };
18
+ return { hasMemberDescriptions: fixes.has(outputFixes.FIX.ANYOF_ONEOF_DESCRIPTIONS) };
19
19
  }
20
20
  function formatValue(value) {
21
21
  const text = typeof value === "object" ? JSON.stringify(value, null, JSON_INDENT) : value;