@formspec/build 0.1.0-alpha.33 → 0.1.0-alpha.34

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.
@@ -8,10 +8,11 @@
8
8
  import * as ts from "typescript";
9
9
  import type { UISchema } from "../ui-schema/types.js";
10
10
  import type { MetadataPolicyInput } from "@formspec/core";
11
- import { type IRClassAnalysis } from "../analyzer/class-analyzer.js";
11
+ import { type DiscriminatorResolutionOptions, type IRClassAnalysis } from "../analyzer/class-analyzer.js";
12
12
  import { type TSDocSource } from "../canonicalize/index.js";
13
13
  import { type GenerateJsonSchemaFromIROptions, type JsonSchema2020 } from "../json-schema/ir-generator.js";
14
14
  import type { ExtensionRegistry } from "../extensions/index.js";
15
+ export type { DiscriminatorResolutionOptions } from "../analyzer/class-analyzer.js";
15
16
  /**
16
17
  * Generated schemas for a class.
17
18
  *
@@ -53,6 +54,8 @@ export interface StaticSchemaGenerationOptions {
53
54
  readonly vendorPrefix?: string | undefined;
54
55
  /** Metadata resolution policy for static schema generation. */
55
56
  readonly metadata?: MetadataPolicyInput | undefined;
57
+ /** Discriminator-specific schema generation behavior. */
58
+ readonly discriminator?: DiscriminatorResolutionOptions | undefined;
56
59
  }
