@distrohelena/canton-typescript-sdk 0.1.24 → 0.1.26

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 (59) hide show
  1. package/README.md +10 -5
  2. package/dist/daml-interface/analysis/analyzed-choice.d.ts +5 -5
  3. package/dist/daml-interface/analysis/analyzed-daml-type-definition.d.ts +6 -0
  4. package/dist/daml-interface/analysis/analyzed-daml-type-definition.js +1 -0
  5. package/dist/daml-interface/analysis/analyzed-daml-type.d.ts +54 -0
  6. package/dist/daml-interface/analysis/analyzed-daml-type.js +1 -0
  7. package/dist/daml-interface/analysis/analyzed-template.d.ts +3 -3
  8. package/dist/daml-interface/analysis/daml-interface-analyzer.d.ts +3 -1
  9. package/dist/daml-interface/analysis/daml-interface-analyzer.js +183 -19
  10. package/dist/daml-interface/emission/named-type-emitter.d.ts +41 -0
  11. package/dist/daml-interface/emission/named-type-emitter.js +441 -0
  12. package/dist/daml-interface/emission/project-emitter.d.ts +5 -1
  13. package/dist/daml-interface/emission/project-emitter.js +20 -3
  14. package/dist/daml-interface/emission/registry-emitter.d.ts +1 -0
  15. package/dist/daml-interface/emission/registry-emitter.js +15 -8
  16. package/dist/daml-interface/emission/support-file-emitter.d.ts +16 -1
  17. package/dist/daml-interface/emission/support-file-emitter.js +206 -6
  18. package/dist/daml-interface/emission/template-binding-emitter.d.ts +25 -1
  19. package/dist/daml-interface/emission/template-binding-emitter.js +373 -72
  20. package/dist/daml-interface/emission/type-script-name-resolver.d.ts +50 -3
  21. package/dist/daml-interface/emission/type-script-name-resolver.js +369 -11
  22. package/dist/daml-interface/emission-model/generated-choice-binding.d.ts +7 -0
  23. package/dist/daml-interface/emission-model/generated-choice-binding.js +6 -0
  24. package/dist/daml-interface/emission-model/generated-daml-interface-project.d.ts +3 -0
  25. package/dist/daml-interface/emission-model/generated-daml-interface-project.js +2 -0
  26. package/dist/daml-interface/emission-model/generated-named-type-file.d.ts +23 -0
  27. package/dist/daml-interface/emission-model/generated-named-type-file.js +23 -0
  28. package/dist/daml-interface/emission-model/generated-template-binding.d.ts +9 -0
  29. package/dist/daml-interface/emission-model/generated-template-binding.js +8 -0
  30. package/dist/daml-interface/index.d.ts +12 -0
  31. package/dist/daml-interface/index.js +9 -0
  32. package/dist/daml-interface/runtime/daml-event-source-normalizer.d.ts +52 -0
  33. package/dist/daml-interface/runtime/daml-event-source-normalizer.js +364 -0
  34. package/dist/daml-interface/runtime/daml-materialization-error.d.ts +5 -0
  35. package/dist/daml-interface/runtime/daml-materialization-error.js +9 -0
  36. package/dist/daml-interface/runtime/daml-template.d.ts +6 -0
  37. package/dist/daml-interface/runtime/daml-template.js +10 -0
  38. package/dist/daml-interface/runtime/daml-type-descriptor.d.ts +71 -0
  39. package/dist/daml-interface/runtime/daml-type-descriptor.js +1 -0
  40. package/dist/daml-interface/runtime/daml-value-converter.d.ts +7 -0
  41. package/dist/daml-interface/runtime/daml-value-converter.js +370 -0
  42. package/dist/daml-interface/runtime/daml-value-materializer.d.ts +3 -0
  43. package/dist/daml-interface/runtime/daml-value-materializer.js +23 -0
  44. package/dist/daml-interface/writing/daml-interface-writer.js +1 -0
  45. package/dist/daml-lf/daml-lf-compilation.d.ts +1 -0
  46. package/dist/daml-lf/daml-lf-compilation.js +24 -3
  47. package/dist/daml-lf/model/daml-lf-builtin-type.d.ts +9 -0
  48. package/dist/daml-lf/model/daml-lf-builtin-type.js +9 -0
  49. package/dist/daml-lf/model/daml-lf-data-type.d.ts +18 -1
  50. package/dist/daml-lf/model/daml-lf-data-type.js +8 -1
  51. package/dist/daml-lf/model/daml-lf-type.d.ts +2 -0
  52. package/dist/daml-lf/model/daml-lf-type.js +2 -0
  53. package/dist/daml-lf/model/lf-2-model-mapper.d.ts +1 -0
  54. package/dist/daml-lf/model/lf-2-model-mapper.js +81 -25
  55. package/dist/daml-lf/semantics/daml-lf-semantic-model.d.ts +3 -0
  56. package/dist/daml-lf/semantics/daml-lf-semantic-model.js +5 -1
  57. package/dist/query/pqs/pqs-query-client.js +15 -0
  58. package/dist/query/pqs/pqs-sql-compiler.js +35 -7
  59. package/package.json +1 -1
