@helios-lang/contract-utils 0.3.5 → 0.3.7

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 (56) hide show
  1. package/package.json +1 -1
  2. package/src/artifacts/Artifact.js +14 -0
  3. package/src/artifacts/ArtifactWriter.js +199 -0
  4. package/src/artifacts/ChildArtifactWriter.js +118 -0
  5. package/src/artifacts/FunctionArtifact.js +90 -0
  6. package/src/artifacts/ModuleArtifact.js +83 -0
  7. package/src/artifacts/RootArtifact.js +105 -0
  8. package/src/artifacts/TypeArtifact.js +104 -0
  9. package/src/artifacts/ValidatorArtifact.js +158 -0
  10. package/src/artifacts/index.js +1 -0
  11. package/src/artifacts/symbols.js +16 -0
  12. package/src/cast/Cast.js +45 -9
  13. package/src/cast/UserFunc.js +182 -131
  14. package/src/cast/index.js +12 -3
  15. package/src/codegen/LoadedScriptsWriter.js +35 -11
  16. package/src/codegen/TypeSchema.js +126 -0
  17. package/src/context/index.js +1 -0
  18. package/src/hl2ts.js +0 -4
  19. package/src/index.js +36 -8
  20. package/src/internal.js +12 -0
  21. package/types/artifacts/Artifact.d.ts +11 -0
  22. package/types/artifacts/Artifact.d.ts.map +1 -0
  23. package/types/artifacts/ArtifactWriter.d.ts +64 -0
  24. package/types/artifacts/ArtifactWriter.d.ts.map +1 -0
  25. package/types/artifacts/ChildArtifactWriter.d.ts +35 -0
  26. package/types/artifacts/ChildArtifactWriter.d.ts.map +1 -0
  27. package/types/artifacts/FunctionArtifact.d.ts +14 -0
  28. package/types/artifacts/FunctionArtifact.d.ts.map +1 -0
  29. package/types/artifacts/ModuleArtifact.d.ts +29 -0
  30. package/types/artifacts/ModuleArtifact.d.ts.map +1 -0
  31. package/types/artifacts/RootArtifact.d.ts +11 -0
  32. package/types/artifacts/RootArtifact.d.ts.map +1 -0
  33. package/types/artifacts/TypeArtifact.d.ts +17 -0
  34. package/types/artifacts/TypeArtifact.d.ts.map +1 -0
  35. package/types/artifacts/ValidatorArtifact.d.ts +17 -0
  36. package/types/artifacts/ValidatorArtifact.d.ts.map +1 -0
  37. package/types/artifacts/index.d.ts +2 -0
  38. package/types/artifacts/index.d.ts.map +1 -0
  39. package/types/artifacts/symbols.d.ts +8 -0
  40. package/types/artifacts/symbols.d.ts.map +1 -0
  41. package/types/cast/Cast.d.ts +31 -0
  42. package/types/cast/Cast.d.ts.map +1 -1
  43. package/types/cast/UserFunc.d.ts +39 -0
  44. package/types/cast/UserFunc.d.ts.map +1 -1
  45. package/types/cast/index.d.ts +2 -2
  46. package/types/codegen/LoadedScriptsWriter.d.ts +18 -0
  47. package/types/codegen/LoadedScriptsWriter.d.ts.map +1 -1
  48. package/types/codegen/TypeSchema.d.ts +5 -0
  49. package/types/codegen/TypeSchema.d.ts.map +1 -1
  50. package/types/context/writeContractContextArtifacts.d.ts +30 -0
  51. package/types/context/writeContractContextArtifacts.d.ts.map +1 -0
  52. package/types/hl2ts.d.ts.map +1 -1
  53. package/types/index.d.ts +30 -4
  54. package/types/index.d.ts.map +1 -1
  55. package/types/internal.d.ts +5 -0
  56. package/types/internal.d.ts.map +1 -0
