@shaclmate/compiler 4.0.13 → 4.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/Compiler.d.ts +4 -1
  2. package/dist/Compiler.js +3 -1
  3. package/dist/ShapesGraphToAstTransformer.d.ts +10 -2
  4. package/dist/ShapesGraphToAstTransformer.js +74 -3
  5. package/dist/_ShapesGraphToAstTransformer/ShapeStack.js +6 -5
  6. package/dist/_ShapesGraphToAstTransformer/nodeShapeIdentifierMintingStrategy.d.ts +3 -2
  7. package/dist/_ShapesGraphToAstTransformer/nodeShapeIdentifierMintingStrategy.js +17 -13
  8. package/dist/_ShapesGraphToAstTransformer/nodeShapeTsFeatures.js +2 -1
  9. package/dist/_ShapesGraphToAstTransformer/shapeAstTypeName.js +6 -6
  10. package/dist/_ShapesGraphToAstTransformer/shapeNodeKinds.d.ts +2 -1
  11. package/dist/_ShapesGraphToAstTransformer/shapeNodeKinds.js +37 -30
  12. package/dist/_ShapesGraphToAstTransformer/shapeOntology.d.ts +5 -0
  13. package/dist/_ShapesGraphToAstTransformer/shapeOntology.js +25 -0
  14. package/dist/_ShapesGraphToAstTransformer/transformPropertyShapeToAstObjectTypeProperty.js +23 -16
  15. package/dist/_ShapesGraphToAstTransformer/transformShapeToAstCompoundType.js +10 -6
  16. package/dist/_ShapesGraphToAstTransformer/transformShapeToAstListType.js +22 -22
  17. package/dist/_ShapesGraphToAstTransformer/transformShapeToAstObjectType.js +127 -118
  18. package/dist/_ShapesGraphToAstTransformer/transformShapeToAstTermType.js +10 -8
  19. package/dist/_ShapesGraphToAstTransformer/transformShapeToAstType.js +3 -3
  20. package/dist/ast/ObjectType.d.ts +3 -3
  21. package/dist/enums/IdentifierMintingStrategy.d.ts +4 -0
  22. package/dist/enums/IdentifierMintingStrategy.js +17 -1
  23. package/dist/enums/TsObjectDeclarationType.d.ts +4 -0
  24. package/dist/enums/TsObjectDeclarationType.js +15 -1
  25. package/dist/enums/Visibility.d.ts +6 -0
  26. package/dist/enums/Visibility.js +18 -0
  27. package/dist/generators/ts/AbstractCollectionType.js +1 -7
  28. package/dist/generators/ts/AbstractTermType.d.ts +1 -0
  29. package/dist/generators/ts/AbstractTermType.js +6 -0
  30. package/dist/generators/ts/AbstractUnionType.d.ts +31 -9
  31. package/dist/generators/ts/AbstractUnionType.js +252 -126
  32. package/dist/generators/ts/SetType.d.ts +1 -0
  33. package/dist/generators/ts/SetType.js +12 -0
  34. package/dist/generators/ts/_NamedObjectType/AbstractProperty.d.ts +3 -3
  35. package/dist/input/ShapesGraph.d.ts +39 -22
  36. package/dist/input/ShapesGraph.js +56 -60
  37. package/dist/input/generated.d.ts +389 -191
  38. package/dist/input/generated.js +2501 -829
  39. package/dist/input/index.d.ts +1 -5
  40. package/dist/input/index.js +1 -5
  41. package/package.json +2 -2
  42. package/dist/enums/PropertyVisibility.d.ts +0 -2
  43. package/dist/enums/PropertyVisibility.js +0 -2
  44. package/dist/input/NodeShape.d.ts +0 -49
  45. package/dist/input/NodeShape.js +0 -154
  46. package/dist/input/Ontology.d.ts +0 -13
  47. package/dist/input/Ontology.js +0 -40
  48. package/dist/input/PropertyShape.d.ts +0 -20
  49. package/dist/input/PropertyShape.js +0 -78
  50. package/dist/input/Shape.d.ts +0 -4
  51. package/dist/input/Shape.js +0 -2
  52. package/dist/input/ancestorClassIris.d.ts +0 -4
  53. package/dist/input/ancestorClassIris.js +0 -24
  54. package/dist/input/descendantClassIris.d.ts +0 -4
  55. package/dist/input/descendantClassIris.js +0 -27
@@ -4,6 +4,7 @@ import type { BlankNodeType } from "./BlankNodeType.js";
4
4
  import type { IdentifierType } from "./IdentifierType.js";
5
5
  import type { IriType } from "./IriType.js";
6
6
  import type { Type } from "./Type.js";
7
+ import type { Typeof } from "./Typeof.js";
7
8
  import { type Code } from "./ts-poet-wrapper.js";
