codama-renderers-dart 0.4.3 → 0.5.1

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/LICENSE +21 -0
  2. package/dist/index.browser.cjs +634 -159
  3. package/dist/index.browser.cjs.map +1 -1
  4. package/dist/index.browser.js +635 -161
  5. package/dist/index.browser.js.map +1 -1
  6. package/dist/index.node.cjs +634 -159
  7. package/dist/index.node.cjs.map +1 -1
  8. package/dist/index.node.js +635 -161
  9. package/dist/index.node.js.map +1 -1
  10. package/dist/index.react-native.js +635 -161
  11. package/dist/index.react-native.js.map +1 -1
  12. package/dist/types/fragments/accountPage.d.ts.map +1 -1
  13. package/dist/types/fragments/instructionPage.d.ts.map +1 -1
  14. package/dist/types/fragments/programPage.d.ts +1 -1
  15. package/dist/types/fragments/programPage.d.ts.map +1 -1
  16. package/dist/types/fragments/typePage.d.ts.map +1 -1
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/index.d.ts.map +1 -1
  19. package/dist/types/utils/discriminators.d.ts +10 -0
  20. package/dist/types/utils/discriminators.d.ts.map +1 -0
  21. package/dist/types/utils/exactDecoder.d.ts +17 -0
  22. package/dist/types/utils/exactDecoder.d.ts.map +1 -0
  23. package/dist/types/utils/formatCode.d.ts +1 -1
  24. package/dist/types/utils/formatCode.d.ts.map +1 -1
  25. package/dist/types/utils/importMap.d.ts.map +1 -1
  26. package/dist/types/utils/index.d.ts +4 -0
  27. package/dist/types/utils/index.d.ts.map +1 -1
  28. package/dist/types/utils/nameTransformers.d.ts +1 -1
  29. package/dist/types/utils/nameTransformers.d.ts.map +1 -1
  30. package/dist/types/utils/normalizeRootNode.d.ts +11 -0
  31. package/dist/types/utils/normalizeRootNode.d.ts.map +1 -0
  32. package/dist/types/utils/valueNodes.d.ts +16 -0
  33. package/dist/types/utils/valueNodes.d.ts.map +1 -0
  34. package/dist/types/visitors/getTypeManifestVisitor.d.ts +1 -1
  35. package/dist/types/visitors/getTypeManifestVisitor.d.ts.map +1 -1
  36. package/dist/types/visitors/renderVisitor.d.ts.map +1 -1
  37. package/package.json +31 -23
  38. package/readme.md +30 -3
  39. package/src/fragments/accountPage.ts +90 -17
  40. package/src/fragments/instructionPage.ts +109 -72
  41. package/src/fragments/programPage.ts +165 -6
  42. package/src/fragments/typePage.ts +36 -15
  43. package/src/index.ts +1 -0
  44. package/src/utils/discriminators.ts +121 -0
  45. package/src/utils/exactDecoder.ts +82 -0
  46. package/src/utils/formatCode.ts +7 -11
  47. package/src/utils/importMap.ts +16 -3
  48. package/src/utils/index.ts +4 -0
  49. package/src/utils/nameTransformers.ts +3 -2
  50. package/src/utils/normalizeRootNode.ts +76 -0
  51. package/src/utils/valueNodes.ts +87 -0
  52. package/src/utils/wellKnownAddresses.ts +4 -4
  53. package/src/visitors/getRenderMapVisitor.ts +1 -1
  54. package/src/visitors/getTypeManifestVisitor.ts +48 -29
  55. package/src/visitors/renderVisitor.ts +11 -4
@@ -3,18 +3,76 @@ import { join, dirname, posix } from 'path';
3
3
  import { staticVisitor, extendVisitor, visit, NodeStack, LinkableDictionary, pipe, recordNodeStackVisitor, recordLinkablesOnFirstVisitVisitor, rootNodeVisitor } from '@codama/visitors-core';
4
4
  import { createRenderMap, addToRenderMap, mergeRenderMaps, deleteDirectory } from '@codama/renderers-core';
5
5
  import { execSync } from 'child_process';
6
- import { resolveNestedTypeNode } from '@codama/nodes';
6
+ import { resolveNestedTypeNode, getAllInstructionsWithSubs } from '@codama/nodes';
7
7
  import { CodamaError, CODAMA_ERROR__UNEXPECTED_NODE_KIND } from '@codama/errors';
8
8
 
9
9
  // src/visitors/renderVisitor.ts