@@ -37,7 +37,6 @@ class UserFuncImpl {
37
37
  uplc
38
38
 
39
39
  /**
40
- * @private
41
40
  * @readonly
42
41
  * @type {UserFuncProps}
43
42
  */
@@ -65,45 +64,7 @@ class UserFuncImpl {
65
64
  * @returns {RetT}
66
65
  */
67
66
  eval(namedArgs, logOptions = undefined) {
68
- /**
69
- * @type {{[argName: string]: any}}
70
- */
71
- const unsafeNamedArgs = {}
72
-
73
- Object.entries(namedArgs).forEach(([argName, argValue]) => {
74
- const argDetails = this.props.arguments.find(
75
- (a) => a.name == argName
76
- )
77
-
78
- if (argDetails) {
79
- const typeSchema = argDetails.type
80
-
81
- unsafeNamedArgs[argName] = makeCast(
82
- typeSchema,
83
- this.props.castConfig
84
- ).toUplcData(argValue)
85
- } else if (["$currentScript", "$scriptContext"].includes(argName)) {
86
- unsafeNamedArgs[argName] = argValue
87
- } else {
88
- console.error(
89
- `invalid arg '${argName}' for user function ${this.props.name}`
90
- )
91
- }
92
- })
93
-
94
- const result = this.evalUnsafe(
95
- /** @type {UnsafeArgsT<ArgsT>} */ (unsafeNamedArgs),
96
- logOptions
97
- )
98
-
99
- if (this.props.returns) {
100
- return makeCast(
101
- this.props.returns,
102
- this.props.castConfig
103
- ).fromUplcData(expectDefined(/** @type {any} */ (result)))
104
- } else {
105
- return /** @type {any} */ (undefined)
106
- }
67
+ return evalUserFunc(this.uplc, this.props, namedArgs, logOptions)
107
68
  }
108
69
 
109
70
  /**
@@ -112,17 +73,7 @@ class UserFuncImpl {
112
73
  * @returns {RetT extends void ? void : UplcData}
113
74
  */
114
75
  evalUnsafe(namedArgs, logOptions = undefined) {
115
- const result = this.profile(namedArgs, logOptions).result
116
-
117
- if (isLeft(result)) {
118
- throw new UplcRuntimeError(result.left.error, result.left.callSites)
119
- } else if (!isString(result.right) && result.right.kind == "data") {
120
- return /** @type {any} */ (result.right.value)
121
- } else if (this.props.returns) {
122
- throw new Error(`${result.right.toString()} isn't a UplcDataValue`)
123
- } else {
124
- return /** @type {any} */ (undefined)
125
- }
76
+ return evalUserFuncUnsafe(this.uplc, this.props, namedArgs, logOptions)
126
77
  }
127
78
 
128
79
  /**
@@ -131,108 +82,208 @@ class UserFuncImpl {
131
82
  * @returns {CekResult}
132
83
  */
133
84
  profile(namedArgs, logOptions = undefined) {
134
- const isMain = this.name == "main"
135
-
136
- /**
137
- * @type {UplcData[]}
138
- */
139
- const args = []
140
-
141
- this.props.arguments.forEach(({ name, type, isOptional }) => {
142
- if (isMain) {
143
- if (isOptional) {
144
- // used for $datum in mixed script
145
- if (name in namedArgs && namedArgs[name]) {
146
- args.push(namedArgs[name])
147
- }
148
- } else {
149
- args.push(expectDefined(namedArgs[name]))
85
+ return profileUserFunc(this.uplc, this.props, namedArgs, logOptions)
86
+ }
87
+ }
88
+
89
+ /**
90
+ * @template {{[argName: string]: any}} ArgsT
91
+ * @template RetT
92
+ * @param {UplcProgram} program
93
+ * @param {UserFuncProps} props
94
+ * @param {ArgsT} namedArgs
95
+ * @param {UplcLogger | undefined} logOptions
96
+ * @returns {RetT}
97
+ */
98
+ export function evalUserFunc(
99
+ program,
100
+ props,
101
+ namedArgs,
102
+ logOptions = undefined
103
+ ) {
104
+ /**
105
+ * @type {{[argName: string]: any}}
106
+ */
107
+ const unsafeNamedArgs = {}
108
+
109
+ Object.entries(namedArgs).forEach(([argName, argValue]) => {
110
+ const argDetails = props.arguments.find((a) => a.name == argName)
111
+
112
+ if (argDetails) {
113
+ const typeSchema = argDetails.type
114
+
115
+ unsafeNamedArgs[argName] = makeCast(
116
+ typeSchema,
117
+ props.castConfig
118
+ ).toUplcData(argValue)
119
+ } else if (["$currentScript", "$scriptContext"].includes(argName)) {
120
+ unsafeNamedArgs[argName] = argValue
121
+ } else {
122
+ console.error(
123
+ `invalid arg '${argName}' for user function ${props.name}`
124
+ )
125
+ }
126
+ })
127
+
128
+ const result = evalUserFuncUnsafe(
129
+ program,
130
+ props,
131
+ /** @type {UnsafeArgsT<ArgsT>} */ (unsafeNamedArgs),
132
+ logOptions
133
+ )
134
+
135
+ if (props.returns) {
136
+ return makeCast(props.returns, props.castConfig).fromUplcData(
137
+ expectDefined(/** @type {any} */ (result))
138
+ )
139
+ } else {
140
+ return /** @type {any} */ (undefined)
141
+ }
142
+ }
143
+
144
+ /**
145
+ * @template {{[argName: string]: any}} ArgsT
146
+ * @template RetT
147
+ * @param {UplcProgram} program
148
+ * @param {UserFuncProps} props
149
+ * @param {UnsafeArgsT<ArgsT>} namedArgs
150
+ * @param {UplcLogger | undefined} logOptions
151
+ * @returns {RetT extends void ? void : UplcData}
152
+ */
153
+ export function evalUserFuncUnsafe(
154
+ program,
155
+ props,
156
+ namedArgs,
157
+ logOptions = undefined
158
+ ) {
159
+ const result = profileUserFunc(program, props, namedArgs, logOptions).result
160
+
161
+ if (isLeft(result)) {
162
+ throw new UplcRuntimeError(result.left.error, result.left.callSites)
163
+ } else if (!isString(result.right) && result.right.kind == "data") {
164
+ return /** @type {any} */ (result.right.value)
165
+ } else if (props.returns) {
166
+ throw new Error(`${result.right.toString()} isn't a UplcDataValue`)
167
+ } else {
168
+ return /** @type {any} */ (undefined)
169
+ }
170
+ }
171
+
172
+ /**
173
+ * @template {{[argName: string]: any}} ArgsT
174
+ * @param {UplcProgram} program
175
+ * @param {UserFuncProps} props
176
+ * @param {UnsafeArgsT<ArgsT>} namedArgs
177
+ * @param {UplcLogger | undefined} logOptions - optional, passed to UplcProgram.eval if provided
178
+ * @returns {CekResult}
179
+ */
180
+ export function profileUserFunc(
181
+ program,
182
+ props,
183
+ namedArgs,
184
+ logOptions = undefined
185
+ ) {
186
+ const isMain = props.name == "main"
187
+
188
+ /**
189
+ * @type {UplcData[]}
190
+ */
191
+ const args = []
192
+
193
+ props.arguments.forEach(({ name, type, isOptional }) => {
194
+ if (isMain) {
195
+ if (isOptional) {
196
+ // used for $datum in mixed script
197
+ if (name in namedArgs && namedArgs[name]) {
198
+ args.push(namedArgs[name])
150
199
  }
151
200
  } else {
152
- if (isOptional) {
153
- if (name in namedArgs && namedArgs[name]) {
154
- args.push(makeConstrData(0, [namedArgs[name]]))
155
- } else {
156
- args.push(makeConstrData(1, []))
157
- }
201
+ args.push(expectDefined(namedArgs[name]))
202
+ }
203
+ } else {
204
+ if (isOptional) {
205
+ if (name in namedArgs && namedArgs[name]) {
206
+ args.push(makeConstrData(0, [namedArgs[name]]))
158
207
  } else {
159
- args.push(expectDefined(namedArgs[name]))
208
+ args.push(makeConstrData(1, []))
160
209
  }
210
+ } else {
211
+ args.push(expectDefined(namedArgs[name]))
161
212
  }
162
- })
163
-
164
- if (this.props.requiresScriptContext) {
165
- args.push(expectDefined(namedArgs["$scriptContext"]))
166
213
  }
214
+ })
167
215
 
168
- if (this.props.requiresCurrentScript) {
169
- const currentScriptName = expectDefined(
170
- /** @type {any} */ (namedArgs)["$currentScript"]
171
- )
216
+ if (props.requiresScriptContext) {
217
+ args.push(expectDefined(namedArgs["$scriptContext"]))
218
+ }
172
219
 
173
- const index = expectDefined(
174
- expectDefined(this.props.validatorIndices)[currentScriptName]
175
- )
220
+ if (props.requiresCurrentScript) {
221
+ const currentScriptName = expectDefined(
222
+ /** @type {any} */ (namedArgs)["$currentScript"]
223
+ )
176
224
 
177
- args.push(makeConstrData(index, []))
178
- }
225
+ const index = expectDefined(
226
+ expectDefined(props.validatorIndices)[currentScriptName]
227
+ )
228
+
229
+ args.push(makeConstrData(index, []))
230
+ }
179
231
 
180
- const argValues = args.map((a) => makeUplcDataValue(a))
232
+ const argValues = args.map((a) => makeUplcDataValue(a))
181
233
 
182
- const cekResult = this.uplc.eval(argValues, {
234
+ const cekResult = program.eval(argValues, {
235
+ logOptions: logOptions ?? undefined
236
+ })
237
+
238
+ if (program.alt?.plutusVersion == "PlutusScriptV2") {
239
+ const cekResultUnoptim = program.alt.eval(argValues, {
183
240
  logOptions: logOptions ?? undefined
184
241
  })
242
+ const resultUnoptim = cekResultUnoptim.result
243
+ const resultUnoptimStr = evalResultToString(resultUnoptim)
244
+ const resultStr = evalResultToString(cekResult.result)
245
+
246
+ if (resultStr != resultUnoptimStr) {
247
+ console.error(
248
+ `## Unoptimized IR:\n${program.alt.ir ?? "not available"}`
249
+ )
185
250
 
186
- if (this.uplc.alt?.plutusVersion == "PlutusScriptV2") {
187
- const cekResultUnoptim = this.uplc.alt.eval(argValues, {
188
- logOptions: logOptions ?? undefined
251
+ args.forEach((a, i) => {
252
+ console.error(`## Arg ${i}: ${bytesToHex(a.toCbor())}`)
189
253
  })
190
- const resultUnoptim = cekResultUnoptim.result
191
- const resultUnoptimStr = evalResultToString(resultUnoptim)
192
- const resultStr = evalResultToString(cekResult.result)
193
-
194
- if (resultStr != resultUnoptimStr) {
195
- console.error(
196
- `## Unoptimized IR:\n${this.uplc.alt.ir ?? "not available"}`
197
- )
198
-
199
- args.forEach((a, i) => {
200
- console.error(`## Arg ${i}: ${bytesToHex(a.toCbor())}`)
201
- })
202
-
203
- throw new Error(
204
- `Critical error: expected ${resultUnoptimStr}, but got ${resultStr}. Contact Helios maintainers and share this console output`
205
- )
206
- }
207
254
 
208
- // also make sure the cost is an improvement
209
- if (cekResult.cost.mem > cekResultUnoptim.cost.mem) {
210
- throw new Error(
211
- `Critical error: optimizer worsened memory cost of ${this.props.name}`
212
- )
213
- }
255
+ throw new Error(
256
+ `Critical error: expected ${resultUnoptimStr}, but got ${resultStr}. Contact Helios maintainers and share this console output`
257
+ )
258
+ }
214
259
 
215
- if (cekResult.cost.cpu > cekResultUnoptim.cost.cpu) {
216
- throw new Error(
217
- `Critical error: optimizer worsened cpu cost of ${this.props.name}`
218
- )
219
- }
260
+ // also make sure the cost is an improvement
261
+ if (cekResult.cost.mem > cekResultUnoptim.cost.mem) {
262
+ throw new Error(
263
+ `Critical error: optimizer worsened memory cost of ${props.name}`
264
+ )
265
+ }
220
266
 
221
- if (
222
- cekResult.cost.mem == cekResultUnoptim.cost.mem &&
223
- cekResult.cost.cpu == cekResultUnoptim.cost.cpu
224
- ) {
225
- console.error(
226
- `Warning: optimizer didn't improve cost of ${this.props.name}`
227
- )
228
- }
267
+ if (cekResult.cost.cpu > cekResultUnoptim.cost.cpu) {
268
+ throw new Error(
269
+ `Critical error: optimizer worsened cpu cost of ${props.name}`
270
+ )
271
+ }
229
272
 
230
- // overwrite the optimized cekResult.result with the unoptimized result because it contains more information
231
- cekResult.result = resultUnoptim
273
+ if (
274
+ cekResult.cost.mem == cekResultUnoptim.cost.mem &&
275
+ cekResult.cost.cpu == cekResultUnoptim.cost.cpu
276
+ ) {
277
+ console.error(
278
+ `Warning: optimizer didn't improve cost of ${props.name}`
279
+ )
232
280
  }
233
281
 
234
- return cekResult
282
+ // overwrite the optimized cekResult.result with the unoptimized result because it contains more information
283
+ cekResult.result = resultUnoptim
235
284
  }
285
+
286
+ return cekResult
236
287
  }
237
288
 
238
289
  /**
package/src/cast/index.js CHANGED
@@ -1,3 +1,12 @@
1
- export { makeCast } from "./Cast.js"
2
- export { configureCast } from "./Cast.js"
3
- export { makeUserFunc } from "./UserFunc.js"
1
+ export {
2
+ configureCast,
3
+ convertFromUplcData,
4
+ convertToUplcData,
5
+ makeCast
6
+ } from "./Cast.js"
7
+ export {
8
+ evalUserFunc,
9
+ evalUserFuncUnsafe,
10
+ makeUserFunc,
11
+ profileUserFunc
12
+ } from "./UserFunc.js"
@@ -134,9 +134,8 @@ class LoadedScriptsWriterImpl {
134
134
  * @returns {LoadedScriptsWriter}
135
135
  */
136
136
  writeImportType(path, ...typeNames) {
137
- this.definition.writeLine("/**")
138
-
139
137
  this.definition
138
+ .writeLine("/**")
140
139
  .writeLine(` * @import { ${typeNames.join(", ")} } from "${path}";`)
141
140
  .writeLine(" */")
142
141
  ;[this.declaration, this.combined].forEach((w) => {
@@ -389,29 +388,54 @@ ${datumTypes ? ` $Datum: (config: CastConfig) => makeCast<${datumTypes[0]}, $
389
388
  }
390
389
 
391
390
  /**
392
- * @param {TypeCheckedUserFunc} fn
393
- * @returns {[string, string]}
391
+ * @param {TypeCheckedUserFunc} props
392
+ * @param {boolean} unsafe
393
+ * @returns {string}
394
+ */
395
+ export function genUserFuncRetType(props, unsafe = false) {
396
+ const retTypeStr = props?.returns ? genTypes(props.returns)[0] : "void"
397
+
398
+ if (unsafe) {
399
+ return retTypeStr == "void" ? "void" : "UplcData"
400
+ } else {
401
+ return retTypeStr
402
+ }
403
+ }
404
+
405
+ /**
406
+ * @param {TypeCheckedUserFunc} props
407
+ * @param {boolean} [unsafe]
408
+ * @returns {string}
394
409
  */
395
- function genFuncType(fn) {
410
+ export function genUserFuncArgsType(props, unsafe = false) {
396
411
  /**
397
412
  * @type {string[]}
398
413
  */
399
414
  const fields = []
400
415
 
401
- if (fn.requiresScriptContext) {
416
+ if (props.requiresScriptContext) {
402
417
  fields.push("$scriptContext: UplcData")
403
418
  }
404
419
 
405
- if (fn.requiresCurrentScript) {
420
+ if (props.requiresCurrentScript) {
406
421
  fields.push("$currentScript: string")
407
422
  }
408
423
 
409
- fn.arguments.forEach(({ name, type, isOptional }, i) => {
410
- fields.push(`${name}${isOptional ? "?" : ""}: ${genTypes(type)[1]}`)
424
+ props.arguments.forEach(({ name, type, isOptional }, i) => {
425
+ fields.push(
426
+ `${name}${isOptional ? "?" : ""}: ${unsafe ? "UplcData" : genTypes(type)[1]}`
427
+ )
411
428
  })
412
429
 
413
430
  const argsTypeStr = `{${fields.join(", ")}}`
414
- const retTypeStr = fn?.returns ? genTypes(fn.returns)[0] : "void"
415
431
 
416
- return [argsTypeStr, retTypeStr]
432
+ return argsTypeStr
433
+ }
434
+
435
+ /**
436
+ * @param {TypeCheckedUserFunc} fn
437
+ * @returns {[string, string]}
438
+ */
439
+ export function genFuncType(fn) {
440
+ return [genUserFuncArgsType(fn, false), genUserFuncRetType(fn)]
417
441
  }
@@ -166,3 +166,129 @@ export function genTypes(schema) {
166
166
  throw new Error(`unhandled TypeSchema kind '${kind}'`)
167
167
  }
168
168
  }
169
+
170
+ /**
171
+ * @param {TypeSchema} schema
172
+ * @returns {Map<string, string>} - key=name, value=from
173
+ */
174
+ export function collectBuiltinTypes(schema) {
175
+ /**
176
+ * @type {Map<string, string>}
177
+ */
178
+ const m = new Map()
179
+
180
+ collectBuiltinTypesInternal(schema, m)
181
+
182
+ return m
183
+ }
184
+
185
+ /**
186
+ * @param {TypeSchema} schema
187
+ * @param {Map<string, string>} m - key=name, value=from
188
+ */
189
+ function collectBuiltinTypesInternal(schema, m) {
190
+ const kind = schema.kind
191
+
192
+ switch (kind) {
193
+ case "internal":
194
+ const name = schema.name
195
+ switch (name) {
196
+ case "Bool":
197
+ case "ByteArray":
198
+ case "Real":
199
+ case "String":
200
+ break
201
+ case "AssetClass":
202
+ m.set("AssetClass", "@helios-lang/ledger")
203
+ m.set("MintingPolicyHash", "@helios-lang/ledger")
204
+ break
205
+ case "Any":
206
+ case "Data":
207
+ m.set("UplcData", "@helios-lang/uplc")
208
+ break
209
+ case "Int":
210
+ case "Duration":
211
+ case "Ratio":
212
+ m.set("IntLike", "@helios-lang/codec-utils")
213
+ break
214
+ case "Time":
215
+ m.set("TimeLike", "@helios-lang/ledger")
216
+ break
217
+ case "Address":
218
+ case "MintingPolicyHash":
219
+ case "PubKey":
220
+ case "PubKeyHash":
221
+ case "SpendingCredential":
222
+ case "StakingCredential":
223
+ case "StakingValidatorHash":
224
+ case "TimeLike":
225
+ case "TxId":
226
+ case "TxInput":
227
+ case "TxOutput":
228
+ case "TxOutputId":
229
+ case "ValidatorHash":
230
+ m.set(name, "@helios-lang/ledger")
231
+ break
232
+ case "StakingHash":
233
+ // TODO: implement this
234
+ return ["never", "never"]
235
+ case "TimeRange":
236
+ m.set("TimeRange", "@helios-lang/ledger")
237
+ m.set("TimeLike", "@helios-lang/ledger")
238
+ break
239
+ case "TxOutputDatum":
240
+ m.set("TxOutputDatum", "@helios-lang/ledger")
241
+ m.set("DatumHash", "@helios-lang/ledger")
242
+ m.set("UplcData", "@helios-lang/uplc")
243
+ break
244
+ case "Value":
245
+ m.set("Value", "@helios-lang/ledger")
246
+ m.set("IntLike", "@helios-lang/codec-utils")
247
+ m.set("MintingPolicyHash", "@helios-lang/ledger")
248
+ break
249
+ default:
250
+ throw new Error(`unhandled primitive '${name}' in hl2ts`)
251
+ }
252
+ break
253
+ case "list": {
254
+ collectBuiltinTypesInternal(schema.itemType, m)
255
+ break
256
+ }
257
+ case "map": {
258
+ collectBuiltinTypesInternal(schema.keyType, m)
259
+ collectBuiltinTypesInternal(schema.valueType, m)
260
+ break
261
+ }
262
+ case "tuple": {
263
+ schema.itemTypes.forEach((it) => collectBuiltinTypesInternal(it, m))
264
+ break
265
+ }
266
+ case "option": {
267
+ collectBuiltinTypesInternal(schema.someType, m)
268
+ break
269
+ }
270
+ case "struct": {
271
+ schema.fieldTypes.forEach(({ type }) => {
272
+ collectBuiltinTypesInternal(type, m)
273
+ })
274
+ break
275
+ }
276
+ case "enum": {
277
+ schema.variantTypes.forEach((variant) => {
278
+ collectBuiltinTypesInternal(variant, m)
279
+ })
280
+ break
281
+ }
282
+ case "variant": {
283
+ schema.fieldTypes.forEach(({ type }) => {
284
+ collectBuiltinTypesInternal(type, m)
285
+ })
286
+
287
+ break
288
+ }
289
+ case "reference":
290
+ throw new Error("recursive data structures not yet handled")
291
+ default:
292
+ throw new Error(`unhandled TypeSchema kind '${kind}'`)
293
+ }
294
+ }
@@ -1,2 +1,3 @@
1
1
  export { makeContractContextBuilder } from "./ContractContextBuilder.js"
2
+
2
3
  export { contractContextCache } from "./ContractContextCache.js"
package/src/hl2ts.js CHANGED
@@ -13,10 +13,6 @@ import { makeLoadedScriptsWriter } from "./codegen/index.js"
13
13
  import { loadCompilerLib } from "./compiler/index.js"
14
14
  import { typeCheckFiles } from "./compiler/ops.js"
15
15
 
16
- /**
17
- * @import { CompilerLib, TypeCheckedModule, TypeCheckedValidator } from "./index.js"
18
- */
19
-
20
16
  /**
21
17
  * @typedef {{
22
18
  * name: string