57
60
  /**
58
61
  * Options for generating schemas from a decorated class.
@@ -1 +1 @@
1
- {"version":3,"file":"class-schema.d.ts","sourceRoot":"","sources":["../../src/generators/class-schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAO1D,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAEL,KAAK,+BAA+B,EACpC,KAAK,cAAc,EACpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,UAAU,EAAE,cAAc,CAAC;IAC3B,yCAAyC;IACzC,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,eAAe,EACzB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,+BAA+B,GAAG;IAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAA;CAAE,GACzF,YAAY,CA2Bd;AAmBD;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACrD;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAyB,SAAQ,6BAA6B;IAC7E,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,yCAAyC;IACzC,UAAU,EAAE,cAAc,CAAC;IAC3B,yCAAyC;IACzC,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,iCAAkC,SAAQ,6BAA6B;IACtF,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,wBAAwB,GAChC,uBAAuB,CAwBzB;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAuB,SAAQ,6BAA6B;IAC3E,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,uBAAuB,CAMxF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,uBAAuB,CAAC"}
1
+ {"version":3,"file":"class-schema.d.ts","sourceRoot":"","sources":["../../src/generators/class-schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAO1D,OAAO,EAEL,KAAK,8BAA8B,EACnC,KAAK,eAAe,EACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAEL,KAAK,+BAA+B,EACpC,KAAK,cAAc,EACpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,YAAY,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAEpF;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,UAAU,EAAE,cAAc,CAAC;IAC3B,yCAAyC;IACzC,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,eAAe,EACzB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,+BAA+B,GAAG;IAAE,QAAQ,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAA;CAAE,GACzF,YAAY,CA2Bd;AAmBD;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACpD,yDAAyD;IACzD,QAAQ,CAAC,aAAa,CAAC,EAAE,8BAA8B,GAAG,SAAS,CAAC;CACrE;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAyB,SAAQ,6BAA6B;IAC7E,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,yCAAyC;IACzC,UAAU,EAAE,cAAc,CAAC;IAC3B,yCAAyC;IACzC,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,iCAAkC,SAAQ,6BAA6B;IACtF,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,wBAAwB,GAChC,uBAAuB,CAyBzB;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAuB,SAAQ,6BAA6B;IAC3E,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,uBAAuB,CAMxF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,uBAAuB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"discovered-schema.d.ts","sourceRoot":"","sources":["../../src/generators/discovered-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAQjC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAU7D,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAK/F;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAC/B,EAAE,CAAC,gBAAgB,GACnB,EAAE,CAAC,oBAAoB,GACvB,EAAE,CAAC,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,MAAM,WAAW,qCAAsC,SAAQ,6BAA6B;IAC1F,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,uBAAuB,CAAC;CAC/C;AAED;;;;GAIG;AACH,MAAM,WAAW,8BAA+B,SAAQ,6BAA6B;IACnF,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,SAAS,CAAC;IAC1C,sDAAsD;IACtD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,mCAAoC,SAAQ,6BAA6B;IACxF,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,oBAAoB,CAAC;CAC7C;AAED;;;;GAIG;AACH,MAAM,WAAW,oCAAqC,SAAQ,6BAA6B;IACzF,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,oBAAoB,CAAC;CAC/C;AAwSD;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,qCAAqC,GAC7C,qBAAqB,CA4EvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,8BAA8B,GACtC,qBAAqB,CAEvB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,mCAAmC,GAC3C,qBAAqB,CAOvB;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,oCAAoC,GAC5C,qBAAqB,CAkBvB"}
1
+ {"version":3,"file":"discovered-schema.d.ts","sourceRoot":"","sources":["../../src/generators/discovered-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAQjC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAU7D,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAK/F;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAC/B,EAAE,CAAC,gBAAgB,GACnB,EAAE,CAAC,oBAAoB,GACvB,EAAE,CAAC,oBAAoB,CAAC;AAE5B;;;;GAIG;AACH,MAAM,WAAW,qCAAsC,SAAQ,6BAA6B;IAC1F,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,uBAAuB,CAAC;CAC/C;AAED;;;;GAIG;AACH,MAAM,WAAW,8BAA+B,SAAQ,6BAA6B;IACnF,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,SAAS,CAAC;IAC1C,sDAAsD;IACtD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,mCAAoC,SAAQ,6BAA6B;IACxF,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,oBAAoB,CAAC;CAC7C;AAED;;;;GAIG;AACH,MAAM,WAAW,oCAAqC,SAAQ,6BAA6B;IACzF,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,oBAAoB,CAAC;CAC/C;AAwSD;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,qCAAqC,GAC7C,qBAAqB,CA+EvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,8BAA8B,GACtC,qBAAqB,CAEvB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,mCAAmC,GAC3C,qBAAqB,CAOvB;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,oCAAoC,GAC5C,qBAAqB,CAkBvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"mixed-authoring.d.ts","sourceRoot":"","sources":["../../src/generators/mixed-authoring.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAItD,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAGvE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iCAAkC,SAAQ,6BAA6B;IACtF,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2GAA2G;IAC3G,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;CACrD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,qBAAqB,CAmBvB"}
1
+ {"version":3,"file":"mixed-authoring.d.ts","sourceRoot":"","sources":["../../src/generators/mixed-authoring.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAItD,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAGvE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iCAAkC,SAAQ,6BAA6B;IACtF,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2GAA2G;IAC3G,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;CACrD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,qBAAqB,CAoBvB"}
package/dist/index.cjs CHANGED
@@ -2922,6 +2922,9 @@ function extractDefaultValueAnnotation(initializer, file = "") {
2922
2922
  function isObjectType(type) {
2923
2923
  return !!(type.flags & ts3.TypeFlags.Object);
2924
2924
  }
2925
+ function isIntersectionType(type) {
2926
+ return !!(type.flags & ts3.TypeFlags.Intersection);
2927
+ }
2925
2928
  function isTypeReference(type) {
2926
2929
  return !!(type.flags & ts3.TypeFlags.Object) && !!(type.objectFlags & ts3.ObjectFlags.Reference);
2927
2930
  }
@@ -2942,10 +2945,11 @@ function makeParseOptions(extensionRegistry, fieldType, checker, subjectType, ho
2942
2945
  ...hostType !== void 0 && { hostType }
2943
2946
  };
2944
2947
  }
2945
- function createAnalyzerMetadataPolicy(input) {
2948
+ function createAnalyzerMetadataPolicy(input, discriminator) {
2946
2949
  return {
2947
2950
  raw: input,
2948
- normalized: normalizeMetadataPolicy(input)
2951
+ normalized: normalizeMetadataPolicy(input),
2952
+ discriminator
2949
2953
  };
2950
2954
  }
2951
2955
  function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
@@ -3013,8 +3017,11 @@ function analyzeDeclarationRootInfo(declaration, checker, file = "", extensionRe
3013
3017
  diagnostics: docResult.diagnostics
3014
3018
  };
3015
3019
  }
3016
- function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
3017
- const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
3020
+ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
3021
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
3022
+ metadataPolicy,
3023
+ discriminatorOptions
3024
+ );
3018
3025
  const name = classDecl.name?.text ?? "AnonymousClass";
3019
3026
  const fields = [];
3020
3027
  const fieldLayouts = [];
@@ -3095,8 +3102,11 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
3095
3102
  staticMethods
3096
3103
  };
3097
3104
  }
3098
- function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy) {
3099
- const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
3105
+ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
3106
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
3107
+ metadataPolicy,
3108
+ discriminatorOptions
3109
+ );
3100
3110
  const name = interfaceDecl.name.text;
3101
3111
  const fields = [];
3102
3112
  const typeRegistry = {};
@@ -3164,19 +3174,31 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
3164
3174
  staticMethods: []
3165
3175
  };
3166
3176
  }
3167
- function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry, metadataPolicy) {
3168
- if (!ts3.isTypeLiteralNode(typeAlias.type)) {
3177
+ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
3178
+ const members = getObjectLikeTypeAliasMembers(typeAlias.type);
3179
+ if (members === null) {
3169
3180
  const sourceFile = typeAlias.getSourceFile();
3170
3181
  const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
3171
3182
  const kindDesc = ts3.SyntaxKind[typeAlias.type.kind] ?? "unknown";
3172
3183
  return {
3173
3184
  ok: false,
3174
- error: `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} is not an object type literal (found ${kindDesc})`
3185
+ error: `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} is not an object-like type alias (found ${kindDesc})`
3175
3186
  };
3176
3187
  }
3177
- const typeLiteral = typeAlias.type;
3178
- const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
3188
+ const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
3189
+ metadataPolicy,
3190
+ discriminatorOptions
3191
+ );
3179
3192
  const name = typeAlias.name.text;
3193
+ const duplicatePropertyNames = findDuplicateObjectLikeTypeAliasPropertyNames(members);
3194
+ if (duplicatePropertyNames.length > 0) {
3195
+ const sourceFile = typeAlias.getSourceFile();
3196
+ const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
3197
+ return {
3198
+ ok: false,
3199
+ error: `Type alias "${name}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`
3200
+ };
3201
+ }
3180
3202
  const fields = [];
3181
3203
  const typeRegistry = {};
3182
3204
  const diagnostics = [];
@@ -3189,7 +3211,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
3189
3211
  const annotations = [...typeAliasDoc.annotations];
3190
3212
  diagnostics.push(...typeAliasDoc.diagnostics);
3191
3213
  const visiting = /* @__PURE__ */ new Set();