10
10
  function formatDartDirectory(dir) {
11
- try {
12
- execSync(`dart format --fix "${dir}"`, {
13
- encoding: "utf-8",
14
- timeout: 6e4,
15
- stdio: ["pipe", "pipe", "pipe"]
16
- });
17
- } catch {
11
+ execSync(`dart format "${dir}"`, {
12
+ encoding: "utf-8",
13
+ timeout: 6e4,
14
+ stdio: ["pipe", "pipe", "pipe"]
15
+ });
16
+ }
17
+
18
+ // src/utils/normalizeRootNode.ts
19
+ function normalizeRootNode(root) {
20
+ return normalizeNode(root);
21
+ }
22
+ function normalizeNode(value) {
23
+ if (Array.isArray(value)) {
24
+ return value.map(normalizeNode);
25
+ }
26
+ if (!isRecord(value)) {
27
+ return value;
28
+ }
29
+ const normalized = Object.fromEntries(
30
+ Object.entries(value).map(([key, child]) => [key, normalizeNode(child)])
31
+ );
32
+ switch (normalized.kind) {
33
+ case "rootNode":
34
+ setEmptyCollection(normalized, "additionalPrograms");
35
+ break;
36
+ case "programNode":
37
+ setEmptyCollection(normalized, "accounts");
38
+ setEmptyCollection(normalized, "constants");
39
+ setEmptyCollection(normalized, "definedTypes");
40
+ setEmptyCollection(normalized, "errors");
41
+ setEmptyCollection(normalized, "events");
42
+ setEmptyCollection(normalized, "instructions");
43
+ setEmptyCollection(normalized, "pdas");
44
+ break;
45
+ case "instructionNode":
46
+ setEmptyCollection(normalized, "accounts");
47
+ setEmptyCollection(normalized, "arguments");
48
+ break;
49
+ case "pdaNode":
50
+ setEmptyCollection(normalized, "seeds");
51
+ break;
52
+ case "structTypeNode":
53
+ setEmptyCollection(normalized, "fields");
54
+ break;
55
+ case "enumTypeNode":
56
+ setEmptyCollection(normalized, "variants");
57
+ break;
58
+ case "tupleTypeNode":
59
+ setEmptyCollection(normalized, "items");
60
+ break;
61
+ case "hiddenPrefixTypeNode":
62
+ setEmptyCollection(normalized, "prefix");
63
+ break;
64
+ case "hiddenSuffixTypeNode":
65
+ setEmptyCollection(normalized, "suffix");
66
+ break;
67
+ }
68
+ return normalized;
69
+ }
70
+ function isRecord(value) {
71
+ return typeof value === "object" && value !== null;
72
+ }
73
+ function setEmptyCollection(record, key) {
74
+ if (record[key] === void 0) {
75
+ record[key] = [];
18
76
  }
19
77
  }
20
78
 
@@ -46,7 +104,7 @@ function createDartNameApi() {
46
104
  errorConstant: (programName, errorName) => `${camelCase(programName)}Error${pascalCase(errorName)}`,
47
105
  errorMessageFunction: (name) => `get${pascalCase(name)}ErrorMessage`,
48
106
  enumVariant: (name) => camelCase(name),
49
- sealedClassVariant: (_parentName, variantName) => pascalCase(variantName),
107
+ sealedClassVariant: (parentName, variantName) => `${pascalCase(parentName)}${pascalCase(variantName)}`,
50
108
  isTypeFunction: (name) => `is${pascalCase(name)}`,
51
109
  fileName: (name) => snakeCase(name),
52
110
  discriminatorConstant: (name) => `${camelCase(name)}Discriminator`
@@ -120,11 +178,16 @@ var DartImportMap = class {
120
178
  const uris = /* @__PURE__ */ new Set();
121
179
  for (const module of this._imports) {
122
180
  if (module in internalMap) {
123
- uris.add(internalMap[module]);
181
+ const uri = internalMap[module];
182
+ if (uri) {
183
+ uris.add(uri);
184
+ }
124
185
  } else if (module in DART_EXTERNAL_PACKAGE_MAP) {
125
186
  uris.add(DART_EXTERNAL_PACKAGE_MAP[module]);
126
- } else {
187
+ } else if (isRawDartImportUri(module)) {
127
188
  uris.add(module);
189
+ } else {
190
+ throw new Error(`Unresolved Dart import module "${module}"`);
128
191
  }
129
192
  }
130
193
  return [...uris].sort((a, b) => {
@@ -153,6 +216,9 @@ var DartImportMap = class {
153
216
  return lines.join("\n");
154
217
  }
155
218
  };
219
+ function isRawDartImportUri(module) {
220
+ return module.startsWith("dart:") || module.startsWith("package:") || module.endsWith(".dart") && !module.includes(":");
221
+ }
156
222
 
157
223
  // src/utils/fragment.ts
158
224
  function fragment(strings, ...values) {
@@ -196,17 +262,6 @@ function use(typeName, module) {
196
262
  return { content: typeName, imports };
197
263
  }
198
264
 
199
- // src/utils/typeManifest.ts
200
- function emptyTypeManifest() {
201
- return {
202
- type: emptyFragment(),
203
- encoder: emptyFragment(),
204
- decoder: emptyFragment(),
205
- value: emptyFragment(),
206
- isEnum: false
207
- };
208
- }
209
-
210
265
  // src/utils/wellKnownAddresses.ts
211
266
  var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
212
267
  // Agave / Solana native programs
@@ -244,10 +299,10 @@ var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
244
299
  ["Sysvar1111111111111111111111111111111111111", "sysvarOwnerAddress"],
245
300
  // SPL programs
246
301
  ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "tokenProgramAddress"],
247
- ["TokenzQdBNb4qyze1S1U9AHB8MGXmNK1REkTPT5Z3Y", "token2022ProgramAddress"],
248
- ["ATokenGPvbdGVxr1b2hvZbsiqW5xWH25ef7s3c8BnQKu", "associatedTokenProgramAddress"],
249
- ["Memo1UhkJRfRhVq1sR7Y7Nto1s3J2mXTT3L6Wk4K2m6", "memoProgramAddress"],
250
- ["MemoSq4gqABXKKYWVqKkV3m3kb1cTR7F2UMy9r6kFNK", "memoLegacyProgramAddress"],
302
+ ["TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", "token2022ProgramAddress"],
303
+ ["ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", "associatedTokenProgramAddress"],
304
+ ["MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr", "memoProgramAddress"],
305
+ ["Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo", "memoLegacyProgramAddress"],
251
306
  // Metaplex programs
252
307
  ["metaqbxxU9qX8rZXkmUJ7haCrXXz2W1PSUq1Rn3E1od", "tokenMetadataProgramAddress"],
253
308
  ["BGUMAp9V1mQ2KV8t34L5u3gZsXYZaYDBdKkc1xYk1qA1", "mplBubblegumProgramAddress"],
@@ -261,6 +316,207 @@ var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
261
316
  ["Es9vMFrzaCERm6YKXx6bqKr1Rmd9b5v3J8rM5e4rfF4", "usdtAddress"]
262
317
  ]);
263
318
 
319
+ // src/utils/valueNodes.ts
320
+ function getDartValueFragment(value, dartType) {
321
+ switch (value.kind) {
322
+ case "numberValueNode":
323
+ return fragmentFromString(
324
+ dartType === "BigInt" ? `BigInt.from(${value.number})` : String(value.number)
325
+ );
326
+ case "booleanValueNode":
327
+ return fragmentFromString(String(value.boolean));
328
+ case "stringValueNode":
329
+ return fragmentFromString(toDartStringLiteral(value.string));
330
+ case "noneValueNode":
331
+ return fragmentFromString("null");
332
+ case "bytesValueNode": {
333
+ if (value.encoding !== "base16") {
334
+ throw new Error(
335
+ `Unsupported deterministic bytes encoding: ${value.encoding}`
336
+ );
337
+ }
338
+ const clean = value.data.replace(/^0x/, "");
339
+ if (clean.length % 2 !== 0 || !/^[0-9a-f]*$/i.test(clean)) {
340
+ throw new Error(`Invalid hexadecimal bytes value: ${value.data}`);
341
+ }
342
+ const bytes = clean.match(/.{2}/g)?.map((byte) => `0x${byte}`) ?? [];
343
+ return fragment`${use("Uint8List", "dartTypedData")}.fromList([${fragmentFromString(bytes.join(", "))}])`;
344
+ }
345
+ case "publicKeyValueNode": {
346
+ const wellKnownName = WELL_KNOWN_ADDRESSES.get(value.publicKey);
347
+ return wellKnownName ? fragment`${use(wellKnownName, "solanaAddresses")}` : fragment`${use("Address", "solanaAddresses")}(${fragmentFromString(toDartStringLiteral(value.publicKey))})`;
348
+ }
349
+ default:
350
+ throw new Error(
351
+ `Unsupported deterministic Dart value node: ${value.kind}`
352
+ );
353
+ }
354
+ }
355
+ function isConstDartValueNode(value) {
356
+ switch (value.kind) {
357
+ case "numberValueNode":
358
+ case "booleanValueNode":
359
+ case "stringValueNode":
360
+ case "noneValueNode":
361
+ case "publicKeyValueNode":
362
+ return true;
363
+ default:
364
+ return false;
365
+ }
366
+ }
367
+ function toDartStringLiteral(value) {
368
+ return `'${value.replaceAll("\\", "\\\\").replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll(" ", "\\t").replaceAll("\b", "\\b").replaceAll("\f", "\\f").replaceAll("$", "\\$").replaceAll("'", "\\'")}'`;
369
+ }
370
+
371
+ // src/utils/discriminators.ts
372
+ function getDiscriminatorValidationFragment(node, scope) {
373
+ const discriminators = node.discriminators ?? [];
374
+ if (discriminators.length === 0) return emptyFragment();
375
+ const fields = getDiscriminatorFields(node);
376
+ const fragments = discriminators.map((discriminator) => {
377
+ switch (discriminator.kind) {
378
+ case "constantDiscriminatorNode":
379
+ return getConstantValidationFragment(
380
+ discriminator.constant,
381
+ discriminator.offset,
382
+ scope
383
+ );
384
+ case "fieldDiscriminatorNode": {
385
+ const field = fields.find(
386
+ (candidate) => candidate.name === discriminator.name
387
+ );
388
+ if (field?.defaultValue == null) {
389
+ throw new Error(
390
+ `Field discriminator "${discriminator.name}" on ${node.kind} "${node.name}" must reference a field with a default value.`
391
+ );
392
+ }
393
+ return getConstantValidationFragment(
394
+ {
395
+ type: field.type,
396
+ value: field.defaultValue
397
+ },
398
+ discriminator.offset,
399
+ scope
400
+ );
401
+ }
402
+ case "sizeDiscriminatorNode": {
403
+ if (!Number.isSafeInteger(discriminator.size) || discriminator.size < 0) {
404
+ throw new Error(
405
+ `Discriminator size must be a non-negative safe integer, got ${discriminator.size}.`
406
+ );
407
+ }
408
+ return fragment`if (bytes.length - offset != ${fragmentFromString(String(discriminator.size))}) {
409
+ throw ${use("SolanaError", "solanaErrors")}(
410
+ ${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
411
+ {
412
+ 'codecDescription': '${fragmentFromString(node.name)} discriminator',
413
+ 'expected': ${fragmentFromString(String(discriminator.size))},
414
+ 'bytesLength': bytes.length - offset,
415
+ },
416
+ );
417
+ }`;
418
+ }
419
+ }
420
+ });
421
+ return mergeFragments(fragments, (contents) => contents.join("\n"));
422
+ }
423
+ function getConstantValidationFragment(constant, discriminatorOffset, scope) {
424
+ if (!Number.isSafeInteger(discriminatorOffset) || discriminatorOffset < 0) {
425
+ throw new Error(
426
+ `Discriminator offset must be a non-negative safe integer, got ${discriminatorOffset}.`
427
+ );
428
+ }
429
+ const manifest = visit(constant.type, scope.typeManifestVisitor);
430
+ const value = getDartValueFragment(
431
+ constant.value,
432
+ manifest.type.content
433
+ );
434
+ return fragment`${use("getConstantDecoder", "solanaCodecsDataStructures")}(
435
+ ${manifest.encoder}.encode(${value}),
436
+ ).read(bytes, offset + ${fragmentFromString(String(discriminatorOffset))});`;
437
+ }
438
+ function getDiscriminatorFields(node) {
439
+ if (node.kind === "accountNode") {
440
+ return resolveNestedTypeNode(node.data).fields ?? [];
441
+ }
442
+ return (node.arguments ?? []).map(
443
+ (argument) => ({
444
+ ...argument,
445
+ kind: "structFieldTypeNode"
446
+ })
447
+ );
448
+ }
449
+
450
+ // src/utils/exactDecoder.ts
451
+ function getTopLevelDecoderFragment({
452
+ typeName,
453
+ description,
454
+ discriminatorValidation,
455
+ fromMapFields,
456
+ requireExactConsumption
457
+ }) {
458
+ const validation = discriminatorValidation.content ? ` ${discriminatorValidation.content.replaceAll("\n", "\n ")}
459
+ ` : "";
460
+ const consumptionCheck = requireExactConsumption ? ` if (newOffset != bytes.length) {
461
+ throwInvalidByteLength(newOffset - offset, bytes.length - offset);
462
+ }
463
+ ` : "";
464
+ const fixedSizeCheck = requireExactConsumption ? "bytesLength != structDecoder.fixedSize" : "bytesLength < structDecoder.fixedSize";
465
+ const result = fragment` Never throwInvalidByteLength(int expected, int bytesLength) {
466
+ throw ${use("SolanaError", "solanaErrors")}(
467
+ ${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
468
+ {
469
+ 'codecDescription': '${fragmentFromString(description)}',
470
+ 'expected': expected,
471
+ 'bytesLength': bytesLength,
472
+ },
473
+ );
474
+ }
475
+
476
+ (${fragmentFromString(typeName)}, int) readTopLevel(Uint8List bytes, int offset) {
477
+ ${fragmentFromString(validation)} final (map, newOffset) = structDecoder.read(bytes, offset);
478
+ ${fragmentFromString(consumptionCheck)}
479
+ return (
480
+ ${fragmentFromString(typeName)}(
481
+ ${fragmentFromString(fromMapFields)}
482
+ ),
483
+ newOffset,
484
+ );
485
+ }
486
+
487
+ return switch (structDecoder) {
488
+ ${use("FixedSizeDecoder", "solanaCodecsCore")}<Map<String, Object?>>() =>
489
+ ${use("FixedSizeDecoder", "solanaCodecsCore")}<${fragmentFromString(typeName)}>(
490
+ fixedSize: structDecoder.fixedSize,
491
+ read: (bytes, offset) {
492
+ final bytesLength = bytes.length - offset;
493
+ if (${fragmentFromString(fixedSizeCheck)}) {
494
+ throwInvalidByteLength(structDecoder.fixedSize, bytesLength);
495
+ }
496
+ return readTopLevel(bytes, offset);
497
+ },
498
+ ),
499
+ ${use("VariableSizeDecoder", "solanaCodecsCore")}<Map<String, Object?>>() =>
500
+ ${use("VariableSizeDecoder", "solanaCodecsCore")}<${fragmentFromString(typeName)}>(
501
+ read: readTopLevel,
502
+ maxSize: structDecoder.maxSize,
503
+ ),
504
+ };`;
505
+ result.imports.mergeWith(discriminatorValidation.imports);
506
+ return result;
507
+ }
508
+
509
+ // src/utils/typeManifest.ts
510
+ function emptyTypeManifest() {
511
+ return {
512
+ type: emptyFragment(),
513
+ encoder: emptyFragment(),
514
+ decoder: emptyFragment(),
515
+ value: emptyFragment(),
516
+ isEnum: false
517
+ };
518
+ }
519
+
264
520
  // src/visitors/getTypeManifestVisitor.ts
265
521
  function getTypeManifestVisitor(input) {
266
522
  const { nameApi, linkables, nonScalarEnums = [] } = input;
@@ -402,17 +658,23 @@ function getTypeManifestVisitor(input) {
402
658
  },
403
659
  visitArrayType(node, { self }) {
404
660
  const itemManifest = visit(node.item, self);
405
- const sizeExpr = getArraySizeExpression(node);
661
+ const encoderSizeExpr = getArraySizeExpression(node, "Encoder");
662
+ const decoderSizeExpr = getArraySizeExpression(node, "Decoder");
663
+ const itemType = fragmentFromString(itemManifest.type.content);
664
+ const itemEncoder = fragment`${use(
665
+ "transformEncoder",
666
+ "solanaCodecsCore"
667
+ )}(${itemManifest.encoder}, (${itemType} value) => value)`;
406
668
  return {
407
669
  type: fragment`List<${itemManifest.type}>`,
408
670
  encoder: fragment`${use(
409
671
  "getArrayEncoder",
410
672
  "solanaCodecsDataStructures"
411
- )}(${itemManifest.encoder}${sizeExpr})`,
673
+ )}<${itemType}>(${itemEncoder}${encoderSizeExpr})`,
412
674
  decoder: fragment`${use(
413
675
  "getArrayDecoder",
414
676
  "solanaCodecsDataStructures"
415
- )}(${itemManifest.decoder}${sizeExpr})`,
677
+ )}(${itemManifest.decoder}${decoderSizeExpr})`,
416
678
  value: emptyTypeManifest().value,
417
679
  isEnum: false
418
680
  };
@@ -420,40 +682,42 @@ function getTypeManifestVisitor(input) {
420
682
  visitMapType(node, { self }) {
421
683
  const keyManifest = visit(node.key, self);
422
684
  const valueManifest = visit(node.value, self);
423
- const sizeExpr = getMapSizeExpression(node);
685
+ const encoderSizeExpr = getMapSizeExpression(node, "Encoder");
686
+ const decoderSizeExpr = getMapSizeExpression(node, "Decoder");
424
687
  return {
425
688
  type: fragment`Map<${keyManifest.type}, ${valueManifest.type}>`,
426
689
  encoder: fragment`${use(
427
690
  "getMapEncoder",
428
691
  "solanaCodecsDataStructures"
429
- )}(${keyManifest.encoder}, ${valueManifest.encoder}${sizeExpr})`,
692
+ )}(${keyManifest.encoder}, ${valueManifest.encoder}${encoderSizeExpr})`,
430
693
  decoder: fragment`${use(
431
694
  "getMapDecoder",
432
695
  "solanaCodecsDataStructures"
433
- )}(${keyManifest.decoder}, ${valueManifest.decoder}${sizeExpr})`,
696
+ )}(${keyManifest.decoder}, ${valueManifest.decoder}${decoderSizeExpr})`,
434
697
  value: emptyTypeManifest().value,
435
698
  isEnum: false
436
699
  };
437
700
  },
438
701
  visitSetType(node, { self }) {
439
702
  const itemManifest = visit(node.item, self);
440
- const sizeExpr = getSetSizeExpression(node);
703
+ const encoderSizeExpr = getSetSizeExpression(node, "Encoder");
704
+ const decoderSizeExpr = getSetSizeExpression(node, "Decoder");
441
705
  return {
442
706
  type: fragment`Set<${itemManifest.type}>`,
443
707
  encoder: fragment`${use(
444
708
  "getSetEncoder",
445
709
  "solanaCodecsDataStructures"
446
- )}(${itemManifest.encoder}${sizeExpr})`,
710
+ )}(${itemManifest.encoder}${encoderSizeExpr})`,
447
711
  decoder: fragment`${use(
448
712
  "getSetDecoder",
449
713
  "solanaCodecsDataStructures"
450
- )}(${itemManifest.decoder}${sizeExpr})`,
714
+ )}(${itemManifest.decoder}${decoderSizeExpr})`,
451
715
  value: emptyTypeManifest().value,
452
716
  isEnum: false
453
717
  };