8
9
  export declare abstract class AbstractUnionType<MemberTypeT extends Type> extends AbstractType {
9
10
  private readonly discriminant;
@@ -45,18 +46,37 @@ export declare abstract class AbstractUnionType<MemberTypeT extends Type> extend
45
46
  jsonUiSchemaElement(): Maybe<Code>;
46
47
  protected inlineHashStatements({ depth, variables, }: Parameters<AbstractType["hashStatements"]>[0]): readonly Code[];
47
48
  }
48
- type Discriminant = EnvelopeDiscriminant | InlineDiscriminant | TypeofDiscriminant;
49
- type EnvelopeDiscriminant = {
50
- kind: "envelope";
51
- } & AbstractType.DiscriminantProperty;
52
- type InlineDiscriminant = {
53
- kind: "inline";
54
- } & AbstractType.DiscriminantProperty;
49
+ type Discriminant = ExtrinsicDiscriminant | HybridDiscriminant | IntrinsicDiscriminant | TypeofDiscriminant;
50
+ type ExtrinsicDiscriminant = {
51
+ readonly kind: "extrinsic";
52
+ readonly memberValues: readonly AbstractType.DiscriminantProperty.Value[];
53
+ readonly name: string;
54
+ };
55
+ type HybridDiscriminant = {
56
+ readonly kind: "hybrid";
57
+ readonly memberValues: readonly {
58
+ readonly kind: "extrinsic" | "intrinsic";
59
+ readonly ownValues: readonly AbstractType.DiscriminantProperty.Value[];
60
+ }[];
61
+ readonly name: string;
62
+ };
63
+ type IntrinsicDiscriminant = {
64
+ readonly kind: "intrinsic";
65
+ readonly memberValues: readonly {
66
+ readonly descendantValues: readonly AbstractType.DiscriminantProperty.Value[];
67
+ readonly ownValues: readonly AbstractType.DiscriminantProperty.Value[];
68
+ }[];
69
+ readonly name: string;
70
+ };
55
71
  type TypeofDiscriminant = {
56
- kind: "typeof";
72
+ readonly kind: "typeof";
73
+ readonly memberValues: readonly Typeof[];
57
74
  };
58
75
  export declare namespace Discriminant {
59
- function infer(memberTypes: readonly Type[]): Discriminant;
76
+ function infer(members: readonly {
77
+ readonly discriminantValue: Maybe<number | string>;
78
+ readonly type: Type;
79
+ }[]): Discriminant;
60
80
  }
