openapi-typesafe 1.0.0-rc.1 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -5
- package/dist/adapters/redocly-loader/configured-headers.cjs +32 -0
- package/dist/adapters/redocly-loader/configured-headers.cjs.map +1 -0
- package/dist/adapters/redocly-loader/configured-headers.mjs +30 -0
- package/dist/adapters/redocly-loader/configured-headers.mjs.map +1 -0
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +19 -6
- package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +18 -5
- package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.cjs +37 -4
- package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-access.mjs +37 -4
- package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
- package/dist/adapters/redocly-loader/ref-resolution-check.cjs +191 -0
- package/dist/adapters/redocly-loader/ref-resolution-check.cjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-resolution-check.mjs +189 -0
- package/dist/adapters/redocly-loader/ref-resolution-check.mjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-resolution-steps.cjs +73 -0
- package/dist/adapters/redocly-loader/ref-resolution-steps.cjs.map +1 -0
- package/dist/adapters/redocly-loader/ref-resolution-steps.mjs +60 -0
- package/dist/adapters/redocly-loader/ref-resolution-steps.mjs.map +1 -0
- package/dist/adapters/redocly-loader/remote-fetch.cjs +41 -14
- package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
- package/dist/adapters/redocly-loader/remote-fetch.mjs +40 -14
- package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-load-errors.cjs +23 -5
- package/dist/adapters/redocly-loader/schema-load-errors.cjs.map +1 -1
- package/dist/adapters/redocly-loader/schema-load-errors.mjs +23 -5
- package/dist/adapters/redocly-loader/schema-load-errors.mjs.map +1 -1
- package/dist/adapters/redocly-loader/unsupported-keys.cjs +9 -1
- package/dist/adapters/redocly-loader/unsupported-keys.cjs.map +1 -1
- package/dist/adapters/redocly-loader/unsupported-keys.mjs +9 -1
- package/dist/adapters/redocly-loader/unsupported-keys.mjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.cjs +6 -4
- package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
- package/dist/adapters/terminal-logger/terminal-logger.mjs +6 -4
- package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs +2 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs.map +1 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs +2 -1
- package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs.map +1 -1
- package/dist/adapters/type-ast-bridge/print-typescript.cjs.map +1 -1
- package/dist/adapters/type-ast-bridge/print-typescript.mjs.map +1 -1
- package/dist/api/default-ports.cjs +9 -0
- package/dist/api/default-ports.cjs.map +1 -1
- package/dist/api/default-ports.mjs +8 -1
- package/dist/api/default-ports.mjs.map +1 -1
- package/dist/api/discriminator-patch.cjs +5 -1
- package/dist/api/discriminator-patch.cjs.map +1 -1
- package/dist/api/discriminator-patch.mjs +5 -1
- package/dist/api/discriminator-patch.mjs.map +1 -1
- package/dist/api/document-refs.cjs +15 -12
- package/dist/api/document-refs.cjs.map +1 -1
- package/dist/api/document-refs.mjs +15 -12
- package/dist/api/document-refs.mjs.map +1 -1
- package/dist/api/document-run.cjs +4 -2
- package/dist/api/document-run.cjs.map +1 -1
- package/dist/api/document-run.mjs +4 -2
- package/dist/api/document-run.mjs.map +1 -1
- package/dist/api/footer-sink.cjs +25 -2
- package/dist/api/footer-sink.cjs.map +1 -1
- package/dist/api/footer-sink.mjs +25 -2
- package/dist/api/footer-sink.mjs.map +1 -1
- package/dist/api/legacy-callback-warning.cjs +4 -1
- package/dist/api/legacy-callback-warning.cjs.map +1 -1
- package/dist/api/legacy-callback-warning.mjs +4 -1
- package/dist/api/legacy-callback-warning.mjs.map +1 -1
- package/dist/api/legacy-ts-helpers.cjs.map +1 -1
- package/dist/api/legacy-ts-helpers.mjs.map +1 -1
- package/dist/api/legacy-utils.cjs.map +1 -1
- package/dist/api/legacy-utils.mjs.map +1 -1
- package/dist/api/openapi-ts.cjs +2 -1
- package/dist/api/openapi-ts.cjs.map +1 -1
- package/dist/api/openapi-ts.mjs +3 -2
- package/dist/api/openapi-ts.mjs.map +1 -1
- package/dist/api/transform-context.cjs +1 -1
- package/dist/api/transform-context.cjs.map +1 -1
- package/dist/api/transform-context.mjs +1 -1
- package/dist/api/transform-context.mjs.map +1 -1
- package/dist/api/transform-schema.cjs.map +1 -1
- package/dist/api/transform-schema.mjs.map +1 -1
- package/dist/application/print/type-printer.cjs +2 -1
- package/dist/application/print/type-printer.cjs.map +1 -1
- package/dist/application/print/type-printer.mjs +2 -1
- package/dist/application/print/type-printer.mjs.map +1 -1
- package/dist/application/transform/document/parameters.cjs +1 -1
- package/dist/application/transform/document/parameters.cjs.map +1 -1
- package/dist/application/transform/document/parameters.mjs +1 -1
- package/dist/application/transform/document/parameters.mjs.map +1 -1
- package/dist/application/transform/document/paths.cjs +1 -1
- package/dist/application/transform/document/paths.cjs.map +1 -1
- package/dist/application/transform/document/paths.mjs +1 -1
- package/dist/application/transform/document/paths.mjs.map +1 -1
- package/dist/application/transform/footer/evaluation.cjs +9 -0
- package/dist/application/transform/footer/evaluation.cjs.map +1 -1
- package/dist/application/transform/footer/evaluation.mjs +8 -1
- package/dist/application/transform/footer/evaluation.mjs.map +1 -1
- package/dist/application/transform/footer/type-evaluation.cjs +4 -112
- package/dist/application/transform/footer/type-evaluation.cjs.map +1 -1
- package/dist/application/transform/footer/type-evaluation.mjs +4 -112
- package/dist/application/transform/footer/type-evaluation.mjs.map +1 -1
- package/dist/application/transform/footer/type-indexing.cjs +107 -0
- package/dist/application/transform/footer/type-indexing.cjs.map +1 -0
- package/dist/application/transform/footer/type-indexing.mjs +105 -0
- package/dist/application/transform/footer/type-indexing.mjs.map +1 -0
- package/dist/cli/api-settings.cjs +78 -0
- package/dist/cli/api-settings.cjs.map +1 -0
- package/dist/cli/api-settings.mjs +73 -0
- package/dist/cli/api-settings.mjs.map +1 -0
- package/dist/cli/cli-arguments.cjs +1 -0
- package/dist/cli/cli-arguments.cjs.map +1 -1
- package/dist/cli/cli-arguments.mjs +1 -1
- package/dist/cli/cli-arguments.mjs.map +1 -1
- package/dist/cli/help-text.cjs +3 -3
- package/dist/cli/help-text.cjs.map +1 -1
- package/dist/cli/help-text.mjs +3 -3
- package/dist/cli/help-text.mjs.map +1 -1
- package/dist/cli/redocly-apis.cjs +8 -4
- package/dist/cli/redocly-apis.cjs.map +1 -1
- package/dist/cli/redocly-apis.mjs +7 -3
- package/dist/cli/redocly-apis.mjs.map +1 -1
- package/dist/cli/run-cli.cjs +5 -1
- package/dist/cli/run-cli.cjs.map +1 -1
- package/dist/cli/run-cli.mjs +5 -1
- package/dist/cli/run-cli.mjs.map +1 -1
- package/dist/domain/errors.cjs +4 -1
- package/dist/domain/errors.cjs.map +1 -1
- package/dist/domain/errors.mjs +4 -1
- package/dist/domain/errors.mjs.map +1 -1
- package/dist/domain/ir/constructors.cjs +2 -0
- package/dist/domain/ir/constructors.cjs.map +1 -1
- package/dist/domain/ir/constructors.mjs +2 -1
- package/dist/domain/ir/constructors.mjs.map +1 -1
- package/dist/domain/openapi/path-templates.cjs +1 -1
- package/dist/domain/openapi/path-templates.cjs.map +1 -1
- package/dist/domain/openapi/path-templates.mjs +1 -1
- package/dist/domain/openapi/path-templates.mjs.map +1 -1
- package/dist/domain/url-credentials.cjs +10 -0
- package/dist/domain/url-credentials.cjs.map +1 -0
- package/dist/domain/url-credentials.mjs +8 -0
- package/dist/domain/url-credentials.mjs.map +1 -0
- package/dist/domain/warnings.cjs +9 -1
- package/dist/domain/warnings.cjs.map +1 -1
- package/dist/domain/warnings.mjs +9 -1
- package/dist/domain/warnings.mjs.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1160 -53
- package/dist/index.d.mts +1160 -53
- package/dist/index.d.ts +1160 -53
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/transform/path-item-object.cjs.map +1 -1
- package/dist/transform/path-item-object.mjs.map +1 -1
- package/package.json +6 -5
- package/src/adapters/redocly-loader/configured-headers.ts +65 -0
- package/src/adapters/redocly-loader/redocly-schema-loader.ts +22 -7
- package/src/adapters/redocly-loader/ref-access.ts +60 -5
- package/src/adapters/redocly-loader/ref-resolution-check.ts +257 -0
- package/src/adapters/redocly-loader/ref-resolution-steps.ts +113 -0
- package/src/adapters/redocly-loader/remote-fetch.ts +77 -21
- package/src/adapters/redocly-loader/schema-load-errors.ts +33 -11
- package/src/adapters/redocly-loader/unsupported-keys.ts +17 -2
- package/src/adapters/terminal-logger/terminal-logger.ts +9 -5
- package/src/adapters/type-ast-bridge/ir-to-typescript.ts +2 -1
- package/src/adapters/type-ast-bridge/print-typescript.ts +3 -1
- package/src/adapters/type-ast-bridge/typescript-types.ts +57 -5
- package/src/api/default-ports.ts +16 -0
- package/src/api/discriminator-patch.ts +7 -2
- package/src/api/document-refs.ts +19 -15
- package/src/api/document-run.ts +9 -6
- package/src/api/footer-sink.ts +34 -2
- package/src/api/legacy-callback-warning.ts +7 -3
- package/src/api/legacy-ts-helpers.ts +7 -5
- package/src/api/legacy-utils.ts +1 -1
- package/src/api/openapi-ts.ts +2 -0
- package/src/api/run-context.ts +34 -0
- package/src/api/transform-context.ts +10 -8
- package/src/api/transform-schema.ts +6 -5
- package/src/application/print/type-printer.ts +2 -1
- package/src/application/transform/document/parameters.ts +2 -1
- package/src/application/transform/document/paths.ts +2 -1
- package/src/application/transform/footer/evaluation.ts +10 -0
- package/src/application/transform/footer/type-evaluation.ts +6 -133
- package/src/application/transform/footer/type-indexing.ts +152 -0
- package/src/cli/api-settings.ts +109 -0
- package/src/cli/cli-arguments.ts +5 -2
- package/src/cli/help-text.ts +4 -4
- package/src/cli/redocly-apis.ts +13 -7
- package/src/cli/run-cli.ts +5 -1
- package/src/domain/errors.ts +8 -2
- package/src/domain/ir/constructors.ts +3 -0
- package/src/domain/ir/nodes.ts +9 -6
- package/src/domain/openapi/path-templates.ts +2 -1
- package/src/domain/url-credentials.ts +18 -0
- package/src/domain/warnings.ts +8 -0
- package/src/index.ts +1 -0
- package/src/transform/path-item-object.ts +6 -2
- package/src/types/generator-options.ts +12 -32
- package/src/types/openapi-common.ts +1 -0
- package/src/types/openapi-request.ts +3 -0
- package/src/types/openapi-schema.ts +2 -0
- package/src/types/openapi-security.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluation.cjs","sources":["../../../../src/application/transform/footer/evaluation.ts"],"sourcesContent":["import type { IrPropertyName, IrType } from \"../../../domain/ir/nodes.js\";\n\n/** The values the evaluator of the `--enum-values` check works with (ADR-027). */\n\n/** A type as evaluated: `deep` is set inside `FlattenedDeepRequired`. */\nexport interface Evaluated {\n readonly kind: \"type\";\n readonly type: IrType;\n readonly deep: boolean;\n}\n\nexport type Evaluation = Evaluated | { readonly kind: \"missing\" } | { readonly kind: \"opaque\" };\n\nexport const MISSING: Evaluation = { kind: \"missing\" };\nexport const OPAQUE: Evaluation = { kind: \"opaque\" };\n\nexport const NEVER: IrType = { kind: \"keyword\", keyword: \"never\" };\n\nexport function unionType(types: readonly IrType[]): IrType {\n if (types.length === 1) {\n return types[0] as IrType;\n }\n return types.length === 0 ? NEVER : { kind: \"union\", types };\n}\n\nexport function propertyKey(name: IrPropertyName): string {\n return name.kind === \"string\" ? name.value : name.text;\n}\n\nfunction isKeyword(member: Evaluation, keyword: string): boolean {\n return (\n member.kind === \"type\" && member.type.kind === \"keyword\" && member.type.keyword === keyword\n );\n}\n\n/**\n * Union members as TypeScript reduces them: `any` absorbs every member, `unknown` every member\n * but `any`, so `{ a: X } | unknown` is `unknown`. An opaque member may be `any`.\n */\nexport function absorbed(members: readonly Evaluation[]): readonly Evaluation[] {\n const any = members.find((member) => isKeyword(member, \"any\"));\n const unknown = members.find((member) => isKeyword(member, \"unknown\"));\n if (any !== undefined || unknown === undefined) {\n return any === undefined ? members : [any];\n }\n return members.some((member) => member.kind !== \"type\") ? [OPAQUE] : [unknown];\n}\n"],"names":[],"mappings":";;AAaO,MAAM,OAAA,GAAsB,EAAE,IAAA,EAAM,SAAA;AACpC,MAAM,MAAA,GAAqB,EAAE,IAAA,EAAM,QAAA;AAEnC,MAAM,KAAA,GAAgB,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,OAAA;AAElD,SAAS,UAAU,KAAA,EAAkC;AAC1D,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,OAAO,MAAM,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,MAAM,MAAA,KAAW,CAAA,GAAI,QAAQ,EAAE,IAAA,EAAM,SAAS,KAAA,EAAM;AAC7D;AAEO,SAAS,YAAY,IAAA,EAA8B;AACxD,EAAA,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,GAAW,IAAA,CAAK,QAAQ,IAAA,CAAK,IAAA;AACpD;AAEA,SAAS,SAAA,CAAU,QAAoB,OAAA,EAA0B;AAC/D,EAAA,OACE,MAAA,CAAO,SAAS,MAAA,IAAU,MAAA,CAAO,KAAK,IAAA,KAAS,SAAA,IAAa,MAAA,CAAO,IAAA,CAAK,OAAA,KAAY,OAAA;AAExF;AAMO,SAAS,SAAS,OAAA,EAAuD;AAC9E,EAAA,MAAM,GAAA,GAAM,QAAQ,IAAA,CAAK,CAAC,WAAW,SAAA,CAAU,MAAA,EAAQ,KAAK,CAAC,CAAA;AAC7D,EAAA,MAAM,OAAA,GAAU,QAAQ,IAAA,CAAK,CAAC,WAAW,SAAA,CAAU,MAAA,EAAQ,SAAS,CAAC,CAAA;AACrE,EAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,OAAA,KAAY,MAAA,EAAW;AAC9C,IAAA,OAAO,GAAA,KAAQ,MAAA,GAAY,OAAA,GAAU,CAAC,GAAG,CAAA;AAAA,EAC3C;AACA,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,KAAS,MAAM,CAAA,GAAI,CAAC,MAAM,CAAA,GAAI,CAAC,OAAO,CAAA;AAC/E
|
|
1
|
+
{"version":3,"file":"evaluation.cjs","sources":["../../../../src/application/transform/footer/evaluation.ts"],"sourcesContent":["import type { IrPropertyName, IrType } from \"../../../domain/ir/nodes.js\";\n\n/** The values the evaluator of the `--enum-values` check works with (ADR-027). */\n\n/** A type as evaluated: `deep` is set inside `FlattenedDeepRequired`. */\nexport interface Evaluated {\n readonly kind: \"type\";\n readonly type: IrType;\n readonly deep: boolean;\n}\n\nexport type Evaluation = Evaluated | { readonly kind: \"missing\" } | { readonly kind: \"opaque\" };\n\nexport const MISSING: Evaluation = { kind: \"missing\" };\nexport const OPAQUE: Evaluation = { kind: \"opaque\" };\n\nexport const NEVER: IrType = { kind: \"keyword\", keyword: \"never\" };\n\nexport function unionType(types: readonly IrType[]): IrType {\n if (types.length === 1) {\n return types[0] as IrType;\n }\n return types.length === 0 ? NEVER : { kind: \"union\", types };\n}\n\nexport function intersectionType(types: readonly IrType[]): IrType {\n return types.length === 1 ? (types[0] as IrType) : { kind: \"intersection\", types };\n}\n\nconst NULLISH: ReadonlySet<string> = new Set([\"null\", \"undefined\"]);\n\nexport function isNullish(type: IrType): boolean {\n return type.kind === \"keyword\" && NULLISH.has(type.keyword);\n}\n\nexport function propertyKey(name: IrPropertyName): string {\n return name.kind === \"string\" ? name.value : name.text;\n}\n\nfunction isKeyword(member: Evaluation, keyword: string): boolean {\n return (\n member.kind === \"type\" && member.type.kind === \"keyword\" && member.type.keyword === keyword\n );\n}\n\n/**\n * Union members as TypeScript reduces them: `any` absorbs every member, `unknown` every member\n * but `any`, so `{ a: X } | unknown` is `unknown`. An opaque member may be `any`.\n */\nexport function absorbed(members: readonly Evaluation[]): readonly Evaluation[] {\n const any = members.find((member) => isKeyword(member, \"any\"));\n const unknown = members.find((member) => isKeyword(member, \"unknown\"));\n if (any !== undefined || unknown === undefined) {\n return any === undefined ? members : [any];\n }\n return members.some((member) => member.kind !== \"type\") ? [OPAQUE] : [unknown];\n}\n"],"names":[],"mappings":";;AAaO,MAAM,OAAA,GAAsB,EAAE,IAAA,EAAM,SAAA;AACpC,MAAM,MAAA,GAAqB,EAAE,IAAA,EAAM,QAAA;AAEnC,MAAM,KAAA,GAAgB,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,OAAA;AAElD,SAAS,UAAU,KAAA,EAAkC;AAC1D,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,OAAO,MAAM,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,MAAM,MAAA,KAAW,CAAA,GAAI,QAAQ,EAAE,IAAA,EAAM,SAAS,KAAA,EAAM;AAC7D;AAEO,SAAS,iBAAiB,KAAA,EAAkC;AACjE,EAAA,OAAO,KAAA,CAAM,WAAW,CAAA,GAAK,KAAA,CAAM,CAAC,CAAA,GAAe,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAM;AACnF;AAEA,MAAM,0BAA+B,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,WAAW,CAAC,CAAA;AAE3D,SAAS,UAAU,IAAA,EAAuB;AAC/C,EAAA,OAAO,KAAK,IAAA,KAAS,SAAA,IAAa,OAAA,CAAQ,GAAA,CAAI,KAAK,OAAO,CAAA;AAC5D;AAEO,SAAS,YAAY,IAAA,EAA8B;AACxD,EAAA,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,GAAW,IAAA,CAAK,QAAQ,IAAA,CAAK,IAAA;AACpD;AAEA,SAAS,SAAA,CAAU,QAAoB,OAAA,EAA0B;AAC/D,EAAA,OACE,MAAA,CAAO,SAAS,MAAA,IAAU,MAAA,CAAO,KAAK,IAAA,KAAS,SAAA,IAAa,MAAA,CAAO,IAAA,CAAK,OAAA,KAAY,OAAA;AAExF;AAMO,SAAS,SAAS,OAAA,EAAuD;AAC9E,EAAA,MAAM,GAAA,GAAM,QAAQ,IAAA,CAAK,CAAC,WAAW,SAAA,CAAU,MAAA,EAAQ,KAAK,CAAC,CAAA;AAC7D,EAAA,MAAM,OAAA,GAAU,QAAQ,IAAA,CAAK,CAAC,WAAW,SAAA,CAAU,MAAA,EAAQ,SAAS,CAAC,CAAA;AACrE,EAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,OAAA,KAAY,MAAA,EAAW;AAC9C,IAAA,OAAO,GAAA,KAAQ,MAAA,GAAY,OAAA,GAAU,CAAC,GAAG,CAAA;AAAA,EAC3C;AACA,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,KAAS,MAAM,CAAA,GAAI,CAAC,MAAM,CAAA,GAAI,CAAC,OAAO,CAAA;AAC/E;;;;;;;;;"}
|
|
@@ -7,6 +7,13 @@ function unionType(types) {
|
|
|
7
7
|
}
|
|
8
8
|
return types.length === 0 ? NEVER : { kind: "union", types };
|
|
9
9
|
}
|
|
10
|
+
function intersectionType(types) {
|
|
11
|
+
return types.length === 1 ? types[0] : { kind: "intersection", types };
|
|
12
|
+
}
|
|
13
|
+
const NULLISH = /* @__PURE__ */ new Set(["null", "undefined"]);
|
|
14
|
+
function isNullish(type) {
|
|
15
|
+
return type.kind === "keyword" && NULLISH.has(type.keyword);
|
|
16
|
+
}
|
|
10
17
|
function propertyKey(name) {
|
|
11
18
|
return name.kind === "string" ? name.value : name.text;
|
|
12
19
|
}
|
|
@@ -22,5 +29,5 @@ function absorbed(members) {
|
|
|
22
29
|
return members.some((member) => member.kind !== "type") ? [OPAQUE] : [unknown];
|
|
23
30
|
}
|
|
24
31
|
|
|
25
|
-
export { MISSING, NEVER, OPAQUE, absorbed, propertyKey, unionType };
|
|
32
|
+
export { MISSING, NEVER, OPAQUE, absorbed, intersectionType, isNullish, propertyKey, unionType };
|
|
26
33
|
//# sourceMappingURL=evaluation.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluation.mjs","sources":["../../../../src/application/transform/footer/evaluation.ts"],"sourcesContent":["import type { IrPropertyName, IrType } from \"../../../domain/ir/nodes.js\";\n\n/** The values the evaluator of the `--enum-values` check works with (ADR-027). */\n\n/** A type as evaluated: `deep` is set inside `FlattenedDeepRequired`. */\nexport interface Evaluated {\n readonly kind: \"type\";\n readonly type: IrType;\n readonly deep: boolean;\n}\n\nexport type Evaluation = Evaluated | { readonly kind: \"missing\" } | { readonly kind: \"opaque\" };\n\nexport const MISSING: Evaluation = { kind: \"missing\" };\nexport const OPAQUE: Evaluation = { kind: \"opaque\" };\n\nexport const NEVER: IrType = { kind: \"keyword\", keyword: \"never\" };\n\nexport function unionType(types: readonly IrType[]): IrType {\n if (types.length === 1) {\n return types[0] as IrType;\n }\n return types.length === 0 ? NEVER : { kind: \"union\", types };\n}\n\nexport function propertyKey(name: IrPropertyName): string {\n return name.kind === \"string\" ? name.value : name.text;\n}\n\nfunction isKeyword(member: Evaluation, keyword: string): boolean {\n return (\n member.kind === \"type\" && member.type.kind === \"keyword\" && member.type.keyword === keyword\n );\n}\n\n/**\n * Union members as TypeScript reduces them: `any` absorbs every member, `unknown` every member\n * but `any`, so `{ a: X } | unknown` is `unknown`. An opaque member may be `any`.\n */\nexport function absorbed(members: readonly Evaluation[]): readonly Evaluation[] {\n const any = members.find((member) => isKeyword(member, \"any\"));\n const unknown = members.find((member) => isKeyword(member, \"unknown\"));\n if (any !== undefined || unknown === undefined) {\n return any === undefined ? members : [any];\n }\n return members.some((member) => member.kind !== \"type\") ? [OPAQUE] : [unknown];\n}\n"],"names":[],"mappings":"AAaO,MAAM,OAAA,GAAsB,EAAE,IAAA,EAAM,SAAA;AACpC,MAAM,MAAA,GAAqB,EAAE,IAAA,EAAM,QAAA;AAEnC,MAAM,KAAA,GAAgB,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,OAAA;AAElD,SAAS,UAAU,KAAA,EAAkC;AAC1D,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,OAAO,MAAM,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,MAAM,MAAA,KAAW,CAAA,GAAI,QAAQ,EAAE,IAAA,EAAM,SAAS,KAAA,EAAM;AAC7D;AAEO,SAAS,YAAY,IAAA,EAA8B;AACxD,EAAA,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,GAAW,IAAA,CAAK,QAAQ,IAAA,CAAK,IAAA;AACpD;AAEA,SAAS,SAAA,CAAU,QAAoB,OAAA,EAA0B;AAC/D,EAAA,OACE,MAAA,CAAO,SAAS,MAAA,IAAU,MAAA,CAAO,KAAK,IAAA,KAAS,SAAA,IAAa,MAAA,CAAO,IAAA,CAAK,OAAA,KAAY,OAAA;AAExF;AAMO,SAAS,SAAS,OAAA,EAAuD;AAC9E,EAAA,MAAM,GAAA,GAAM,QAAQ,IAAA,CAAK,CAAC,WAAW,SAAA,CAAU,MAAA,EAAQ,KAAK,CAAC,CAAA;AAC7D,EAAA,MAAM,OAAA,GAAU,QAAQ,IAAA,CAAK,CAAC,WAAW,SAAA,CAAU,MAAA,EAAQ,SAAS,CAAC,CAAA;AACrE,EAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,OAAA,KAAY,MAAA,EAAW;AAC9C,IAAA,OAAO,GAAA,KAAQ,MAAA,GAAY,OAAA,GAAU,CAAC,GAAG,CAAA;AAAA,EAC3C;AACA,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,KAAS,MAAM,CAAA,GAAI,CAAC,MAAM,CAAA,GAAI,CAAC,OAAO,CAAA;AAC/E;;"}
|
|
1
|
+
{"version":3,"file":"evaluation.mjs","sources":["../../../../src/application/transform/footer/evaluation.ts"],"sourcesContent":["import type { IrPropertyName, IrType } from \"../../../domain/ir/nodes.js\";\n\n/** The values the evaluator of the `--enum-values` check works with (ADR-027). */\n\n/** A type as evaluated: `deep` is set inside `FlattenedDeepRequired`. */\nexport interface Evaluated {\n readonly kind: \"type\";\n readonly type: IrType;\n readonly deep: boolean;\n}\n\nexport type Evaluation = Evaluated | { readonly kind: \"missing\" } | { readonly kind: \"opaque\" };\n\nexport const MISSING: Evaluation = { kind: \"missing\" };\nexport const OPAQUE: Evaluation = { kind: \"opaque\" };\n\nexport const NEVER: IrType = { kind: \"keyword\", keyword: \"never\" };\n\nexport function unionType(types: readonly IrType[]): IrType {\n if (types.length === 1) {\n return types[0] as IrType;\n }\n return types.length === 0 ? NEVER : { kind: \"union\", types };\n}\n\nexport function intersectionType(types: readonly IrType[]): IrType {\n return types.length === 1 ? (types[0] as IrType) : { kind: \"intersection\", types };\n}\n\nconst NULLISH: ReadonlySet<string> = new Set([\"null\", \"undefined\"]);\n\nexport function isNullish(type: IrType): boolean {\n return type.kind === \"keyword\" && NULLISH.has(type.keyword);\n}\n\nexport function propertyKey(name: IrPropertyName): string {\n return name.kind === \"string\" ? name.value : name.text;\n}\n\nfunction isKeyword(member: Evaluation, keyword: string): boolean {\n return (\n member.kind === \"type\" && member.type.kind === \"keyword\" && member.type.keyword === keyword\n );\n}\n\n/**\n * Union members as TypeScript reduces them: `any` absorbs every member, `unknown` every member\n * but `any`, so `{ a: X } | unknown` is `unknown`. An opaque member may be `any`.\n */\nexport function absorbed(members: readonly Evaluation[]): readonly Evaluation[] {\n const any = members.find((member) => isKeyword(member, \"any\"));\n const unknown = members.find((member) => isKeyword(member, \"unknown\"));\n if (any !== undefined || unknown === undefined) {\n return any === undefined ? members : [any];\n }\n return members.some((member) => member.kind !== \"type\") ? [OPAQUE] : [unknown];\n}\n"],"names":[],"mappings":"AAaO,MAAM,OAAA,GAAsB,EAAE,IAAA,EAAM,SAAA;AACpC,MAAM,MAAA,GAAqB,EAAE,IAAA,EAAM,QAAA;AAEnC,MAAM,KAAA,GAAgB,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,OAAA;AAElD,SAAS,UAAU,KAAA,EAAkC;AAC1D,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,OAAO,MAAM,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,MAAM,MAAA,KAAW,CAAA,GAAI,QAAQ,EAAE,IAAA,EAAM,SAAS,KAAA,EAAM;AAC7D;AAEO,SAAS,iBAAiB,KAAA,EAAkC;AACjE,EAAA,OAAO,KAAA,CAAM,WAAW,CAAA,GAAK,KAAA,CAAM,CAAC,CAAA,GAAe,EAAE,IAAA,EAAM,cAAA,EAAgB,KAAA,EAAM;AACnF;AAEA,MAAM,0BAA+B,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,WAAW,CAAC,CAAA;AAE3D,SAAS,UAAU,IAAA,EAAuB;AAC/C,EAAA,OAAO,KAAK,IAAA,KAAS,SAAA,IAAa,OAAA,CAAQ,GAAA,CAAI,KAAK,OAAO,CAAA;AAC5D;AAEO,SAAS,YAAY,IAAA,EAA8B;AACxD,EAAA,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,GAAW,IAAA,CAAK,QAAQ,IAAA,CAAK,IAAA;AACpD;AAEA,SAAS,SAAA,CAAU,QAAoB,OAAA,EAA0B;AAC/D,EAAA,OACE,MAAA,CAAO,SAAS,MAAA,IAAU,MAAA,CAAO,KAAK,IAAA,KAAS,SAAA,IAAa,MAAA,CAAO,IAAA,CAAK,OAAA,KAAY,OAAA;AAExF;AAMO,SAAS,SAAS,OAAA,EAAuD;AAC9E,EAAA,MAAM,GAAA,GAAM,QAAQ,IAAA,CAAK,CAAC,WAAW,SAAA,CAAU,MAAA,EAAQ,KAAK,CAAC,CAAA;AAC7D,EAAA,MAAM,OAAA,GAAU,QAAQ,IAAA,CAAK,CAAC,WAAW,SAAA,CAAU,MAAA,EAAQ,SAAS,CAAC,CAAA;AACrE,EAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,OAAA,KAAY,MAAA,EAAW;AAC9C,IAAA,OAAO,GAAA,KAAQ,MAAA,GAAY,OAAA,GAAU,CAAC,GAAG,CAAA;AAAA,EAC3C;AACA,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,KAAS,MAAM,CAAA,GAAI,CAAC,MAAM,CAAA,GAAI,CAAC,OAAO,CAAA;AAC/E;;"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const evaluation = require('./evaluation.cjs');
|
|
4
|
+
const typeIndexing = require('./type-indexing.cjs');
|
|
4
5
|
const typeRules = require('./type-rules.cjs');
|
|
5
6
|
|
|
6
7
|
const MAX_EXPANSIONS = 200;
|
|
7
8
|
const DEEP_PREFIX = "FlattenedDeepRequired<";
|
|
8
9
|
const MAX_DISTRIBUTED = 64;
|
|
9
|
-
const NULLISH = /* @__PURE__ */ new Set(["null", "undefined"]);
|
|
10
10
|
class TypeEvaluator {
|
|
11
11
|
declared = /* @__PURE__ */ new Map();
|
|
12
12
|
expansions = 0;
|
|
@@ -110,14 +110,14 @@ class TypeEvaluator {
|
|
|
110
110
|
for (const list of memberLists) {
|
|
111
111
|
combinations = combinations.flatMap((done) => list.map((member) => [...done, member.type]));
|
|
112
112
|
}
|
|
113
|
-
return combinations.map((types) => ({ ...value, type: intersectionType(types) }));
|
|
113
|
+
return combinations.map((types) => ({ ...value, type: evaluation.intersectionType(types) }));
|
|
114
114
|
}
|
|
115
115
|
withoutNullish(value) {
|
|
116
116
|
const members = this.membersOf(value);
|
|
117
117
|
if (members.some((member) => member.kind !== "type")) {
|
|
118
118
|
return evaluation.OPAQUE;
|
|
119
119
|
}
|
|
120
|
-
const kept = members.filter((member) => !isNullish(member.type));
|
|
120
|
+
const kept = members.filter((member) => !evaluation.isNullish(member.type));
|
|
121
121
|
return { ...value, type: evaluation.unionType(kept.map((member) => member.type)) };
|
|
122
122
|
}
|
|
123
123
|
/** `Extract<T, { key: unknown }>` keeps the members that have `key`; other probes are opaque. */
|
|
@@ -130,116 +130,8 @@ class TypeEvaluator {
|
|
|
130
130
|
}
|
|
131
131
|
/** `value[index]` for a string literal, `string` or `number` index. */
|
|
132
132
|
index(value, index) {
|
|
133
|
-
|
|
134
|
-
if (owner.kind !== "type") {
|
|
135
|
-
return owner;
|
|
136
|
-
}
|
|
137
|
-
if (this.membersOf(owner).length > 1) {
|
|
138
|
-
return this.unionIndex(owner, index);
|
|
139
|
-
}
|
|
140
|
-
const { type } = owner;
|
|
141
|
-
switch (type.kind) {
|
|
142
|
-
case "object":
|
|
143
|
-
return this.memberType(owner, type.members, index);
|
|
144
|
-
case "intersection":
|
|
145
|
-
return this.partsIndex(owner, type.types, index);
|
|
146
|
-
case "union":
|
|
147
|
-
return this.unionIndex(owner, index);
|
|
148
|
-
case "array":
|
|
149
|
-
return isNumberIndex(index) ? this.flattened(owner, type.element) : builtInIndex(index);
|
|
150
|
-
case "keyword":
|
|
151
|
-
return type.keyword === "never" ? owner : builtInIndex(index);
|
|
152
|
-
default:
|
|
153
|
-
return builtInIndex(index);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
memberType(owner, members, index) {
|
|
157
|
-
const key = indexKey(index);
|
|
158
|
-
const property = members.find(
|
|
159
|
-
(member) => member.kind === "property" && key !== null && evaluation.propertyKey(member.name) === key
|
|
160
|
-
);
|
|
161
|
-
if (property !== void 0) {
|
|
162
|
-
return this.flattened(owner, property.type);
|
|
163
|
-
}
|
|
164
|
-
const signature = members.find((member) => member.kind === "indexSignature");
|
|
165
|
-
if (signature !== void 0) {
|
|
166
|
-
return this.flattened(owner, signature.type);
|
|
167
|
-
}
|
|
168
|
-
return key === null || isObjectBuiltIn(key) ? evaluation.OPAQUE : evaluation.MISSING;
|
|
169
|
-
}
|
|
170
|
-
partsIndex(owner, parts, index) {
|
|
171
|
-
if (typeRules.isNeverIntersection(this, owner, parts)) {
|
|
172
|
-
return { ...owner, type: evaluation.NEVER };
|
|
173
|
-
}
|
|
174
|
-
const found = parts.map((type) => this.index({ ...owner, type }, index));
|
|
175
|
-
if (found.some((part) => part.kind === "opaque")) {
|
|
176
|
-
return evaluation.OPAQUE;
|
|
177
|
-
}
|
|
178
|
-
const read = parts.map((type, at) => ({ type, found: found[at] }));
|
|
179
|
-
const types = typeRules.declaredFirst(this, owner, indexKey(index), read).flatMap(
|
|
180
|
-
(part) => part.kind === "type" ? [part.type] : []
|
|
181
|
-
);
|
|
182
|
-
return types.length === 0 ? evaluation.MISSING : { ...owner, type: intersectionType(types) };
|
|
183
|
-
}
|
|
184
|
-
unionIndex(owner, index) {
|
|
185
|
-
const found = this.membersOf(owner).map(
|
|
186
|
-
(member) => member.kind === "type" ? this.index(member, index) : member
|
|
187
|
-
);
|
|
188
|
-
if (found.some((member) => member.kind === "missing")) {
|
|
189
|
-
return evaluation.MISSING;
|
|
190
|
-
}
|
|
191
|
-
if (found.some((member) => member.kind === "opaque")) {
|
|
192
|
-
return evaluation.OPAQUE;
|
|
193
|
-
}
|
|
194
|
-
return { ...owner, type: evaluation.unionType(found.map((member) => member.type)) };
|
|
133
|
+
return typeIndexing.indexType(this, value, index);
|
|
195
134
|
}
|
|
196
|
-
/**
|
|
197
|
-
* A member read through `FlattenedDeepRequired`: a value that is only arrays (and `undefined` or
|
|
198
|
-
* `null`) is replaced by its elements, anything else loses `undefined` and `null`.
|
|
199
|
-
*/
|
|
200
|
-
flattened(owner, type) {
|
|
201
|
-
const member = { ...owner, type };
|
|
202
|
-
if (!owner.deep) {
|
|
203
|
-
return this.expand(member);
|
|
204
|
-
}
|
|
205
|
-
const members = this.membersOf(member);
|
|
206
|
-
if (members.some((candidate) => candidate.kind !== "type")) {
|
|
207
|
-
return evaluation.OPAQUE;
|
|
208
|
-
}
|
|
209
|
-
const present = members.filter((candidate) => !isNullish(candidate.type));
|
|
210
|
-
const elements = present.map((candidate) => arrayElement(candidate.type));
|
|
211
|
-
if (present.length > 0 && elements.every((element) => element !== null)) {
|
|
212
|
-
return this.expand({ ...owner, type: evaluation.unionType(elements) });
|
|
213
|
-
}
|
|
214
|
-
return { ...owner, type: evaluation.unionType(present.map((candidate) => candidate.type)) };
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
function isNullish(type) {
|
|
218
|
-
return type.kind === "keyword" && NULLISH.has(type.keyword);
|
|
219
|
-
}
|
|
220
|
-
function arrayElement(type) {
|
|
221
|
-
return type.kind === "array" ? type.element : null;
|
|
222
|
-
}
|
|
223
|
-
function intersectionType(types) {
|
|
224
|
-
return types.length === 1 ? types[0] : { kind: "intersection", types };
|
|
225
|
-
}
|
|
226
|
-
function indexKey(index) {
|
|
227
|
-
if (index.kind === "stringLiteral") {
|
|
228
|
-
return index.value;
|
|
229
|
-
}
|
|
230
|
-
return index.kind === "numberLiteral" ? String(index.value) : null;
|
|
231
|
-
}
|
|
232
|
-
function isNumberIndex(index) {
|
|
233
|
-
const key = indexKey(index);
|
|
234
|
-
return index.kind === "keyword" && index.keyword === "number" || /^\d+$/.test(key ?? "");
|
|
235
|
-
}
|
|
236
|
-
function isObjectBuiltIn(key) {
|
|
237
|
-
return key in {};
|
|
238
|
-
}
|
|
239
|
-
function builtInIndex(index) {
|
|
240
|
-
const key = indexKey(index);
|
|
241
|
-
const isBuiltIn = key === null || key in String.prototype || key in Array.prototype;
|
|
242
|
-
return isBuiltIn || key in Number.prototype ? evaluation.OPAQUE : evaluation.MISSING;
|
|
243
135
|
}
|
|
244
136
|
|
|
245
137
|
exports.TypeEvaluator = TypeEvaluator;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-evaluation.cjs","sources":["../../../../src/application/transform/footer/type-evaluation.ts"],"sourcesContent":["import type { IrDeclaration, IrMember, IrType } from \"../../../domain/ir/nodes.js\";\nimport {\n absorbed,\n type Evaluated,\n type Evaluation,\n MISSING,\n NEVER,\n OPAQUE,\n propertyKey,\n unionType,\n} from \"./evaluation.js\";\nimport {\n declaredFirst,\n extracted,\n isNeverIntersection,\n markerObject,\n omitted,\n} from \"./type-rules.js\";\n\n/**\n * A small evaluator of the generated types, as TypeScript reads them, for the `--enum-values`\n * check (ADR-027). It follows the declarations of the document and the helper types the generator\n * writes (`NonNullable`, `Extract`, `WithRequired`, `Omit`, `Record`, `FlattenedDeepRequired`). Its\n * answers are sure: a key is `missing` only where TypeScript reports it, and every type it does\n * not model is `opaque`, which never counts as an error.\n */\n\n/** How many references one evaluation expands; a deeper one is opaque. */\nconst MAX_EXPANSIONS = 200;\nconst DEEP_PREFIX = \"FlattenedDeepRequired<\";\n/** How many members distributing an intersection may give; more is opaque. */\nconst MAX_DISTRIBUTED = 64;\nconst NULLISH: ReadonlySet<string> = new Set([\"null\", \"undefined\"]);\n\nexport class TypeEvaluator {\n private readonly declared = new Map<string, IrType>();\n private expansions = 0;\n\n constructor(declarations: readonly IrDeclaration[]) {\n for (const declaration of declarations) {\n if (declaration.kind === \"interface\") {\n this.declared.set(declaration.name, { kind: \"object\", members: declaration.members });\n } else if (declaration.kind === \"typeAlias\") {\n this.declared.set(declaration.name, declaration.type);\n }\n }\n }\n\n /** Evaluate a type written in the footer; the expansion budget starts again. */\n evaluate(type: IrType): Evaluation {\n this.expansions = 0;\n return this.expand({ kind: \"type\", type, deep: false });\n }\n\n /** The type with references, `readonly` and indexed access resolved at the top. */\n expand(value: Evaluated): Evaluation {\n const { type } = value;\n switch (type.kind) {\n case \"readonly\":\n return this.expand({ ...value, type: type.type });\n case \"indexedAccess\":\n return this.indexedAccess(value, type.object, type.index);\n case \"reference\":\n return this.reference(value, type.name, type.typeArguments);\n case \"raw\":\n case \"tuple\":\n return OPAQUE;\n default:\n return value;\n }\n }\n\n private indexedAccess(value: Evaluated, object: IrType, index: IrType): Evaluation {\n const owner = this.expand({ ...value, type: object });\n return owner.kind === \"type\" ? this.index(owner, index) : owner;\n }\n\n private reference(value: Evaluated, name: string, args: readonly IrType[]): Evaluation {\n // Only references cost budget: re-expanding an already expanded value (as the checks after\n // `evaluate` do) is free, so a large evaluation does not leave its checks opaque.\n if (this.expansions++ > MAX_EXPANSIONS) {\n return OPAQUE;\n }\n if (name.startsWith(DEEP_PREFIX) && name.endsWith(\">\")) {\n const root = this.declared.get(name.slice(DEEP_PREFIX.length, -1));\n return root === undefined ? OPAQUE : this.expand({ kind: \"type\", type: root, deep: true });\n }\n const declared = args.length === 0 ? this.declared.get(name) : undefined;\n if (declared !== undefined) {\n return this.expand({ ...value, type: declared });\n }\n const [first, second] = args;\n if (first === undefined) {\n return OPAQUE;\n }\n const argument = this.expand({ ...value, type: first });\n if (argument.kind !== \"type\") {\n return argument;\n }\n return this.helper(name, argument, second);\n }\n\n private helper(name: string, argument: Evaluated, second: IrType | undefined): Evaluation {\n switch (name) {\n case \"NonNullable\":\n return this.withoutNullish(argument);\n case \"WithRequired\":\n case \"Readonly\":\n return argument;\n case \"Extract\":\n return second === undefined ? OPAQUE : this.extract(argument, second);\n case \"Omit\":\n return second === undefined ? OPAQUE : omitted(this, argument, second);\n default:\n return markerObject(name, argument) ?? OPAQUE;\n }\n }\n\n /**\n * The members of a union, each expanded; an intersection with unions in it is distributed over\n * them (`A & (B | C)` is `(A & B) | (A & C)`), as TypeScript normalizes it. A type that is not a\n * union is its only member. A union with an `any` or `unknown` member is that keyword alone.\n */\n membersOf(value: Evaluated): readonly Evaluation[] {\n const expanded = this.expand(value);\n if (expanded.kind !== \"type\") {\n return [expanded];\n }\n const { type } = expanded;\n if (type.kind === \"union\") {\n return absorbed(\n type.types.flatMap((member) => this.membersOf({ ...expanded, type: member })),\n );\n }\n return type.kind === \"intersection\" ? this.distributed(expanded, type.types) : [expanded];\n }\n\n private distributed(value: Evaluated, parts: readonly IrType[]): readonly Evaluation[] {\n const memberLists = parts.map((part) => this.membersOf({ ...value, type: part }));\n const size = memberLists.reduce((product, list) => product * list.length, 1);\n if (size > MAX_DISTRIBUTED || memberLists.some((list) => list.some((m) => m.kind !== \"type\"))) {\n return [OPAQUE];\n }\n let combinations: IrType[][] = [[]];\n for (const list of memberLists as Evaluated[][]) {\n combinations = combinations.flatMap((done) => list.map((member) => [...done, member.type]));\n }\n return combinations.map((types) => ({ ...value, type: intersectionType(types) }));\n }\n\n private withoutNullish(value: Evaluated): Evaluation {\n const members = this.membersOf(value);\n if (members.some((member) => member.kind !== \"type\")) {\n return OPAQUE;\n }\n const kept = (members as Evaluated[]).filter((member) => !isNullish(member.type));\n return { ...value, type: unionType(kept.map((member) => member.type)) };\n }\n\n /** `Extract<T, { key: unknown }>` keeps the members that have `key`; other probes are opaque. */\n private extract(value: Evaluated, probe: IrType): Evaluation {\n const [member] = probe.kind === \"object\" ? probe.members : [];\n if (probe.kind !== \"object\" || probe.members.length !== 1 || member?.kind !== \"property\") {\n return OPAQUE;\n }\n return extracted(this, value, propertyKey(member.name));\n }\n\n /** `value[index]` for a string literal, `string` or `number` index. */\n index(value: Evaluated, index: IrType): Evaluation {\n const owner = this.expand(value);\n if (owner.kind !== \"type\") {\n return owner;\n }\n if (this.membersOf(owner).length > 1) {\n return this.unionIndex(owner, index);\n }\n const { type } = owner;\n switch (type.kind) {\n case \"object\":\n return this.memberType(owner, type.members, index);\n case \"intersection\":\n return this.partsIndex(owner, type.types, index);\n case \"union\":\n return this.unionIndex(owner, index);\n case \"array\":\n return isNumberIndex(index) ? this.flattened(owner, type.element) : builtInIndex(index);\n case \"keyword\":\n return type.keyword === \"never\" ? owner : builtInIndex(index);\n default:\n return builtInIndex(index);\n }\n }\n\n private memberType(owner: Evaluated, members: readonly IrMember[], index: IrType): Evaluation {\n const key = indexKey(index);\n const property = members.find(\n (member) => member.kind === \"property\" && key !== null && propertyKey(member.name) === key,\n );\n if (property !== undefined) {\n return this.flattened(owner, property.type);\n }\n const signature = members.find((member) => member.kind === \"indexSignature\");\n if (signature !== undefined) {\n return this.flattened(owner, signature.type);\n }\n return key === null || isObjectBuiltIn(key) ? OPAQUE : MISSING;\n }\n\n private partsIndex(owner: Evaluated, parts: readonly IrType[], index: IrType): Evaluation {\n if (isNeverIntersection(this, owner, parts)) {\n return { ...owner, type: NEVER };\n }\n const found = parts.map((type) => this.index({ ...owner, type }, index));\n if (found.some((part) => part.kind === \"opaque\")) {\n return OPAQUE;\n }\n const read = parts.map((type, at) => ({ type, found: found[at] as Evaluation }));\n const types = declaredFirst(this, owner, indexKey(index), read).flatMap((part) =>\n part.kind === \"type\" ? [part.type] : [],\n );\n return types.length === 0 ? MISSING : { ...owner, type: intersectionType(types) };\n }\n\n private unionIndex(owner: Evaluated, index: IrType): Evaluation {\n const found = this.membersOf(owner).map((member) =>\n member.kind === \"type\" ? this.index(member, index) : member,\n );\n if (found.some((member) => member.kind === \"missing\")) {\n return MISSING;\n }\n if (found.some((member) => member.kind === \"opaque\")) {\n return OPAQUE;\n }\n return { ...owner, type: unionType((found as Evaluated[]).map((member) => member.type)) };\n }\n\n /**\n * A member read through `FlattenedDeepRequired`: a value that is only arrays (and `undefined` or\n * `null`) is replaced by its elements, anything else loses `undefined` and `null`.\n */\n private flattened(owner: Evaluated, type: IrType): Evaluation {\n const member: Evaluated = { ...owner, type };\n if (!owner.deep) {\n return this.expand(member);\n }\n const members = this.membersOf(member);\n if (members.some((candidate) => candidate.kind !== \"type\")) {\n return OPAQUE;\n }\n const present = (members as Evaluated[]).filter((candidate) => !isNullish(candidate.type));\n const elements = present.map((candidate) => arrayElement(candidate.type));\n if (present.length > 0 && elements.every((element) => element !== null)) {\n return this.expand({ ...owner, type: unionType(elements as IrType[]) });\n }\n return { ...owner, type: unionType(present.map((candidate) => candidate.type)) };\n }\n}\n\nfunction isNullish(type: IrType): boolean {\n return type.kind === \"keyword\" && NULLISH.has(type.keyword);\n}\n\n/** The element of an expanded member; expanding already dropped `readonly`. */\nfunction arrayElement(type: IrType): IrType | null {\n return type.kind === \"array\" ? type.element : null;\n}\n\nfunction intersectionType(types: readonly IrType[]): IrType {\n return types.length === 1 ? (types[0] as IrType) : { kind: \"intersection\", types };\n}\n\nfunction indexKey(index: IrType): string | null {\n if (index.kind === \"stringLiteral\") {\n return index.value;\n }\n return index.kind === \"numberLiteral\" ? String(index.value) : null;\n}\n\nfunction isNumberIndex(index: IrType): boolean {\n const key = indexKey(index);\n return (index.kind === \"keyword\" && index.keyword === \"number\") || /^\\d+$/.test(key ?? \"\");\n}\n\nfunction isObjectBuiltIn(key: string): boolean {\n return key in {};\n}\n\n/** A key of a primitive or an array: a built-in member is opaque, any other key is missing. */\nfunction builtInIndex(index: IrType): Evaluation {\n const key = indexKey(index);\n const isBuiltIn = key === null || key in String.prototype || key in Array.prototype;\n return isBuiltIn || key in Number.prototype ? OPAQUE : MISSING;\n}\n"],"names":["OPAQUE","omitted","markerObject","absorbed","unionType","extracted","propertyKey","MISSING","isNeverIntersection","NEVER","declaredFirst"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"type-evaluation.cjs","sources":["../../../../src/application/transform/footer/type-evaluation.ts"],"sourcesContent":["import type { IrDeclaration, IrType } from \"../../../domain/ir/nodes.js\";\nimport {\n absorbed,\n type Evaluated,\n type Evaluation,\n intersectionType,\n isNullish,\n OPAQUE,\n propertyKey,\n unionType,\n} from \"./evaluation.js\";\nimport { indexType } from \"./type-indexing.js\";\nimport { extracted, markerObject, omitted } from \"./type-rules.js\";\n\n/**\n * A small evaluator of the generated types, as TypeScript reads them, for the `--enum-values`\n * check (ADR-027). It follows the declarations of the document and the helper types the generator\n * writes (`NonNullable`, `Extract`, `WithRequired`, `Omit`, `Record`, `FlattenedDeepRequired`). Its\n * answers are sure: a key is `missing` only where TypeScript reports it, and every type it does\n * not model is `opaque`, which never counts as an error.\n */\n\n/** How many references one evaluation expands; a deeper one is opaque. */\nconst MAX_EXPANSIONS = 200;\nconst DEEP_PREFIX = \"FlattenedDeepRequired<\";\n/** How many members distributing an intersection may give; more is opaque. */\nconst MAX_DISTRIBUTED = 64;\n\nexport class TypeEvaluator {\n private readonly declared = new Map<string, IrType>();\n private expansions = 0;\n\n constructor(declarations: readonly IrDeclaration[]) {\n for (const declaration of declarations) {\n if (declaration.kind === \"interface\") {\n this.declared.set(declaration.name, { kind: \"object\", members: declaration.members });\n } else if (declaration.kind === \"typeAlias\") {\n this.declared.set(declaration.name, declaration.type);\n }\n }\n }\n\n /** Evaluate a type written in the footer; the expansion budget starts again. */\n evaluate(type: IrType): Evaluation {\n this.expansions = 0;\n return this.expand({ kind: \"type\", type, deep: false });\n }\n\n /** The type with references, `readonly` and indexed access resolved at the top. */\n expand(value: Evaluated): Evaluation {\n const { type } = value;\n switch (type.kind) {\n case \"readonly\":\n return this.expand({ ...value, type: type.type });\n case \"indexedAccess\":\n return this.indexedAccess(value, type.object, type.index);\n case \"reference\":\n return this.reference(value, type.name, type.typeArguments);\n case \"raw\":\n case \"tuple\":\n return OPAQUE;\n default:\n return value;\n }\n }\n\n private indexedAccess(value: Evaluated, object: IrType, index: IrType): Evaluation {\n const owner = this.expand({ ...value, type: object });\n return owner.kind === \"type\" ? this.index(owner, index) : owner;\n }\n\n private reference(value: Evaluated, name: string, args: readonly IrType[]): Evaluation {\n // Only references cost budget: re-expanding an already expanded value (as the checks after\n // `evaluate` do) is free, so a large evaluation does not leave its checks opaque.\n if (this.expansions++ > MAX_EXPANSIONS) {\n return OPAQUE;\n }\n if (name.startsWith(DEEP_PREFIX) && name.endsWith(\">\")) {\n const root = this.declared.get(name.slice(DEEP_PREFIX.length, -1));\n return root === undefined ? OPAQUE : this.expand({ kind: \"type\", type: root, deep: true });\n }\n const declared = args.length === 0 ? this.declared.get(name) : undefined;\n if (declared !== undefined) {\n return this.expand({ ...value, type: declared });\n }\n const [first, second] = args;\n if (first === undefined) {\n return OPAQUE;\n }\n const argument = this.expand({ ...value, type: first });\n if (argument.kind !== \"type\") {\n return argument;\n }\n return this.helper(name, argument, second);\n }\n\n private helper(name: string, argument: Evaluated, second: IrType | undefined): Evaluation {\n switch (name) {\n case \"NonNullable\":\n return this.withoutNullish(argument);\n case \"WithRequired\":\n case \"Readonly\":\n return argument;\n case \"Extract\":\n return second === undefined ? OPAQUE : this.extract(argument, second);\n case \"Omit\":\n return second === undefined ? OPAQUE : omitted(this, argument, second);\n default:\n return markerObject(name, argument) ?? OPAQUE;\n }\n }\n\n /**\n * The members of a union, each expanded; an intersection with unions in it is distributed over\n * them (`A & (B | C)` is `(A & B) | (A & C)`), as TypeScript normalizes it. A type that is not a\n * union is its only member. A union with an `any` or `unknown` member is that keyword alone.\n */\n membersOf(value: Evaluated): readonly Evaluation[] {\n const expanded = this.expand(value);\n if (expanded.kind !== \"type\") {\n return [expanded];\n }\n const { type } = expanded;\n if (type.kind === \"union\") {\n return absorbed(\n type.types.flatMap((member) => this.membersOf({ ...expanded, type: member })),\n );\n }\n return type.kind === \"intersection\" ? this.distributed(expanded, type.types) : [expanded];\n }\n\n private distributed(value: Evaluated, parts: readonly IrType[]): readonly Evaluation[] {\n const memberLists = parts.map((part) => this.membersOf({ ...value, type: part }));\n const size = memberLists.reduce((product, list) => product * list.length, 1);\n if (size > MAX_DISTRIBUTED || memberLists.some((list) => list.some((m) => m.kind !== \"type\"))) {\n return [OPAQUE];\n }\n let combinations: IrType[][] = [[]];\n for (const list of memberLists as Evaluated[][]) {\n combinations = combinations.flatMap((done) => list.map((member) => [...done, member.type]));\n }\n return combinations.map((types) => ({ ...value, type: intersectionType(types) }));\n }\n\n private withoutNullish(value: Evaluated): Evaluation {\n const members = this.membersOf(value);\n if (members.some((member) => member.kind !== \"type\")) {\n return OPAQUE;\n }\n const kept = (members as Evaluated[]).filter((member) => !isNullish(member.type));\n return { ...value, type: unionType(kept.map((member) => member.type)) };\n }\n\n /** `Extract<T, { key: unknown }>` keeps the members that have `key`; other probes are opaque. */\n private extract(value: Evaluated, probe: IrType): Evaluation {\n const [member] = probe.kind === \"object\" ? probe.members : [];\n if (probe.kind !== \"object\" || probe.members.length !== 1 || member?.kind !== \"property\") {\n return OPAQUE;\n }\n return extracted(this, value, propertyKey(member.name));\n }\n\n /** `value[index]` for a string literal, `string` or `number` index. */\n index(value: Evaluated, index: IrType): Evaluation {\n return indexType(this, value, index);\n }\n}\n"],"names":["OPAQUE","omitted","markerObject","absorbed","intersectionType","isNullish","unionType","extracted","propertyKey","indexType"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { OPAQUE, absorbed,
|
|
2
|
-
import {
|
|
1
|
+
import { OPAQUE, absorbed, intersectionType, isNullish, unionType, propertyKey } from './evaluation.mjs';
|
|
2
|
+
import { indexType } from './type-indexing.mjs';
|
|
3
|
+
import { markerObject, omitted, extracted } from './type-rules.mjs';
|
|
3
4
|
|
|
4
5
|
const MAX_EXPANSIONS = 200;
|
|
5
6
|
const DEEP_PREFIX = "FlattenedDeepRequired<";
|
|
6
7
|
const MAX_DISTRIBUTED = 64;
|
|
7
|
-
const NULLISH = /* @__PURE__ */ new Set(["null", "undefined"]);
|
|
8
8
|
class TypeEvaluator {
|
|
9
9
|
declared = /* @__PURE__ */ new Map();
|
|
10
10
|
expansions = 0;
|
|
@@ -128,116 +128,8 @@ class TypeEvaluator {
|
|
|
128
128
|
}
|
|
129
129
|
/** `value[index]` for a string literal, `string` or `number` index. */
|
|
130
130
|
index(value, index) {
|
|
131
|
-
|
|
132
|
-
if (owner.kind !== "type") {
|
|
133
|
-
return owner;
|
|
134
|
-
}
|
|
135
|
-
if (this.membersOf(owner).length > 1) {
|
|
136
|
-
return this.unionIndex(owner, index);
|
|
137
|
-
}
|
|
138
|
-
const { type } = owner;
|
|
139
|
-
switch (type.kind) {
|
|
140
|
-
case "object":
|
|
141
|
-
return this.memberType(owner, type.members, index);
|
|
142
|
-
case "intersection":
|
|
143
|
-
return this.partsIndex(owner, type.types, index);
|
|
144
|
-
case "union":
|
|
145
|
-
return this.unionIndex(owner, index);
|
|
146
|
-
case "array":
|
|
147
|
-
return isNumberIndex(index) ? this.flattened(owner, type.element) : builtInIndex(index);
|
|
148
|
-
case "keyword":
|
|
149
|
-
return type.keyword === "never" ? owner : builtInIndex(index);
|
|
150
|
-
default:
|
|
151
|
-
return builtInIndex(index);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
memberType(owner, members, index) {
|
|
155
|
-
const key = indexKey(index);
|
|
156
|
-
const property = members.find(
|
|
157
|
-
(member) => member.kind === "property" && key !== null && propertyKey(member.name) === key
|
|
158
|
-
);
|
|
159
|
-
if (property !== void 0) {
|
|
160
|
-
return this.flattened(owner, property.type);
|
|
161
|
-
}
|
|
162
|
-
const signature = members.find((member) => member.kind === "indexSignature");
|
|
163
|
-
if (signature !== void 0) {
|
|
164
|
-
return this.flattened(owner, signature.type);
|
|
165
|
-
}
|
|
166
|
-
return key === null || isObjectBuiltIn(key) ? OPAQUE : MISSING;
|
|
167
|
-
}
|
|
168
|
-
partsIndex(owner, parts, index) {
|
|
169
|
-
if (isNeverIntersection(this, owner, parts)) {
|
|
170
|
-
return { ...owner, type: NEVER };
|
|
171
|
-
}
|
|
172
|
-
const found = parts.map((type) => this.index({ ...owner, type }, index));
|
|
173
|
-
if (found.some((part) => part.kind === "opaque")) {
|
|
174
|
-
return OPAQUE;
|
|
175
|
-
}
|
|
176
|
-
const read = parts.map((type, at) => ({ type, found: found[at] }));
|
|
177
|
-
const types = declaredFirst(this, owner, indexKey(index), read).flatMap(
|
|
178
|
-
(part) => part.kind === "type" ? [part.type] : []
|
|
179
|
-
);
|
|
180
|
-
return types.length === 0 ? MISSING : { ...owner, type: intersectionType(types) };
|
|
181
|
-
}
|
|
182
|
-
unionIndex(owner, index) {
|
|
183
|
-
const found = this.membersOf(owner).map(
|
|
184
|
-
(member) => member.kind === "type" ? this.index(member, index) : member
|
|
185
|
-
);
|
|
186
|
-
if (found.some((member) => member.kind === "missing")) {
|
|
187
|
-
return MISSING;
|
|
188
|
-
}
|
|
189
|
-
if (found.some((member) => member.kind === "opaque")) {
|
|
190
|
-
return OPAQUE;
|
|
191
|
-
}
|
|
192
|
-
return { ...owner, type: unionType(found.map((member) => member.type)) };
|
|
131
|
+
return indexType(this, value, index);
|
|
193
132
|
}
|
|
194
|
-
/**
|
|
195
|
-
* A member read through `FlattenedDeepRequired`: a value that is only arrays (and `undefined` or
|
|
196
|
-
* `null`) is replaced by its elements, anything else loses `undefined` and `null`.
|
|
197
|
-
*/
|
|
198
|
-
flattened(owner, type) {
|
|
199
|
-
const member = { ...owner, type };
|
|
200
|
-
if (!owner.deep) {
|
|
201
|
-
return this.expand(member);
|
|
202
|
-
}
|
|
203
|
-
const members = this.membersOf(member);
|
|
204
|
-
if (members.some((candidate) => candidate.kind !== "type")) {
|
|
205
|
-
return OPAQUE;
|
|
206
|
-
}
|
|
207
|
-
const present = members.filter((candidate) => !isNullish(candidate.type));
|
|
208
|
-
const elements = present.map((candidate) => arrayElement(candidate.type));
|
|
209
|
-
if (present.length > 0 && elements.every((element) => element !== null)) {
|
|
210
|
-
return this.expand({ ...owner, type: unionType(elements) });
|
|
211
|
-
}
|
|
212
|
-
return { ...owner, type: unionType(present.map((candidate) => candidate.type)) };
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
function isNullish(type) {
|
|
216
|
-
return type.kind === "keyword" && NULLISH.has(type.keyword);
|
|
217
|
-
}
|
|
218
|
-
function arrayElement(type) {
|
|
219
|
-
return type.kind === "array" ? type.element : null;
|
|
220
|
-
}
|
|
221
|
-
function intersectionType(types) {
|
|
222
|
-
return types.length === 1 ? types[0] : { kind: "intersection", types };
|
|
223
|
-
}
|
|
224
|
-
function indexKey(index) {
|
|
225
|
-
if (index.kind === "stringLiteral") {
|
|
226
|
-
return index.value;
|
|
227
|
-
}
|
|
228
|
-
return index.kind === "numberLiteral" ? String(index.value) : null;
|
|
229
|
-
}
|
|
230
|
-
function isNumberIndex(index) {
|
|
231
|
-
const key = indexKey(index);
|
|
232
|
-
return index.kind === "keyword" && index.keyword === "number" || /^\d+$/.test(key ?? "");
|
|
233
|
-
}
|
|
234
|
-
function isObjectBuiltIn(key) {
|
|
235
|
-
return key in {};
|
|
236
|
-
}
|
|
237
|
-
function builtInIndex(index) {
|
|
238
|
-
const key = indexKey(index);
|
|
239
|
-
const isBuiltIn = key === null || key in String.prototype || key in Array.prototype;
|
|
240
|
-
return isBuiltIn || key in Number.prototype ? OPAQUE : MISSING;
|
|
241
133
|
}
|
|
242
134
|
|
|
243
135
|
export { TypeEvaluator };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-evaluation.mjs","sources":["../../../../src/application/transform/footer/type-evaluation.ts"],"sourcesContent":["import type { IrDeclaration, IrMember, IrType } from \"../../../domain/ir/nodes.js\";\nimport {\n absorbed,\n type Evaluated,\n type Evaluation,\n MISSING,\n NEVER,\n OPAQUE,\n propertyKey,\n unionType,\n} from \"./evaluation.js\";\nimport {\n declaredFirst,\n extracted,\n isNeverIntersection,\n markerObject,\n omitted,\n} from \"./type-rules.js\";\n\n/**\n * A small evaluator of the generated types, as TypeScript reads them, for the `--enum-values`\n * check (ADR-027). It follows the declarations of the document and the helper types the generator\n * writes (`NonNullable`, `Extract`, `WithRequired`, `Omit`, `Record`, `FlattenedDeepRequired`). Its\n * answers are sure: a key is `missing` only where TypeScript reports it, and every type it does\n * not model is `opaque`, which never counts as an error.\n */\n\n/** How many references one evaluation expands; a deeper one is opaque. */\nconst MAX_EXPANSIONS = 200;\nconst DEEP_PREFIX = \"FlattenedDeepRequired<\";\n/** How many members distributing an intersection may give; more is opaque. */\nconst MAX_DISTRIBUTED = 64;\nconst NULLISH: ReadonlySet<string> = new Set([\"null\", \"undefined\"]);\n\nexport class TypeEvaluator {\n private readonly declared = new Map<string, IrType>();\n private expansions = 0;\n\n constructor(declarations: readonly IrDeclaration[]) {\n for (const declaration of declarations) {\n if (declaration.kind === \"interface\") {\n this.declared.set(declaration.name, { kind: \"object\", members: declaration.members });\n } else if (declaration.kind === \"typeAlias\") {\n this.declared.set(declaration.name, declaration.type);\n }\n }\n }\n\n /** Evaluate a type written in the footer; the expansion budget starts again. */\n evaluate(type: IrType): Evaluation {\n this.expansions = 0;\n return this.expand({ kind: \"type\", type, deep: false });\n }\n\n /** The type with references, `readonly` and indexed access resolved at the top. */\n expand(value: Evaluated): Evaluation {\n const { type } = value;\n switch (type.kind) {\n case \"readonly\":\n return this.expand({ ...value, type: type.type });\n case \"indexedAccess\":\n return this.indexedAccess(value, type.object, type.index);\n case \"reference\":\n return this.reference(value, type.name, type.typeArguments);\n case \"raw\":\n case \"tuple\":\n return OPAQUE;\n default:\n return value;\n }\n }\n\n private indexedAccess(value: Evaluated, object: IrType, index: IrType): Evaluation {\n const owner = this.expand({ ...value, type: object });\n return owner.kind === \"type\" ? this.index(owner, index) : owner;\n }\n\n private reference(value: Evaluated, name: string, args: readonly IrType[]): Evaluation {\n // Only references cost budget: re-expanding an already expanded value (as the checks after\n // `evaluate` do) is free, so a large evaluation does not leave its checks opaque.\n if (this.expansions++ > MAX_EXPANSIONS) {\n return OPAQUE;\n }\n if (name.startsWith(DEEP_PREFIX) && name.endsWith(\">\")) {\n const root = this.declared.get(name.slice(DEEP_PREFIX.length, -1));\n return root === undefined ? OPAQUE : this.expand({ kind: \"type\", type: root, deep: true });\n }\n const declared = args.length === 0 ? this.declared.get(name) : undefined;\n if (declared !== undefined) {\n return this.expand({ ...value, type: declared });\n }\n const [first, second] = args;\n if (first === undefined) {\n return OPAQUE;\n }\n const argument = this.expand({ ...value, type: first });\n if (argument.kind !== \"type\") {\n return argument;\n }\n return this.helper(name, argument, second);\n }\n\n private helper(name: string, argument: Evaluated, second: IrType | undefined): Evaluation {\n switch (name) {\n case \"NonNullable\":\n return this.withoutNullish(argument);\n case \"WithRequired\":\n case \"Readonly\":\n return argument;\n case \"Extract\":\n return second === undefined ? OPAQUE : this.extract(argument, second);\n case \"Omit\":\n return second === undefined ? OPAQUE : omitted(this, argument, second);\n default:\n return markerObject(name, argument) ?? OPAQUE;\n }\n }\n\n /**\n * The members of a union, each expanded; an intersection with unions in it is distributed over\n * them (`A & (B | C)` is `(A & B) | (A & C)`), as TypeScript normalizes it. A type that is not a\n * union is its only member. A union with an `any` or `unknown` member is that keyword alone.\n */\n membersOf(value: Evaluated): readonly Evaluation[] {\n const expanded = this.expand(value);\n if (expanded.kind !== \"type\") {\n return [expanded];\n }\n const { type } = expanded;\n if (type.kind === \"union\") {\n return absorbed(\n type.types.flatMap((member) => this.membersOf({ ...expanded, type: member })),\n );\n }\n return type.kind === \"intersection\" ? this.distributed(expanded, type.types) : [expanded];\n }\n\n private distributed(value: Evaluated, parts: readonly IrType[]): readonly Evaluation[] {\n const memberLists = parts.map((part) => this.membersOf({ ...value, type: part }));\n const size = memberLists.reduce((product, list) => product * list.length, 1);\n if (size > MAX_DISTRIBUTED || memberLists.some((list) => list.some((m) => m.kind !== \"type\"))) {\n return [OPAQUE];\n }\n let combinations: IrType[][] = [[]];\n for (const list of memberLists as Evaluated[][]) {\n combinations = combinations.flatMap((done) => list.map((member) => [...done, member.type]));\n }\n return combinations.map((types) => ({ ...value, type: intersectionType(types) }));\n }\n\n private withoutNullish(value: Evaluated): Evaluation {\n const members = this.membersOf(value);\n if (members.some((member) => member.kind !== \"type\")) {\n return OPAQUE;\n }\n const kept = (members as Evaluated[]).filter((member) => !isNullish(member.type));\n return { ...value, type: unionType(kept.map((member) => member.type)) };\n }\n\n /** `Extract<T, { key: unknown }>` keeps the members that have `key`; other probes are opaque. */\n private extract(value: Evaluated, probe: IrType): Evaluation {\n const [member] = probe.kind === \"object\" ? probe.members : [];\n if (probe.kind !== \"object\" || probe.members.length !== 1 || member?.kind !== \"property\") {\n return OPAQUE;\n }\n return extracted(this, value, propertyKey(member.name));\n }\n\n /** `value[index]` for a string literal, `string` or `number` index. */\n index(value: Evaluated, index: IrType): Evaluation {\n const owner = this.expand(value);\n if (owner.kind !== \"type\") {\n return owner;\n }\n if (this.membersOf(owner).length > 1) {\n return this.unionIndex(owner, index);\n }\n const { type } = owner;\n switch (type.kind) {\n case \"object\":\n return this.memberType(owner, type.members, index);\n case \"intersection\":\n return this.partsIndex(owner, type.types, index);\n case \"union\":\n return this.unionIndex(owner, index);\n case \"array\":\n return isNumberIndex(index) ? this.flattened(owner, type.element) : builtInIndex(index);\n case \"keyword\":\n return type.keyword === \"never\" ? owner : builtInIndex(index);\n default:\n return builtInIndex(index);\n }\n }\n\n private memberType(owner: Evaluated, members: readonly IrMember[], index: IrType): Evaluation {\n const key = indexKey(index);\n const property = members.find(\n (member) => member.kind === \"property\" && key !== null && propertyKey(member.name) === key,\n );\n if (property !== undefined) {\n return this.flattened(owner, property.type);\n }\n const signature = members.find((member) => member.kind === \"indexSignature\");\n if (signature !== undefined) {\n return this.flattened(owner, signature.type);\n }\n return key === null || isObjectBuiltIn(key) ? OPAQUE : MISSING;\n }\n\n private partsIndex(owner: Evaluated, parts: readonly IrType[], index: IrType): Evaluation {\n if (isNeverIntersection(this, owner, parts)) {\n return { ...owner, type: NEVER };\n }\n const found = parts.map((type) => this.index({ ...owner, type }, index));\n if (found.some((part) => part.kind === \"opaque\")) {\n return OPAQUE;\n }\n const read = parts.map((type, at) => ({ type, found: found[at] as Evaluation }));\n const types = declaredFirst(this, owner, indexKey(index), read).flatMap((part) =>\n part.kind === \"type\" ? [part.type] : [],\n );\n return types.length === 0 ? MISSING : { ...owner, type: intersectionType(types) };\n }\n\n private unionIndex(owner: Evaluated, index: IrType): Evaluation {\n const found = this.membersOf(owner).map((member) =>\n member.kind === \"type\" ? this.index(member, index) : member,\n );\n if (found.some((member) => member.kind === \"missing\")) {\n return MISSING;\n }\n if (found.some((member) => member.kind === \"opaque\")) {\n return OPAQUE;\n }\n return { ...owner, type: unionType((found as Evaluated[]).map((member) => member.type)) };\n }\n\n /**\n * A member read through `FlattenedDeepRequired`: a value that is only arrays (and `undefined` or\n * `null`) is replaced by its elements, anything else loses `undefined` and `null`.\n */\n private flattened(owner: Evaluated, type: IrType): Evaluation {\n const member: Evaluated = { ...owner, type };\n if (!owner.deep) {\n return this.expand(member);\n }\n const members = this.membersOf(member);\n if (members.some((candidate) => candidate.kind !== \"type\")) {\n return OPAQUE;\n }\n const present = (members as Evaluated[]).filter((candidate) => !isNullish(candidate.type));\n const elements = present.map((candidate) => arrayElement(candidate.type));\n if (present.length > 0 && elements.every((element) => element !== null)) {\n return this.expand({ ...owner, type: unionType(elements as IrType[]) });\n }\n return { ...owner, type: unionType(present.map((candidate) => candidate.type)) };\n }\n}\n\nfunction isNullish(type: IrType): boolean {\n return type.kind === \"keyword\" && NULLISH.has(type.keyword);\n}\n\n/** The element of an expanded member; expanding already dropped `readonly`. */\nfunction arrayElement(type: IrType): IrType | null {\n return type.kind === \"array\" ? type.element : null;\n}\n\nfunction intersectionType(types: readonly IrType[]): IrType {\n return types.length === 1 ? (types[0] as IrType) : { kind: \"intersection\", types };\n}\n\nfunction indexKey(index: IrType): string | null {\n if (index.kind === \"stringLiteral\") {\n return index.value;\n }\n return index.kind === \"numberLiteral\" ? String(index.value) : null;\n}\n\nfunction isNumberIndex(index: IrType): boolean {\n const key = indexKey(index);\n return (index.kind === \"keyword\" && index.keyword === \"number\") || /^\\d+$/.test(key ?? \"\");\n}\n\nfunction isObjectBuiltIn(key: string): boolean {\n return key in {};\n}\n\n/** A key of a primitive or an array: a built-in member is opaque, any other key is missing. */\nfunction builtInIndex(index: IrType): Evaluation {\n const key = indexKey(index);\n const isBuiltIn = key === null || key in String.prototype || key in Array.prototype;\n return isBuiltIn || key in Number.prototype ? OPAQUE : MISSING;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"type-evaluation.mjs","sources":["../../../../src/application/transform/footer/type-evaluation.ts"],"sourcesContent":["import type { IrDeclaration, IrType } from \"../../../domain/ir/nodes.js\";\nimport {\n absorbed,\n type Evaluated,\n type Evaluation,\n intersectionType,\n isNullish,\n OPAQUE,\n propertyKey,\n unionType,\n} from \"./evaluation.js\";\nimport { indexType } from \"./type-indexing.js\";\nimport { extracted, markerObject, omitted } from \"./type-rules.js\";\n\n/**\n * A small evaluator of the generated types, as TypeScript reads them, for the `--enum-values`\n * check (ADR-027). It follows the declarations of the document and the helper types the generator\n * writes (`NonNullable`, `Extract`, `WithRequired`, `Omit`, `Record`, `FlattenedDeepRequired`). Its\n * answers are sure: a key is `missing` only where TypeScript reports it, and every type it does\n * not model is `opaque`, which never counts as an error.\n */\n\n/** How many references one evaluation expands; a deeper one is opaque. */\nconst MAX_EXPANSIONS = 200;\nconst DEEP_PREFIX = \"FlattenedDeepRequired<\";\n/** How many members distributing an intersection may give; more is opaque. */\nconst MAX_DISTRIBUTED = 64;\n\nexport class TypeEvaluator {\n private readonly declared = new Map<string, IrType>();\n private expansions = 0;\n\n constructor(declarations: readonly IrDeclaration[]) {\n for (const declaration of declarations) {\n if (declaration.kind === \"interface\") {\n this.declared.set(declaration.name, { kind: \"object\", members: declaration.members });\n } else if (declaration.kind === \"typeAlias\") {\n this.declared.set(declaration.name, declaration.type);\n }\n }\n }\n\n /** Evaluate a type written in the footer; the expansion budget starts again. */\n evaluate(type: IrType): Evaluation {\n this.expansions = 0;\n return this.expand({ kind: \"type\", type, deep: false });\n }\n\n /** The type with references, `readonly` and indexed access resolved at the top. */\n expand(value: Evaluated): Evaluation {\n const { type } = value;\n switch (type.kind) {\n case \"readonly\":\n return this.expand({ ...value, type: type.type });\n case \"indexedAccess\":\n return this.indexedAccess(value, type.object, type.index);\n case \"reference\":\n return this.reference(value, type.name, type.typeArguments);\n case \"raw\":\n case \"tuple\":\n return OPAQUE;\n default:\n return value;\n }\n }\n\n private indexedAccess(value: Evaluated, object: IrType, index: IrType): Evaluation {\n const owner = this.expand({ ...value, type: object });\n return owner.kind === \"type\" ? this.index(owner, index) : owner;\n }\n\n private reference(value: Evaluated, name: string, args: readonly IrType[]): Evaluation {\n // Only references cost budget: re-expanding an already expanded value (as the checks after\n // `evaluate` do) is free, so a large evaluation does not leave its checks opaque.\n if (this.expansions++ > MAX_EXPANSIONS) {\n return OPAQUE;\n }\n if (name.startsWith(DEEP_PREFIX) && name.endsWith(\">\")) {\n const root = this.declared.get(name.slice(DEEP_PREFIX.length, -1));\n return root === undefined ? OPAQUE : this.expand({ kind: \"type\", type: root, deep: true });\n }\n const declared = args.length === 0 ? this.declared.get(name) : undefined;\n if (declared !== undefined) {\n return this.expand({ ...value, type: declared });\n }\n const [first, second] = args;\n if (first === undefined) {\n return OPAQUE;\n }\n const argument = this.expand({ ...value, type: first });\n if (argument.kind !== \"type\") {\n return argument;\n }\n return this.helper(name, argument, second);\n }\n\n private helper(name: string, argument: Evaluated, second: IrType | undefined): Evaluation {\n switch (name) {\n case \"NonNullable\":\n return this.withoutNullish(argument);\n case \"WithRequired\":\n case \"Readonly\":\n return argument;\n case \"Extract\":\n return second === undefined ? OPAQUE : this.extract(argument, second);\n case \"Omit\":\n return second === undefined ? OPAQUE : omitted(this, argument, second);\n default:\n return markerObject(name, argument) ?? OPAQUE;\n }\n }\n\n /**\n * The members of a union, each expanded; an intersection with unions in it is distributed over\n * them (`A & (B | C)` is `(A & B) | (A & C)`), as TypeScript normalizes it. A type that is not a\n * union is its only member. A union with an `any` or `unknown` member is that keyword alone.\n */\n membersOf(value: Evaluated): readonly Evaluation[] {\n const expanded = this.expand(value);\n if (expanded.kind !== \"type\") {\n return [expanded];\n }\n const { type } = expanded;\n if (type.kind === \"union\") {\n return absorbed(\n type.types.flatMap((member) => this.membersOf({ ...expanded, type: member })),\n );\n }\n return type.kind === \"intersection\" ? this.distributed(expanded, type.types) : [expanded];\n }\n\n private distributed(value: Evaluated, parts: readonly IrType[]): readonly Evaluation[] {\n const memberLists = parts.map((part) => this.membersOf({ ...value, type: part }));\n const size = memberLists.reduce((product, list) => product * list.length, 1);\n if (size > MAX_DISTRIBUTED || memberLists.some((list) => list.some((m) => m.kind !== \"type\"))) {\n return [OPAQUE];\n }\n let combinations: IrType[][] = [[]];\n for (const list of memberLists as Evaluated[][]) {\n combinations = combinations.flatMap((done) => list.map((member) => [...done, member.type]));\n }\n return combinations.map((types) => ({ ...value, type: intersectionType(types) }));\n }\n\n private withoutNullish(value: Evaluated): Evaluation {\n const members = this.membersOf(value);\n if (members.some((member) => member.kind !== \"type\")) {\n return OPAQUE;\n }\n const kept = (members as Evaluated[]).filter((member) => !isNullish(member.type));\n return { ...value, type: unionType(kept.map((member) => member.type)) };\n }\n\n /** `Extract<T, { key: unknown }>` keeps the members that have `key`; other probes are opaque. */\n private extract(value: Evaluated, probe: IrType): Evaluation {\n const [member] = probe.kind === \"object\" ? probe.members : [];\n if (probe.kind !== \"object\" || probe.members.length !== 1 || member?.kind !== \"property\") {\n return OPAQUE;\n }\n return extracted(this, value, propertyKey(member.name));\n }\n\n /** `value[index]` for a string literal, `string` or `number` index. */\n index(value: Evaluated, index: IrType): Evaluation {\n return indexType(this, value, index);\n }\n}\n"],"names":[],"mappings":";;;;AAuBA,MAAM,cAAA,GAAiB,GAAA;AACvB,MAAM,WAAA,GAAc,wBAAA;AAEpB,MAAM,eAAA,GAAkB,EAAA;AAEjB,MAAM,aAAA,CAAc;AAAA,EACR,QAAA,uBAAe,GAAA,EAAoB;AAAA,EAC5C,UAAA,GAAa,CAAA;AAAA,EAErB,YAAY,YAAA,EAAwC;AAClD,IAAA,KAAA,MAAW,eAAe,YAAA,EAAc;AACtC,MAAA,IAAI,WAAA,CAAY,SAAS,WAAA,EAAa;AACpC,QAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,WAAA,CAAY,IAAA,EAAM,EAAE,MAAM,QAAA,EAAU,OAAA,EAAS,WAAA,CAAY,OAAA,EAAS,CAAA;AAAA,MACtF,CAAA,MAAA,IAAW,WAAA,CAAY,IAAA,KAAS,WAAA,EAAa;AAC3C,QAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,WAAA,CAAY,IAAA,EAAM,YAAY,IAAI,CAAA;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,SAAS,IAAA,EAA0B;AACjC,IAAA,IAAA,CAAK,UAAA,GAAa,CAAA;AAClB,IAAA,OAAO,IAAA,CAAK,OAAO,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AAAA,EACxD;AAAA;AAAA,EAGA,OAAO,KAAA,EAA8B;AACnC,IAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,IAAA,QAAQ,KAAK,IAAA;AAAM,MACjB,KAAK,UAAA;AACH,QAAA,OAAO,IAAA,CAAK,OAAO,EAAE,GAAG,OAAO,IAAA,EAAM,IAAA,CAAK,MAAM,CAAA;AAAA,MAClD,KAAK,eAAA;AACH,QAAA,OAAO,KAAK,aAAA,CAAc,KAAA,EAAO,IAAA,CAAK,MAAA,EAAQ,KAAK,KAAK,CAAA;AAAA,MAC1D,KAAK,WAAA;AACH,QAAA,OAAO,KAAK,SAAA,CAAU,KAAA,EAAO,IAAA,CAAK,IAAA,EAAM,KAAK,aAAa,CAAA;AAAA,MAC5D,KAAK,KAAA;AAAA,MACL,KAAK,OAAA;AACH,QAAA,OAAO,MAAA;AAAA,MACT;AACE,QAAA,OAAO,KAAA;AAAA;AACX,EACF;AAAA,EAEQ,aAAA,CAAc,KAAA,EAAkB,MAAA,EAAgB,KAAA,EAA2B;AACjF,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,QAAQ,CAAA;AACpD,IAAA,OAAO,MAAM,IAAA,KAAS,MAAA,GAAS,KAAK,KAAA,CAAM,KAAA,EAAO,KAAK,CAAA,GAAI,KAAA;AAAA,EAC5D;AAAA,EAEQ,SAAA,CAAU,KAAA,EAAkB,IAAA,EAAc,IAAA,EAAqC;AAGrF,IAAA,IAAI,IAAA,CAAK,eAAe,cAAA,EAAgB;AACtC,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,IAAI,KAAK,UAAA,CAAW,WAAW,KAAK,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AACtD,MAAA,MAAM,IAAA,GAAO,KAAK,QAAA,CAAS,GAAA,CAAI,KAAK,KAAA,CAAM,WAAA,CAAY,MAAA,EAAQ,EAAE,CAAC,CAAA;AACjE,MAAA,OAAO,IAAA,KAAS,MAAA,GAAY,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,IAC3F;AACA,IAAA,MAAM,QAAA,GAAW,KAAK,MAAA,KAAW,CAAA,GAAI,KAAK,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA,GAAI,MAAA;AAC/D,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,OAAO,KAAK,MAAA,CAAO,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,UAAU,CAAA;AAAA,IACjD;AACA,IAAA,MAAM,CAAC,KAAA,EAAO,MAAM,CAAA,GAAI,IAAA;AACxB,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAM,QAAA,GAAW,KAAK,MAAA,CAAO,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,OAAO,CAAA;AACtD,IAAA,IAAI,QAAA,CAAS,SAAS,MAAA,EAAQ;AAC5B,MAAA,OAAO,QAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,QAAA,EAAU,MAAM,CAAA;AAAA,EAC3C;AAAA,EAEQ,MAAA,CAAO,IAAA,EAAc,QAAA,EAAqB,MAAA,EAAwC;AACxF,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,aAAA;AACH,QAAA,OAAO,IAAA,CAAK,eAAe,QAAQ,CAAA;AAAA,MACrC,KAAK,cAAA;AAAA,MACL,KAAK,UAAA;AACH,QAAA,OAAO,QAAA;AAAA,MACT,KAAK,SAAA;AACH,QAAA,OAAO,WAAW,MAAA,GAAY,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,UAAU,MAAM,CAAA;AAAA,MACtE,KAAK,MAAA;AACH,QAAA,OAAO,WAAW,MAAA,GAAY,MAAA,GAAS,OAAA,CAAQ,IAAA,EAAM,UAAU,MAAM,CAAA;AAAA,MACvE;AACE,QAAA,OAAO,YAAA,CAAa,IAAA,EAAM,QAAQ,CAAA,IAAK,MAAA;AAAA;AAC3C,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,KAAA,EAAyC;AACjD,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AAClC,IAAA,IAAI,QAAA,CAAS,SAAS,MAAA,EAAQ;AAC5B,MAAA,OAAO,CAAC,QAAQ,CAAA;AAAA,IAClB;AACA,IAAA,MAAM,EAAE,MAAK,GAAI,QAAA;AACjB,IAAA,IAAI,IAAA,CAAK,SAAS,OAAA,EAAS;AACzB,MAAA,OAAO,QAAA;AAAA,QACL,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,MAAA,KAAW,IAAA,CAAK,SAAA,CAAU,EAAE,GAAG,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,CAAC;AAAA,OAC9E;AAAA,IACF;AACA,IAAA,OAAO,IAAA,CAAK,IAAA,KAAS,cAAA,GAAiB,IAAA,CAAK,WAAA,CAAY,UAAU,IAAA,CAAK,KAAK,CAAA,GAAI,CAAC,QAAQ,CAAA;AAAA,EAC1F;AAAA,EAEQ,WAAA,CAAY,OAAkB,KAAA,EAAiD;AACrF,IAAA,MAAM,WAAA,GAAc,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,SAAA,CAAU,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,CAAC,CAAA;AAChF,IAAA,MAAM,IAAA,GAAO,YAAY,MAAA,CAAO,CAAC,SAAS,IAAA,KAAS,OAAA,GAAU,IAAA,CAAK,MAAA,EAAQ,CAAC,CAAA;AAC3E,IAAA,IAAI,IAAA,GAAO,eAAA,IAAmB,WAAA,CAAY,IAAA,CAAK,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,MAAM,CAAC,CAAA,EAAG;AAC7F,MAAA,OAAO,CAAC,MAAM,CAAA;AAAA,IAChB;AACA,IAAA,IAAI,YAAA,GAA2B,CAAC,EAAE,CAAA;AAClC,IAAA,KAAA,MAAW,QAAQ,WAAA,EAA8B;AAC/C,MAAA,YAAA,GAAe,YAAA,CAAa,OAAA,CAAQ,CAAC,IAAA,KAAS,KAAK,GAAA,CAAI,CAAC,MAAA,KAAW,CAAC,GAAG,IAAA,EAAM,MAAA,CAAO,IAAI,CAAC,CAAC,CAAA;AAAA,IAC5F;AACA,IAAA,OAAO,YAAA,CAAa,GAAA,CAAI,CAAC,KAAA,MAAW,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,gBAAA,CAAiB,KAAK,CAAA,EAAE,CAAE,CAAA;AAAA,EAClF;AAAA,EAEQ,eAAe,KAAA,EAA8B;AACnD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AACpC,IAAA,IAAI,QAAQ,IAAA,CAAK,CAAC,WAAW,MAAA,CAAO,IAAA,KAAS,MAAM,CAAA,EAAG;AACpD,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAQ,QAAwB,MAAA,CAAO,CAAC,WAAW,CAAC,SAAA,CAAU,MAAA,CAAO,IAAI,CAAC,CAAA;AAChF,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,SAAA,CAAU,IAAA,CAAK,GAAA,CAAI,CAAC,MAAA,KAAW,MAAA,CAAO,IAAI,CAAC,CAAA,EAAE;AAAA,EACxE;AAAA;AAAA,EAGQ,OAAA,CAAQ,OAAkB,KAAA,EAA2B;AAC3D,IAAA,MAAM,CAAC,MAAM,CAAA,GAAI,KAAA,CAAM,SAAS,QAAA,GAAW,KAAA,CAAM,UAAU,EAAC;AAC5D,IAAA,IAAI,KAAA,CAAM,SAAS,QAAA,IAAY,KAAA,CAAM,QAAQ,MAAA,KAAW,CAAA,IAAK,MAAA,EAAQ,IAAA,KAAS,UAAA,EAAY;AACxF,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAO,UAAU,IAAA,EAAM,KAAA,EAAO,WAAA,CAAY,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,EACxD;AAAA;AAAA,EAGA,KAAA,CAAM,OAAkB,KAAA,EAA2B;AACjD,IAAA,OAAO,SAAA,CAAU,IAAA,EAAM,KAAA,EAAO,KAAK,CAAA;AAAA,EACrC;AACF;;"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const evaluation = require('./evaluation.cjs');
|
|
4
|
+
const typeRules = require('./type-rules.cjs');
|
|
5
|
+
|
|
6
|
+
function indexType(types, value, index) {
|
|
7
|
+
const owner = types.expand(value);
|
|
8
|
+
if (owner.kind !== "type") {
|
|
9
|
+
return owner;
|
|
10
|
+
}
|
|
11
|
+
if (types.membersOf(owner).length > 1) {
|
|
12
|
+
return unionIndex(types, owner, index);
|
|
13
|
+
}
|
|
14
|
+
const { type } = owner;
|
|
15
|
+
switch (type.kind) {
|
|
16
|
+
case "object":
|
|
17
|
+
return memberType(types, owner, type.members, index);
|
|
18
|
+
case "intersection":
|
|
19
|
+
return partsIndex(types, owner, type.types, index);
|
|
20
|
+
case "union":
|
|
21
|
+
return unionIndex(types, owner, index);
|
|
22
|
+
case "array":
|
|
23
|
+
return isNumberIndex(index) ? flattened(types, owner, type.element) : builtInIndex(index);
|
|
24
|
+
case "keyword":
|
|
25
|
+
return type.keyword === "never" ? owner : builtInIndex(index);
|
|
26
|
+
default:
|
|
27
|
+
return builtInIndex(index);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function memberType(types, owner, members, index) {
|
|
31
|
+
const key = indexKey(index);
|
|
32
|
+
const property = members.find(
|
|
33
|
+
(member) => member.kind === "property" && key !== null && evaluation.propertyKey(member.name) === key
|
|
34
|
+
);
|
|
35
|
+
if (property !== void 0) {
|
|
36
|
+
return flattened(types, owner, property.type);
|
|
37
|
+
}
|
|
38
|
+
const signature = members.find((member) => member.kind === "indexSignature");
|
|
39
|
+
if (signature !== void 0) {
|
|
40
|
+
return flattened(types, owner, signature.type);
|
|
41
|
+
}
|
|
42
|
+
return key === null || isObjectBuiltIn(key) ? evaluation.OPAQUE : evaluation.MISSING;
|
|
43
|
+
}
|
|
44
|
+
function partsIndex(types, owner, parts, index) {
|
|
45
|
+
if (typeRules.isNeverIntersection(types, owner, parts)) {
|
|
46
|
+
return { ...owner, type: evaluation.NEVER };
|
|
47
|
+
}
|
|
48
|
+
const found = parts.map((type) => types.index({ ...owner, type }, index));
|
|
49
|
+
if (found.some((part) => part.kind === "opaque")) {
|
|
50
|
+
return evaluation.OPAQUE;
|
|
51
|
+
}
|
|
52
|
+
const read = parts.map((type, at) => ({ type, found: found[at] }));
|
|
53
|
+
const kept = typeRules.declaredFirst(types, owner, indexKey(index), read).flatMap(
|
|
54
|
+
(part) => part.kind === "type" ? [part.type] : []
|
|
55
|
+
);
|
|
56
|
+
return kept.length === 0 ? evaluation.MISSING : { ...owner, type: evaluation.intersectionType(kept) };
|
|
57
|
+
}
|
|
58
|
+
function unionIndex(types, owner, index) {
|
|
59
|
+
const found = types.membersOf(owner).map((member) => member.kind === "type" ? types.index(member, index) : member);
|
|
60
|
+
if (found.some((member) => member.kind === "missing")) {
|
|
61
|
+
return evaluation.MISSING;
|
|
62
|
+
}
|
|
63
|
+
if (found.some((member) => member.kind === "opaque")) {
|
|
64
|
+
return evaluation.OPAQUE;
|
|
65
|
+
}
|
|
66
|
+
return { ...owner, type: evaluation.unionType(found.map((member) => member.type)) };
|
|
67
|
+
}
|
|
68
|
+
function flattened(types, owner, type) {
|
|
69
|
+
const member = { ...owner, type };
|
|
70
|
+
if (!owner.deep) {
|
|
71
|
+
return types.expand(member);
|
|
72
|
+
}
|
|
73
|
+
const members = types.membersOf(member);
|
|
74
|
+
if (members.some((candidate) => candidate.kind !== "type")) {
|
|
75
|
+
return evaluation.OPAQUE;
|
|
76
|
+
}
|
|
77
|
+
const present = members.filter((candidate) => !evaluation.isNullish(candidate.type));
|
|
78
|
+
const elements = present.map((candidate) => arrayElement(candidate.type));
|
|
79
|
+
if (present.length > 0 && elements.every((element) => element !== null)) {
|
|
80
|
+
return types.expand({ ...owner, type: evaluation.unionType(elements) });
|
|
81
|
+
}
|
|
82
|
+
return { ...owner, type: evaluation.unionType(present.map((candidate) => candidate.type)) };
|
|
83
|
+
}
|
|
84
|
+
function arrayElement(type) {
|
|
85
|
+
return type.kind === "array" ? type.element : null;
|
|
86
|
+
}
|
|
87
|
+
function indexKey(index) {
|
|
88
|
+
if (index.kind === "stringLiteral") {
|
|
89
|
+
return index.value;
|
|
90
|
+
}
|
|
91
|
+
return index.kind === "numberLiteral" ? String(index.value) : null;
|
|
92
|
+
}
|
|
93
|
+
function isNumberIndex(index) {
|
|
94
|
+
const key = indexKey(index);
|
|
95
|
+
return index.kind === "keyword" && index.keyword === "number" || /^\d+$/.test(key ?? "");
|
|
96
|
+
}
|
|
97
|
+
function isObjectBuiltIn(key) {
|
|
98
|
+
return key in {};
|
|
99
|
+
}
|
|
100
|
+
function builtInIndex(index) {
|
|
101
|
+
const key = indexKey(index);
|
|
102
|
+
const isBuiltIn = key === null || key in String.prototype || key in Array.prototype;
|
|
103
|
+
return isBuiltIn || key in Number.prototype ? evaluation.OPAQUE : evaluation.MISSING;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
exports.indexType = indexType;
|
|
107
|
+
//# sourceMappingURL=type-indexing.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-indexing.cjs","sources":["../../../../src/application/transform/footer/type-indexing.ts"],"sourcesContent":["import type { IrMember, IrType } from \"../../../domain/ir/nodes.js\";\nimport {\n type Evaluated,\n type Evaluation,\n intersectionType,\n isNullish,\n MISSING,\n NEVER,\n OPAQUE,\n propertyKey,\n unionType,\n} from \"./evaluation.js\";\nimport { declaredFirst, isNeverIntersection, type TypeExpansion } from \"./type-rules.js\";\n\n/**\n * Indexed access (`T[\"key\"]`, `T[number]`) on the generated types, as TypeScript reads it, for\n * the evaluator of the `--enum-values` check (ADR-027).\n */\n\n/** The part of the evaluator that indexed access uses. */\nexport interface IndexedTypes extends TypeExpansion {\n expand(value: Evaluated): Evaluation;\n index(value: Evaluated, index: IrType): Evaluation;\n}\n\n/** `value[index]` for a string literal, `string` or `number` index. */\nexport function indexType(types: IndexedTypes, value: Evaluated, index: IrType): Evaluation {\n const owner = types.expand(value);\n if (owner.kind !== \"type\") {\n return owner;\n }\n if (types.membersOf(owner).length > 1) {\n return unionIndex(types, owner, index);\n }\n const { type } = owner;\n switch (type.kind) {\n case \"object\":\n return memberType(types, owner, type.members, index);\n case \"intersection\":\n return partsIndex(types, owner, type.types, index);\n case \"union\":\n return unionIndex(types, owner, index);\n case \"array\":\n return isNumberIndex(index) ? flattened(types, owner, type.element) : builtInIndex(index);\n case \"keyword\":\n return type.keyword === \"never\" ? owner : builtInIndex(index);\n default:\n return builtInIndex(index);\n }\n}\n\nfunction memberType(\n types: IndexedTypes,\n owner: Evaluated,\n members: readonly IrMember[],\n index: IrType,\n): Evaluation {\n const key = indexKey(index);\n const property = members.find(\n (member) => member.kind === \"property\" && key !== null && propertyKey(member.name) === key,\n );\n if (property !== undefined) {\n return flattened(types, owner, property.type);\n }\n const signature = members.find((member) => member.kind === \"indexSignature\");\n if (signature !== undefined) {\n return flattened(types, owner, signature.type);\n }\n return key === null || isObjectBuiltIn(key) ? OPAQUE : MISSING;\n}\n\nfunction partsIndex(\n types: IndexedTypes,\n owner: Evaluated,\n parts: readonly IrType[],\n index: IrType,\n): Evaluation {\n if (isNeverIntersection(types, owner, parts)) {\n return { ...owner, type: NEVER };\n }\n const found = parts.map((type) => types.index({ ...owner, type }, index));\n if (found.some((part) => part.kind === \"opaque\")) {\n return OPAQUE;\n }\n const read = parts.map((type, at) => ({ type, found: found[at] as Evaluation }));\n const kept = declaredFirst(types, owner, indexKey(index), read).flatMap((part) =>\n part.kind === \"type\" ? [part.type] : [],\n );\n return kept.length === 0 ? MISSING : { ...owner, type: intersectionType(kept) };\n}\n\nfunction unionIndex(types: IndexedTypes, owner: Evaluated, index: IrType): Evaluation {\n const found = types\n .membersOf(owner)\n .map((member) => (member.kind === \"type\" ? types.index(member, index) : member));\n if (found.some((member) => member.kind === \"missing\")) {\n return MISSING;\n }\n if (found.some((member) => member.kind === \"opaque\")) {\n return OPAQUE;\n }\n return { ...owner, type: unionType((found as Evaluated[]).map((member) => member.type)) };\n}\n\n/**\n * A member read through `FlattenedDeepRequired`: a value that is only arrays (and `undefined` or\n * `null`) is replaced by its elements, anything else loses `undefined` and `null`.\n */\nfunction flattened(types: IndexedTypes, owner: Evaluated, type: IrType): Evaluation {\n const member: Evaluated = { ...owner, type };\n if (!owner.deep) {\n return types.expand(member);\n }\n const members = types.membersOf(member);\n if (members.some((candidate) => candidate.kind !== \"type\")) {\n return OPAQUE;\n }\n const present = (members as Evaluated[]).filter((candidate) => !isNullish(candidate.type));\n const elements = present.map((candidate) => arrayElement(candidate.type));\n if (present.length > 0 && elements.every((element) => element !== null)) {\n return types.expand({ ...owner, type: unionType(elements as IrType[]) });\n }\n return { ...owner, type: unionType(present.map((candidate) => candidate.type)) };\n}\n\n/** The element of an expanded member; expanding already dropped `readonly`. */\nfunction arrayElement(type: IrType): IrType | null {\n return type.kind === \"array\" ? type.element : null;\n}\n\nfunction indexKey(index: IrType): string | null {\n if (index.kind === \"stringLiteral\") {\n return index.value;\n }\n return index.kind === \"numberLiteral\" ? String(index.value) : null;\n}\n\nfunction isNumberIndex(index: IrType): boolean {\n const key = indexKey(index);\n return (index.kind === \"keyword\" && index.keyword === \"number\") || /^\\d+$/.test(key ?? \"\");\n}\n\nfunction isObjectBuiltIn(key: string): boolean {\n return key in {};\n}\n\n/** A key of a primitive or an array: a built-in member is opaque, any other key is missing. */\nfunction builtInIndex(index: IrType): Evaluation {\n const key = indexKey(index);\n const isBuiltIn = key === null || key in String.prototype || key in Array.prototype;\n return isBuiltIn || key in Number.prototype ? OPAQUE : MISSING;\n}\n"],"names":["propertyKey","OPAQUE","MISSING","isNeverIntersection","NEVER","declaredFirst","intersectionType","unionType","isNullish"],"mappings":"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"}
|