@@ -1,119 +1,420 @@
1
+ import { DamlLfBuiltinType } from "../../daml-lf/model/daml-lf-builtin-type.js";
1
2
  import { GeneratedChoiceBinding } from "../emission-model/generated-choice-binding.js";
2
- import { GeneratedTemplateBinding } from "../emission-model/generated-template-binding.js";
3
- import { GeneratedTemplateBindingField, } from "../emission-model/generated-template-binding.js";
3
+ import { GeneratedTemplateBinding, GeneratedTemplateBindingField, } from "../emission-model/generated-template-binding.js";
4
4
  import { GeneratedTemplateBindingFile } from "../emission-model/generated-template-binding-file.js";
5
5
  import { TypeScriptNameResolver } from "./type-script-name-resolver.js";
6
+ /** Emits typed contract and exercise-event bindings for analyzed DAML templates. */
6
7
  export class TemplateBindingEmitter {
7
8
  nameResolver;
8
9
  constructor(nameResolver = new TypeScriptNameResolver()) {
9
10
  this.nameResolver = nameResolver;
10
11
  void this.nameResolver;
11
12
  }
13
+ /** Prepares stable collision-safe names before emitting a complete project. */
14
+ prepareTemplatesOrThrow(templates) {
15
+ this.nameResolver.prepareTemplatesOrThrow(templates);
16
+ }
12
17
  /** Emits a generated TypeScript file for one analyzed DAML template. */
13
- emitTemplateFile(template) {
14
- const binding = this.createBinding(template);
15
- const contents = this.emitContents(binding);
18
+ emitTemplateFile(template, namedTypeFiles = []) {
19
+ const namedReferences = this.resolveNamedReferences(template, namedTypeFiles);
20
+ const binding = this.createBinding(template, namedReferences);
21
+ return new GeneratedTemplateBindingFile({
22
+ path: binding.path,
23
+ contents: this.emitContents(binding, namedReferences),
24
+ binding,
25
+ });
26
+ }
27
+ /** Emits binding metadata without source, for resolving named declaration exports first. */
28
+ emitTemplateBindingFile(template) {
29
+ const namedReferences = this.resolveNamedReferences(template, []);
30
+ const binding = this.createBinding(template, namedReferences);
16
31
  return new GeneratedTemplateBindingFile({
17
32
  path: binding.path,
18
- contents,
33
+ contents: "",
19
34
  binding,
20
35
  });
21
36
  }
22
- createBinding(template) {
37
+ createBinding(template, namedReferences) {
23
38
  return new GeneratedTemplateBinding({
24
- className: template.className,
39
+ templateIdentityKey: this.nameResolver.getTemplateIdentityKey(template),
40
+ namespaceAlias: this.nameResolver.getNamespaceAlias(template),
41
+ className: this.nameResolver.getTemplateClassName(template),
25
42
  templateIdLiteral: this.nameResolver.getTemplateIdLiteral(template),
26
43
  path: this.nameResolver.getTemplateFilePath(template),
27
44
  createFieldsTypeName: this.nameResolver.getCreateFieldsTypeName(template),
28
45
  createdEventTypeName: this.nameResolver.getCreatedEventTypeName(template),
29
46
  createFields: template.createFields.map((field) => new GeneratedTemplateBindingField({
30
47
  name: field.name,
31
- propertyName: field.propertyName,
32
- typeName: this.nameResolver.getTypeName(field.type),
48
+ propertyName: this.nameResolver.getFieldPropertyName(template, field),
49
+ constructorParameterName: this.nameResolver.getFieldConstructorParameterName(template, field),
50
+ type: this.normalizeType(field.type),
51
+ typeName: this.getTypeName(this.normalizeType(field.type), namedReferences),
33
52
  })),
34
53
  choices: template.choices.map((choice) => new GeneratedChoiceBinding({
54
+ choiceIdentityKey: this.nameResolver.getChoiceIdentityKey(template, choice),
35
55
  name: choice.name,
36
- methodName: choice.methodName,
56
+ methodName: this.nameResolver.getChoiceMethodName(template, choice),
37
57
  choiceTypeName: this.nameResolver.getChoiceTypeName(template, choice),
38
58
  exercisedEventTypeName: this.nameResolver.getExercisedEventTypeName(template, choice),
39
- parameterName: choice.parameterName,
40
- parameterTypeName: this.nameResolver.getTypeName(choice.parameterType),
41
- returnTypeName: this.nameResolver.getTypeName(choice.returnType),
59
+ parameterName: this.nameResolver.getChoiceParameterName(template, choice),
60
+ parameterType: this.normalizeType(choice.parameterType),
61
+ parameterTypeName: this.getTypeName(this.normalizeType(choice.parameterType), namedReferences),
62
+ returnType: this.normalizeType(choice.returnType),
63
+ returnTypeName: this.getTypeName(this.normalizeType(choice.returnType), namedReferences),
42
64
  })),
43
65
  });
44
66
  }
45
- emitContents(binding) {
46
- const createFields = binding.createFields
47
- .map((field) => ` ${field.propertyName}: ${field.typeName};`)
48
- .join("\n");
49
- const choiceInterfaces = binding.choices
50
- .map((choice) => [
51
- `export interface ${choice.choiceTypeName} {`,
52
- ` ${choice.parameterName}: ${choice.parameterTypeName};`,
53
- "}",
54
- ].join("\n"))
55
- .join("\n\n");
56
- const exercisedEvents = binding.choices
57
- .map((choice) => [
58
- `export interface ${choice.exercisedEventTypeName} {`,
59
- ` choiceName: "${choice.name}";`,
60
- ` result: ${choice.returnTypeName};`,
61
- "}",
62
- ].join("\n"))
63
- .join("\n\n");
64
- const choiceMethods = binding.choices
65
- .map((choice) => [
66
- ` public static ${choice.methodName}(`,
67
- " contractId: string,",
68
- ` choice: ${choice.choiceTypeName},`,
69
- " ): unknown {",
70
- " return {",
71
- " contractId,",
72
- ` choiceName: "${choice.name}",`,
73
- " choice,",
74
- " };",
75
- " }",
76
- ].join("\n"))
77
- .join("\n\n");
78
- const exercisedReturnType = binding.choices.length === 1
79
- ? binding.choices[0].exercisedEventTypeName
80
- : binding.choices
81
- .map((choice) => choice.exercisedEventTypeName)
82
- .join(" | ");
67
+ emitContents(binding, namedReferences) {
68
+ const imports = this.emitImports(binding, namedReferences);
69
+ const fields = binding.createFields.map((field) => ` readonly ${field.propertyName}: ${field.typeName};`);
70
+ const constructorParameters = binding.createFields.map((field) => `${field.constructorParameterName}: ${field.typeName}`);
71
+ const constructorAssignments = binding.createFields.map((field) => ` this.${field.propertyName} = ${field.constructorParameterName};`);
72
+ const orderedArguments = binding.createFields.map((field) => ` fields.${field.propertyName},`);
73
+ const exercisedReturnType = binding.choices.length === 0
74
+ ? "never"
75
+ : binding.choices.map((choice) => choice.exercisedEventTypeName).join(" | ");
83
76
  return [
77
+ ...imports,
78
+ "",
84
79
  `export interface ${binding.createFieldsTypeName} {`,
85
- createFields,
80
+ ...fields,
86
81
  "}",
87
82
  "",
88
- choiceInterfaces,
83
+ this.emitTemplateClass(binding, constructorParameters, constructorAssignments, orderedArguments, exercisedReturnType),
84
+ ...(binding.choices.length === 0 ? [] : ["", ...binding.choices.flatMap((choice) => [
85
+ this.emitChoiceEventClass(binding, choice),
86
+ "",
87
+ ])]),
88
+ ].join("\n");
89
+ }
90
+ emitImports(binding, namedReferences) {
91
+ const namedImports = new Map();
92
+ for (const reference of namedReferences.values()) {
93
+ const imported = namedImports.get(reference.path) ?? new Map();
94
+ imported.set(reference.exportedName, reference.alias);
95
+ namedImports.set(reference.path, imported);
96
+ }
97
+ return [
98
+ 'import { DamlMaterializationError, DamlTemplate, decodeDamlValue, materializeDamlValue, normalizeDamlCreatedEventSource, normalizeDamlExercisedEventSource } from "@distrohelena/canton-typescript-sdk/daml-interface";',
99
+ 'import type { DamlCreatedEventSource, DamlDate, DamlExercisedEventMetadata, DamlExercisedEventSource, DamlNormalizedExercisedEvent, DamlNumeric, DamlParty, DamlTimestamp, DamlTypeDescriptor, DamlUnit } from "@distrohelena/canton-typescript-sdk/daml-interface";',
100
+ `import { generatedDamlTypeDescriptorRegistry } from ${JSON.stringify(this.relativeFilePath(binding.path, "generated/support/descriptors.ts"))};`,
101
+ ...[...namedImports.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([path, imported]) => `import type { ${[...imported.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([name, alias]) => `${name} as ${alias}`).join(", ")} } from ${JSON.stringify(path)};`),
102
+ ];
103
+ }
104
+ emitTemplateClass(binding, constructorParameters, constructorAssignments, orderedArguments, exercisedReturnType) {
105
+ return [
106
+ `export class ${binding.className} extends DamlTemplate implements ${binding.createFieldsTypeName} {`,
107
+ ` public static readonly templateId = ${JSON.stringify(binding.templateIdLiteral)};`,
108
+ ` private static readonly descriptor: DamlTypeDescriptor = ${this.emitTemplateDescriptor(binding)};`,
89
109
  "",
90
- `export interface ${binding.createdEventTypeName} {`,
91
- " templateId: string;",
92
- ` payload: ${binding.createFieldsTypeName};`,
93
- "}",
110
+ ...binding.createFields.map((field) => ` public readonly ${field.propertyName}: ${field.typeName};`),
111
+ ...(binding.createFields.length === 0 ? [] : [""]),
112
+ ` public constructor(contractId: string${constructorParameters.length === 0 ? "" : `, ${constructorParameters.join(", ")}`}) {`,
113
+ " super(contractId);",
114
+ ...constructorAssignments,
115
+ " }",
116
+ "",
117
+ ` public static fromCreatedEvent(event: DamlCreatedEventSource): ${binding.className} {`,
118
+ " const normalized = normalizeDamlCreatedEventSource(event);",
119
+ ` ${binding.className}.assertTemplateIdentity(normalized.metadata.templateId);`,
120
+ ` const fields = materializeDamlValue<${binding.createFieldsTypeName}>(decodeDamlValue(normalized.payload, ${binding.className}.descriptor, generatedDamlTypeDescriptorRegistry, "create arguments"));`,
121
+ ` return new ${binding.className}(`,
122
+ " normalized.contractId,",
123
+ ...orderedArguments,
124
+ " );",
125
+ " }",
126
+ "",
127
+ ` public static fromExercisedEvent(event: DamlExercisedEventSource): ${exercisedReturnType} {`,
128
+ " const normalized = normalizeDamlExercisedEventSource(event);",
129
+ ` ${binding.className}.assertTemplateIdentity(normalized.metadata.templateId);`,
130
+ " switch (normalized.choice) {",
131
+ ...binding.choices.map((choice) => ` case ${JSON.stringify(choice.name)}:\n return ${choice.exercisedEventTypeName}.fromNormalizedEvent(normalized);`),
132
+ " default:",
133
+ ` throw new DamlMaterializationError("choice", \`Unexpected choice '\${normalized.choice}' for template '${binding.templateIdLiteral}'\`);`,
134
+ " }",
135
+ " }",
94
136
  "",
95
- exercisedEvents,
137
+ " private static assertTemplateIdentity(identity: { readonly packageId: string; readonly moduleName: string; readonly entityName: string }): void {",
138
+ ` if (identity.packageId !== ${JSON.stringify(this.packageId(binding))} || identity.moduleName !== ${JSON.stringify(this.moduleName(binding))} || identity.entityName !== ${JSON.stringify(this.entityName(binding))}) {`,
139
+ ` throw new DamlMaterializationError("template ID", \`Expected template '${binding.templateIdLiteral}' but received '\${identity.packageId}:\${identity.moduleName}:\${identity.entityName}'\`);`,
140
+ " }",
141
+ " }",
142
+ "}",
143
+ ].join("\n");
144
+ }
145
+ emitChoiceEventClass(binding, choice) {
146
+ return [
147
+ `export class ${choice.exercisedEventTypeName} {`,
148
+ ` private static readonly argumentDescriptor: DamlTypeDescriptor = ${this.emitDescriptor(choice.parameterType)};`,
149
+ ` private static readonly resultDescriptor: DamlTypeDescriptor = ${this.emitDescriptor(choice.returnType)};`,
96
150
  "",
97
- `export class ${binding.className} {`,
98
- ` public static readonly templateId = "${binding.templateIdLiteral}";`,
151
+ ` public readonly choiceName = ${JSON.stringify(choice.name)} as const;`,
152
+ " public readonly contractId: string;",
153
+ ` public readonly argument: ${choice.parameterTypeName};`,
154
+ ` public readonly result: ${choice.returnTypeName};`,
155
+ " public readonly consuming: boolean;",
156
+ " public readonly metadata: DamlExercisedEventMetadata;",
99
157
  "",
100
- ` public static create(fields: ${binding.createFieldsTypeName}): unknown {`,
101
- " return {",
102
- ` templateId: ${binding.className}.templateId,`,
103
- " fields,",
104
- " };",
158
+ " public constructor(contractId: string, argument: " + choice.parameterTypeName + ", result: " + choice.returnTypeName + ", consuming: boolean, metadata: DamlExercisedEventMetadata) {",
159
+ " this.contractId = contractId;",
160
+ " this.argument = argument;",
161
+ " this.result = result;",
162
+ " this.consuming = consuming;",
163
+ " this.metadata = metadata;",
105
164
  " }",
106
165
  "",
107
- choiceMethods,
166
+ ` public static fromExercisedEvent(event: DamlExercisedEventSource): ${choice.exercisedEventTypeName} {`,
167
+ " const normalized = normalizeDamlExercisedEventSource(event);",
168
+ ` ${choice.exercisedEventTypeName}.assertTemplateIdentity(normalized.metadata.templateId);`,
169
+ ` return ${choice.exercisedEventTypeName}.fromNormalizedEvent(normalized);`,
170
+ " }",
108
171
  "",
109
- ` public static decodeCreatedEvent(event: unknown): ${binding.createdEventTypeName} {`,
110
- ` return event as ${binding.createdEventTypeName};`,
172
+ ` public static fromNormalizedEvent(event: DamlNormalizedExercisedEvent): ${choice.exercisedEventTypeName} {`,
173
+ ` ${choice.exercisedEventTypeName}.assertTemplateIdentity(event.metadata.templateId);`,
174
+ ` if (event.choice !== ${JSON.stringify(choice.name)}) {`,
175
+ ` throw new DamlMaterializationError("choice", \`Expected choice '${choice.name}' but received '\${event.choice}'\`);`,
176
+ " }",
177
+ ` const argument = materializeDamlValue<${choice.parameterTypeName}>(decodeDamlValue(event.argument, ${choice.exercisedEventTypeName}.argumentDescriptor, generatedDamlTypeDescriptorRegistry, "choice argument"));`,
178
+ ` const result = materializeDamlValue<${choice.returnTypeName}>(decodeDamlValue(event.result, ${choice.exercisedEventTypeName}.resultDescriptor, generatedDamlTypeDescriptorRegistry, "exercise result"));`,
179
+ ` return new ${choice.exercisedEventTypeName}(event.contractId, argument, result, event.consuming, event.metadata);`,
111
180
  " }",
112
181
  "",
113
- ` public static decodeExercisedEvent(event: unknown): ${exercisedReturnType} {`,
114
- ` return event as ${exercisedReturnType};`,
182
+ " private static assertTemplateIdentity(identity: { readonly packageId: string; readonly moduleName: string; readonly entityName: string }): void {",
183
+ ` if (identity.packageId !== ${JSON.stringify(this.packageId(binding))} || identity.moduleName !== ${JSON.stringify(this.moduleName(binding))} || identity.entityName !== ${JSON.stringify(this.entityName(binding))}) {`,
184
+ ` throw new DamlMaterializationError("template ID", \`Expected template '${binding.templateIdLiteral}' but received '\${identity.packageId}:\${identity.moduleName}:\${identity.entityName}'\`);`,
185
+ " }",
115
186
  " }",
116
187
  "}",
117
- ].filter((item) => item.length > 0).join("\n");
188
+ ].join("\n");
189
+ }
190
+ emitTemplateDescriptor(binding) {
191
+ return `{ kind: "record", fields: [${binding.createFields.map((field) => `{ damlLabel: ${JSON.stringify(field.name)}, propertyName: ${JSON.stringify(field.propertyName)}, type: ${this.emitDescriptor(field.type)} }`).join(", ")}] }`;
192
+ }
193
+ emitDescriptor(type) {
194
+ switch (type.kind) {
195
+ case "primitive":
196
+ return `{ kind: "primitive", primitive: ${JSON.stringify(type.builtinType)}${type.numericScale === undefined ? "" : `, numericScale: ${type.numericScale}`} }`;
197
+ case "contractId":
198
+ return '{ kind: "contractId" }';
199
+ case "optional":
200
+ return `{ kind: "optional", element: ${this.emitDescriptor(type.element)} }`;
201
+ case "list":
202
+ return `{ kind: "list", element: ${this.emitDescriptor(type.element)} }`;
203
+ case "textMap":
204
+ return `{ kind: "textMap", value: ${this.emitDescriptor(type.value)} }`;
205
+ case "genMap":
206
+ return `{ kind: "genMap", key: ${this.emitDescriptor(type.key)}, value: ${this.emitDescriptor(type.value)} }`;
207
+ case "record":
208
+ return `{ kind: "record", fields: [${type.fields.map((field) => `{ damlLabel: ${JSON.stringify(field.damlLabel)}, propertyName: ${JSON.stringify(field.propertyName)}, type: ${this.emitDescriptor(field.type)} }`).join(", ")}] }`;
209
+ case "variant":
210
+ return `{ kind: "variant", constructors: [${type.constructors.map((constructor) => `{ constructor: ${JSON.stringify(constructor.constructor)}, payload: ${this.emitDescriptor(constructor.payload)} }`).join(", ")}] }`;
211
+ case "enum":
212
+ return `{ kind: "enum", constructors: [${type.constructors.map((constructor) => JSON.stringify(constructor)).join(", ")}] }`;
213
+ case "namedReference":
214
+ return `{ kind: "namedReference", identity: { packageId: ${JSON.stringify(type.identity.packageId)}, moduleName: ${JSON.stringify(type.identity.moduleName)}, entityName: ${JSON.stringify(type.identity.name)} } }`;
215
+ }
216
+ }
217
+ getTypeName(type, namedReferences) {
218
+ switch (type.kind) {
219
+ case "primitive":
220
+ return this.getPrimitiveTypeName(type.builtinType);
221
+ case "contractId":
222
+ return "string";
223
+ case "optional":
224
+ return `${this.getTypeName(type.element, namedReferences)} | undefined`;
225
+ case "list":
226
+ return `readonly ${this.getTypeName(type.element, namedReferences)}[]`;
227
+ case "textMap":
228
+ return `ReadonlyMap<string, ${this.getTypeName(type.value, namedReferences)}>`;
229
+ case "genMap":
230
+ return `ReadonlyMap<${this.getTypeName(type.key, namedReferences)}, ${this.getTypeName(type.value, namedReferences)}>`;
231
+ case "record":
232
+ return `{ ${type.fields.map((field) => `readonly ${field.propertyName}: ${this.getTypeName(field.type, namedReferences)};`).join(" ")} }`;
233
+ case "variant":
234
+ return type.constructors.map((constructor) => `{ readonly tag: ${JSON.stringify(constructor.constructor)}; readonly value: ${this.getTypeName(constructor.payload, namedReferences)}; }`).join(" | ");
235
+ case "enum":
236
+ return type.constructors.map((constructor) => JSON.stringify(constructor)).join(" | ");
237
+ case "namedReference":
238
+ return this.getNamedReference(type.identity, namedReferences).alias;
239
+ }
240
+ }
241
+ getPrimitiveTypeName(type) {
242
+ switch (type) {
243
+ case DamlLfBuiltinType.unit: return "DamlUnit";
244
+ case DamlLfBuiltinType.bool: return "boolean";
245
+ case DamlLfBuiltinType.int64: return "bigint";
246
+ case DamlLfBuiltinType.date: return "DamlDate";
247
+ case DamlLfBuiltinType.timestamp: return "DamlTimestamp";
248
+ case DamlLfBuiltinType.numeric: return "DamlNumeric";
249
+ case DamlLfBuiltinType.party: return "DamlParty";
250
+ case DamlLfBuiltinType.text: return "string";
251
+ default: throw new Error(`Cannot emit unsupported primitive DAML type '${type}'`);
252
+ }
253
+ }
254
+ normalizeType(type) {
255
+ if ("kind" in type) {
256
+ return type;
257
+ }
258
+ else if (type.builtinType === DamlLfBuiltinType.contractId) {
259
+ if (type.typeArguments.length !== 1) {
260
+ throw new Error("DAML ContractId requires exactly one type argument");
261
+ }
262
+ return { kind: "contractId" };
263
+ }
264
+ else if (type.typeConReference !== undefined) {
265
+ return { kind: "namedReference", identity: type.typeConReference };
266
+ }
267
+ const arguments_ = type.typeArguments.map((argument) => this.normalizeType(argument));
268
+ switch (type.builtinType) {
269
+ case DamlLfBuiltinType.optional:
270
+ return { kind: "optional", element: arguments_[0] ?? { kind: "primitive", builtinType: DamlLfBuiltinType.text } };
271
+ case DamlLfBuiltinType.list:
272
+ return { kind: "list", element: arguments_[0] ?? { kind: "primitive", builtinType: DamlLfBuiltinType.text } };
273
+ case DamlLfBuiltinType.textMap:
274
+ return { kind: "textMap", value: arguments_[0] ?? { kind: "primitive", builtinType: DamlLfBuiltinType.text } };
275
+ case DamlLfBuiltinType.genMap:
276
+ return { kind: "genMap", key: arguments_[0] ?? { kind: "primitive", builtinType: DamlLfBuiltinType.text }, value: arguments_[1] ?? { kind: "primitive", builtinType: DamlLfBuiltinType.text } };
277
+ case DamlLfBuiltinType.unit:
278
+ case DamlLfBuiltinType.bool:
279
+ case DamlLfBuiltinType.int64:
280
+ case DamlLfBuiltinType.date:
281
+ case DamlLfBuiltinType.timestamp:
282
+ case DamlLfBuiltinType.numeric:
283
+ case DamlLfBuiltinType.party:
284
+ case DamlLfBuiltinType.text:
285
+ return { kind: "primitive", builtinType: type.builtinType, numericScale: type.numericScale };
286
+ case DamlLfBuiltinType.unknown:
287
+ throw new Error("Cannot emit an unknown DAML type");
288
+ default:
289
+ throw new Error("Cannot emit unsupported DAML type");
290
+ }
291
+ }
292
+ resolveNamedReferences(template, namedTypeFiles) {
293
+ const identities = new Map();
294
+ for (const type of [
295
+ ...template.createFields.map((field) => this.normalizeType(field.type)),
296
+ ...template.choices.flatMap((choice) => [
297
+ this.normalizeType(choice.parameterType),
298
+ this.normalizeType(choice.returnType),
299
+ ]),
300
+ ]) {
301
+ for (const reference of this.walkNamedReferences(type)) {
302
+ identities.set(this.getNamedReferenceKey(reference.identity), reference);
303
+ }
304
+ }
305
+ const aliases = new Map();
306
+ const usedAliases = new Set();
307
+ for (const [key, reference] of [...identities.entries()].sort(([left], [right]) => left.localeCompare(right))) {
308
+ const file = namedTypeFiles.find((candidate) => candidate.packageId === reference.identity.packageId
309
+ && candidate.moduleName === reference.identity.moduleName);
310
+ const exportedName = file?.exportedTypeNamesByIdentity.get(key);
311
+ if (file === undefined || exportedName === undefined) {
312
+ if (namedTypeFiles.length !== 0) {
313
+ throw new Error(`Cannot emit unresolved named DAML type '${reference.identity.name}'`);
314
+ }
315
+ aliases.set(key, reference.identity.name);
316
+ continue;
317
+ }
318
+ const baseAlias = this.toTypeName(`${reference.identity.packageId} ${reference.identity.moduleName} ${exportedName}`);
319
+ let alias = baseAlias;
320
+ let escalation = 2;
321
+ while (usedAliases.has(alias)) {
322
+ alias = `${baseAlias}_${this.shortHash(key)}_${escalation}`;
323
+ escalation += 1;
324
+ }
325
+ usedAliases.add(alias);
326
+ aliases.set(key, alias);
327
+ }
328
+ return new Map([...identities.entries()].map(([key, reference]) => {
329
+ const file = namedTypeFiles.find((candidate) => candidate.packageId === reference.identity.packageId
330
+ && candidate.moduleName === reference.identity.moduleName);
331
+ const exportedName = file?.exportedTypeNamesByIdentity.get(key);
332
+ const alias = aliases.get(key);
333
+ if (file === undefined || exportedName === undefined) {
334
+ return [key, {
335
+ path: "",
336
+ exportedName: reference.identity.name,
337
+ alias: alias ?? reference.identity.name,
338
+ }];
339
+ }
340
+ return [key, {
341
+ path: this.relativeFilePath(this.nameResolver.getTemplateFilePath(template), file.path),
342
+ exportedName,
343
+ alias: alias,
344
+ }];
345
+ }));
346
+ }
347
+ *walkNamedReferences(type) {
348
+ switch (type.kind) {
349
+ case "namedReference":
350
+ yield type;
351
+ return;
352
+ case "contractId": return;
353
+ case "optional":
354
+ case "list":
355
+ yield* this.walkNamedReferences(type.element);
356
+ return;
357
+ case "textMap":
358
+ yield* this.walkNamedReferences(type.value);
359
+ return;
360
+ case "genMap":
361
+ yield* this.walkNamedReferences(type.key);
362
+ yield* this.walkNamedReferences(type.value);
363
+ return;
364
+ case "record":
365
+ for (const field of type.fields) {
366
+ yield* this.walkNamedReferences(field.type);
367
+ }
368
+ return;
369
+ case "variant":
370
+ for (const constructor of type.constructors) {
371
+ yield* this.walkNamedReferences(constructor.payload);
372
+ }
373
+ return;
374
+ case "primitive":
375
+ case "enum": return;
376
+ }
377
+ }
378
+ getNamedReference(identity, namedReferences) {
379
+ const reference = namedReferences.get(this.getNamedReferenceKey(identity));
380
+ if (reference === undefined) {
381
+ throw new Error(`Cannot resolve named DAML type '${identity.name}'`);
382
+ }
383
+ return reference;
384
+ }
385
+ getNamedReferenceKey(identity) {
386
+ return `${identity.packageId}\u0000${identity.moduleName}\u0000${identity.name}`;
387
+ }
388
+ toTypeName(value) {
389
+ const normalized = value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[^A-Za-z0-9]+/g, " ").trim();
390
+ const name = normalized.split(/\s+/).map((part) => `${part[0]?.toUpperCase()}${part.slice(1)}`).join("");
391
+ return /^[0-9]/.test(name) ? `_${name}` : name;
392
+ }
393
+ shortHash(value) {
394
+ let hash = 0x811c9dc5;
395
+ for (const character of value) {
396
+ hash ^= character.charCodeAt(0);
397
+ hash = Math.imul(hash, 0x01000193);
398
+ }
399
+ return (hash >>> 0).toString(36).padStart(6, "0").slice(-6);
400
+ }
401
+ packageId(binding) {
402
+ return binding.templateIdLiteral.split(":")[0];
403
+ }
404
+ moduleName(binding) {
405
+ return binding.templateIdLiteral.split(":")[1];
406
+ }
407
+ entityName(binding) {
408
+ return binding.templateIdLiteral.split(":")[2];
409
+ }
410
+ relativeFilePath(fromPath, toPath) {
411
+ const from = fromPath.split("/").slice(0, -1);
412
+ const to = toPath.split("/");
413
+ while (from[0] === to[0] && from.length > 0) {
414
+ from.shift();
415
+ to.shift();
416
+ }
417
+ const relative = from.map(() => "..").concat(to).join("/") || ".";
418
+ return `${relative.startsWith(".") ? relative : `./${relative}`}`.replace(/\.ts$/, ".js");
118
419
  }
119
420
  }
@@ -1,21 +1,68 @@
1
- import { DamlLfType } from "../../daml-lf/model/daml-lf-type.js";
2
1
  import { AnalyzedChoice } from "../analysis/analyzed-choice.js";
3
- import { AnalyzedTemplate } from "../analysis/analyzed-template.js";
2
+ import { AnalyzedDamlType } from "../analysis/analyzed-daml-type.js";
3
+ import { AnalyzedDamlTypeDefinition } from "../analysis/analyzed-daml-type-definition.js";
4
+ import { AnalyzedTemplate, AnalyzedTemplateField } from "../analysis/analyzed-template.js";
4
5
  export declare class TypeScriptNameResolver {
6
+ private readonly templatesByIdentity;
7
+ private resolvedTemplates;
8
+ private resolvedModules;
9
+ constructor(templates?: readonly AnalyzedTemplate[]);
10
+ /** Prepares a project-wide name table and rejects irreconcilable output collisions. */
11
+ prepareTemplatesOrThrow(templates: readonly AnalyzedTemplate[]): void;
12
+ /** Prepares shared package/module paths for template and named DAML type output. */
13
+ prepareProjectOrThrow(templates: readonly AnalyzedTemplate[], typeDefinitions: readonly AnalyzedDamlTypeDefinition[]): void;
14
+ /** Resolves the full package/module/entity identity key for a template. */
15
+ getTemplateIdentityKey(template: AnalyzedTemplate): string;
16
+ /** Resolves the generated namespace alias for a template package/module. */
17
+ getNamespaceAlias(template: AnalyzedTemplate): string;
5
18
  /** Resolves the generated file path for a template binding. */
6
19
  getTemplateFilePath(template: AnalyzedTemplate): string;
20
+ /** Resolves the generated class name for a template binding. */
21
+ getTemplateClassName(template: AnalyzedTemplate): string;
22
+ /** Resolves the output directory shared by a named DAML type package/module. */
23
+ getNamedTypeModuleDirectoryPath(packageId: string, moduleName: string): string;
24
+ /** Resolves the generated namespace alias shared by templates and named DAML types. */
25
+ getNamedTypeModuleNamespaceAlias(packageId: string, moduleName: string): string;
7
26
  /** Resolves the generated create-fields type name for a template. */
8
27
  getCreateFieldsTypeName(template: AnalyzedTemplate): string;
9
28
  /** Resolves the generated created-event type name for a template. */
10
29
  getCreatedEventTypeName(template: AnalyzedTemplate): string;
30
+ /** Resolves the generated property name for an original DAML template field. */
31
+ getFieldPropertyName(template: AnalyzedTemplate, field: AnalyzedTemplateField): string;
32
+ /** Resolves the generated constructor parameter for an original DAML template field. */
33
+ getFieldConstructorParameterName(template: AnalyzedTemplate, field: AnalyzedTemplateField): string;
34
+ /** Resolves the generated exercise method name for a DAML choice. */
35
+ getChoiceMethodName(template: AnalyzedTemplate, choice: AnalyzedChoice): string;
11
36
  /** Resolves the generated choice payload type name for a template choice. */
12
37
  getChoiceTypeName(template: AnalyzedTemplate, choice: AnalyzedChoice): string;
13
38
  /** Resolves the generated exercised-event type name for a template choice. */
14
39
  getExercisedEventTypeName(template: AnalyzedTemplate, choice: AnalyzedChoice): string;
40
+ /** Resolves the generated parameter property name for a DAML choice. */
41
+ getChoiceParameterName(template: AnalyzedTemplate, choice: AnalyzedChoice): string;
42
+ /** Resolves the full identity key for a DAML choice. */
43
+ getChoiceIdentityKey(template: AnalyzedTemplate, choice: AnalyzedChoice): string;
15
44
  /** Resolves the TypeScript type name for a supported DAML-LF type. */
16
- getTypeName(type: DamlLfType): string;
45
+ getTypeName(type: AnalyzedDamlType): string;
17
46
  /** Resolves the literal template identifier used by generated helpers. */
18
47
  getTemplateIdLiteral(template: AnalyzedTemplate): string;
48
+ private getResolvedTemplate;
49
+ private getResolvedModule;
50
+ private getResolvedField;
51
+ private getResolvedChoice;
52
+ private resolveFieldNames;
53
+ private resolveChoiceNames;
54
+ private resolveNames;
55
+ private assertDistinctTemplateOutput;
56
+ private assertDistinctNamespaceAliases;
19
57
  private getModuleDirectory;
58
+ private getTemplateFileBaseName;
59
+ private getPackageModuleIdentityKey;
60
+ private getPackageModuleIdentityKeyFromParts;
61
+ private safeTypeName;
62
+ private safeNamespaceAlias;
63
+ private safeMemberName;
64
+ private toPascalCase;
20
65
  private toKebabCase;
66
+ private shortHash;
67
+ private describeTemplate;
21
68
  }