454
718
  },
455
719
  visitTupleType(node, { self }) {
456
- const itemManifests = node.items.map((item) => visit(item, self));
720
+ const itemManifests = (node.items ?? []).map((item) => visit(item, self));
457
721
  const typeList = itemManifests.map((m) => m.type.content).join(", ");
458
722
  const encoderList = itemManifests.map((m) => m.encoder);
459
723
  const decoderList = itemManifests.map((m) => m.decoder);
@@ -486,8 +750,9 @@ function getTypeManifestVisitor(input) {
486
750
  };
487
751
  },
488
752
  visitStructType(node, { self }) {
489
- const fields = node.fields.map((f) => visit(f, self));
490
- const fieldNames = node.fields.map((f) => f.name);
753
+ const nodeFields = node.fields ?? [];
754
+ const fields = nodeFields.map((f) => visit(f, self));
755
+ const fieldNames = nodeFields.map((f) => f.name);
491
756
  const typeStr = "Map<String, Object?>";
492
757
  const encoderFields = fields.map((f, i) => `('${fieldNames[i]}', ${f.encoder.content})`).join(", ");
493
758
  const encoderFrag = fragment`${use(
@@ -517,7 +782,7 @@ function getTypeManifestVisitor(input) {
517
782
  return visit(node.type, self);
518
783
  },
519
784
  visitEnumType(node, { self }) {
520
- const isScalar = node.variants.every(
785
+ const isScalar = (node.variants ?? []).every(
521
786
  (v) => v.kind === "enumEmptyVariantTypeNode"
522
787
  );
523
788
  if (isScalar) {
@@ -609,7 +874,7 @@ function getTypeManifestVisitor(input) {
609
874
  encoder: fragment`${use(
610
875
  "fixEncoderSize",
611
876
  "solanaCodecsCore"
612
- )}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))})`,
877
+ )}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))}, allowTruncation: false)`,
613
878
  decoder: fragment`${use(
614
879
  "fixDecoderSize",
615
880
  "solanaCodecsCore"
@@ -623,9 +888,10 @@ function getTypeManifestVisitor(input) {
623
888
  const bigIntFormats = /* @__PURE__ */ new Set(["u64", "u128", "i64", "i128"]);
624
889
  let prefixManifest;
625
890
  if (node.prefix.kind === "numberTypeNode" && bigIntFormats.has(node.prefix.format)) {
891
+ const codecName = getNumberCodecName(node.prefix.format);
626
892
  prefixManifest = {
627
- encoder: fragment`${use("getU32Encoder", "solanaCodecsNumbers")}()`,
628
- decoder: fragment`${use("getU32Decoder", "solanaCodecsNumbers")}()`
893
+ encoder: fragment`transformEncoder(${use(`get${codecName}Encoder`, "solanaCodecsNumbers")}(), (size) => BigInt.from(size))`,
894
+ decoder: fragment`transformDecoder(${use(`get${codecName}Decoder`, "solanaCodecsNumbers")}(), (size, _, __) => size.toInt())`
629
895
  };
630
896
  } else {
631
897
  prefixManifest = visit(node.prefix, self);
@@ -646,7 +912,7 @@ function getTypeManifestVisitor(input) {
646
912
  },
647
913
  visitHiddenPrefixType(node, { self }) {
648
914
  const innerManifest = visit(node.type, self);
649
- const prefixes = node.prefix.map((p) => getHiddenAffixManifest(p, self));
915
+ const prefixes = (node.prefix ?? []).map((p) => getHiddenAffixManifest(p, self));
650
916
  const prefixEncoders = prefixes.map((p) => p.encoder.content).join(", ");
651
917
  const prefixDecoders = prefixes.map((p) => p.decoder.content).join(", ");
652
918
  const encoderFrag = fragment`${use(
@@ -673,7 +939,7 @@ function getTypeManifestVisitor(input) {
673
939
  },
674
940
  visitHiddenSuffixType(node, { self }) {
675
941
  const innerManifest = visit(node.type, self);
676
- const suffixes = node.suffix.map((s) => getHiddenAffixManifest(s, self));
942
+ const suffixes = (node.suffix ?? []).map((s) => getHiddenAffixManifest(s, self));
677
943
  const suffixEncoders = suffixes.map((s) => s.encoder.content).join(", ");
678
944
  const suffixDecoders = suffixes.map((s) => s.decoder.content).join(", ");
679
945
  const encoderFrag = fragment`${use(
@@ -812,7 +1078,7 @@ function getNumberCodecExpression(format, codecType) {
812
1078
  const name = getNumberCodecName(format);
813
1079
  return `get${name}${codecType}()`;
814
1080
  }
815
- function getArraySizeExpression(node) {
1081
+ function getArraySizeExpression(node, codecType) {
816
1082
  if (!("count" in node) || !node.count) return "";
817
1083
  const count = node.count;
818
1084
  switch (count.kind) {
@@ -825,13 +1091,13 @@ function getArraySizeExpression(node) {
825
1091
  if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
826
1092
  return "";
827
1093
  }
828
- return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
1094
+ return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
829
1095
  }
830
1096
  default:
831
1097
  return "";
832
1098
  }
833
1099
  }
834
- function getMapSizeExpression(node) {
1100
+ function getMapSizeExpression(node, codecType) {
835
1101
  if (!("count" in node) || !node.count) return "";
836
1102
  const count = node.count;
837
1103
  switch (count.kind) {
@@ -844,13 +1110,13 @@ function getMapSizeExpression(node) {
844
1110
  if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
845
1111
  return "";
846
1112
  }
847
- return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
1113
+ return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
848
1114
  }
849
1115
  default:
850
1116
  return "";
851
1117
  }
852
1118
  }
853
- function getSetSizeExpression(node) {
1119
+ function getSetSizeExpression(node, codecType) {
854
1120
  if (!("count" in node) || !node.count) return "";
855
1121
  const count = node.count;
856
1122
  switch (count.kind) {
@@ -863,7 +1129,7 @@ function getSetSizeExpression(node) {
863
1129
  if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
864
1130
  return "";
865
1131
  }
866
- return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
1132
+ return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
867
1133
  }
868
1134
  default:
869
1135
  return "";
@@ -960,19 +1226,52 @@ function hexToBytes(hex) {
960
1226
  function getAccountPageFragment(node, scope) {
961
1227
  const name = node.name;
962
1228
  const typeName = scope.nameApi.dataType(name);
963
- const dataNode = resolveNestedTypeNode(node.data);
964
- const fields = dataNode.fields;
1229
+ const fields = resolveNestedTypeNode(node.data).fields ?? [];
965
1230
  const fieldManifests = fields.map((f) => ({
966
1231
  field: f,
967
1232
  manifest: visit(f.type, scope.typeManifestVisitor)
968
1233
  }));
1234
+ const omittedFields = fields.filter(isOmittedDefaultField);
1235
+ const constructorFields = fields.filter(
1236
+ (field) => !isOmittedDefaultField(field)
1237
+ );
1238
+ const forcedFields = /* @__PURE__ */ new Set([
1239
+ ...omittedFields,
1240
+ ...fields.filter((field) => isFieldDiscriminator(field, node))
1241
+ ]);
1242
+ const fieldDefaults = new Map(
1243
+ fieldManifests.flatMap(({ field, manifest }) => {
1244
+ if (!forcedFields.has(field) || field.defaultValue == null) return [];
1245
+ return [
1246
+ [
1247
+ field,
1248
+ getDartValueFragment(field.defaultValue, manifest.type.content)
1249
+ ]
1250
+ ];
1251
+ })
1252
+ );
1253
+ for (const field of forcedFields) {
1254
+ if (!fieldDefaults.has(field)) {
1255
+ throw new Error(
1256
+ `Forced field "${field.name}" on account "${node.name}" must have a deterministic default value.`
1257
+ );
1258
+ }
1259
+ }
969
1260
  const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
970
1261
  return ` final ${manifest.type.content} ${camelCase(f.name)};`;
971
1262
  }).join("\n");
972
- const ctorParams = fields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
973
- const ctorSignature = fields.length === 0 ? `const ${typeName}();` : `const ${typeName}({
1263
+ const ctorParams = constructorFields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
1264
+ const ctorInitializers = omittedFields.map((field) => {
1265
+ const fieldName = camelCase(field.name);
1266
+ return `${fieldName} = ${fieldDefaults.get(field).content}`;
1267
+ }).join(",\n ");
1268
+ const ctorKeyword = omittedFields.every(
1269
+ (field) => isConstDartValueNode(field.defaultValue)
1270
+ ) ? "const " : "";
1271
+ const ctorSignature = constructorFields.length === 0 ? `${ctorKeyword}${typeName}()${ctorInitializers ? ` : ${ctorInitializers}` : ""};` : `${ctorKeyword}${typeName}({
974
1272
  ${ctorParams}
975
- });`;
1273
+ })${ctorInitializers ? ` :
1274
+ ${ctorInitializers}` : ""};`;
976
1275
  const eqChecks = fields.length === 0 ? "true" : fields.map(
977
1276
  (f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`
978
1277
  ).join(" &&\n ");
@@ -987,10 +1286,11 @@ ${ctorParams}
987
1286
  const decFields = fieldManifests.map(({ field: f, manifest }) => {
988
1287
  return ` ('${f.name}', ${manifest.decoder.content}),`;
989
1288
  }).join("\n");
990
- const toMapFields = fields.map(
991
- (f) => ` '${f.name}': value.${camelCase(f.name)},`
992
- ).join("\n");
993
- const fromMapFields = fieldManifests.map(({ field: f, manifest }) => {
1289
+ const toMapFields = fields.map((f) => {
1290
+ const value = forcedFields.has(f) ? fieldDefaults.get(f).content : `value.${camelCase(f.name)}`;
1291
+ return ` '${f.name}': ${value},`;
1292
+ }).join("\n");
1293
+ const fromMapFields = fieldManifests.filter(({ field }) => !isOmittedDefaultField(field)).map(({ field: f, manifest }) => {
994
1294
  const typeStr = manifest.type.content;
995
1295
  const isNullable = typeStr.endsWith("?");
996
1296
  const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
@@ -1004,6 +1304,19 @@ ${ctorParams}
1004
1304
  /// The size of the [${fragmentFromString(typeName)}] account data in bytes.
1005
1305
  const int ${fragmentFromString(scope.nameApi.accountSizeConstant(name))} = ${fragmentFromString(String(node.size))};` : emptyFragment();
1006
1306
  const discFragment = getDiscriminatorConstantsFragment(node, scope);
1307
+ const discriminatorValidation = getDiscriminatorValidationFragment(
1308
+ node,
1309
+ scope
1310
+ );
1311
+ const topLevelDecoder = getTopLevelDecoderFragment({
1312
+ typeName,
1313
+ description: `${name} account decoder`,
1314
+ discriminatorValidation,
1315
+ fromMapFields,
1316
+ requireExactConsumption: (node.discriminators ?? []).some(
1317
+ (discriminator) => discriminator.kind === "sizeDiscriminatorNode"
1318
+ )
1319
+ });
1007
1320
  const parts = [
1008
1321
  fragment`// Auto-generated. Do not edit.
1009
1322
  // ignore_for_file: type=lint
@@ -1063,12 +1376,7 @@ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
1063
1376
  ${fragmentFromString(decFields)}
1064
1377
  ]);
1065
1378
 
1066
- return transformDecoder(
1067
- structDecoder,
1068
- (Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}(
1069
- ${fragmentFromString(fromMapFields)}
1070
- ),
1071
- );
1379
+ ${topLevelDecoder}
1072
1380
  }
1073
1381
 
1074
1382
  Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
@@ -1084,8 +1392,19 @@ Account<${fragmentFromString(typeName)}> ${fragmentFromString(decodeFnName)}(Enc
1084
1392
  result.imports.mergeWith(manifest.decoder.imports);
1085
1393
  result.imports.mergeWith(manifest.type.imports);
1086
1394
  }
1395
+ for (const defaultValue of fieldDefaults.values()) {
1396
+ result.imports.mergeWith(defaultValue.imports);
1397
+ }
1087
1398
  return result;
1088
1399
  }
1400
+ function isOmittedDefaultField(field) {
1401
+ return field.defaultValue != null && field.defaultValueStrategy === "omitted";
1402
+ }
1403
+ function isFieldDiscriminator(field, node) {
1404
+ return (node.discriminators ?? []).some(
1405
+ (discriminator) => discriminator.kind === "fieldDiscriminatorNode" && discriminator.name === field.name
1406
+ );
1407
+ }
1089
1408
 
1090
1409
  // src/fragments/errorPage.ts
1091
1410
  function getErrorPageFragment(programNode, scope) {
@@ -1146,7 +1465,7 @@ function getIndexPageFragment(fileNames, relativePath = "") {
1146
1465
  "// Auto-generated. Do not edit.\n// ignore_for_file: type=lint\n"
1147
1466
  );
1148
1467
  }
1149
- const exports$1 = fileNames.sort().map((f) => {
1468
+ const exports = fileNames.sort().map((f) => {
1150
1469
  const path = relativePath ? `${relativePath}/${f}` : f;
1151
1470
  return `export '${path}';`;
1152
1471
  }).join("\n");
@@ -1154,17 +1473,17 @@ function getIndexPageFragment(fileNames, relativePath = "") {
1154
1473
  `// Auto-generated. Do not edit.
1155
1474
  // ignore_for_file: type=lint
1156
1475
 
1157
- ${exports$1}
1476
+ ${exports}
1158
1477
  `
1159
1478
  );
1160
1479
  }
1161
1480
  function getRootIndexPageFragment(categories) {
1162
- const exports$1 = categories.sort().map((cat) => `export '${cat}/${cat}.dart';`).join("\n");
1481
+ const exports = categories.sort().map((cat) => `export '${cat}/${cat}.dart';`).join("\n");
1163
1482
  return fragmentFromString(
1164
1483
  `// Auto-generated. Do not edit.
1165
1484
  // ignore_for_file: type=lint
1166
1485
 
1167
- ${exports$1}
1486
+ ${exports}
1168
1487
  `
1169
1488
  );
1170
1489
  }
@@ -1174,30 +1493,62 @@ function getInstructionPageFragment(node, scope) {
1174
1493
  const instrFnName = scope.nameApi.instructionFunction(name);
1175
1494
  const parseFnName = scope.nameApi.instructionParseFunction(name);
1176
1495
  const accounts = node.accounts ?? [];
1177
- const args = (node.arguments ?? []).filter(
1178
- (arg) => !isDiscriminatorArg(arg, node)
1179
- );
1180
1496
  const allArgs = node.arguments ?? [];
1497
+ const optionalAccountStrategy = node.optionalAccountStrategy ?? "programId";
1498
+ if (optionalAccountStrategy !== "programId" && optionalAccountStrategy !== "omitted") {
1499
+ throw new Error(
1500
+ `Unsupported optional account strategy on instruction "${node.name}": ${optionalAccountStrategy}`
1501
+ );
1502
+ }
1503
+ const args = allArgs.filter(
1504
+ (arg) => !isDiscriminatorArg(arg, node) && !isOmittedDefaultArgument(arg)
1505
+ );
1181
1506
  const dataClassName = `${typeName}InstructionData`;
1182
- const allArgManifests = allArgs.map((arg) => ({
1507
+ const allArgManifests = (node.arguments ?? []).map((arg) => ({
1183
1508
  arg,
1184
1509
  manifest: visit(arg.type, scope.typeManifestVisitor)
1185
1510
  }));
1511
+ const argDefaultValues = new Map(
1512
+ allArgManifests.flatMap(({ arg, manifest }) => {
1513
+ if (arg.defaultValue == null) return [];
1514
+ const needsRenderedDefault = isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node) || arg.defaultValue.kind !== "accountBumpValueNode";
1515
+ if (!needsRenderedDefault) return [];
1516
+ return [
1517
+ [
1518
+ arg,
1519
+ getDartValueFragment(arg.defaultValue, manifest.type.content)
1520
+ ]
1521
+ ];
1522
+ })
1523
+ );
1524
+ for (const arg of allArgs.filter(
1525
+ (candidate) => isDiscriminatorArg(candidate, node)
1526
+ )) {
1527
+ if (!argDefaultValues.has(arg)) {
1528
+ throw new Error(
1529
+ `Field discriminator "${arg.name}" on instruction "${node.name}" must reference a field with a default value.`
1530
+ );
1531
+ }
1532
+ }
1186
1533
  const dataFieldDecls = allArgManifests.map(({ arg, manifest }) => {
1187
1534
  const fieldName = camelCase(arg.name);
1188
1535
  return ` final ${manifest.type.content} ${fieldName};`;
1189
1536
  }).join("\n");
1190
1537
  const dataCtorParams = allArgManifests.map(({ arg, manifest }) => {
1191
1538
  const fieldName = camelCase(arg.name);
1539
+ if (isOmittedDefaultArgument(arg)) return "";
1192
1540
  if (isDiscriminatorArg(arg, node)) {
1193
- return isConstDefaultValue(arg.defaultValue) ? ` this.${fieldName} = ${getDiscriminatorDefault(arg)},` : ` ${manifest.type.content}? ${fieldName},`;
1541
+ return isConstDefaultValue(arg.defaultValue) ? ` this.${fieldName} = ${argDefaultValues.get(arg).content},` : ` ${manifest.type.content}? ${fieldName},`;
1194
1542
  }
1195
1543
  return ` required this.${fieldName},`;
1196
- }).join("\n");
1544
+ }).filter(Boolean).join("\n");
1197
1545
  const dataCtorInitializers = allArgManifests.map(({ arg }) => {
1198
1546
  const fieldName = camelCase(arg.name);
1547
+ if (isOmittedDefaultArgument(arg)) {
1548
+ return ` ${fieldName} = ${argDefaultValues.get(arg).content}`;
1549
+ }
1199
1550
  if (isDiscriminatorArg(arg, node) && !isConstDefaultValue(arg.defaultValue)) {
1200
- return ` ${fieldName} = ${fieldName} ?? ${getDiscriminatorDefault(arg)}`;
1551
+ return ` ${fieldName} = ${fieldName} ?? ${argDefaultValues.get(arg).content}`;
1201
1552
  }
1202
1553
  return null;
1203
1554
  }).filter((value) => value !== null).join(",\n");
@@ -1207,16 +1558,26 @@ function getInstructionPageFragment(node, scope) {
1207
1558
  const decFields = allArgManifests.map(({ arg, manifest }) => {
1208
1559
  return ` ('${arg.name}', ${manifest.decoder.content}),`;
1209
1560
  }).join("\n");
1210
- const toMapFields = allArgs.map(
1211
- (arg) => ` '${arg.name}': value.${camelCase(arg.name)},`
1212
- ).join("\n");
1213
- const fromMapFields = allArgManifests.map(({ arg, manifest }) => {
1561
+ const toMapFields = allArgs.map((arg) => {
1562
+ const value = isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node) ? argDefaultValues.get(arg).content : `value.${camelCase(arg.name)}`;
1563
+ return ` '${arg.name}': ${value},`;
1564
+ }).join("\n");
1565
+ const fromMapFields = allArgManifests.filter(({ arg }) => !isOmittedDefaultArgument(arg)).map(({ arg, manifest }) => {
1214
1566
  const typeStr = manifest.type.content;
1215
1567
  const isNullable = typeStr.endsWith("?");
1216
1568
  const accessor = isNullable ? `map['${arg.name}']` : `map['${arg.name}']!`;
1217
1569
  return ` ${camelCase(arg.name)}: ${accessor} as ${typeStr},`;
1218
1570
  }).join("\n");
1219
- const dataCtorKeyword = dataCtorInitializers ? "" : "const ";
1571
+ const dataCtorKeyword = allArgs.every(
1572
+ (arg) => !isOmittedDefaultArgument(arg) || isConstDartValueNode(arg.defaultValue)
1573
+ ) && allArgs.every(
1574
+ (arg) => !isDiscriminatorArg(arg, node) || isConstDefaultValue(arg.defaultValue)
1575
+ ) ? "const " : "";
1576
+ const dataCtorSignature = dataCtorParams ? `${dataCtorKeyword}${dataClassName}({
1577
+ ${dataCtorParams}
1578
+ })${dataCtorInitializers ? ` :
1579
+ ${dataCtorInitializers}` : ""};` : `${dataCtorKeyword}${dataClassName}()${dataCtorInitializers ? ` :
1580
+ ${dataCtorInitializers}` : ""};`;
1220
1581
  const dataEncoderName = `get${typeName}InstructionDataEncoder`;
1221
1582
  const dataDecoderName = `get${typeName}InstructionDataDecoder`;
1222
1583
  const dataCodecName = `get${typeName}InstructionDataCodec`;
@@ -1234,7 +1595,7 @@ function getInstructionPageFragment(node, scope) {
1234
1595
  const manifest = argManifestMap.get(arg);
1235
1596
  const fieldName = camelCase(arg.name);
1236
1597
  const typeStr = manifest.type.content;
1237
- const hasDefault = arg.defaultValue != null;
1598
+ const hasDefault = arg.defaultValue != null && arg.defaultValue.kind !== "accountBumpValueNode";
1238
1599
  if (hasDefault) {
1239
1600
  const nullableType = typeStr.endsWith("?") ? typeStr : `${typeStr}?`;
1240
1601
  return ` ${nullableType} ${fieldName},`;
@@ -1246,18 +1607,33 @@ function getInstructionPageFragment(node, scope) {
1246
1607
  const role = getAccountRole(acc);
1247
1608
  const isOptional = acc.isOptional ?? false;
1248
1609
  if (isOptional) {
1249
- return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}),`;
1610
+ if (optionalAccountStrategy === "omitted") {
1611
+ return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}),`;
1612
+ }
1613
+ return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}) else AccountMeta(address: ${instrProgramParam}, role: AccountRole.readonly),`;
1250
1614
  }
1251
1615
  return ` AccountMeta(address: ${fieldName}, role: ${role}),`;
1252
1616
  }).join("\n");
1253
1617
  const dataConstruction = allArgs.map((arg) => {
1254
1618
  const fieldName = camelCase(arg.name);
1255
- if (isDiscriminatorArg(arg, node)) {
1619
+ if (isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node)) {
1256
1620
  return "";
1257
1621
  }
1258
- return ` ${fieldName}: ${fieldName}${arg.defaultValue != null ? ` ?? ${getDefaultValue(arg)}` : ""},`;
1622
+ const skipDefault = arg.defaultValue?.kind === "accountBumpValueNode";
1623
+ return ` ${fieldName}: ${fieldName}${arg.defaultValue != null && !skipDefault ? ` ?? ${argDefaultValues.get(arg).content}` : ""},`;
1259
1624
  }).filter(Boolean).join("\n");
1260
1625
  const discFragment = getDiscriminatorConstantsFragment(node, scope);
1626
+ const discriminatorValidation = getDiscriminatorValidationFragment(
1627
+ node,
1628
+ scope
1629
+ );
1630
+ const topLevelDecoder = getTopLevelDecoderFragment({
1631
+ typeName: dataClassName,
1632
+ description: `${name} instruction decoder`,
1633
+ discriminatorValidation,
1634
+ fromMapFields,
1635
+ requireExactConsumption: true
1636
+ });
1261
1637
  const parts = [
1262
1638
  fragment`// Auto-generated. Do not edit.
1263
1639
  // ignore_for_file: type=lint
@@ -1281,10 +1657,7 @@ ${use("AccountRole", "solanaInstructions")}`
1281
1657
  parts.push(fragment`
1282
1658
  @immutable
1283
1659
  class ${fragmentFromString(dataClassName)} {
1284
- ${fragmentFromString(dataCtorKeyword)}${fragmentFromString(dataClassName)}({
1285
- ${fragmentFromString(dataCtorParams)}
1286
- })${fragmentFromString(dataCtorInitializers ? ` :
1287
- ${dataCtorInitializers}` : "")};
1660
+ ${fragmentFromString(dataCtorSignature)}
1288
1661
 
1289
1662
  ${fragmentFromString(dataFieldDecls)}
1290
1663
  }`);
@@ -1307,12 +1680,7 @@ Decoder<${fragmentFromString(dataClassName)}> ${fragmentFromString(dataDecoderNa
1307
1680
  ${fragmentFromString(decFields)}
1308
1681
  ]);
1309
1682
 
1310
- return transformDecoder(
1311
- structDecoder,
1312
- (Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(dataClassName)}(
1313
- ${fragmentFromString(fromMapFields)}
1314
- ),
1315
- );
1683
+ ${topLevelDecoder}
1316
1684
  }
1317
1685
 
1318
1686
  Codec<${fragmentFromString(dataClassName)}, ${fragmentFromString(dataClassName)}> ${fragmentFromString(dataCodecName)}() {
@@ -1348,6 +1716,9 @@ ${fragmentFromString(dataClassName)} ${fragmentFromString(parseFnName)}(Instruct
1348
1716
  result.imports.mergeWith(manifest.decoder.imports);
1349
1717
  result.imports.mergeWith(manifest.type.imports);
1350
1718
  }
1719
+ for (const defaultValue of argDefaultValues.values()) {
1720
+ result.imports.mergeWith(defaultValue.imports);
1721
+ }
1351
1722
  return result;
1352
1723
  }
1353
1724
  function getAccountRole(acc) {
@@ -1364,19 +1735,6 @@ function isDiscriminatorArg(arg, node) {
1364
1735
  (d) => d.kind === "fieldDiscriminatorNode" && d.name === arg.name
1365
1736
  );
1366
1737
  }
1367
- function getDiscriminatorDefault(arg, _node) {
1368
- if (arg.defaultValue) {
1369
- if (arg.defaultValue.kind === "numberValueNode") {
1370
- return String(arg.defaultValue.number);
1371
- }
1372
- if (arg.defaultValue.kind === "bytesValueNode") {
1373
- const data = arg.defaultValue.data;
1374
- const bytes = data.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? [];
1375
- return `Uint8List.fromList([${bytes.join(", ")}])`;
1376
- }
1377
- }
1378
- return "0";
1379
- }
1380
1738
  function isConstDefaultValue(defaultValue) {
1381
1739
  if (!defaultValue) return false;
1382
1740
  switch (defaultValue.kind) {
@@ -1389,33 +1747,8 @@ function isConstDefaultValue(defaultValue) {
1389
1747
  return false;
1390
1748
  }
1391
1749
  }
1392
- function getDefaultValue(arg) {
1393
- if (!arg.defaultValue) return "null";
1394
- const dv = arg.defaultValue;
1395
- switch (dv.kind) {
1396
- case "numberValueNode":
1397
- return String(dv.number);
1398
- case "booleanValueNode":
1399
- return String(dv.boolean);
1400
- case "stringValueNode":
1401
- return `'${dv.string}'`;
1402
- case "publicKeyValueNode": {
1403
- const wellKnownName = WELL_KNOWN_ADDRESSES.get(dv.publicKey);
1404
- if (wellKnownName) {
1405
- use(wellKnownName, "solanaAddresses");
1406
- return wellKnownName;
1407
- }
1408
- return `Address('${dv.publicKey}')`;
1409
- }
1410
- case "noneValueNode":
1411
- return "null";
1412
- case "bytesValueNode": {
1413
- const bytes = dv.data.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? [];
1414
- return `Uint8List.fromList([${bytes.join(", ")}])`;
1415
- }
1416
- default:
1417
- return "null";
1418
- }
1750
+ function isOmittedDefaultArgument(arg) {
1751
+ return arg.defaultValue != null && arg.defaultValueStrategy === "omitted";
1419
1752
  }
1420
1753
  function getPdaPageFragment(node, scope) {
1421
1754
  const name = node.name;
@@ -1534,8 +1867,6 @@ function bytesValueToDart(hex) {
1534
1867
  }
1535
1868
  return `[${pairs.join(", ")}]`;
1536
1869
  }
1537
-
1538
- // src/fragments/programPage.ts
1539
1870
  function getProgramPageFragment(node, scope) {
1540
1871
  const name = node.name;
1541
1872
  const addressConstName = scope.nameApi.programAddressConstant(name);
@@ -1567,41 +1898,171 @@ enum ${fragmentFromString(pascalCase(name))}Account {
1567
1898
  ${fragmentFromString(accountVariants)}
1568
1899
  }`);
1569
1900
  }
1570
- const instructions = node.instructions ?? [];
1901
+ const instructions = getAllInstructionsWithSubs(node);
1571
1902
  if (instructions.length > 0) {
1903
+ const programName = pascalCase(name);
1904
+ const instructionEnum = `${programName}Instruction`;
1572
1905
  const instrVariants = instructions.map((instr) => ` ${camelCase(instr.name)},`).join("\n");
1573
1906
  parts.push(fragment`
1574
- /// Known instructions for the ${fragmentFromString(pascalCase(name))} program.
1575
- enum ${fragmentFromString(pascalCase(name))}Instruction {
1907
+ /// Known instructions for the ${fragmentFromString(programName)} program.
1908
+ enum ${fragmentFromString(instructionEnum)} {
1576
1909
  ${fragmentFromString(instrVariants)}
1577
1910
  }`);
1911
+ const identifiableInstructions = instructions.map((instruction) => ({
1912
+ instruction,
1913
+ condition: getInstructionDiscriminatorCondition(instruction, scope)
1914
+ })).filter(({ condition }) => condition !== null);
1915
+ if (identifiableInstructions.length > 0) {
1916
+ const identifyBranches = identifiableInstructions.map(
1917
+ ({ instruction, condition }) => fragment` if (${condition}) {
1918
+ return ${fragmentFromString(instructionEnum)}.${fragmentFromString(camelCase(instruction.name))};
1919
+ }`
1920
+ );
1921
+ const parsedBase = `Parsed${programName}Instruction`;
1922
+ const parsedClasses = instructions.map((instruction) => {
1923
+ const instructionName = pascalCase(instruction.name);
1924
+ const variant = camelCase(instruction.name);
1925
+ const parsedClass = `Parsed${instructionName}`;
1926
+ const dataClass = `${instructionName}InstructionData`;
1927
+ return fragment`/// A parsed ${fragmentFromString(instructionName)} instruction.
1928
+ final class ${fragmentFromString(parsedClass)} extends ${fragmentFromString(parsedBase)} {
1929
+ const ${fragmentFromString(parsedClass)}({required this.data})
1930
+ : super(${fragmentFromString(instructionEnum)}.${fragmentFromString(variant)});
1931
+
1932
+ final ${use(dataClass, "../instructions/instructions.dart")} data;
1933
+ }`;
1934
+ });
1935
+ const parseBranches = instructions.map((instruction) => {
1936
+ const instructionName = pascalCase(instruction.name);
1937
+ const variant = camelCase(instruction.name);
1938
+ const parsedClass = `Parsed${instructionName}`;
1939
+ const parseFunction = scope.nameApi.instructionParseFunction(
1940
+ instruction.name
1941
+ );
1942
+ return fragment` ${fragmentFromString(instructionEnum)}.${fragmentFromString(variant)} => ${fragmentFromString(parsedClass)}(
1943
+ data: ${use(parseFunction, "../instructions/instructions.dart")}(instruction),
1944
+ ),`;
1945
+ });
1946
+ parts.push(fragment`
1947
+ /// Identifies the type of a ${fragmentFromString(programName)} instruction.
1948
+ ${fragmentFromString(instructionEnum)} identify${fragmentFromString(programName)}Instruction(
1949
+ ${use("Uint8List", "dartTypedData")} data,
1950
+ ) {
1951
+ ${mergeFragments(identifyBranches, (cs) => cs.join("\n"))}
1952
+
1953
+ throw ${use("SolanaError", "solanaErrors")}(
1954
+ ${use("SolanaErrorCode", "solanaErrors")}.programClientsFailedToIdentifyInstruction,
1955
+ {
1956
+ 'instructionData': data,
1957
+ 'programName': '${fragmentFromString(name)}',
1958
+ },
1959
+ );
1960
+ }
1961
+
1962
+ /// A parsed instruction from the ${fragmentFromString(programName)} program.
1963
+ sealed class ${fragmentFromString(parsedBase)} {
1964
+ const ${fragmentFromString(parsedBase)}(this.instructionType);
1965
+
1966
+ final ${fragmentFromString(instructionEnum)} instructionType;
1967
+ }
1968
+
1969
+ ${mergeFragments(parsedClasses, (cs) => cs.join("\n\n"))}
1970
+
1971
+ /// Parses a ${fragmentFromString(programName)} instruction.
1972
+ ${fragmentFromString(parsedBase)} parse${fragmentFromString(programName)}Instruction(
1973
+ ${use("Instruction", "solanaInstructions")} instruction,
1974
+ ) {
1975
+ return switch (identify${fragmentFromString(programName)}Instruction(
1976
+ instruction.data ?? Uint8List(0),
1977
+ )) {
1978
+ ${mergeFragments(parseBranches, (cs) => cs.join("\n"))}
1979
+ };
1980
+ }`);
1981
+ }
1578
1982
  }
1579
1983
  return mergeFragments(parts, (cs) => cs.join("\n"));
1580
1984
  }
1985
+ function getInstructionDiscriminatorCondition(instruction, scope) {
1986
+ const discriminators = instruction.discriminators ?? [];
1987
+ if (discriminators.length === 0) return null;
1988
+ const conditions = discriminators.map((discriminator) => {
1989
+ switch (discriminator.kind) {
1990
+ case "sizeDiscriminatorNode":
1991
+ return fragment`data.length == ${discriminator.size}`;
1992
+ case "constantDiscriminatorNode": {
1993
+ const manifest = visit(
1994
+ discriminator.constant.type,
1995
+ scope.typeManifestVisitor
1996
+ );
1997
+ const value = getValueFragment(
1998
+ discriminator.constant.value,
1999
+ manifest.type.content
2000
+ );
2001
+ if (value === null) return null;
2002
+ return fragment`${use("containsBytes", "solanaCodecsCore")}(data, ${manifest.encoder}.encode(${value}), ${discriminator.offset})`;
2003
+ }
2004
+ case "fieldDiscriminatorNode": {
2005
+ const argument = (instruction.arguments ?? []).find(
2006
+ (candidate) => candidate.name === discriminator.name
2007
+ );
2008
+ if (argument?.defaultValue == null) return null;
2009
+ const manifest = visit(argument.type, scope.typeManifestVisitor);
2010
+ const value = getValueFragment(
2011
+ argument.defaultValue,
2012
+ manifest.type.content
2013
+ );
2014
+ if (value === null) return null;
2015
+ return fragment`${use("containsBytes", "solanaCodecsCore")}(data, ${manifest.encoder}.encode(${value}), ${discriminator.offset})`;
2016
+ }
2017
+ }
2018
+ });
2019
+ if (conditions.some((condition) => condition === null)) return null;
2020
+ return mergeFragments(conditions, (cs) => cs.join(" && "));
2021
+ }
2022
+ function getValueFragment(value, dartType) {
2023
+ switch (value.kind) {
2024
+ case "numberValueNode":
2025
+ return fragmentFromString(
2026
+ dartType === "BigInt" ? `BigInt.from(${value.number})` : String(value.number)
2027
+ );
2028
+ case "booleanValueNode":
2029
+ return fragmentFromString(String(value.boolean));
2030
+ case "stringValueNode":
2031
+ return fragmentFromString(`'${value.string.replaceAll("'", "\\'")}'`);
2032
+ case "bytesValueNode": {
2033
+ const clean = value.data.replace(/^0x/, "");
2034
+ const bytes = clean.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) ?? [];
2035
+ return fragment`${use("Uint8List", "dartTypedData")}.fromList([${fragmentFromString(bytes.join(", "))}])`;
2036
+ }
2037
+ default:
2038
+ return null;
2039
+ }
2040
+ }
1581
2041
  function getTypePageFragment(node, scope) {
1582
2042
  const name = node.name;
1583
2043
  scope.nameApi.dataType(name);
1584
2044
  const typeNode = node.type;
1585
2045
  if (typeNode.kind === "enumTypeNode") {
1586
- const isScalar = typeNode.variants.every(
2046
+ const variants = typeNode.variants ?? [];
2047
+ const isScalar = variants.every(
1587
2048
  (v) => v.kind === "enumEmptyVariantTypeNode"
1588
2049
  );
1589
2050
  if (isScalar) {
1590
- return getScalarEnumPageFragment(node, scope);
2051
+ return getScalarEnumPageFragment(node, variants, scope);
1591
2052
  }
1592
- return getDataEnumPageFragment(node, scope);
2053
+ return getDataEnumPageFragment(node, variants, scope);
1593
2054
  }
1594
2055
  if (typeNode.kind === "structTypeNode") {
1595
2056
  return getStructPageFragment(node, scope);
1596
2057
  }
1597
2058
  return getTypeAliasPageFragment(node, scope);
1598
2059
  }
1599
- function getScalarEnumPageFragment(node, scope) {
2060
+ function getScalarEnumPageFragment(node, enumVariants, scope) {
1600
2061
  const name = node.name;
1601
2062
  const typeName = scope.nameApi.dataType(name);
1602
2063
  const enumNode = node.type;
1603
2064
  if (enumNode.kind !== "enumTypeNode") return emptyFragment();
1604
- const variants = enumNode.variants.map((v) => {
2065
+ const variants = enumVariants.map((v) => {
1605
2066
  const variantName = scope.nameApi.enumVariant(v.name);
1606
2067
  return variantName;
1607
2068
  });
@@ -1612,6 +2073,14 @@ function getScalarEnumPageFragment(node, scope) {
1612
2073
  const resolvedSize = resolveNestedTypeNode(enumNode.size);
1613
2074
  const sizeType = resolvedSize.format ?? "u8";
1614
2075
  const sizeCodecName = getNumberCodecName2(sizeType);
2076
+ const isU64 = sizeType === "u64";
2077
+ const encodedVariantIndex = isU64 ? "BigInt.from(value.index)" : "value.index";
2078
+ const decodedVariant = isU64 ? `(BigInt value, Uint8List bytes, int offset) {
2079
+ if (value.isNegative || value >= BigInt.from(${typeName}.values.length)) {
2080
+ throw RangeError('Invalid ${typeName} discriminator: ' + value.toString());
2081
+ }
2082
+ return ${typeName}.values[value.toInt()];
2083
+ }` : `(int value, Uint8List bytes, int offset) => ${typeName}.values[value]`;
1615
2084
  return fragment`// Auto-generated. Do not edit.
1616
2085
  // ignore_for_file: type=lint
1617
2086
 
@@ -1632,14 +2101,14 @@ ${fragmentFromString(variantLines)}
1632
2101
  Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
1633
2102
  return transformEncoder(
1634
2103
  get${fragmentFromString(sizeCodecName)}Encoder(),
1635
- (${fragmentFromString(typeName)} value) => value.index,
2104
+ (${fragmentFromString(typeName)} value) => ${fragmentFromString(encodedVariantIndex)},
1636
2105
  );
1637
2106
  }
1638
2107
 
1639
2108
  Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
1640
2109
  return transformDecoder(
1641
2110
  get${fragmentFromString(sizeCodecName)}Decoder(),
1642
- (int value, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}.values[value],
2111
+ ${fragmentFromString(decodedVariant)},
1643
2112
  );
1644
2113
  }
1645
2114
 
@@ -1647,7 +2116,7 @@ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragme
1647
2116
  return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
1648
2117
  }`;
1649
2118
  }
1650
- function getDataEnumPageFragment(node, scope) {
2119
+ function getDataEnumPageFragment(node, variants, scope) {
1651
2120
  const name = node.name;
1652
2121
  const typeName = scope.nameApi.dataType(name);
1653
2122
  const enumNode = node.type;
@@ -1658,8 +2127,9 @@ function getDataEnumPageFragment(node, scope) {
1658
2127
  const encodeCases = [];
1659
2128
  const decodeCases = [];
1660
2129
  const allVariantManifests = [];
1661
- for (let i = 0; i < enumNode.variants.length; i++) {
1662
- const variant = enumNode.variants[i];
2130
+ for (let i = 0; i < variants.length; i++) {
2131
+ const variant = variants[i];
2132
+ const variantName = pascalCase(variant.name);
1663
2133
  const variantClassName = scope.nameApi.sealedClassVariant(
1664
2134
  name,
1665
2135
  variant.name
@@ -1676,7 +2146,7 @@ function getDataEnumPageFragment(node, scope) {
1676
2146
  int get hashCode => runtimeType.hashCode;
1677
2147
 
1678
2148
  @override
1679
- String toString() => '${typeName}.${variantClassName}()';
2149
+ String toString() => '${typeName}.${variantName}()';
1680
2150
  }`);
1681
2151
  encoderVariants.push(
1682
2152
  `(${i}, getStructEncoder(<(String, Encoder<Object?>)>[]))`
@@ -1688,7 +2158,7 @@ function getDataEnumPageFragment(node, scope) {
1688
2158
  decodeCases.push(`case ${i}: return const ${variantClassName}();`);
1689
2159
  } else if (variant.kind === "enumStructVariantTypeNode") {
1690
2160
  const resolvedStruct = resolveNestedTypeNode(variant.struct);
1691
- const fields = resolvedStruct.fields;
2161
+ const fields = resolvedStruct.fields ?? [];
1692
2162
  const fieldManifests = fields.map((f) => ({
1693
2163
  field: f,
1694
2164
  manifest: visit(f.type, scope.typeManifestVisitor)
@@ -1723,7 +2193,7 @@ ${fieldDecls}
1723
2193
  int get hashCode => ${hashExpression};
1724
2194
 
1725
2195
  @override
1726
- String toString() => '${typeName}.${variantClassName}(${toStringFields})';
2196
+ String toString() => '${typeName}.${variantName}(${toStringFields})';
1727
2197
  }`);
1728
2198
  const encFields = fieldManifests.map(({ field: f, manifest }) => {
1729
2199
  return `('${f.name}', ${manifest.encoder.content})`;
@@ -1754,7 +2224,7 @@ ${fieldDecls}
1754
2224
  decodeCases.push(`case ${i}: return ${variantClassName}(${fromMapFields.replace(/\n/g, " ").replace(/,$/, "")});`);
1755
2225
  } else if (variant.kind === "enumTupleVariantTypeNode") {
1756
2226
  const resolvedTuple = resolveNestedTypeNode(variant.tuple);
1757
- const items = resolvedTuple.items;
2227
+ const items = resolvedTuple.items ?? [];
1758
2228
  if (items.length === 1) {
1759
2229
  const manifest = visit(items[0], scope.typeManifestVisitor);
1760
2230
  allVariantManifests.push(manifest);
@@ -1772,7 +2242,7 @@ ${fieldDecls}
1772
2242
  int get hashCode => value.hashCode;
1773
2243
 
1774
2244
  @override
1775
- String toString() => '${typeName}.${variantClassName}($value)';
2245
+ String toString() => '${typeName}.${variantName}($value)';
1776
2246
  }`);
1777
2247
  encoderVariants.push(
1778
2248
  `(${i}, transformEncoder<${manifest.type.content}, Map<String, Object?>>(${manifest.encoder.content}, (Map<String, Object?> map) => map['value']! as ${manifest.type.content}))`
@@ -1854,7 +2324,7 @@ function getStructPageFragment(node, scope) {
1854
2324
  const typeName = scope.nameApi.dataType(name);
1855
2325
  const structNode = node.type;
1856
2326
  if (structNode.kind !== "structTypeNode") return emptyFragment();
1857
- const fields = structNode.fields;
2327
+ const fields = structNode.fields ?? [];
1858
2328
  const fieldManifests = fields.map((f) => ({
1859
2329
  field: f,
1860
2330
  manifest: visit(f.type, scope.typeManifestVisitor)
@@ -2061,7 +2531,7 @@ function getRenderMapVisitor(options = {}) {
2061
2531
  visitRoot(node, { self }) {
2062
2532
  const programMaps = [
2063
2533
  visit(node.program, self),
2064
- ...node.additionalPrograms.map((p) => visit(p, self))
2534
+ ...(node.additionalPrograms ?? []).map((p) => visit(p, self))
2065
2535
  ];
2066
2536
  const mergedProgramMap = mergeRenderMaps(programMaps);
2067
2537
  const categoryMaps = getSharedCategoryIndexMaps(mergedProgramMap);
@@ -2207,16 +2677,17 @@ function renderVisitor(outputDir, options = {}) {
2207
2677
  dependencyMap
2208
2678
  } = options;
2209
2679
  return rootNodeVisitor((root) => {
2680
+ const normalizedRoot = normalizeRootNode(root);
2210
2681
  if (deleteFolderBeforeRendering && existsSync(outputDir)) {
2211
2682
  deleteDirectory(outputDir);
2212
2683
  }
2213
2684
  const renderMap = visit(
2214
- root,
2685
+ normalizedRoot,
2215
2686
  getRenderMapVisitor({ nameApi, dependencyMap })
2216
2687
  );
2217
2688
  const typePathMap = {};
2218
2689
  for (const renderPath of renderMap.keys()) {
2219
- const match = renderPath.match(/^(?:.*\/)?types\/([a-z_]+)\.dart$/);
2690
+ const match = renderPath.match(/^(?:.*\/)?types\/([a-z0-9_]+)\.dart$/);
2220
2691
  if (match) {
2221
2692
  typePathMap[`definedType:${match[1]}`] = renderPath;
2222
2693
  }
@@ -2230,7 +2701,10 @@ function renderVisitor(outputDir, options = {}) {
2230
2701
  const fileDir = dirname(filePath);
2231
2702
  const internalMap = {};
2232
2703
  for (const [key, typePath] of Object.entries(typePathMap)) {
2233
- if (typePath === filePath) continue;
2704
+ if (typePath === filePath) {
2705
+ internalMap[key] = "";
2706
+ continue;
2707
+ }
2234
2708
  let rel = posix.relative(fileDir, typePath);
2235
2709
  if (!rel.startsWith(".")) {
2236
2710
  rel = `./${rel}`;
@@ -2290,6 +2764,6 @@ function cleanFragmentContent(content) {
2290
2764
  // src/index.ts
2291
2765
  var src_default = renderVisitor;
2292
2766
 
2293
- export { DART_EXTERNAL_PACKAGE_MAP, DartImportMap, createDartNameApi, src_default as default, getRenderMapVisitor, getTypeManifestVisitor, renderVisitor };
2767
+ export { DART_EXTERNAL_PACKAGE_MAP, DartImportMap, createDartNameApi, src_default as default, getRenderMapVisitor, getTypeManifestVisitor, normalizeRootNode, renderVisitor };
2294
2768
  //# sourceMappingURL=index.node.js.map
2295
2769
  //# sourceMappingURL=index.node.js.map