61
81
  export declare namespace AbstractUnionType {
62
82
  interface AbstractMember<TypeT extends Type> {
@@ -67,10 +87,12 @@ export declare namespace AbstractUnionType {
67
87
  interface ConcreteMember<TypeT extends Type> {
68
88
  readonly abstract: false;
69
89
  readonly discriminantValues: readonly AbstractType.DiscriminantProperty.Value[];
90
+ readonly jsonType: Code | string;
70
91
  readonly jsonTypeCheck: (instance: Code) => Code;
71
92
  readonly primaryDiscriminantValue: AbstractType.DiscriminantProperty.Value;
72
93
  readonly type: TypeT;
73
94
  readonly typeCheck: (instance: Code) => Code;
95
+ readonly typeToJsonExpression: (valueVariable: Code) => Code;
74
96
  readonly unwrap: (instance: Code) => Code;
75
97
  readonly wrap: (instance: Code) => Code;
76
98
  }
@@ -13,6 +13,19 @@ import { removeUndefined } from "./removeUndefined.js";
13
13
  import { snippets } from "./snippets.js";
14
14
  import { syntheticNamePrefix } from "./syntheticNamePrefix.js";
15
15
  import { code, joinCode, literalOf } from "./ts-poet-wrapper.js";
16
+ const emptyTermTypesSet = new Set();
17
+ function termTypes(type) {
18
+ switch (type.kind) {
19
+ case "BlankNodeType":
20
+ case "IriType":
21
+ case "IdentifierType":
22
+ case "LiteralType":
23
+ case "TermType":
24
+ return type.termTypes;
25
+ default:
26
+ return emptyTermTypesSet;
27
+ }
28
+ }
16
29
  export class AbstractUnionType extends AbstractType {
17
30
  discriminant;
18
31
  identifierType;
@@ -24,27 +37,22 @@ export class AbstractUnionType extends AbstractType {
24
37
  this.identifierType = identifierType;
25
38
  invariant(members.length >= 2);
26
39
  this.recursive = recursive;
27
- if (members.some((member) => member.discriminantValue.isJust())) {
28
- this.discriminant = {
29
- descendantValues: [],
30
- kind: "envelope",
31
- name: "type",
32
- ownValues: members.map((member, memberI) => member.discriminantValue.orDefault(memberI)),
33
- };
34
- }
35
- else {
36
- this.discriminant = Discriminant.infer(members.map((member) => member.type));
37
- }
40
+ this.discriminant = Discriminant.infer(members);
38
41
  this.lazyMembers = () => members.map((member, memberI) => {
39
42
  if (member.type.abstract) {
40
43
  return { abstract: true, discriminantValues: [], type: member.type };
41
44
  }
42
45
  let discriminantValues;
46
+ invariant(this.discriminant.memberValues.length === members.length);
43
47
  switch (this.discriminant.kind) {
44
- case "envelope":
45
- discriminantValues = [this.discriminant.ownValues[memberI]];
48
+ case "extrinsic":
49
+ discriminantValues = [this.discriminant.memberValues[memberI]];
46
50
  break;
47
- case "inline": {
51
+ case "hybrid":
52
+ discriminantValues =
53
+ this.discriminant.memberValues[memberI].ownValues;
54
+ break;
55
+ case "intrinsic": {
48
56
  // A member type's combined discriminant property values are its "own" values plus any descendant values that are
49
57
  // not the "own" values of some other member type.
50
58
  // So if you have type A, type B, and B inherits A, then
@@ -70,7 +78,7 @@ export class AbstractUnionType extends AbstractType {
70
78
  break;
71
79
  }
72
80
  case "typeof":
73
- discriminantValues = member.type.typeofs;
81
+ discriminantValues = [this.discriminant.memberValues[memberI]];
74
82
  break;
75
83
  default:
76
84
  throw this.discriminant;
@@ -79,45 +87,62 @@ export class AbstractUnionType extends AbstractType {
79
87
  return { abstract: true, discriminantValues: [], type: member.type };
80
88
  }
81
89
  const typeCheck = (json) => (instance) => {
82
- switch (this.discriminant.kind) {
83
- case "envelope":
84
- return code `(${joinCode(discriminantValues.map((discriminantValue) => code `${instance}.${this.discriminant.name} === ${literalOf(discriminantValue)}`), { on: " || " })})`;
85
- case "inline": {
86
- if (!json) {
87
- switch (member.type.kind) {
88
- case "NamedObjectUnionType":
89
- case "NamedUnionType":
90
- case "NamedObjectType":
91
- return code `${member.type.staticModuleName}.is${member.type.name}(${instance})`;
92
- }
93
- }
94
- return code `(${joinCode(discriminantValues.map((discriminantValue) => code `${instance}.${this.discriminant.name} === ${literalOf(discriminantValue)}`), { on: " || " })})`;
90
+ const discriminant = this.discriminant; // To get type narrowing to work
91
+ if (discriminant.kind === "typeof") {
92
+ return code `(${joinCode(discriminantValues.map((discriminantValue) => code `typeof ${instance} === ${literalOf(discriminantValue)}`), { on: " || " })})`;
93
+ }
94
+ if (discriminant.kind === "intrinsic" && !json) {
95
+ switch (member.type.kind) {
96
+ case "NamedObjectUnionType":
97
+ case "NamedUnionType":
98
+ case "NamedObjectType":
99
+ return code `${member.type.staticModuleName}.is${member.type.name}(${instance})`;
95
100
  }
96
- case "typeof":
97
- return code `(${joinCode(discriminantValues.map((discriminantValue) => code `typeof ${instance} === ${literalOf(discriminantValue)}`), { on: " || " })})`;
98
101
  }
102
+ return code `(${joinCode(discriminantValues.map((discriminantValue) => code `${instance}.${discriminant.name} === ${literalOf(discriminantValue)}`), { on: " || " })})`;
99
103
  };
100
104
  return {
101
105
  abstract: false,
102
106
  discriminantValues,
107
+ jsonType: member.type.jsonType({
108
+ includeDiscriminantProperty: this.discriminant.kind === "intrinsic" ||
109
+ (this.discriminant.kind === "hybrid" &&
110
+ this.discriminant.memberValues[memberI].kind === "intrinsic"),
111
+ }).name,
103
112
  jsonTypeCheck: typeCheck(true),
104
113
  primaryDiscriminantValue: discriminantValues[0],
105
114
  type: member.type,
106
115
  typeCheck: typeCheck(false),
116
+ typeToJsonExpression: (valueVariable) => member.type.toJsonExpression({
117
+ includeDiscriminantProperty: this.discriminant.kind === "intrinsic" ||
118
+ (this.discriminant.kind === "hybrid" &&
119
+ this.discriminant.memberValues[memberI].kind === "intrinsic"),
120
+ variables: { value: valueVariable },
121
+ }),
107
122
  unwrap: (instance) => {
108
123
  switch (this.discriminant.kind) {
109
- case "envelope":
124
+ case "extrinsic":
110
125
  return code `${instance}.value`;
111
- case "inline":
126
+ case "hybrid":
127
+ return this.discriminant.memberValues[memberI].kind ===
128
+ "intrinsic"
129
+ ? instance
130
+ : code `${instance}.value`;
131
+ case "intrinsic":
112
132
  case "typeof":
113
133
  return instance;
114
134
  }
115
135
  },
116
136
  wrap: (instance) => {
117
137
  switch (this.discriminant.kind) {
118
- case "envelope":
119
- return code `{ ${this.discriminant.name}: "${discriminantValues[0]}" as const, value: ${instance} }`;
120
- case "inline":
138
+ case "extrinsic":
139
+ return code `{ ${this.discriminant.name}: ${literalOf(discriminantValues[0])} as const, value: ${instance} }`;
140
+ case "hybrid":
141
+ return this.discriminant.memberValues[memberI].kind ===
142
+ "intrinsic"
143
+ ? instance
144
+ : code `{ ${this.discriminant.name}: ${literalOf(discriminantValues[0])} as const, value: ${instance} }`;
145
+ case "intrinsic":
121
146
  case "typeof":
122
147
  return instance;
123
148
  }
@@ -127,8 +152,9 @@ export class AbstractUnionType extends AbstractType {
127
152
  }
128
153
  get conversions() {
129
154
  switch (this.discriminant.kind) {
130
- case "envelope":
131
- case "inline":
155
+ case "extrinsic":
156
+ case "hybrid":
157
+ case "intrinsic":
132
158
  return [
133
159
  {
134
160
  conversionExpression: (value) => value,
@@ -150,9 +176,24 @@ export class AbstractUnionType extends AbstractType {
150
176
  }
151
177
  get discriminantProperty() {
152
178
  switch (this.discriminant.kind) {
153
- case "envelope":
154
- case "inline":
155
- return Maybe.of(this.discriminant);
179
+ case "extrinsic":
180
+ return Maybe.of({
181
+ descendantValues: [],
182
+ ownValues: this.discriminant.memberValues,
183
+ name: this.discriminant.name,
184
+ });
185
+ case "hybrid":
186
+ return Maybe.of({
187
+ descendantValues: [],
188
+ ownValues: this.discriminant.memberValues.flatMap((_) => _.ownValues),
189
+ name: "termType",
190
+ });
191
+ case "intrinsic":
192
+ return Maybe.of({
193
+ descendantValues: this.discriminant.memberValues.flatMap((_) => _.descendantValues),
194
+ name: this.discriminant.name,
195
+ ownValues: this.discriminant.memberValues.flatMap((_) => _.ownValues),
196
+ });
156
197
  case "typeof":
157
198
  return Maybe.empty();
158
199
  default:
@@ -172,7 +213,7 @@ export class AbstractUnionType extends AbstractType {
172
213
  invariant(this.kind.endsWith("Type"));
173
214
  return code `${{
174
215
  // discriminant: {
175
- // kind: '"envelope" | "inline" | "typeof"',
216
+ // kind: '"extrinsic" | "intrinsic" | "typeof"',
176
217
  // },
177
218
  kind: code `${literalOf(this.kind.substring(0, this.kind.length - "Type".length))}`,
178
219
  members: code `{ ${joinCode(this.concreteMembers.map(({ type, primaryDiscriminantValue }) => code `readonly ${literalOf(primaryDiscriminantValue)}: ${{
@@ -228,9 +269,9 @@ if (filter.on?.[${literalOf(primaryDiscriminantValue)}] !== undefined && ${typeC
228
269
  get inlineFromJsonFunction() {
229
270
  return code `\
230
271
  ((value: ${this.jsonType().name}): ${this.name} => {
231
- ${joinCode(this.concreteMembers.map(({ jsonTypeCheck, type, unwrap, wrap }) => code `if (${jsonTypeCheck(code `value`)}) { return ${wrap(type.fromJsonExpression({
272
+ ${joinCode(this.concreteMembers.map(({ jsonType, jsonTypeCheck, type, unwrap, wrap }) => code `if (${jsonTypeCheck(code `value`)}) { return ${wrap(type.fromJsonExpression({
232
273
  variables: {
233
- value: code `(${unwrap(code `value`)} as ${type.jsonType().name})`,
274
+ value: code `(${unwrap(code `value`)} as ${jsonType})`,
234
275
  },
235
276
  }))}; }`))}
236
277
 
@@ -251,7 +292,7 @@ ${joinCode(this.concreteMembers.map(({ jsonTypeCheck, type, unwrap, wrap }) => c
251
292
  (((values, _options) =>
252
293
  values.chain(values => values.chainMap(value => {
253
294
  const valueAsValues = ${imports.Right}(value.toValues());
254
- return ${this.concreteMembers.reduce((expression, { type, primaryDiscriminantValue }) => {
295
+ return ${this.concreteMembers.reduce((expression, { type, primaryDiscriminantValue }, memberI) => {
255
296
  let typeExpression = type.fromRdfResourceValuesExpression({
256
297
  variables: {
257
298
  context: variables.context,
@@ -264,7 +305,9 @@ ${joinCode(this.concreteMembers.map(({ jsonTypeCheck, type, unwrap, wrap }) => c
264
305
  resourceValues: code `valueAsValues`,
265
306
  },
266
307
  });
267
- if (this.discriminant.kind === "envelope") {
308
+ if (this.discriminant.kind === "extrinsic" ||
309
+ (this.discriminant.kind === "hybrid" &&
310
+ this.discriminant.memberValues[memberI].kind === "extrinsic")) {
268
311
  typeExpression = code `${typeExpression}.map(values => values.map(value => ({ ${this.discriminant.name}: ${literalOf(primaryDiscriminantValue)} as const, value }) as (${this.name})))`;
269
312
  }
270
313
  typeExpression = code `(${typeExpression} as ${imports.Either}<Error, ${imports.Resource}.Values<${this.name}>>)`;
@@ -276,38 +319,75 @@ ${joinCode(this.concreteMembers.map(({ jsonTypeCheck, type, unwrap, wrap }) => c
276
319
  ) satisfies ${snippets.FromRdfResourceValuesFunction}<${this.name}>)`;
277
320
  }
278
321
  get inlineJsonType() {
279
- switch (this.discriminant.kind) {
280
- case "envelope":
281
- return new AbstractType.JsonType(code `(${joinCode(this.concreteMembers.map(({ type, primaryDiscriminantValue }) => code `{ ${this.discriminant.name}: ${literalOf(primaryDiscriminantValue)}, value: ${type.jsonType().name} }`), { on: "|" })})`);
282
- case "inline":
322
+ const discriminant = this.discriminant; // To get type narrowing to work
323
+ switch (discriminant.kind) {
324
+ case "extrinsic":
325
+ return new AbstractType.JsonType(code `(${joinCode(this.concreteMembers.map(({ jsonType, primaryDiscriminantValue }) => code `{ ${discriminant.name}: ${literalOf(primaryDiscriminantValue)}, value: ${jsonType} }`), { on: "|" })})`);
326
+ case "hybrid":
327
+ return new AbstractType.JsonType(code `(${joinCode(this.concreteMembers.map(({ jsonType, primaryDiscriminantValue }, memberI) => {
328
+ switch (discriminant.memberValues[memberI].kind) {
329
+ case "extrinsic":
330
+ return code `{ ${discriminant.name}: ${literalOf(primaryDiscriminantValue)}, value: ${jsonType} }`;
331
+ case "intrinsic":
332
+ return code `${jsonType}`;
333
+ default:
334
+ throw new Error();
335
+ }
336
+ }), { on: "|" })})`);
337
+ case "intrinsic":
283
338
  case "typeof":
284
- return new AbstractType.JsonType(joinCode(this.concreteMembers.map(({ type }) => code `${type.jsonType({
285
- includeDiscriminantProperty: this.discriminant.kind === "inline",
286
- }).name}`), { on: "|" }));
339
+ return new AbstractType.JsonType(joinCode(this.concreteMembers.map(({ jsonType }) => code `${jsonType}`), { on: "|" }));
287
340
  default:
288
- throw this.discriminant;
341
+ throw discriminant;
289
342
  }
290
343
  }
291
344
  get inlineJsonSchema() {
292
- switch (this.discriminant.kind) {
293
- case "envelope":
294
- return code `${imports.z}.discriminatedUnion("${this.discriminant.name}", [${joinCode(this.concreteMembers.map(({ type, primaryDiscriminantValue }) => code `${imports.z}.object({ ${this.discriminant.name}: ${imports.z}.literal(${literalOf(primaryDiscriminantValue)}), value: ${type.jsonSchema({ context: "type" })} })`), { on: "," })}])`;
295
- case "inline":
296
- return code `${imports.z}.discriminatedUnion("${this.discriminant.name}", [${joinCode(this.concreteMembers.map(({ type }) => type.jsonSchema({
345
+ const discriminant = this.discriminant; // To get type narrowing to work
346
+ switch (discriminant.kind) {
347
+ case "extrinsic":
348
+ return code `${imports.z}.discriminatedUnion("${discriminant.name}", [${joinCode(this.concreteMembers.map(({ type, primaryDiscriminantValue }) => code `${imports.z}.object({ ${discriminant.name}: ${imports.z}.literal(${literalOf(primaryDiscriminantValue)}), value: ${type.jsonSchema({ context: "type" })} })`), { on: "," })}]).readonly()`;
349
+ case "hybrid":
350
+ return code `${imports.z}.discriminatedUnion("${discriminant.name}", [${joinCode(this.concreteMembers.map(({ primaryDiscriminantValue, type }, memberI) => {
351
+ switch (discriminant.memberValues[memberI].kind) {
352
+ case "extrinsic":
353
+ return code `${imports.z}.object({ ${discriminant.name}: ${imports.z}.literal(${literalOf(primaryDiscriminantValue)}), value: ${type.jsonSchema({ context: "type" })} })`;
354
+ case "intrinsic":
355
+ return type.jsonSchema({
356
+ includeDiscriminantProperty: true,
357
+ context: "type",
358
+ });
359
+ default:
360
+ throw new Error();
361
+ }
362
+ }), { on: "," })}]).readonly()`;
363
+ case "intrinsic":
364
+ return code `${imports.z}.discriminatedUnion("${discriminant.name}", [${joinCode(this.concreteMembers.map(({ type }) => type.jsonSchema({
297
365
  includeDiscriminantProperty: true,
298
366
  context: "type",
299
367
  })), { on: "," })}]).readonly()`;
300
368
  case "typeof":
301
369
  return code `${imports.z}.union([${joinCode(this.concreteMembers.map(({ type }) => type.jsonSchema({ context: "type" })), { on: "," })}]).readonly()`;
302
370
  default:
303
- throw this.discriminant;
371
+ throw discriminant;
304
372
  }
305
373
  }
306
374
  get inlineName() {
307
- switch (this.discriminant.kind) {
308
- case "envelope":
309
- return code `(${joinCode(this.concreteMembers.map(({ type, primaryDiscriminantValue }) => code `{ ${this.discriminant.name}: ${literalOf(primaryDiscriminantValue)}, value: ${type.name} }`), { on: "|" })})`;
310
- case "inline":
375
+ const discriminant = this.discriminant; // To get type narrowing to work
376
+ switch (discriminant.kind) {
377
+ case "extrinsic":
378
+ return code `(${joinCode(this.concreteMembers.map(({ type, primaryDiscriminantValue }) => code `{ ${discriminant.name}: ${literalOf(primaryDiscriminantValue)}, value: ${type.name} }`), { on: "|" })})`;
379
+ case "hybrid":
380
+ return code `(${joinCode(this.concreteMembers.map(({ primaryDiscriminantValue, type }, memberI) => {
381
+ switch (discriminant.memberValues[memberI].kind) {
382
+ case "extrinsic":
383
+ return code `{ ${discriminant.name}: ${literalOf(primaryDiscriminantValue)}, value: ${type.name} }`;
384
+ case "intrinsic":
385
+ return code `${type.name}`;
386
+ default:
387
+ throw new Error();
388
+ }
389
+ }), { on: "|" })})`;
390
+ case "intrinsic":
311
391
  // If every type shares a discriminant (e.g., RDF/JS "termType" or generated NamedObjectType "type"),
312
392
  // just join their names with "|"
313
393
  return code `(${joinCode(this.members.map(({ type }) => code `${type.name}`), { on: "|" })})`;
@@ -316,7 +396,7 @@ ${joinCode(this.concreteMembers.map(({ jsonTypeCheck, type, unwrap, wrap }) => c
316
396
  // of the different member types are known to be different.
317
397
  return code `(${joinCode(this.members.map(({ type }) => code `${type.name}`), { on: "|" })})`;
318
398
  default:
319
- this.discriminant;
399
+ discriminant;
320
400
  throw new Error("should never reach this point");
321
401
  }
322
402
  }
@@ -345,10 +425,7 @@ unionPatterns.push({ patterns: ${type.valueSparqlWherePatternsFunction}({ ...oth
345
425
  get inlineToJsonFunction() {
346
426
  return code `\
347
427
  ((value: ${this.name}): ${this.jsonType().name} => {
348
- ${joinCode(this.concreteMembers.map(({ type, typeCheck, unwrap, wrap }) => code `if (${typeCheck(code `value`)}) { return ${wrap(type.toJsonExpression({
349
- includeDiscriminantProperty: this.discriminant.kind === "inline",
350
- variables: { value: unwrap(code `value`) },
351
- }))}; }`))}
428
+ ${joinCode(this.concreteMembers.map(({ typeCheck, typeToJsonExpression, unwrap, wrap }) => code `if (${typeCheck(code `value`)}) { return ${wrap(typeToJsonExpression(unwrap(code `value`)))}; }`))}
352
429
 
353
430
  throw new Error("unable to serialize to JSON");
354
431
  })`;
@@ -437,77 +514,126 @@ __decorate([
437
514
  ], AbstractUnionType.prototype, "inlineValueSparqlWherePatternsFunction", null);
438
515
  export var Discriminant;
439
516
  (function (Discriminant) {
440
- function inlineDiscriminantProperty(memberTypes) {
441
- let inlineDiscriminantProperty;
442
- for (const memberType of memberTypes) {
443
- const memberTypeDiscriminantProperty = memberType.discriminantProperty.extract();
444
- if (!memberTypeDiscriminantProperty) {
445
- inlineDiscriminantProperty = undefined;
446
- break;
517
+ function infer(members) {
518
+ // extrinsic with user-specified values
519
+ if (members.some((member) => member.discriminantValue.isJust())) {
520
+ return {
521
+ kind: "extrinsic",
522
+ memberValues: members.map((member, memberI) => member.discriminantValue.orDefault(memberI)),
523
+ name: "type",
524
+ };
525
+ }
526
+ const memberTypes = members.map((member) => member.type);
527
+ // intrinsic
528
+ {
529
+ let inlineDiscriminantPropertyName;
530
+ const memberValues = [];
531
+ for (const memberType of memberTypes) {
532
+ const memberTypeDiscriminantProperty = memberType.discriminantProperty.extract();
533
+ if (!memberTypeDiscriminantProperty) {
534
+ inlineDiscriminantPropertyName = undefined;
535
+ break;
536
+ }
537
+ if (!inlineDiscriminantPropertyName) {
538
+ inlineDiscriminantPropertyName = memberTypeDiscriminantProperty.name;
539
+ }
540
+ else if (memberTypeDiscriminantProperty.name !== inlineDiscriminantPropertyName) {
541
+ inlineDiscriminantPropertyName = undefined;
542
+ break;
543
+ }
544
+ memberValues.push({
545
+ descendantValues: memberTypeDiscriminantProperty.descendantValues,
546
+ ownValues: memberTypeDiscriminantProperty.ownValues,
547
+ });
447
548
  }
448
- if (!inlineDiscriminantProperty) {
449
- inlineDiscriminantProperty = {
450
- name: memberTypeDiscriminantProperty.name,
451
- ownValues: memberTypeDiscriminantProperty.ownValues.concat(),
452
- descendantValues: memberTypeDiscriminantProperty.descendantValues.concat(),
549
+ if (inlineDiscriminantPropertyName) {
550
+ return {
551
+ kind: "intrinsic",
552
+ memberValues,
553
+ name: inlineDiscriminantPropertyName,
453
554
  };
454
555
  }
455
- else if (memberTypeDiscriminantProperty.name === inlineDiscriminantProperty.name) {
456
- inlineDiscriminantProperty.descendantValues =
457
- inlineDiscriminantProperty.descendantValues.concat(memberTypeDiscriminantProperty.descendantValues);
458
- inlineDiscriminantProperty.ownValues =
459
- inlineDiscriminantProperty.ownValues.concat(memberTypeDiscriminantProperty.ownValues);
556
+ }
557
+ // typeof
558
+ {
559
+ const memberTypeofsSet = new Set();
560
+ for (const memberType of memberTypes) {
561
+ for (const memberTypeof of memberType.typeofs) {
562
+ memberTypeofsSet.add(memberTypeof);
563
+ }
460
564
  }
461
- else {
462
- return undefined;
565
+ if (memberTypeofsSet.size === memberTypes.length) {
566
+ return {
567
+ memberValues: memberTypes.flatMap((memberType) => memberType.typeofs),
568
+ kind: "typeof",
569
+ };
463
570
  }
464
571
  }
465
- return inlineDiscriminantProperty;
466
- }
467
- function infer(memberTypes) {
468
- // Infer the discriminant kind
469
- const inlineDiscriminantProperty_ = inlineDiscriminantProperty(memberTypes);
470
- if (inlineDiscriminantProperty_) {
572
+ // hybrid
573
+ // If some member type is an RDF/JS term then reuse "termType" as the discriminant.
574
+ if (memberTypes.some((memberType) => termTypes(memberType).size > 0)) {
575
+ const extrinsicMemberTypeNamesSet = new Set();
576
+ let extrinsicMemberTypeCount = 0;
577
+ for (const memberType of memberTypes) {
578
+ if (termTypes(memberType).size > 0) {
579
+ continue;
580
+ }
581
+ extrinsicMemberTypeCount++;
582
+ if (typeof memberType.name === "string") {
583
+ extrinsicMemberTypeNamesSet.add(memberType.name);
584
+ }
585
+ else {
586
+ break;
587
+ }
588
+ }
471
589
  return {
472
- ...inlineDiscriminantProperty_,
473
- kind: "inline",
590
+ kind: "hybrid",
591
+ memberValues: memberTypes.map((memberType, memberTypeI) => {
592
+ const memberTermTypes = termTypes(memberType);
593
+ if (memberTermTypes.size > 0) {
594
+ return {
595
+ kind: "intrinsic",
596
+ ownValues: [...memberTermTypes],
597
+ };
598
+ }
599
+ return {
600
+ kind: "extrinsic",
601
+ ownValues: extrinsicMemberTypeNamesSet.size === extrinsicMemberTypeCount
602
+ ? [memberType.name]
603
+ : [memberTypeI.toString()],
604
+ };
605
+ }),
606
+ name: "termType",
474
607
  };
475
608
  }
476
- const memberTypeofs = new Set();
477
- for (const memberType of memberTypes) {
478
- for (const typeof_ of memberType.typeofs) {
479
- memberTypeofs.add(typeof_);
609
+ // extrinsic with inferred values
610
+ {
611
+ let memberValues;
612
+ {
613
+ const memberTypeNames = memberTypes.map((memberType) => memberType.name);
614
+ if (memberTypeNames.every((memberTypeName) => typeof memberTypeName === "string")) {
615
+ const memberTypeNamesSet = new Set(memberTypeNames);
616
+ if (memberTypeNamesSet.size === memberTypeNames.length) {
617
+ memberValues = memberTypeNames;
618
+ }
619
+ else {
620
+ // Otherwise prefix the non-unique strings with an index and use those as the discriminant values.
621
+ memberValues = memberTypeNames.map((memberTypeName, memberTypeI) => `${memberTypeI}-${memberTypeName}`);
622
+ }
623
+ }
624
+ else {
625
+ // At least one member type name is Code
626
+ // Use member type indices as the discriminant values.
627
+ memberValues = memberTypes.map((_, memberTypeI) => memberTypeI);
628
+ }
480
629
  }
481
- }
482
- if (memberTypeofs.size === memberTypes.length) {
630
+ invariant(memberValues.length === memberTypes.length);
483
631
  return {
484
- kind: "typeof",
632
+ kind: "extrinsic",
633
+ name: "type",
634
+ memberValues: memberValues,
485
635
  };
486
636
  }
487
- let ownValues;
488
- const memberTypeNames = memberTypes.map((memberType) => memberType.name);
489
- if (memberTypeNames.every((memberTypeName) => typeof memberTypeName === "string")) {
490
- const memberTypeNamesSet = new Set(memberTypeNames);
491
- if (memberTypeNamesSet.size === memberTypeNames.length) {
492
- // If every member type name is a unique string, use those strings as the discriminant values.
493
- ownValues = memberTypeNames;
494
- }
495
- else {
496
- // Otherwise prefix the non-unique strings with an index and use those as the discriminant values.
497
- ownValues = memberTypeNames.map((memberTypeName, memberTypeIndex) => `${memberTypeIndex}-${memberTypeName}`);
498
- }
499
- }
500
- else {
501
- // At least one member type name is Code
502
- // Use member type indices as the discriminant values.
503
- ownValues = memberTypes.map((_, memberTypeIndex) => memberTypeIndex);
504
- }
505
- return {
506
- descendantValues: [],
507
- kind: "envelope",
508
- name: "type",
509
- ownValues,
510
- };
511
637
  }
512
638
  Discriminant.infer = infer;
513
639
  })(Discriminant || (Discriminant = {}));
@@ -3,6 +3,7 @@ import { type Code } from "./ts-poet-wrapper.js";
3
3
  export declare class SetType<ItemTypeT extends SetType.ItemType> extends AbstractCollectionType<ItemTypeT> {
4
4
  readonly graphqlArgs: AbstractCollectionType<ItemTypeT>["graphqlArgs"];
5
5
  readonly kind = "SetType";
6
+ get conversions(): readonly AbstractCollectionType.Conversion[];
6
7
  get valueSparqlConstructTriplesFunction(): Code;
7
8
  get valueSparqlWherePatternsFunction(): Code;
8
9
  fromRdfResourceValuesExpression(parameters: Parameters<AbstractCollectionType<ItemTypeT>["fromRdfResourceValuesExpression"]>[0]): Code;
@@ -13,6 +13,18 @@ import { code, joinCode } from "./ts-poet-wrapper.js";
13
13
  export class SetType extends AbstractCollectionType {
14
14
  graphqlArgs = Maybe.empty();
15
15
  kind = "SetType";
16
+ get conversions() {
17
+ const conversions = [];
18
+ if (this.minCount === 0) {
19
+ conversions.push({
20
+ conversionExpression: () => code `[]`,
21
+ sourceTypeCheckExpression: (value) => code `${value} === undefined`,
22
+ sourceTypeName: code `undefined`,
23
+ sourceTypeof: "undefined",
24
+ });
25
+ }
26
+ return conversions.concat(super.conversions);
27
+ }
16
28
  get valueSparqlConstructTriplesFunction() {
17
29
  return code `${snippets.setSparqlConstructTriples}<${this.itemType.filterType}, ${this.itemType.schemaType}>(${this.itemType.valueSparqlConstructTriplesFunction})`;
18
30
  }
@@ -1,5 +1,5 @@
1
1
  import type { Maybe } from "purify-ts";
2
- import type { PropertyVisibility } from "../../../enums/PropertyVisibility.js";
2
+ import type { Visibility } from "../../../enums/Visibility.js";
3
3
  import type { NamedObjectType } from "../NamedObjectType.js";
4
4
  import type { Type } from "../Type.js";
5
5
  import { type Code } from "../ts-poet-wrapper.js";
@@ -74,12 +74,12 @@ export declare abstract class AbstractProperty<TypeT extends Pick<Type, "filterF
74
74
  /**
75
75
  * Property visibility: private, protected, public.
76
76
  */
77
- readonly visibility: PropertyVisibility;
77
+ readonly visibility: Visibility;
78
78
  constructor({ name, namedObjectType, type, visibility, }: {
79
79
  name: string;
80
80
  namedObjectType: NamedObjectType;
81
81
  type: TypeT;
82
- visibility: PropertyVisibility;
82
+ visibility: Visibility;
83
83
  });
84
84
  /**
85
85
  * TypeScript object describing this type, for runtime use.