3192
- for (const member of typeLiteral.members) {
3214
+ for (const member of members) {
3193
3215
  if (ts3.isPropertySignature(member)) {
3194
3216
  const fieldNode = analyzeInterfacePropertyToIR(
3195
3217
  member,
@@ -3298,15 +3320,43 @@ function isNullishSemanticType(type) {
3298
3320
  }
3299
3321
  return type.isUnion() && type.types.some((member) => isNullishSemanticType(member));
3300
3322
  }
3301
- function isStringLikeSemanticType(type) {
3323
+ function isStringLikeSemanticType(type, checker, seen = /* @__PURE__ */ new Set()) {
3324
+ if (seen.has(type)) {
3325
+ return false;
3326
+ }
3327
+ seen.add(type);
3302
3328
  if (type.flags & ts3.TypeFlags.StringLike) {
3303
3329
  return true;
3304
3330
  }
3305
3331
  if (type.isUnion()) {
3306
- return type.types.length > 0 && type.types.every((member) => isStringLikeSemanticType(member));
3332
+ return type.types.length > 0 && type.types.every((member) => isStringLikeSemanticType(member, checker, seen));
3333
+ }
3334
+ const baseConstraint = checker.getBaseConstraintOfType(type);
3335
+ if (baseConstraint !== void 0 && baseConstraint !== type) {
3336
+ return isStringLikeSemanticType(baseConstraint, checker, seen);
3307
3337
  }
3308
3338
  return false;
3309
3339
  }
3340
+ function getObjectLikeTypeAliasMembers(typeNode) {
3341
+ if (ts3.isParenthesizedTypeNode(typeNode)) {
3342
+ return getObjectLikeTypeAliasMembers(typeNode.type);
3343
+ }
3344
+ if (ts3.isTypeLiteralNode(typeNode)) {
3345
+ return [...typeNode.members];
3346
+ }
3347
+ if (ts3.isIntersectionTypeNode(typeNode)) {
3348
+ const members = [];
3349
+ for (const intersectionMember of typeNode.types) {
3350
+ const resolvedMembers = getObjectLikeTypeAliasMembers(intersectionMember);
3351
+ if (resolvedMembers === null) {
3352
+ return null;
3353
+ }
3354
+ members.push(...resolvedMembers);
3355
+ }
3356
+ return members;
3357
+ }
3358
+ return null;
3359
+ }
3310
3360
  function extractDiscriminatorDirective(node, file, diagnostics) {
3311
3361
  const discriminatorTags = getLeadingParsedTags(node).filter(
3312
3362
  (tag) => tag.normalizedTagName === "discriminator"
@@ -3413,7 +3463,7 @@ function validateDiscriminatorDirective(node, checker, file, diagnostics) {
3413
3463
  );
3414
3464
  return null;
3415
3465
  }
3416
- if (!isStringLikeSemanticType(property.type)) {
3466
+ if (!isStringLikeSemanticType(property.type, checker)) {
3417
3467
  diagnostics.push(
3418
3468
  makeAnalysisDiagnostic(
3419
3469
  "TYPE_MISMATCH",
@@ -3440,8 +3490,8 @@ function getConcreteTypeArgumentForDiscriminator(node, subjectType, checker, typ
3440
3490
  const localTypeParameter = node.typeParameters?.[typeParameterIndex];
3441
3491
  return localTypeParameter === void 0 ? null : checker.getTypeAtLocation(localTypeParameter);
3442
3492
  }
3443
- function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker, provenance, diagnostics) {
3444
- const propertySymbol = boundType.getProperty(fieldName);
3493
+ function resolveLiteralDiscriminatorPropertyValue(boundType, propertyName, checker, provenance, diagnostics) {
3494
+ const propertySymbol = boundType.getProperty(propertyName);
3445
3495
  if (propertySymbol === void 0) {
3446
3496
  return void 0;
3447
3497
  }
@@ -3472,6 +3522,9 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker,
3472
3522
  }
3473
3523
  return void 0;
3474
3524
  }
3525
+ function getDiscriminatorIdentityPropertyNames(fieldName) {
3526
+ return fieldName === "object" ? ["object"] : [fieldName, "object"];
3527
+ }
3475
3528
  function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
3476
3529
  const declaration = resolveNamedDiscriminatorDeclaration(boundType, checker);
3477
3530
  if (declaration === null) {
@@ -3492,6 +3545,10 @@ function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
3492
3545
  );
3493
3546
  return metadata?.apiName;
3494
3547
  }
3548
+ function applyDiscriminatorApiNamePrefix(value, discriminatorOptions) {
3549
+ const prefix = discriminatorOptions?.apiNamePrefix;
3550
+ return prefix === void 0 || prefix === "" ? value : `${prefix}${value}`;
3551
+ }
3495
3552
  function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__ */ new Set()) {
3496
3553
  if (seen.has(type)) {
3497
3554
  return null;
@@ -3546,22 +3603,27 @@ function resolveDiscriminatorValue(boundType, fieldName, checker, provenance, di
3546
3603
  return null;
3547
3604
  }
3548
3605
  }
3549
- const literalIdentityValue = resolveLiteralDiscriminatorPropertyValue(
3550
- boundType,
3551
- fieldName,
3552
- checker,
3553
- provenance,
3554
- diagnostics
3555
- );
3556
- if (literalIdentityValue !== void 0) {
3557
- return literalIdentityValue;
3606
+ for (const identityPropertyName of getDiscriminatorIdentityPropertyNames(fieldName)) {
3607
+ const literalIdentityValue = resolveLiteralDiscriminatorPropertyValue(
3608
+ boundType,
3609
+ identityPropertyName,
3610
+ checker,
3611
+ provenance,
3612
+ diagnostics
3613
+ );
3614
+ if (literalIdentityValue === null) {
3615
+ return null;
3616
+ }
3617
+ if (literalIdentityValue !== void 0) {
3618
+ return literalIdentityValue;
3619
+ }
3558
3620
  }
3559
3621
  const apiName = resolveDiscriminatorApiName(boundType, checker, metadataPolicy);
3560
3622
  if (apiName?.source === "explicit") {
3561
- return apiName.value;
3623
+ return applyDiscriminatorApiNamePrefix(apiName.value, metadataPolicy.discriminator);
3562
3624
  }
3563
3625
  if (apiName?.source === "inferred") {
3564
- return apiName.value;
3626
+ return applyDiscriminatorApiNamePrefix(apiName.value, metadataPolicy.discriminator);
3565
3627
  }
3566
3628
  diagnostics.push(
3567
3629
  makeAnalysisDiagnostic(
@@ -3624,15 +3686,20 @@ function buildInstantiatedReferenceName(baseName, typeArguments, checker) {
3624
3686
  return renderedArguments.length === 0 ? baseName : `${baseName}__${renderedArguments.join("__")}`;
3625
3687
  }
3626
3688
  function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy, extensionRegistry, diagnostics) {
3627
- const typeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
3628
- if (typeNode === void 0) {
3689
+ const sourceTypeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
3690
+ if (sourceTypeNode === void 0) {
3629
3691
  return [];
3630
3692
  }
3631
- const resolvedTypeNode = resolveAliasedTypeNode(typeNode, checker);
3632
- if (!ts3.isTypeReferenceNode(resolvedTypeNode) || resolvedTypeNode.typeArguments === void 0) {
3693
+ const unwrapParentheses = (typeNode) => ts3.isParenthesizedTypeNode(typeNode) ? unwrapParentheses(typeNode.type) : typeNode;
3694
+ const directTypeNode = unwrapParentheses(sourceTypeNode);
3695
+ const referenceTypeNode = ts3.isTypeReferenceNode(directTypeNode) ? directTypeNode : (() => {
3696
+ const resolvedTypeNode = resolveAliasedTypeNode(directTypeNode, checker);
3697
+ return ts3.isTypeReferenceNode(resolvedTypeNode) ? resolvedTypeNode : null;
3698
+ })();
3699
+ if (referenceTypeNode?.typeArguments === void 0) {
3633
3700
  return [];
3634
3701
  }
3635
- return resolvedTypeNode.typeArguments.map((argumentNode) => {
3702
+ return referenceTypeNode.typeArguments.map((argumentNode) => {
3636
3703
  const argumentType = checker.getTypeFromTypeNode(argumentNode);
3637
3704
  return {
3638
3705
  tsType: argumentType,
@@ -3746,10 +3813,10 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
3746
3813
  };
3747
3814
  }
3748
3815
  function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, metadataPolicy, extensionRegistry) {
3749
- if (!ts3.isIdentifier(prop.name)) {
3816
+ const name = getAnalyzableObjectLikePropertyName(prop.name);
3817
+ if (name === null) {
3750
3818
  return null;
3751
3819
  }
3752
- const name = prop.name.text;
3753
3820
  const tsType = checker.getTypeAtLocation(prop);
3754
3821
  const optional = prop.questionToken !== void 0;
3755
3822
  const provenance = provenanceForNode(prop, file);
@@ -3805,6 +3872,31 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
3805
3872
  provenance
3806
3873
  };
3807
3874
  }
3875
+ function findDuplicateObjectLikeTypeAliasPropertyNames(members) {
3876
+ const seen = /* @__PURE__ */ new Set();
3877
+ const duplicates = /* @__PURE__ */ new Set();
3878
+ for (const member of members) {
3879
+ if (!ts3.isPropertySignature(member)) {
3880
+ continue;
3881
+ }
3882
+ const name = getAnalyzableObjectLikePropertyName(member.name);
3883
+ if (name === null) {
3884
+ continue;
3885
+ }
3886
+ if (seen.has(name)) {
3887
+ duplicates.add(name);
3888
+ continue;
3889
+ }
3890
+ seen.add(name);
3891
+ }
3892
+ return [...duplicates].sort();
3893
+ }
3894
+ function getAnalyzableObjectLikePropertyName(name) {
3895
+ if (!ts3.isIdentifier(name)) {
3896
+ return null;
3897
+ }
3898
+ return name.text;
3899
+ }
3808
3900
  function applyEnumMemberDisplayNames(type, annotations) {
3809
3901
  if (!annotations.some(
3810
3902
  (annotation) => annotation.annotationKind === "displayName" && annotation.value.trim().startsWith(":")
@@ -3997,6 +4089,23 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
3997
4089
  diagnostics
3998
4090
  );
3999
4091
  }
4092
+ if (isIntersectionType(type)) {
4093
+ const sourceTypeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
4094
+ const resolvedSourceTypeNode = sourceTypeNode === void 0 ? void 0 : resolveAliasedTypeNode(sourceTypeNode, checker);
4095
+ if (resolvedSourceTypeNode !== void 0 && getObjectLikeTypeAliasMembers(resolvedSourceTypeNode) !== null) {
4096
+ return resolveObjectType(
4097
+ type,
4098
+ checker,
4099
+ file,
4100
+ typeRegistry,
4101
+ visiting,
4102
+ sourceNode,
4103
+ metadataPolicy,
4104
+ extensionRegistry,
4105
+ diagnostics
4106
+ );
4107
+ }
4108
+ }
4000
4109
  if (isObjectType(type)) {
4001
4110
  return resolveObjectType(
4002
4111
  type,
@@ -4376,7 +4485,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4376
4485
  };
4377
4486
  }
4378
4487
  }
4379
- const recordNode = tryResolveRecordType(
4488
+ const recordNode = isObjectType(type) ? tryResolveRecordType(
4380
4489
  type,
4381
4490
  checker,
4382
4491
  file,
@@ -4385,7 +4494,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
4385
4494
  metadataPolicy,
4386
4495
  extensionRegistry,
4387
4496
  collectedDiagnostics
4388
- );
4497
+ ) : null;
4389
4498
  if (recordNode) {
4390
4499
  visiting.delete(type);
4391
4500
  if (registryTypeName !== void 0 && shouldRegisterNamedType) {
@@ -4582,9 +4691,10 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
4582
4691
  );
4583
4692
  }
4584
4693
  const typeAliasDecl = declarations.find(ts3.isTypeAliasDeclaration);
4585
- if (typeAliasDecl && ts3.isTypeLiteralNode(typeAliasDecl.type)) {
4694
+ const typeAliasMembers = typeAliasDecl === void 0 ? null : getObjectLikeTypeAliasMembers(typeAliasDecl.type);
4695
+ if (typeAliasDecl && typeAliasMembers !== null) {
4586
4696
  return buildFieldNodeInfoMap(
4587
- typeAliasDecl.type.members,
4697
+ typeAliasMembers,
4588
4698
  checker,
4589
4699
  file,
4590
4700
  typeRegistry,
@@ -4875,17 +4985,18 @@ function findInterfaceByName(sourceFile, interfaceName) {
4875
4985
  function findTypeAliasByName(sourceFile, aliasName) {
4876
4986
  return findNodeByName(sourceFile, aliasName, ts4.isTypeAliasDeclaration, (n) => n.name.text);
4877
4987
  }
4878
- function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry, metadataPolicy) {
4988
+ function analyzeNamedTypeToIR(filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
4879
4989
  const ctx = createProgramContext(filePath);
4880
4990
  return analyzeNamedTypeToIRFromProgramContext(
4881
4991
  ctx,
4882
4992
  filePath,
4883
4993
  typeName,
4884
4994
  extensionRegistry,
4885
- metadataPolicy
4995
+ metadataPolicy,
4996
+ discriminatorOptions
4886
4997
  );
4887
4998
  }
4888
- function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy) {
4999
+ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
4889
5000
  const analysisFilePath = path.resolve(filePath);
4890
5001
  const classDecl = findClassByName(ctx.sourceFile, typeName);
4891
5002
  if (classDecl !== null) {
@@ -4894,7 +5005,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
4894
5005
  ctx.checker,
4895
5006
  analysisFilePath,
4896
5007
  extensionRegistry,
4897
- metadataPolicy
5008
+ metadataPolicy,
5009
+ discriminatorOptions
4898
5010
  );
4899
5011
  }
4900
5012
  const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
@@ -4904,7 +5016,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
4904
5016
  ctx.checker,
4905
5017
  analysisFilePath,
4906
5018
  extensionRegistry,
4907
- metadataPolicy
5019
+ metadataPolicy,
5020
+ discriminatorOptions
4908
5021
  );
4909
5022
  }
4910
5023
  const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
@@ -4914,7 +5027,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
4914
5027
  ctx.checker,
4915
5028
  analysisFilePath,
4916
5029
  extensionRegistry,
4917
- metadataPolicy
5030
+ metadataPolicy,
5031
+ discriminatorOptions
4918
5032
  );
4919
5033
  if (result.ok) {
4920
5034
  return result.analysis;
@@ -5049,7 +5163,8 @@ function generateSchemasFromClass(options) {
5049
5163
  ctx.checker,
5050
5164
  options.filePath,
5051
5165
  options.extensionRegistry,
5052
- options.metadata
5166
+ options.metadata,
5167
+ options.discriminator
5053
5168
  );
5054
5169
  return generateClassSchemas(
5055
5170
  analysis,
@@ -5075,7 +5190,8 @@ function generateSchemasFromProgram(options) {
5075
5190
  options.filePath,
5076
5191
  options.typeName,
5077
5192
  options.extensionRegistry,
5078
- options.metadata
5193
+ options.metadata,
5194
+ options.discriminator
5079
5195
  );
5080
5196
  return generateClassSchemas(
5081
5197
  analysis,
@@ -5294,7 +5410,7 @@ function generateSchemasFromResolvedType(options, skipNamedDeclaration = false,
5294
5410
  typeRegistry,
5295
5411
  /* @__PURE__ */ new Set(),
5296
5412
  options.sourceNode,
5297
- createAnalyzerMetadataPolicy(options.metadata),
5413
+ createAnalyzerMetadataPolicy(options.metadata, options.discriminator),
5298
5414
  options.extensionRegistry,
5299
5415
  diagnostics
5300
5416
  );
@@ -5343,7 +5459,8 @@ function generateSchemasFromDeclaration(options) {
5343
5459
  options.context.checker,
5344
5460
  filePath,
5345
5461
  options.extensionRegistry,
5346
- options.metadata
5462
+ options.metadata,
5463
+ options.discriminator
5347
5464
  ),
5348
5465
  filePath,
5349
5466
  options
@@ -5356,7 +5473,8 @@ function generateSchemasFromDeclaration(options) {
5356
5473
  options.context.checker,
5357
5474
  filePath,
5358
5475
  options.extensionRegistry,
5359
- options.metadata
5476
+ options.metadata,
5477
+ options.discriminator
5360
5478
  ),
5361
5479
  filePath,
5362
5480
  options
@@ -5368,7 +5486,8 @@ function generateSchemasFromDeclaration(options) {
5368
5486
  options.context.checker,
5369
5487
  filePath,
5370
5488
  options.extensionRegistry,
5371
- options.metadata
5489
+ options.metadata,
5490
+ options.discriminator
5372
5491
  );
5373
5492
  if (analyzedAlias.ok) {
5374
5493
  return generateSchemasFromAnalysis(analyzedAlias.analysis, filePath, options);
@@ -5434,7 +5553,8 @@ function buildMixedAuthoringSchemas(options) {
5434
5553
  filePath,
5435
5554
  typeName,
5436
5555
  schemaOptions.extensionRegistry,
5437
- schemaOptions.metadata
5556
+ schemaOptions.metadata,
5557
+ schemaOptions.discriminator
5438
5558
  );
5439
5559
  const composedAnalysis = composeAnalysisWithOverlays(analysis, overlays, schemaOptions.metadata);
5440
5560
  const ir = canonicalizeTSDoc(