codama-renderers-dart 0.2.0 → 0.2.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/dist/index.browser.cjs +2102 -0
  2. package/dist/index.browser.cjs.map +1 -0
  3. package/dist/index.browser.js +2092 -0
  4. package/dist/index.browser.js.map +1 -0
  5. package/dist/index.node.cjs +2102 -0
  6. package/dist/index.node.cjs.map +1 -0
  7. package/dist/index.node.js +2092 -0
  8. package/dist/index.node.js.map +1 -0
  9. package/dist/index.react-native.js +2092 -0
  10. package/dist/index.react-native.js.map +1 -0
  11. package/dist/types/fragments/accountPage.d.ts +8 -0
  12. package/dist/types/fragments/accountPage.d.ts.map +1 -0
  13. package/dist/types/fragments/discriminatorConstants.d.ts +8 -0
  14. package/dist/types/fragments/discriminatorConstants.d.ts.map +1 -0
  15. package/dist/types/fragments/errorPage.d.ts +8 -0
  16. package/dist/types/fragments/errorPage.d.ts.map +1 -0
  17. package/dist/types/fragments/index.d.ts +9 -0
  18. package/dist/types/fragments/index.d.ts.map +1 -0
  19. package/dist/types/fragments/indexPage.d.ts +10 -0
  20. package/dist/types/fragments/indexPage.d.ts.map +1 -0
  21. package/dist/types/fragments/instructionPage.d.ts +8 -0
  22. package/dist/types/fragments/instructionPage.d.ts.map +1 -0
  23. package/dist/types/fragments/pdaPage.d.ts +8 -0
  24. package/dist/types/fragments/pdaPage.d.ts.map +1 -0
  25. package/dist/types/fragments/programPage.d.ts +8 -0
  26. package/dist/types/fragments/programPage.d.ts.map +1 -0
  27. package/dist/types/fragments/typePage.d.ts +8 -0
  28. package/dist/types/fragments/typePage.d.ts.map +1 -0
  29. package/dist/types/index.d.ts +12 -0
  30. package/dist/types/index.d.ts.map +1 -0
  31. package/dist/types/utils/codecs.d.ts +10 -0
  32. package/dist/types/utils/codecs.d.ts.map +1 -0
  33. package/dist/types/utils/formatCode.d.ts +10 -0
  34. package/dist/types/utils/formatCode.d.ts.map +1 -0
  35. package/dist/types/utils/fragment.d.ts +31 -0
  36. package/dist/types/utils/fragment.d.ts.map +1 -0
  37. package/dist/types/utils/importMap.d.ts +40 -0
  38. package/dist/types/utils/importMap.d.ts.map +1 -0
  39. package/dist/types/utils/index.d.ts +8 -0
  40. package/dist/types/utils/index.d.ts.map +1 -0
  41. package/dist/types/utils/nameTransformers.d.ts +64 -0
  42. package/dist/types/utils/nameTransformers.d.ts.map +1 -0
  43. package/dist/types/utils/options.d.ts +41 -0
  44. package/dist/types/utils/options.d.ts.map +1 -0
  45. package/dist/types/utils/typeManifest.d.ts +21 -0
  46. package/dist/types/utils/typeManifest.d.ts.map +1 -0
  47. package/dist/types/visitors/getRenderMapVisitor.d.ts +9 -0
  48. package/dist/types/visitors/getRenderMapVisitor.d.ts.map +1 -0
  49. package/dist/types/visitors/getTypeManifestVisitor.d.ts +19 -0
  50. package/dist/types/visitors/getTypeManifestVisitor.d.ts.map +1 -0
  51. package/dist/types/visitors/index.d.ts +4 -0
  52. package/dist/types/visitors/index.d.ts.map +1 -0
  53. package/dist/types/visitors/renderVisitor.d.ts +9 -0
  54. package/dist/types/visitors/renderVisitor.d.ts.map +1 -0
  55. package/package.json +6 -11
@@ -0,0 +1,2092 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { join, dirname, posix } from 'path';
3
+ import { staticVisitor, extendVisitor, visit, NodeStack, LinkableDictionary, pipe, recordNodeStackVisitor, recordLinkablesOnFirstVisitVisitor, rootNodeVisitor } from '@codama/visitors-core';
4
+ import { createRenderMap, addToRenderMap, mergeRenderMaps, deleteDirectory } from '@codama/renderers-core';
5
+ import { execSync } from 'child_process';
6
+ import { resolveNestedTypeNode } from '@codama/nodes';
7
+ import { CodamaError, CODAMA_ERROR__UNEXPECTED_NODE_KIND } from '@codama/errors';
8
+
9
+ // src/visitors/renderVisitor.ts
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 {
18
+ }
19
+ }
20
+
21
+ // src/utils/nameTransformers.ts
22
+ function pascalCase(str) {
23
+ return str.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : "").replace(/^(.)/, (c) => c.toUpperCase());
24
+ }
25
+ function camelCase(str) {
26
+ const pascal = pascalCase(str);
27
+ return pascal.charAt(0).toLowerCase() + pascal.slice(1);
28
+ }
29
+ function snakeCase(str) {
30
+ return str.replace(/([A-Z])/g, "_$1").replace(/[-\s]+/g, "_").replace(/^_/, "").replace(/_+/g, "_").toLowerCase();
31
+ }
32
+ function createDartNameApi() {
33
+ return {
34
+ dataType: (name) => pascalCase(name),
35
+ encoderFunction: (name) => `get${pascalCase(name)}Encoder`,
36
+ decoderFunction: (name) => `get${pascalCase(name)}Decoder`,
37
+ codecFunction: (name) => `get${pascalCase(name)}Codec`,
38
+ accountFetchFunction: (name) => `fetch${pascalCase(name)}`,
39
+ accountFetchMaybeFunction: (name) => `fetchMaybe${pascalCase(name)}`,
40
+ accountDecodeFunction: (name) => `decode${pascalCase(name)}`,
41
+ accountSizeConstant: (name) => `${camelCase(name)}Size`,
42
+ pdaFindFunction: (name) => `find${pascalCase(name)}Pda`,
43
+ instructionFunction: (name) => `get${pascalCase(name)}Instruction`,
44
+ instructionParseFunction: (name) => `parse${pascalCase(name)}Instruction`,
45
+ programAddressConstant: (name) => `${camelCase(name)}ProgramAddress`,
46
+ errorConstant: (programName, errorName) => `${camelCase(programName)}Error${pascalCase(errorName)}`,
47
+ errorMessageFunction: (name) => `get${pascalCase(name)}ErrorMessage`,
48
+ enumVariant: (name) => camelCase(name),
49
+ sealedClassVariant: (_parentName, variantName) => pascalCase(variantName),
50
+ isTypeFunction: (name) => `is${pascalCase(name)}`,
51
+ fileName: (name) => snakeCase(name),
52
+ discriminatorConstant: (name) => `${camelCase(name)}Discriminator`
53
+ };
54
+ }
55
+
56
+ // src/utils/codecs.ts
57
+ function bytesToDartHexList(bytes) {
58
+ const pairs = [];
59
+ for (let i = 0; i < bytes.length; i++) {
60
+ pairs.push(`0x${bytes[i].toString(16).padStart(2, "0")}`);
61
+ }
62
+ return `[${pairs.join(", ")}]`;
63
+ }
64
+
65
+ // src/utils/importMap.ts
66
+ var DART_EXTERNAL_PACKAGE_MAP = {
67
+ // Dart core
68
+ dartTypedData: "dart:typed_data",
69
+ dartConvert: "dart:convert",
70
+ meta: "package:meta/meta.dart",
71
+ // solana_kit packages
72
+ solanaAddresses: "package:solana_kit_addresses/solana_kit_addresses.dart",
73
+ solanaCodecsCore: "package:solana_kit_codecs_core/solana_kit_codecs_core.dart",
74
+ solanaCodecsDataStructures: "package:solana_kit_codecs_data_structures/solana_kit_codecs_data_structures.dart",
75
+ solanaCodecsNumbers: "package:solana_kit_codecs_numbers/solana_kit_codecs_numbers.dart",
76
+ solanaCodecsStrings: "package:solana_kit_codecs_strings/solana_kit_codecs_strings.dart",
77
+ solanaErrors: "package:solana_kit_errors/solana_kit_errors.dart",
78
+ solanaAccounts: "package:solana_kit_accounts/solana_kit_accounts.dart",
79
+ solanaInstructions: "package:solana_kit_instructions/solana_kit_instructions.dart",
80
+ solanaPrograms: "package:solana_kit_programs/solana_kit_programs.dart",
81
+ solanaRpcTypes: "package:solana_kit_rpc_types/solana_kit_rpc_types.dart",
82
+ solanaSigners: "package:solana_kit_signers/solana_kit_signers.dart"
83
+ };
84
+ var DartImportMap = class {
85
+ _imports = /* @__PURE__ */ new Set();
86
+ /**
87
+ * Add a logical module name (resolved via DART_EXTERNAL_PACKAGE_MAP)
88
+ * or a raw Dart import URI.
89
+ */
90
+ add(module) {
91
+ this._imports.add(module);
92
+ return this;
93
+ }
94
+ /**
95
+ * Merge another DartImportMap into this one.
96
+ */
97
+ mergeWith(other) {
98
+ for (const imp of other._imports) {
99
+ this._imports.add(imp);
100
+ }
101
+ return this;
102
+ }
103
+ /**
104
+ * Check if this import map is empty.
105
+ */
106
+ get isEmpty() {
107
+ return this._imports.size === 0;
108
+ }
109
+ /**
110
+ * Get all raw module keys.
111
+ */
112
+ get modules() {
113
+ return new Set(this._imports);
114
+ }
115
+ /**
116
+ * Resolve all imports to Dart import URIs and return them sorted.
117
+ * @param internalMap Maps logical names to relative file paths for generated code cross-references.
118
+ */
119
+ resolve(internalMap = {}) {
120
+ const uris = /* @__PURE__ */ new Set();
121
+ for (const module of this._imports) {
122
+ if (module in internalMap) {
123
+ uris.add(internalMap[module]);
124
+ } else if (module in DART_EXTERNAL_PACKAGE_MAP) {
125
+ uris.add(DART_EXTERNAL_PACKAGE_MAP[module]);
126
+ } else {
127
+ uris.add(module);
128
+ }
129
+ }
130
+ return [...uris].sort((a, b) => {
131
+ const aWeight = a.startsWith("dart:") ? 0 : a.startsWith("package:") ? 1 : 2;
132
+ const bWeight = b.startsWith("dart:") ? 0 : b.startsWith("package:") ? 1 : 2;
133
+ if (aWeight !== bWeight) return aWeight - bWeight;
134
+ return a.localeCompare(b);
135
+ });
136
+ }
137
+ /**
138
+ * Render all imports as Dart import statements.
139
+ */
140
+ toString(internalMap = {}) {
141
+ const resolved = this.resolve(internalMap);
142
+ if (resolved.length === 0) return "";
143
+ const lines = [];
144
+ let lastPrefix = "";
145
+ for (const uri of resolved) {
146
+ const prefix = uri.startsWith("dart:") ? "dart" : uri.startsWith("package:") ? "package" : "relative";
147
+ if (lastPrefix && lastPrefix !== prefix) {
148
+ lines.push("");
149
+ }
150
+ lastPrefix = prefix;
151
+ lines.push(`import '${uri}';`);
152
+ }
153
+ return lines.join("\n");
154
+ }
155
+ };
156
+
157
+ // src/utils/fragment.ts
158
+ function fragment(strings, ...values) {
159
+ const imports = new DartImportMap();
160
+ const parts = [];
161
+ for (let i = 0; i < strings.length; i++) {
162
+ parts.push(strings[i]);
163
+ if (i < values.length) {
164
+ const value = values[i];
165
+ if (value != null && typeof value === "object" && "imports" in value) {
166
+ parts.push(value.content);
167
+ imports.mergeWith(value.imports);
168
+ } else {
169
+ parts.push(String(value ?? ""));
170
+ }
171
+ }
172
+ }
173
+ return {
174
+ content: parts.join(""),
175
+ imports
176
+ };
177
+ }
178
+ function emptyFragment() {
179
+ return { content: "", imports: new DartImportMap() };
180
+ }
181
+ function fragmentFromString(content) {
182
+ return { content, imports: new DartImportMap() };
183
+ }
184
+ function mergeFragments(fragments, joiner) {
185
+ const imports = new DartImportMap();
186
+ const contents = [];
187
+ for (const frag of fragments) {
188
+ contents.push(frag.content);
189
+ imports.mergeWith(frag.imports);
190
+ }
191
+ return { content: joiner(contents), imports };
192
+ }
193
+ function use(typeName, module) {
194
+ const imports = new DartImportMap();
195
+ imports.add(module);
196
+ return { content: typeName, imports };
197
+ }
198
+
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
+ // src/visitors/getTypeManifestVisitor.ts
211
+ function getTypeManifestVisitor(input) {
212
+ const { nameApi, linkables, nonScalarEnums = [] } = input;
213
+ const baseVisitor = staticVisitor(
214
+ (node) => {
215
+ throw new CodamaError(CODAMA_ERROR__UNEXPECTED_NODE_KIND, {
216
+ expectedKinds: ["typeNode"],
217
+ kind: node.kind
218
+ });
219
+ },
220
+ {
221
+ keys: [
222
+ // Type nodes
223
+ "numberTypeNode",
224
+ "booleanTypeNode",
225
+ "stringTypeNode",
226
+ "publicKeyTypeNode",
227
+ "bytesTypeNode",
228
+ "arrayTypeNode",
229
+ "mapTypeNode",
230
+ "setTypeNode",
231
+ "tupleTypeNode",
232
+ "structTypeNode",
233
+ "structFieldTypeNode",
234
+ "enumTypeNode",
235
+ "enumEmptyVariantTypeNode",
236
+ "enumStructVariantTypeNode",
237
+ "enumTupleVariantTypeNode",
238
+ "optionTypeNode",
239
+ "remainderOptionTypeNode",
240
+ "zeroableOptionTypeNode",
241
+ "fixedSizeTypeNode",
242
+ "sizePrefixTypeNode",
243
+ "hiddenPrefixTypeNode",
244
+ "hiddenSuffixTypeNode",
245
+ "sentinelTypeNode",
246
+ "preOffsetTypeNode",
247
+ "postOffsetTypeNode",
248
+ "solAmountTypeNode",
249
+ "amountTypeNode",
250
+ "dateTimeTypeNode",
251
+ "definedTypeLinkNode",
252
+ // Context nodes (for links)
253
+ "definedTypeNode",
254
+ "accountNode",
255
+ "instructionNode"
256
+ ]
257
+ }
258
+ );
259
+ return extendVisitor(baseVisitor, {
260
+ visitNumberType(node, { self }) {
261
+ const { format, endian } = node;
262
+ const endianSuffix = endian === "be" ? ", NumberCodecConfig(endian: Endian.big)" : "";
263
+ const endianDecoderSuffix = endian === "be" ? ", NumberCodecConfig(endian: Endian.big)" : "";
264
+ const dartType = getNumberDartType(format);
265
+ const codecName = getNumberCodecName(format);
266
+ return {
267
+ type: dartType === "BigInt" ? use("BigInt", "dartTypedData") : fragmentFromString(dartType),
268
+ encoder: fragment`${use(
269
+ `get${codecName}Encoder`,
270
+ "solanaCodecsNumbers"
271
+ )}(${endianSuffix ? fragmentFromString(endianSuffix.slice(2)) : fragmentFromString("")})`,
272
+ decoder: fragment`${use(
273
+ `get${codecName}Decoder`,
274
+ "solanaCodecsNumbers"
275
+ )}(${endianDecoderSuffix ? fragmentFromString(endianDecoderSuffix.slice(2)) : fragmentFromString("")})`,
276
+ value: emptyTypeManifest().value,
277
+ isEnum: false
278
+ };
279
+ },
280
+ visitBooleanType(_node, { self }) {
281
+ return {
282
+ type: fragmentFromString("bool"),
283
+ encoder: fragment`${use(
284
+ "getBooleanEncoder",
285
+ "solanaCodecsDataStructures"
286
+ )}()`,
287
+ decoder: fragment`${use(
288
+ "getBooleanDecoder",
289
+ "solanaCodecsDataStructures"
290
+ )}()`,
291
+ value: emptyTypeManifest().value,
292
+ isEnum: false
293
+ };
294
+ },
295
+ visitStringType(node, { self }) {
296
+ const { encoding } = node;
297
+ const codecMap = {
298
+ utf8: "Utf8",
299
+ base58: "Base58",
300
+ base64: "Base64",
301
+ base16: "Base16"
302
+ };
303
+ const codecName = codecMap[encoding] ?? "Utf8";
304
+ return {
305
+ type: fragmentFromString("String"),
306
+ encoder: fragment`${use(
307
+ `get${codecName}Encoder`,
308
+ "solanaCodecsStrings"
309
+ )}()`,
310
+ decoder: fragment`${use(
311
+ `get${codecName}Decoder`,
312
+ "solanaCodecsStrings"
313
+ )}()`,
314
+ value: emptyTypeManifest().value,
315
+ isEnum: false
316
+ };
317
+ },
318
+ visitPublicKeyType(_node, { self }) {
319
+ return {
320
+ type: fragment`${use("Address", "solanaAddresses")}`,
321
+ encoder: fragment`${use(
322
+ "getAddressEncoder",
323
+ "solanaAddresses"
324
+ )}()`,
325
+ decoder: fragment`${use(
326
+ "getAddressDecoder",
327
+ "solanaAddresses"
328
+ )}()`,
329
+ value: emptyTypeManifest().value,
330
+ isEnum: false
331
+ };
332
+ },
333
+ visitBytesType(_node, { self }) {
334
+ return {
335
+ type: fragment`${use("Uint8List", "dartTypedData")}`,
336
+ encoder: fragment`${use(
337
+ "getBytesEncoder",
338
+ "solanaCodecsDataStructures"
339
+ )}()`,
340
+ decoder: fragment`${use(
341
+ "getBytesDecoder",
342
+ "solanaCodecsDataStructures"
343
+ )}()`,
344
+ value: emptyTypeManifest().value,
345
+ isEnum: false
346
+ };
347
+ },
348
+ visitArrayType(node, { self }) {
349
+ const itemManifest = visit(node.item, self);
350
+ const sizeExpr = getArraySizeExpression(node);
351
+ return {
352
+ type: fragment`List<${itemManifest.type}>`,
353
+ encoder: fragment`${use(
354
+ "getArrayEncoder",
355
+ "solanaCodecsDataStructures"
356
+ )}(${itemManifest.encoder}${sizeExpr})`,
357
+ decoder: fragment`${use(
358
+ "getArrayDecoder",
359
+ "solanaCodecsDataStructures"
360
+ )}(${itemManifest.decoder}${sizeExpr})`,
361
+ value: emptyTypeManifest().value,
362
+ isEnum: false
363
+ };
364
+ },
365
+ visitMapType(node, { self }) {
366
+ const keyManifest = visit(node.key, self);
367
+ const valueManifest = visit(node.value, self);
368
+ const sizeExpr = getMapSizeExpression(node);
369
+ return {
370
+ type: fragment`Map<${keyManifest.type}, ${valueManifest.type}>`,
371
+ encoder: fragment`${use(
372
+ "getMapEncoder",
373
+ "solanaCodecsDataStructures"
374
+ )}(${keyManifest.encoder}, ${valueManifest.encoder}${sizeExpr})`,
375
+ decoder: fragment`${use(
376
+ "getMapDecoder",
377
+ "solanaCodecsDataStructures"
378
+ )}(${keyManifest.decoder}, ${valueManifest.decoder}${sizeExpr})`,
379
+ value: emptyTypeManifest().value,
380
+ isEnum: false
381
+ };
382
+ },
383
+ visitSetType(node, { self }) {
384
+ const itemManifest = visit(node.item, self);
385
+ const sizeExpr = getSetSizeExpression(node);
386
+ return {
387
+ type: fragment`Set<${itemManifest.type}>`,
388
+ encoder: fragment`${use(
389
+ "getSetEncoder",
390
+ "solanaCodecsDataStructures"
391
+ )}(${itemManifest.encoder}${sizeExpr})`,
392
+ decoder: fragment`${use(
393
+ "getSetDecoder",
394
+ "solanaCodecsDataStructures"
395
+ )}(${itemManifest.decoder}${sizeExpr})`,
396
+ value: emptyTypeManifest().value,
397
+ isEnum: false
398
+ };
399
+ },
400
+ visitTupleType(node, { self }) {
401
+ const itemManifests = node.items.map((item) => visit(item, self));
402
+ const typeList = itemManifests.map((m) => m.type.content).join(", ");
403
+ const encoderList = itemManifests.map((m) => m.encoder);
404
+ const decoderList = itemManifests.map((m) => m.decoder);
405
+ const typeFragment = fragment`(${fragmentFromString(typeList)})`;
406
+ for (const m of itemManifests) {
407
+ typeFragment.imports.mergeWith(m.type.imports);
408
+ }
409
+ const encoderListStr = encoderList.map((e) => e.content).join(", ");
410
+ const encoderFrag = fragment`${use(
411
+ "getTupleEncoder",
412
+ "solanaCodecsDataStructures"
413
+ )}([${fragmentFromString(encoderListStr)}])`;
414
+ for (const e of encoderList) {
415
+ encoderFrag.imports.mergeWith(e.imports);
416
+ }
417
+ const decoderListStr = decoderList.map((d) => d.content).join(", ");
418
+ const decoderFrag = fragment`${use(
419
+ "getTupleDecoder",
420
+ "solanaCodecsDataStructures"
421
+ )}([${fragmentFromString(decoderListStr)}])`;
422
+ for (const d of decoderList) {
423
+ decoderFrag.imports.mergeWith(d.imports);
424
+ }
425
+ return {
426
+ type: typeFragment,
427
+ encoder: encoderFrag,
428
+ decoder: decoderFrag,
429
+ value: emptyTypeManifest().value,
430
+ isEnum: false
431
+ };
432
+ },
433
+ visitStructType(node, { self }) {
434
+ const fields = node.fields.map((f) => visit(f, self));
435
+ const fieldNames = node.fields.map((f) => f.name);
436
+ const typeStr = "Map<String, Object?>";
437
+ const encoderFields = fields.map((f, i) => `('${fieldNames[i]}', ${f.encoder.content})`).join(", ");
438
+ const encoderFrag = fragment`${use(
439
+ "getStructEncoder",
440
+ "solanaCodecsDataStructures"
441
+ )}([${fragmentFromString(encoderFields)}])`;
442
+ for (const f of fields) {
443
+ encoderFrag.imports.mergeWith(f.encoder.imports);
444
+ }
445
+ const decoderFields = fields.map((f, i) => `('${fieldNames[i]}', ${f.decoder.content})`).join(", ");
446
+ const decoderFrag = fragment`${use(
447
+ "getStructDecoder",
448
+ "solanaCodecsDataStructures"
449
+ )}([${fragmentFromString(decoderFields)}])`;
450
+ for (const f of fields) {
451
+ decoderFrag.imports.mergeWith(f.decoder.imports);
452
+ }
453
+ return {
454
+ type: fragmentFromString(typeStr),
455
+ encoder: encoderFrag,
456
+ decoder: decoderFrag,
457
+ value: emptyTypeManifest().value,
458
+ isEnum: false
459
+ };
460
+ },
461
+ visitStructFieldType(node, { self }) {
462
+ return visit(node.type, self);
463
+ },
464
+ visitEnumType(node, { self }) {
465
+ const isScalar = node.variants.every(
466
+ (v) => v.kind === "enumEmptyVariantTypeNode"
467
+ );
468
+ if (isScalar) {
469
+ return {
470
+ type: emptyTypeManifest().type,
471
+ // Will be replaced by the named type
472
+ encoder: emptyTypeManifest().encoder,
473
+ decoder: emptyTypeManifest().decoder,
474
+ value: emptyTypeManifest().value,
475
+ isEnum: true
476
+ };
477
+ }
478
+ return {
479
+ type: emptyTypeManifest().type,
480
+ encoder: emptyTypeManifest().encoder,
481
+ decoder: emptyTypeManifest().decoder,
482
+ value: emptyTypeManifest().value,
483
+ isEnum: false
484
+ };
485
+ },
486
+ visitEnumEmptyVariantType(_node, { self }) {
487
+ return emptyTypeManifest();
488
+ },
489
+ visitEnumStructVariantType(node, { self }) {
490
+ return visit(node.struct, self);
491
+ },
492
+ visitEnumTupleVariantType(node, { self }) {
493
+ return visit(node.tuple, self);
494
+ },
495
+ visitOptionType(node, { self }) {
496
+ const itemManifest = visit(node.item, self);
497
+ const resolvedPrefix = resolveNestedTypeNode(node.prefix);
498
+ const prefixExpr = resolvedPrefix.format !== "u8" ? `, prefix: ${getNumberCodecExpression(resolvedPrefix.format, "Encoder")}` : "";
499
+ const prefixDecoderExpr = resolvedPrefix.format !== "u8" ? `, prefix: ${getNumberCodecExpression(resolvedPrefix.format, "Decoder")}` : "";
500
+ return {
501
+ type: fragment`${itemManifest.type}?`,
502
+ encoder: fragment`${use(
503
+ "getNullableEncoder",
504
+ "solanaCodecsDataStructures"
505
+ )}(${itemManifest.encoder}${fragmentFromString(prefixExpr)})`,
506
+ decoder: fragment`${use(
507
+ "getNullableDecoder",
508
+ "solanaCodecsDataStructures"
509
+ )}(${itemManifest.decoder}${fragmentFromString(prefixDecoderExpr)})`,
510
+ value: emptyTypeManifest().value,
511
+ isEnum: false
512
+ };
513
+ },
514
+ visitRemainderOptionType(node, { self }) {
515
+ const itemManifest = visit(node.item, self);
516
+ return {
517
+ type: fragment`${itemManifest.type}?`,
518
+ encoder: fragment`${use(
519
+ "getNullableEncoder",
520
+ "solanaCodecsDataStructures"
521
+ )}(${itemManifest.encoder}, hasPrefix: false)`,
522
+ decoder: fragment`${use(
523
+ "getNullableDecoder",
524
+ "solanaCodecsDataStructures"
525
+ )}(${itemManifest.decoder}, hasPrefix: false)`,
526
+ value: emptyTypeManifest().value,
527
+ isEnum: false
528
+ };
529
+ },
530
+ visitZeroableOptionType(node, { self }) {
531
+ const itemManifest = visit(node.item, self);
532
+ return {
533
+ type: fragment`${itemManifest.type}?`,
534
+ encoder: fragment`${use(
535
+ "getNullableEncoder",
536
+ "solanaCodecsDataStructures"
537
+ )}(${itemManifest.encoder}, hasPrefix: false, noneValue: const ZeroesNoneValue())`,
538
+ decoder: fragment`${use(
539
+ "getNullableDecoder",
540
+ "solanaCodecsDataStructures"
541
+ )}(${itemManifest.decoder}, hasPrefix: false, noneValue: const ZeroesNoneValue())`,
542
+ value: emptyTypeManifest().value,
543
+ isEnum: false
544
+ };
545
+ },
546
+ visitFixedSizeType(node, { self }) {
547
+ const innerManifest = visit(node.type, self);
548
+ return {
549
+ type: innerManifest.type,
550
+ encoder: fragment`${use(
551
+ "fixEncoderSize",
552
+ "solanaCodecsCore"
553
+ )}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))})`,
554
+ decoder: fragment`${use(
555
+ "fixDecoderSize",
556
+ "solanaCodecsCore"
557
+ )}(${innerManifest.decoder}, ${fragmentFromString(String(node.size))})`,
558
+ value: innerManifest.value,
559
+ isEnum: innerManifest.isEnum
560
+ };
561
+ },
562
+ visitSizePrefixType(node, { self }) {
563
+ const innerManifest = visit(node.type, self);
564
+ const prefixManifest = visit(node.prefix, self);
565
+ return {
566
+ type: innerManifest.type,
567
+ encoder: fragment`${use(
568
+ "addEncoderSizePrefix",
569
+ "solanaCodecsCore"
570
+ )}(${innerManifest.encoder}, ${prefixManifest.encoder})`,
571
+ decoder: fragment`${use(
572
+ "addDecoderSizePrefix",
573
+ "solanaCodecsCore"
574
+ )}(${innerManifest.decoder}, ${prefixManifest.decoder})`,
575
+ value: innerManifest.value,
576
+ isEnum: innerManifest.isEnum
577
+ };
578
+ },
579
+ visitHiddenPrefixType(node, { self }) {
580
+ const innerManifest = visit(node.type, self);
581
+ const prefixes = node.prefix.map((p) => visit(p, self));
582
+ const prefixEncoders = prefixes.map((p) => p.encoder.content).join(", ");
583
+ const prefixDecoders = prefixes.map((p) => p.decoder.content).join(", ");
584
+ const encoderFrag = fragment`${use(
585
+ "getHiddenPrefixEncoder",
586
+ "solanaCodecsDataStructures"
587
+ )}(${innerManifest.encoder}, [${fragmentFromString(prefixEncoders)}])`;
588
+ for (const p of prefixes) {
589
+ encoderFrag.imports.mergeWith(p.encoder.imports);
590
+ }
591
+ const decoderFrag = fragment`${use(
592
+ "getHiddenPrefixDecoder",
593
+ "solanaCodecsDataStructures"
594
+ )}(${innerManifest.decoder}, [${fragmentFromString(prefixDecoders)}])`;
595
+ for (const p of prefixes) {
596
+ decoderFrag.imports.mergeWith(p.decoder.imports);
597
+ }
598
+ return {
599
+ type: innerManifest.type,
600
+ encoder: encoderFrag,
601
+ decoder: decoderFrag,
602
+ value: innerManifest.value,
603
+ isEnum: innerManifest.isEnum
604
+ };
605
+ },
606
+ visitHiddenSuffixType(node, { self }) {
607
+ const innerManifest = visit(node.type, self);
608
+ const suffixes = node.suffix.map((s) => visit(s, self));
609
+ const suffixEncoders = suffixes.map((s) => s.encoder.content).join(", ");
610
+ const suffixDecoders = suffixes.map((s) => s.decoder.content).join(", ");
611
+ const encoderFrag = fragment`${use(
612
+ "getHiddenSuffixEncoder",
613
+ "solanaCodecsDataStructures"
614
+ )}(${innerManifest.encoder}, [${fragmentFromString(suffixEncoders)}])`;
615
+ for (const s of suffixes) {
616
+ encoderFrag.imports.mergeWith(s.encoder.imports);
617
+ }
618
+ const decoderFrag = fragment`${use(
619
+ "getHiddenSuffixDecoder",
620
+ "solanaCodecsDataStructures"
621
+ )}(${innerManifest.decoder}, [${fragmentFromString(suffixDecoders)}])`;
622
+ for (const s of suffixes) {
623
+ decoderFrag.imports.mergeWith(s.decoder.imports);
624
+ }
625
+ return {
626
+ type: innerManifest.type,
627
+ encoder: encoderFrag,
628
+ decoder: decoderFrag,
629
+ value: innerManifest.value,
630
+ isEnum: innerManifest.isEnum
631
+ };
632
+ },
633
+ visitSentinelType(node, { self }) {
634
+ const innerManifest = visit(node.type, self);
635
+ const sentinelManifest = visit(node.sentinel, self);
636
+ return {
637
+ type: innerManifest.type,
638
+ encoder: fragment`${use(
639
+ "addEncoderSentinel",
640
+ "solanaCodecsCore"
641
+ )}(${innerManifest.encoder}, ${sentinelManifest.encoder})`,
642
+ decoder: fragment`${use(
643
+ "addDecoderSentinel",
644
+ "solanaCodecsCore"
645
+ )}(${innerManifest.decoder}, ${sentinelManifest.decoder})`,
646
+ value: innerManifest.value,
647
+ isEnum: innerManifest.isEnum
648
+ };
649
+ },
650
+ visitPreOffsetType(node, { self }) {
651
+ return visit(node.type, self);
652
+ },
653
+ visitPostOffsetType(node, { self }) {
654
+ return visit(node.type, self);
655
+ },
656
+ visitSolAmountType(node, { self }) {
657
+ return visit(node.number, self);
658
+ },
659
+ visitAmountType(node, { self }) {
660
+ return visit(node.number, self);
661
+ },
662
+ visitDateTimeType(node, { self }) {
663
+ return visit(node.number, self);
664
+ },
665
+ visitDefinedTypeLink(node, { self }) {
666
+ const name = node.name;
667
+ const typeName = nameApi.dataType(name);
668
+ const isNonScalar = nonScalarEnums.includes(node.name);
669
+ const moduleKey = `definedType:${snakeCase(name)}`;
670
+ return {
671
+ type: fragment`${use(typeName, moduleKey)}`,
672
+ encoder: fragment`${use(nameApi.encoderFunction(name), moduleKey)}()`,
673
+ decoder: fragment`${use(nameApi.decoderFunction(name), moduleKey)}()`,
674
+ value: emptyTypeManifest().value,
675
+ isEnum: !isNonScalar
676
+ };
677
+ },
678
+ visitDefinedType(node, { self }) {
679
+ return visit(node.type, self);
680
+ },
681
+ visitAccount(node, { self }) {
682
+ return visit(node.data, self);
683
+ },
684
+ visitInstruction(node, { self }) {
685
+ return emptyTypeManifest();
686
+ }
687
+ });
688
+ }
689
+ function getNumberDartType(format) {
690
+ switch (format) {
691
+ case "u8":
692
+ case "u16":
693
+ case "u32":
694
+ case "i8":
695
+ case "i16":
696
+ case "i32":
697
+ case "shortU16":
698
+ return "int";
699
+ case "u64":
700
+ case "u128":
701
+ case "i64":
702
+ case "i128":
703
+ return "BigInt";
704
+ case "f32":
705
+ case "f64":
706
+ return "double";
707
+ default:
708
+ return "int";
709
+ }
710
+ }
711
+ function getNumberCodecName(format) {
712
+ switch (format) {
713
+ case "u8":
714
+ return "U8";
715
+ case "u16":
716
+ return "U16";
717
+ case "u32":
718
+ return "U32";
719
+ case "u64":
720
+ return "U64";
721
+ case "u128":
722
+ return "U128";
723
+ case "i8":
724
+ return "I8";
725
+ case "i16":
726
+ return "I16";
727
+ case "i32":
728
+ return "I32";
729
+ case "i64":
730
+ return "I64";
731
+ case "i128":
732
+ return "I128";
733
+ case "f32":
734
+ return "F32";
735
+ case "f64":
736
+ return "F64";
737
+ case "shortU16":
738
+ return "ShortU16";
739
+ default:
740
+ return "U8";
741
+ }
742
+ }
743
+ function getNumberCodecExpression(format, codecType) {
744
+ const name = getNumberCodecName(format);
745
+ return `get${name}${codecType}()`;
746
+ }
747
+ function getArraySizeExpression(node) {
748
+ if (!("count" in node) || !node.count) return "";
749
+ const count = node.count;
750
+ switch (count.kind) {
751
+ case "fixedCountNode":
752
+ return `, size: FixedArraySize(${count.value})`;
753
+ case "remainderCountNode":
754
+ return ", size: RemainderArraySize()";
755
+ case "prefixedCountNode": {
756
+ const resolvedPrefix = resolveNestedTypeNode(count.prefix);
757
+ if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
758
+ return "";
759
+ }
760
+ return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
761
+ }
762
+ default:
763
+ return "";
764
+ }
765
+ }
766
+ function getMapSizeExpression(node) {
767
+ if (!("count" in node) || !node.count) return "";
768
+ const count = node.count;
769
+ switch (count.kind) {
770
+ case "fixedCountNode":
771
+ return `, size: FixedArraySize(${count.value})`;
772
+ case "remainderCountNode":
773
+ return ", size: RemainderArraySize()";
774
+ case "prefixedCountNode": {
775
+ const resolvedPrefix = resolveNestedTypeNode(count.prefix);
776
+ if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
777
+ return "";
778
+ }
779
+ return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
780
+ }
781
+ default:
782
+ return "";
783
+ }
784
+ }
785
+ function getSetSizeExpression(node) {
786
+ if (!("count" in node) || !node.count) return "";
787
+ const count = node.count;
788
+ switch (count.kind) {
789
+ case "fixedCountNode":
790
+ return `, size: FixedArraySize(${count.value})`;
791
+ case "remainderCountNode":
792
+ return ", size: RemainderArraySize()";
793
+ case "prefixedCountNode": {
794
+ const resolvedPrefix = resolveNestedTypeNode(count.prefix);
795
+ if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
796
+ return "";
797
+ }
798
+ return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
799
+ }
800
+ default:
801
+ return "";
802
+ }
803
+ }
804
+
805
+ // src/fragments/discriminatorConstants.ts
806
+ function getDiscriminatorConstantsFragment(node, scope) {
807
+ const discriminators = node.discriminators ?? [];
808
+ if (discriminators.length === 0) return emptyFragment();
809
+ const name = node.name;
810
+ const constName = scope.nameApi.discriminatorConstant(name);
811
+ const fragments = [];
812
+ for (const disc of discriminators) {
813
+ switch (disc.kind) {
814
+ case "constantDiscriminatorNode": {
815
+ const constDisc = disc;
816
+ if (constDisc.constant.value.kind === "bytesValueNode") {
817
+ const bytes = hexToBytes(constDisc.constant.value.data);
818
+ const hexList = bytesToDartHexList(bytes);
819
+ fragments.push(
820
+ fragment`/// The discriminator bytes for this ${node.kind === "accountNode" ? "account" : "instruction"}.
821
+ final ${constName} = ${use("Uint8List", "dartTypedData")}.fromList(${fragmentFromString(hexList)});`
822
+ );
823
+ }
824
+ break;
825
+ }
826
+ case "fieldDiscriminatorNode": {
827
+ const fieldDisc = disc;
828
+ fragments.push(
829
+ fragment`/// The discriminator field name: '${fragmentFromString(fieldDisc.name)}'.
830
+ /// Offset: ${fragmentFromString(String(fieldDisc.offset))}.`
831
+ );
832
+ break;
833
+ }
834
+ case "sizeDiscriminatorNode": {
835
+ const sizeDisc = disc;
836
+ fragments.push(
837
+ fragment`/// This ${node.kind === "accountNode" ? "account" : "instruction"} has a size discriminator of ${fragmentFromString(String(sizeDisc.size))} bytes.`
838
+ );
839
+ break;
840
+ }
841
+ }
842
+ }
843
+ if (fragments.length === 0) return emptyFragment();
844
+ return mergeFragments(fragments, (cs) => cs.join("\n\n"));
845
+ }
846
+ function hexToBytes(hex) {
847
+ const clean = hex.replace(/^0x/, "");
848
+ const bytes = new Uint8Array(clean.length / 2);
849
+ for (let i = 0; i < clean.length; i += 2) {
850
+ bytes[i / 2] = parseInt(clean.slice(i, i + 2), 16);
851
+ }
852
+ return bytes;
853
+ }
854
+
855
+ // src/fragments/accountPage.ts
856
+ function getAccountPageFragment(node, scope) {
857
+ const name = node.name;
858
+ const typeName = scope.nameApi.dataType(name);
859
+ const dataNode = resolveNestedTypeNode(node.data);
860
+ const fields = dataNode.fields;
861
+ const fieldManifests = fields.map((f) => ({
862
+ field: f,
863
+ manifest: visit(f.type, scope.typeManifestVisitor)
864
+ }));
865
+ const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
866
+ return ` final ${manifest.type.content} ${camelCase(f.name)};`;
867
+ }).join("\n");
868
+ const ctorParams = fields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
869
+ const eqChecks = fields.length === 0 ? "true" : fields.map(
870
+ (f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`
871
+ ).join(" &&\n ");
872
+ const hashFields = fields.map((f) => camelCase(f.name)).join(", ");
873
+ const toStringFields = fields.map(
874
+ (f) => `${camelCase(f.name)}: $${camelCase(f.name)}`
875
+ ).join(", ");
876
+ const encFields = fieldManifests.map(({ field: f, manifest }) => {
877
+ return ` ('${f.name}', ${manifest.encoder.content}),`;
878
+ }).join("\n");
879
+ const decFields = fieldManifests.map(({ field: f, manifest }) => {
880
+ return ` ('${f.name}', ${manifest.decoder.content}),`;
881
+ }).join("\n");
882
+ const toMapFields = fields.map(
883
+ (f) => ` '${f.name}': value.${camelCase(f.name)},`
884
+ ).join("\n");
885
+ const fromMapFields = fieldManifests.map(({ field: f, manifest }) => {
886
+ const typeStr = manifest.type.content;
887
+ const isNullable = typeStr.endsWith("?");
888
+ const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
889
+ return ` ${camelCase(f.name)}: ${accessor} as ${typeStr},`;
890
+ }).join("\n");
891
+ const encoderName = scope.nameApi.encoderFunction(name);
892
+ const decoderName = scope.nameApi.decoderFunction(name);
893
+ const codecName = scope.nameApi.codecFunction(name);
894
+ const decodeFnName = scope.nameApi.accountDecodeFunction(name);
895
+ const sizeFragment = node.size != null ? fragment`
896
+ /// The size of the [${fragmentFromString(typeName)}] account data in bytes.
897
+ const int ${fragmentFromString(scope.nameApi.accountSizeConstant(name))} = ${fragmentFromString(String(node.size))};` : emptyFragment();
898
+ const discFragment = getDiscriminatorConstantsFragment(node, scope);
899
+ const parts = [
900
+ fragment`// Auto-generated. Do not edit.
901
+ // ignore_for_file: type=lint
902
+
903
+ ${use("Uint8List", "dartTypedData")}
904
+ ${use("immutable", "meta")}
905
+ ${use("Encoder", "solanaCodecsCore")}
906
+ ${use("Decoder", "solanaCodecsCore")}
907
+ ${use("Codec", "solanaCodecsCore")}
908
+ ${use("combineCodec", "solanaCodecsCore")}
909
+ ${use("transformEncoder", "solanaCodecsCore")}
910
+ ${use("transformDecoder", "solanaCodecsCore")}
911
+ ${use("getStructEncoder", "solanaCodecsDataStructures")}
912
+ ${use("getStructDecoder", "solanaCodecsDataStructures")}
913
+ ${use("Account", "solanaAccounts")}
914
+ ${use("EncodedAccount", "solanaAccounts")}
915
+ ${use("decodeAccount", "solanaAccounts")}
916
+
917
+ @immutable
918
+ class ${fragmentFromString(typeName)} {
919
+ const ${fragmentFromString(typeName)}({
920
+ ${fragmentFromString(ctorParams)}
921
+ });
922
+
923
+ ${fragmentFromString(fieldDecls)}
924
+
925
+ @override
926
+ bool operator ==(Object other) =>
927
+ identical(this, other) ||
928
+ other is ${fragmentFromString(typeName)} &&
929
+ runtimeType == other.runtimeType &&
930
+ ${fragmentFromString(eqChecks)};
931
+
932
+ @override
933
+ int get hashCode => Object.hash(${fragmentFromString(hashFields)});
934
+
935
+ @override
936
+ String toString() => '${fragmentFromString(typeName)}(${fragmentFromString(toStringFields)})';
937
+ }`
938
+ ];
939
+ if (sizeFragment.content) parts.push(sizeFragment);
940
+ if (discFragment.content) parts.push(discFragment);
941
+ parts.push(fragment`
942
+ Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
943
+ final structEncoder = getStructEncoder(<(String, Encoder<Object?>)>[
944
+ ${fragmentFromString(encFields)}
945
+ ]);
946
+
947
+ return transformEncoder(
948
+ structEncoder,
949
+ (${fragmentFromString(typeName)} value) => <String, Object?>{
950
+ ${fragmentFromString(toMapFields)}
951
+ },
952
+ );
953
+ }
954
+
955
+ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
956
+ final structDecoder = getStructDecoder(<(String, Decoder<Object?>)>[
957
+ ${fragmentFromString(decFields)}
958
+ ]);
959
+
960
+ return transformDecoder(
961
+ structDecoder,
962
+ (Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}(
963
+ ${fragmentFromString(fromMapFields)}
964
+ ),
965
+ );
966
+ }
967
+
968
+ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
969
+ return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
970
+ }
971
+
972
+ Account<${fragmentFromString(typeName)}> ${fragmentFromString(decodeFnName)}(EncodedAccount encodedAccount) {
973
+ return decodeAccount(encodedAccount, ${fragmentFromString(decoderName)}());
974
+ }`);
975
+ const result = mergeFragments(parts, (cs) => cs.join("\n\n"));
976
+ for (const { manifest } of fieldManifests) {
977
+ result.imports.mergeWith(manifest.encoder.imports);
978
+ result.imports.mergeWith(manifest.decoder.imports);
979
+ result.imports.mergeWith(manifest.type.imports);
980
+ }
981
+ return result;
982
+ }
983
+
984
+ // src/fragments/errorPage.ts
985
+ function getErrorPageFragment(programNode, scope) {
986
+ const errors = programNode.errors ?? [];
987
+ if (errors.length === 0) return emptyFragment();
988
+ const programName = programNode.name;
989
+ const errorConstants = errors.map((err) => {
990
+ const constName = scope.nameApi.errorConstant(
991
+ programName,
992
+ err.name
993
+ );
994
+ const hexCode = `0x${err.code.toString(16)}`;
995
+ const docs = err.docs?.length ? err.docs.map((d) => `/// ${d}`).join("\n") + "\n" : "";
996
+ const message = err.message ? `/// Message: "${err.message}"
997
+ ` : "";
998
+ return `${docs}${message}const int ${constName} = ${hexCode}; // ${err.code}`;
999
+ }).join("\n\n");
1000
+ const messageEntries = errors.map((err) => {
1001
+ const constName = scope.nameApi.errorConstant(
1002
+ programName,
1003
+ err.name
1004
+ );
1005
+ const message = err.message ?? err.name;
1006
+ return ` ${constName}: '${escapeString(message)}',`;
1007
+ }).join("\n");
1008
+ const errorMessageFnName = scope.nameApi.errorMessageFunction(programName);
1009
+ const isErrorFnName = `is${pascalCase(programName)}Error`;
1010
+ return fragment`// Auto-generated. Do not edit.
1011
+ // ignore_for_file: type=lint, constant_identifier_names
1012
+
1013
+ /// Error codes for the ${fragmentFromString(pascalCase(programName))} program.
1014
+
1015
+ ${fragmentFromString(errorConstants)}
1016
+
1017
+ /// Map of error codes to human-readable messages.
1018
+ const Map<int, String> _${fragmentFromString(camelCase(programName))}ErrorMessages = {
1019
+ ${fragmentFromString(messageEntries)}
1020
+ };
1021
+
1022
+ /// Get the error message for a ${fragmentFromString(pascalCase(programName))} program error code.
1023
+ String? ${fragmentFromString(errorMessageFnName)}(int code) {
1024
+ return _${fragmentFromString(camelCase(programName))}ErrorMessages[code];
1025
+ }
1026
+
1027
+ /// Check if an error code belongs to the ${fragmentFromString(pascalCase(programName))} program.
1028
+ bool ${fragmentFromString(isErrorFnName)}(int code) {
1029
+ return _${fragmentFromString(camelCase(programName))}ErrorMessages.containsKey(code);
1030
+ }`;
1031
+ }
1032
+ function escapeString(str) {
1033
+ return str.replace(/'/g, "\\'").replace(/\n/g, "\\n");
1034
+ }
1035
+
1036
+ // src/fragments/indexPage.ts
1037
+ function getIndexPageFragment(fileNames, relativePath = "") {
1038
+ if (fileNames.length === 0) {
1039
+ return fragmentFromString(
1040
+ "// Auto-generated. Do not edit.\n// ignore_for_file: type=lint\n"
1041
+ );
1042
+ }
1043
+ const exports$1 = fileNames.sort().map((f) => {
1044
+ const path = relativePath ? `${relativePath}/${f}` : f;
1045
+ return `export '${path}';`;
1046
+ }).join("\n");
1047
+ return fragmentFromString(
1048
+ `// Auto-generated. Do not edit.
1049
+ // ignore_for_file: type=lint
1050
+
1051
+ ${exports$1}
1052
+ `
1053
+ );
1054
+ }
1055
+ function getRootIndexPageFragment(categories) {
1056
+ const exports$1 = categories.sort().map((cat) => `export '${cat}/${cat}.dart';`).join("\n");
1057
+ return fragmentFromString(
1058
+ `// Auto-generated. Do not edit.
1059
+ // ignore_for_file: type=lint
1060
+
1061
+ ${exports$1}
1062
+ `
1063
+ );
1064
+ }
1065
+ function getInstructionPageFragment(node, scope) {
1066
+ const name = node.name;
1067
+ const typeName = scope.nameApi.dataType(name);
1068
+ const instrFnName = scope.nameApi.instructionFunction(name);
1069
+ const parseFnName = scope.nameApi.instructionParseFunction(name);
1070
+ const accounts = node.accounts ?? [];
1071
+ const args = (node.arguments ?? []).filter(
1072
+ (arg) => !isDiscriminatorArg(arg, node)
1073
+ );
1074
+ const allArgs = node.arguments ?? [];
1075
+ const dataClassName = `${typeName}InstructionData`;
1076
+ const allArgManifests = allArgs.map((arg) => ({
1077
+ arg,
1078
+ manifest: visit(arg.type, scope.typeManifestVisitor)
1079
+ }));
1080
+ const dataFieldDecls = allArgManifests.map(({ arg, manifest }) => {
1081
+ const fieldName = camelCase(arg.name);
1082
+ return ` final ${manifest.type.content} ${fieldName};`;
1083
+ }).join("\n");
1084
+ const dataCtorParams = allArgManifests.map(({ arg }) => {
1085
+ const fieldName = camelCase(arg.name);
1086
+ if (isDiscriminatorArg(arg, node)) {
1087
+ return ` this.${fieldName} = ${getDiscriminatorDefault(arg)},`;
1088
+ }
1089
+ return ` required this.${fieldName},`;
1090
+ }).join("\n");
1091
+ const encFields = allArgManifests.map(({ arg, manifest }) => {
1092
+ return ` ('${arg.name}', ${manifest.encoder.content}),`;
1093
+ }).join("\n");
1094
+ const decFields = allArgManifests.map(({ arg, manifest }) => {
1095
+ return ` ('${arg.name}', ${manifest.decoder.content}),`;
1096
+ }).join("\n");
1097
+ const toMapFields = allArgs.map(
1098
+ (arg) => ` '${arg.name}': value.${camelCase(arg.name)},`
1099
+ ).join("\n");
1100
+ const fromMapFields = allArgManifests.map(({ arg, manifest }) => {
1101
+ const typeStr = manifest.type.content;
1102
+ const isNullable = typeStr.endsWith("?");
1103
+ const accessor = isNullable ? `map['${arg.name}']` : `map['${arg.name}']!`;
1104
+ return ` ${camelCase(arg.name)}: ${accessor} as ${typeStr},`;
1105
+ }).join("\n");
1106
+ const dataEncoderName = `get${typeName}InstructionDataEncoder`;
1107
+ const dataDecoderName = `get${typeName}InstructionDataDecoder`;
1108
+ const dataCodecName = `get${typeName}InstructionDataCodec`;
1109
+ const accountParams = accounts.map((acc) => {
1110
+ const fieldName = camelCase(acc.name);
1111
+ const isRequired = !(acc.isOptional ?? false);
1112
+ return isRequired ? ` required Address ${fieldName},` : ` Address? ${fieldName},`;
1113
+ }).join("\n");
1114
+ const argManifestMap = new Map(allArgManifests.map(({ arg, manifest }) => [arg, manifest]));
1115
+ const argParams = args.map((arg) => {
1116
+ const manifest = argManifestMap.get(arg);
1117
+ const fieldName = camelCase(arg.name);
1118
+ const hasDefault = arg.defaultValue != null;
1119
+ if (hasDefault) {
1120
+ return ` ${manifest.type.content}? ${fieldName},`;
1121
+ }
1122
+ return ` required ${manifest.type.content} ${fieldName},`;
1123
+ }).join("\n");
1124
+ const accountMetas = accounts.map((acc) => {
1125
+ const fieldName = camelCase(acc.name);
1126
+ const role = getAccountRole(acc);
1127
+ const isOptional = acc.isOptional ?? false;
1128
+ if (isOptional) {
1129
+ return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}),`;
1130
+ }
1131
+ return ` AccountMeta(address: ${fieldName}, role: ${role}),`;
1132
+ }).join("\n");
1133
+ const dataConstruction = allArgs.map((arg) => {
1134
+ const fieldName = camelCase(arg.name);
1135
+ if (isDiscriminatorArg(arg, node)) {
1136
+ return "";
1137
+ }
1138
+ return ` ${fieldName}: ${fieldName}${arg.defaultValue != null ? ` ?? ${getDefaultValue(arg)}` : ""},`;
1139
+ }).filter(Boolean).join("\n");
1140
+ const discFragment = getDiscriminatorConstantsFragment(node, scope);
1141
+ const parts = [
1142
+ fragment`// Auto-generated. Do not edit.
1143
+ // ignore_for_file: type=lint
1144
+
1145
+ ${use("Uint8List", "dartTypedData")}
1146
+ ${use("immutable", "meta")}
1147
+ ${use("Encoder", "solanaCodecsCore")}
1148
+ ${use("Decoder", "solanaCodecsCore")}
1149
+ ${use("Codec", "solanaCodecsCore")}
1150
+ ${use("combineCodec", "solanaCodecsCore")}
1151
+ ${use("transformEncoder", "solanaCodecsCore")}
1152
+ ${use("transformDecoder", "solanaCodecsCore")}
1153
+ ${use("getStructEncoder", "solanaCodecsDataStructures")}
1154
+ ${use("getStructDecoder", "solanaCodecsDataStructures")}
1155
+ ${use("Address", "solanaAddresses")}
1156
+ ${use("Instruction", "solanaInstructions")}
1157
+ ${use("AccountMeta", "solanaInstructions")}
1158
+ ${use("AccountRole", "solanaInstructions")}`
1159
+ ];
1160
+ if (discFragment.content) parts.push(discFragment);
1161
+ parts.push(fragment`
1162
+ @immutable
1163
+ class ${fragmentFromString(dataClassName)} {
1164
+ const ${fragmentFromString(dataClassName)}({
1165
+ ${fragmentFromString(dataCtorParams)}
1166
+ });
1167
+
1168
+ ${fragmentFromString(dataFieldDecls)}
1169
+ }`);
1170
+ parts.push(fragment`
1171
+ Encoder<${fragmentFromString(dataClassName)}> ${fragmentFromString(dataEncoderName)}() {
1172
+ final structEncoder = getStructEncoder(<(String, Encoder<Object?>)>[
1173
+ ${fragmentFromString(encFields)}
1174
+ ]);
1175
+
1176
+ return transformEncoder(
1177
+ structEncoder,
1178
+ (${fragmentFromString(dataClassName)} value) => <String, Object?>{
1179
+ ${fragmentFromString(toMapFields)}
1180
+ },
1181
+ );
1182
+ }
1183
+
1184
+ Decoder<${fragmentFromString(dataClassName)}> ${fragmentFromString(dataDecoderName)}() {
1185
+ final structDecoder = getStructDecoder(<(String, Decoder<Object?>)>[
1186
+ ${fragmentFromString(decFields)}
1187
+ ]);
1188
+
1189
+ return transformDecoder(
1190
+ structDecoder,
1191
+ (Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(dataClassName)}(
1192
+ ${fragmentFromString(fromMapFields)}
1193
+ ),
1194
+ );
1195
+ }
1196
+
1197
+ Codec<${fragmentFromString(dataClassName)}, ${fragmentFromString(dataClassName)}> ${fragmentFromString(dataCodecName)}() {
1198
+ return combineCodec(${fragmentFromString(dataEncoderName)}(), ${fragmentFromString(dataDecoderName)}());
1199
+ }`);
1200
+ parts.push(fragment`
1201
+ /// Creates a [${fragmentFromString(typeName)}] instruction.
1202
+ Instruction ${fragmentFromString(instrFnName)}({
1203
+ required Address programAddress,
1204
+ ${fragmentFromString(accountParams)}
1205
+ ${fragmentFromString(argParams)}
1206
+ }) {
1207
+ final data = ${fragmentFromString(dataClassName)}(
1208
+ ${fragmentFromString(dataConstruction)}
1209
+ );
1210
+
1211
+ return Instruction(
1212
+ programAddress: programAddress,
1213
+ accounts: [
1214
+ ${fragmentFromString(accountMetas)}
1215
+ ],
1216
+ data: ${fragmentFromString(dataEncoderName)}().encode(data),
1217
+ );
1218
+ }`);
1219
+ parts.push(fragment`
1220
+ /// Parses a [${fragmentFromString(typeName)}] instruction from raw instruction data.
1221
+ ${fragmentFromString(dataClassName)} ${fragmentFromString(parseFnName)}(Instruction instruction) {
1222
+ return ${fragmentFromString(dataDecoderName)}().decode(instruction.data!);
1223
+ }`);
1224
+ const result = mergeFragments(parts, (cs) => cs.join("\n"));
1225
+ for (const { manifest } of allArgManifests) {
1226
+ result.imports.mergeWith(manifest.encoder.imports);
1227
+ result.imports.mergeWith(manifest.decoder.imports);
1228
+ result.imports.mergeWith(manifest.type.imports);
1229
+ }
1230
+ return result;
1231
+ }
1232
+ function getAccountRole(acc) {
1233
+ const isSigner = acc.isSigner === true || acc.isSigner === "either";
1234
+ const isWritable = acc.isWritable ?? false;
1235
+ if (isSigner && isWritable) return "AccountRole.writableSigner";
1236
+ if (isSigner) return "AccountRole.readonlySigner";
1237
+ if (isWritable) return "AccountRole.writable";
1238
+ return "AccountRole.readonly";
1239
+ }
1240
+ function isDiscriminatorArg(arg, node) {
1241
+ const discriminators = node.discriminators ?? [];
1242
+ return discriminators.some(
1243
+ (d) => d.kind === "fieldDiscriminatorNode" && d.name === arg.name
1244
+ );
1245
+ }
1246
+ function getDiscriminatorDefault(arg, _node) {
1247
+ if (arg.defaultValue) {
1248
+ if (arg.defaultValue.kind === "numberValueNode") {
1249
+ return String(arg.defaultValue.number);
1250
+ }
1251
+ }
1252
+ return "0";
1253
+ }
1254
+ function getDefaultValue(arg) {
1255
+ if (!arg.defaultValue) return "null";
1256
+ const dv = arg.defaultValue;
1257
+ switch (dv.kind) {
1258
+ case "numberValueNode":
1259
+ return String(dv.number);
1260
+ case "booleanValueNode":
1261
+ return String(dv.boolean);
1262
+ case "stringValueNode":
1263
+ return `'${dv.string}'`;
1264
+ case "publicKeyValueNode":
1265
+ return `Address('${dv.publicKey}')`;
1266
+ case "noneValueNode":
1267
+ return "null";
1268
+ default:
1269
+ return "null";
1270
+ }
1271
+ }
1272
+ function getPdaPageFragment(node, scope) {
1273
+ const name = node.name;
1274
+ const findFnName = scope.nameApi.pdaFindFunction(name);
1275
+ const seedsClassName = `${pascalCase(name)}Seeds`;
1276
+ const seeds = node.seeds ?? [];
1277
+ const variableSeeds = seeds.filter(
1278
+ (s) => s.kind === "variablePdaSeedNode"
1279
+ );
1280
+ seeds.filter(
1281
+ (s) => s.kind === "constantPdaSeedNode"
1282
+ );
1283
+ const hasSeedsClass = variableSeeds.length > 0;
1284
+ const seedFieldDecls = variableSeeds.map((s) => {
1285
+ if (s.kind !== "variablePdaSeedNode") return "";
1286
+ const manifest = visit(s.type, scope.typeManifestVisitor);
1287
+ return ` final ${manifest.type.content} ${camelCase(s.name)};`;
1288
+ }).join("\n");
1289
+ const seedCtorParams = variableSeeds.map((s) => {
1290
+ if (s.kind !== "variablePdaSeedNode") return "";
1291
+ return ` required this.${camelCase(s.name)},`;
1292
+ }).join("\n");
1293
+ const seedBytesList = [];
1294
+ for (const seed of seeds) {
1295
+ if (seed.kind === "constantPdaSeedNode") {
1296
+ if (seed.value.kind === "bytesValueNode") {
1297
+ seedBytesList.push(` ...${bytesValueToDart(seed.value.data)},`);
1298
+ } else if (seed.value.kind === "stringValueNode") {
1299
+ seedBytesList.push(` ...utf8.encode('${seed.value.string}'),`);
1300
+ } else if (seed.value.kind === "publicKeyValueNode") {
1301
+ seedBytesList.push(` ...getAddressEncoder().encode(Address('${seed.value.publicKey}')),`);
1302
+ } else if (seed.value.kind === "numberValueNode") {
1303
+ const manifest = visit(seed.type, scope.typeManifestVisitor);
1304
+ seedBytesList.push(` ...${manifest.encoder.content}.encode(${seed.value.number}),`);
1305
+ }
1306
+ } else if (seed.kind === "variablePdaSeedNode") {
1307
+ const manifest = visit(seed.type, scope.typeManifestVisitor);
1308
+ seedBytesList.push(
1309
+ ` ...${manifest.encoder.content}.encode(seeds.${camelCase(seed.name)}),`
1310
+ );
1311
+ }
1312
+ }
1313
+ const programIdParam = node.programId ? `Address programAddress = const Address('${node.programId}')` : "required Address programAddress";
1314
+ const parts = [
1315
+ fragment`// Auto-generated. Do not edit.
1316
+ // ignore_for_file: type=lint
1317
+
1318
+ ${use("Uint8List", "dartTypedData")}
1319
+ ${use("immutable", "meta")}
1320
+ ${use("Address", "solanaAddresses")}
1321
+ ${use("getAddressEncoder", "solanaAddresses")}`
1322
+ ];
1323
+ if (hasSeedsClass) {
1324
+ parts.push(fragment`
1325
+ @immutable
1326
+ class ${fragmentFromString(seedsClassName)} {
1327
+ const ${fragmentFromString(seedsClassName)}({
1328
+ ${fragmentFromString(seedCtorParams)}
1329
+ });
1330
+
1331
+ ${fragmentFromString(seedFieldDecls)}
1332
+ }`);
1333
+ }
1334
+ const seedsParam = hasSeedsClass ? ` required ${seedsClassName} seeds,` : "";
1335
+ parts.push(fragment`
1336
+ /// Finds the program derived address for [${fragmentFromString(pascalCase(name))}].
1337
+ Future<(Address, int)> ${fragmentFromString(findFnName)}({
1338
+ ${fragmentFromString(seedsParam)}
1339
+ ${fragmentFromString(programIdParam)},
1340
+ }) async {
1341
+ final seedBytes = <int>[
1342
+ ${fragmentFromString(seedBytesList.join("\n"))}
1343
+ ];
1344
+
1345
+ // TODO: Call getProgramDerivedAddress with seedBytes and programAddress
1346
+ throw UnimplementedError('PDA derivation not yet implemented');
1347
+ }`);
1348
+ return mergeFragments(parts, (cs) => cs.join("\n"));
1349
+ }
1350
+ function bytesValueToDart(hex) {
1351
+ const clean = hex.replace(/^0x/, "");
1352
+ const pairs = [];
1353
+ for (let i = 0; i < clean.length; i += 2) {
1354
+ pairs.push(`0x${clean.slice(i, i + 2)}`);
1355
+ }
1356
+ return `[${pairs.join(", ")}]`;
1357
+ }
1358
+
1359
+ // src/fragments/programPage.ts
1360
+ function getProgramPageFragment(node, scope) {
1361
+ const name = node.name;
1362
+ const addressConstName = scope.nameApi.programAddressConstant(name);
1363
+ const parts = [
1364
+ fragment`// Auto-generated. Do not edit.
1365
+ // ignore_for_file: type=lint
1366
+
1367
+ ${use("Address", "solanaAddresses")}
1368
+
1369
+ /// The address of the ${fragmentFromString(pascalCase(name))} program.
1370
+ const ${fragmentFromString(addressConstName)} = Address('${fragmentFromString(node.publicKey)}');`
1371
+ ];
1372
+ const accounts = node.accounts ?? [];
1373
+ if (accounts.length > 0) {
1374
+ const accountVariants = accounts.map((acc) => ` ${camelCase(acc.name)},`).join("\n");
1375
+ parts.push(fragment`
1376
+ /// Known accounts for the ${fragmentFromString(pascalCase(name))} program.
1377
+ enum ${fragmentFromString(pascalCase(name))}Account {
1378
+ ${fragmentFromString(accountVariants)}
1379
+ }`);
1380
+ }
1381
+ const instructions = node.instructions ?? [];
1382
+ if (instructions.length > 0) {
1383
+ const instrVariants = instructions.map((instr) => ` ${camelCase(instr.name)},`).join("\n");
1384
+ parts.push(fragment`
1385
+ /// Known instructions for the ${fragmentFromString(pascalCase(name))} program.
1386
+ enum ${fragmentFromString(pascalCase(name))}Instruction {
1387
+ ${fragmentFromString(instrVariants)}
1388
+ }`);
1389
+ }
1390
+ return mergeFragments(parts, (cs) => cs.join("\n"));
1391
+ }
1392
+ function getTypePageFragment(node, scope) {
1393
+ const name = node.name;
1394
+ scope.nameApi.dataType(name);
1395
+ const typeNode = node.type;
1396
+ if (typeNode.kind === "enumTypeNode") {
1397
+ const isScalar = typeNode.variants.every(
1398
+ (v) => v.kind === "enumEmptyVariantTypeNode"
1399
+ );
1400
+ if (isScalar) {
1401
+ return getScalarEnumPageFragment(node, scope);
1402
+ }
1403
+ return getDataEnumPageFragment(node, scope);
1404
+ }
1405
+ if (typeNode.kind === "structTypeNode") {
1406
+ return getStructPageFragment(node, scope);
1407
+ }
1408
+ return getTypeAliasPageFragment(node, scope);
1409
+ }
1410
+ function getScalarEnumPageFragment(node, scope) {
1411
+ const name = node.name;
1412
+ const typeName = scope.nameApi.dataType(name);
1413
+ const enumNode = node.type;
1414
+ if (enumNode.kind !== "enumTypeNode") return emptyFragment();
1415
+ const variants = enumNode.variants.map((v) => {
1416
+ const variantName = scope.nameApi.enumVariant(v.name);
1417
+ return variantName;
1418
+ });
1419
+ const variantLines = variants.map((v) => ` ${v},`).join("\n");
1420
+ const encoderName = scope.nameApi.encoderFunction(name);
1421
+ const decoderName = scope.nameApi.decoderFunction(name);
1422
+ const codecName = scope.nameApi.codecFunction(name);
1423
+ const resolvedSize = resolveNestedTypeNode(enumNode.size);
1424
+ const sizeType = resolvedSize.format ?? "u8";
1425
+ const sizeCodecName = getNumberCodecName2(sizeType);
1426
+ return fragment`// Auto-generated. Do not edit.
1427
+ // ignore_for_file: type=lint
1428
+
1429
+ ${use("Uint8List", "dartTypedData")}
1430
+ ${use("Encoder", "solanaCodecsCore")}
1431
+ ${use("Decoder", "solanaCodecsCore")}
1432
+ ${use("Codec", "solanaCodecsCore")}
1433
+ ${use("combineCodec", "solanaCodecsCore")}
1434
+ ${use("transformEncoder", "solanaCodecsCore")}
1435
+ ${use("transformDecoder", "solanaCodecsCore")}
1436
+ ${use(`get${sizeCodecName}Encoder`, "solanaCodecsNumbers")}
1437
+ ${use(`get${sizeCodecName}Decoder`, "solanaCodecsNumbers")}
1438
+
1439
+ enum ${fragmentFromString(typeName)} {
1440
+ ${fragmentFromString(variantLines)}
1441
+ }
1442
+
1443
+ Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
1444
+ return transformEncoder(
1445
+ get${fragmentFromString(sizeCodecName)}Encoder(),
1446
+ (${fragmentFromString(typeName)} value) => value.index,
1447
+ );
1448
+ }
1449
+
1450
+ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
1451
+ return transformDecoder(
1452
+ get${fragmentFromString(sizeCodecName)}Decoder(),
1453
+ (int value, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}.values[value],
1454
+ );
1455
+ }
1456
+
1457
+ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
1458
+ return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
1459
+ }`;
1460
+ }
1461
+ function getDataEnumPageFragment(node, scope) {
1462
+ const name = node.name;
1463
+ const typeName = scope.nameApi.dataType(name);
1464
+ const enumNode = node.type;
1465
+ if (enumNode.kind !== "enumTypeNode") return emptyFragment();
1466
+ const variantClasses = [];
1467
+ const encoderVariants = [];
1468
+ const decoderVariants = [];
1469
+ const allVariantManifests = [];
1470
+ for (let i = 0; i < enumNode.variants.length; i++) {
1471
+ const variant = enumNode.variants[i];
1472
+ const variantClassName = scope.nameApi.sealedClassVariant(
1473
+ name,
1474
+ variant.name
1475
+ );
1476
+ if (variant.kind === "enumEmptyVariantTypeNode") {
1477
+ variantClasses.push(`final class ${variantClassName} extends ${typeName} {
1478
+ const ${variantClassName}();
1479
+
1480
+ @override
1481
+ bool operator ==(Object other) =>
1482
+ identical(this, other) || other is ${variantClassName};
1483
+
1484
+ @override
1485
+ int get hashCode => runtimeType.hashCode;
1486
+
1487
+ @override
1488
+ String toString() => '${typeName}.${variantClassName}()';
1489
+ }`);
1490
+ encoderVariants.push(
1491
+ `(${i}, getStructEncoder(<(String, Encoder<Object?>)>[]))`
1492
+ );
1493
+ decoderVariants.push(
1494
+ `(${i}, getStructDecoder(<(String, Decoder<Object?>)>[]).map((_) => const ${variantClassName}()))`
1495
+ );
1496
+ } else if (variant.kind === "enumStructVariantTypeNode") {
1497
+ const resolvedStruct = resolveNestedTypeNode(variant.struct);
1498
+ const fields = resolvedStruct.fields;
1499
+ const fieldManifests = fields.map((f) => ({
1500
+ field: f,
1501
+ manifest: visit(f.type, scope.typeManifestVisitor)
1502
+ }));
1503
+ for (const { manifest } of fieldManifests) {
1504
+ allVariantManifests.push(manifest);
1505
+ }
1506
+ const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
1507
+ return ` final ${manifest.type.content} ${camelCase(f.name)};`;
1508
+ }).join("\n");
1509
+ const ctorParams = fields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
1510
+ const eqChecks = fields.map((f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`).join(" &&\n ");
1511
+ const hashFields = fields.map((f) => camelCase(f.name)).join(", ");
1512
+ const toStringFields = fields.map((f) => `${camelCase(f.name)}: $${camelCase(f.name)}`).join(", ");
1513
+ variantClasses.push(`final class ${variantClassName} extends ${typeName} {
1514
+ const ${variantClassName}({
1515
+ ${ctorParams}
1516
+ });
1517
+
1518
+ ${fieldDecls}
1519
+
1520
+ @override
1521
+ bool operator ==(Object other) =>
1522
+ identical(this, other) ||
1523
+ other is ${variantClassName} &&
1524
+ ${eqChecks};
1525
+
1526
+ @override
1527
+ int get hashCode => Object.hash(${hashFields});
1528
+
1529
+ @override
1530
+ String toString() => '${typeName}.${variantClassName}(${toStringFields})';
1531
+ }`);
1532
+ const encFields = fieldManifests.map(({ field: f, manifest }) => {
1533
+ return `('${f.name}', ${manifest.encoder.content})`;
1534
+ }).join(", ");
1535
+ const decFields = fieldManifests.map(({ field: f, manifest }) => {
1536
+ return `('${f.name}', ${manifest.decoder.content})`;
1537
+ }).join(", ");
1538
+ const fromMapFields = fieldManifests.map(
1539
+ ({ field: f, manifest }) => {
1540
+ const typeStr = manifest.type.content;
1541
+ const isNullable = typeStr.endsWith("?");
1542
+ const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
1543
+ return `${camelCase(f.name)}: ${accessor} as ${typeStr}`;
1544
+ }
1545
+ ).join(", ");
1546
+ const toMapFields = fields.map(
1547
+ (f) => `'${f.name}': value.${camelCase(f.name)}`
1548
+ ).join(", ");
1549
+ encoderVariants.push(
1550
+ `(${i}, transformEncoder(getStructEncoder([${encFields}]), (${variantClassName} value) => <String, Object?>{${toMapFields}}))`
1551
+ );
1552
+ decoderVariants.push(
1553
+ `(${i}, transformDecoder(getStructDecoder([${decFields}]), (Map<String, Object?> map, Uint8List bytes, int offset) => ${variantClassName}(${fromMapFields})))`
1554
+ );
1555
+ } else if (variant.kind === "enumTupleVariantTypeNode") {
1556
+ const resolvedTuple = resolveNestedTypeNode(variant.tuple);
1557
+ const items = resolvedTuple.items;
1558
+ if (items.length === 1) {
1559
+ const manifest = visit(items[0], scope.typeManifestVisitor);
1560
+ allVariantManifests.push(manifest);
1561
+ variantClasses.push(`final class ${variantClassName} extends ${typeName} {
1562
+ const ${variantClassName}(this.value);
1563
+
1564
+ final ${manifest.type.content} value;
1565
+
1566
+ @override
1567
+ bool operator ==(Object other) =>
1568
+ identical(this, other) ||
1569
+ other is ${variantClassName} && value == other.value;
1570
+
1571
+ @override
1572
+ int get hashCode => value.hashCode;
1573
+
1574
+ @override
1575
+ String toString() => '${typeName}.${variantClassName}($value)';
1576
+ }`);
1577
+ encoderVariants.push(
1578
+ `(${i}, transformEncoder(${manifest.encoder.content}, (${variantClassName} value) => value.value))`
1579
+ );
1580
+ decoderVariants.push(
1581
+ `(${i}, transformDecoder(${manifest.decoder.content}, (${manifest.type.content} value, Uint8List bytes, int offset) => ${variantClassName}(value)))`
1582
+ );
1583
+ }
1584
+ }
1585
+ }
1586
+ const encoderName = scope.nameApi.encoderFunction(name);
1587
+ const decoderName = scope.nameApi.decoderFunction(name);
1588
+ const codecName = scope.nameApi.codecFunction(name);
1589
+ const resolvedSize = resolveNestedTypeNode(enumNode.size);
1590
+ const sizeType = resolvedSize.format ?? "u8";
1591
+ const sizeCodecName = getNumberCodecName2(sizeType);
1592
+ const result = fragment`// Auto-generated. Do not edit.
1593
+ // ignore_for_file: type=lint
1594
+
1595
+ ${use("Uint8List", "dartTypedData")}
1596
+ ${use("immutable", "meta")}
1597
+ ${use("Encoder", "solanaCodecsCore")}
1598
+ ${use("Decoder", "solanaCodecsCore")}
1599
+ ${use("Codec", "solanaCodecsCore")}
1600
+ ${use("combineCodec", "solanaCodecsCore")}
1601
+ ${use("transformEncoder", "solanaCodecsCore")}
1602
+ ${use("transformDecoder", "solanaCodecsCore")}
1603
+ ${use("getStructEncoder", "solanaCodecsDataStructures")}
1604
+ ${use("getStructDecoder", "solanaCodecsDataStructures")}
1605
+ ${use("getDiscriminatedUnionEncoder", "solanaCodecsDataStructures")}
1606
+ ${use("getDiscriminatedUnionDecoder", "solanaCodecsDataStructures")}
1607
+ ${use(`get${sizeCodecName}Encoder`, "solanaCodecsNumbers")}
1608
+ ${use(`get${sizeCodecName}Decoder`, "solanaCodecsNumbers")}
1609
+
1610
+ sealed class ${fragmentFromString(typeName)} {
1611
+ const ${fragmentFromString(typeName)}();
1612
+ }
1613
+
1614
+ ${fragmentFromString(variantClasses.join("\n\n"))}
1615
+
1616
+ Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
1617
+ return getDiscriminatedUnionEncoder([
1618
+ ${fragmentFromString(encoderVariants.join(",\n "))},
1619
+ ], size: get${fragmentFromString(sizeCodecName)}Encoder());
1620
+ }
1621
+
1622
+ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
1623
+ return getDiscriminatedUnionDecoder([
1624
+ ${fragmentFromString(decoderVariants.join(",\n "))},
1625
+ ], size: get${fragmentFromString(sizeCodecName)}Decoder());
1626
+ }
1627
+
1628
+ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
1629
+ return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
1630
+ }`;
1631
+ for (const manifest of allVariantManifests) {
1632
+ result.imports.mergeWith(manifest.encoder.imports);
1633
+ result.imports.mergeWith(manifest.decoder.imports);
1634
+ result.imports.mergeWith(manifest.type.imports);
1635
+ }
1636
+ return result;
1637
+ }
1638
+ function getStructPageFragment(node, scope) {
1639
+ const name = node.name;
1640
+ const typeName = scope.nameApi.dataType(name);
1641
+ const structNode = node.type;
1642
+ if (structNode.kind !== "structTypeNode") return emptyFragment();
1643
+ const fields = structNode.fields;
1644
+ const fieldManifests = fields.map((f) => ({
1645
+ field: f,
1646
+ manifest: visit(f.type, scope.typeManifestVisitor)
1647
+ }));
1648
+ const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
1649
+ return ` final ${manifest.type.content} ${camelCase(f.name)};`;
1650
+ }).join("\n");
1651
+ const ctorParams = fields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
1652
+ const eqChecks = fields.length === 0 ? "true" : fields.map(
1653
+ (f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`
1654
+ ).join(" &&\n ");
1655
+ const hashFields = fields.map((f) => camelCase(f.name)).join(", ");
1656
+ const toStringFields = fields.map(
1657
+ (f) => `${camelCase(f.name)}: $${camelCase(f.name)}`
1658
+ ).join(", ");
1659
+ const encoderName = scope.nameApi.encoderFunction(name);
1660
+ const decoderName = scope.nameApi.decoderFunction(name);
1661
+ const codecName = scope.nameApi.codecFunction(name);
1662
+ const encFields = fieldManifests.map(({ field: f, manifest }) => {
1663
+ return ` ('${f.name}', ${manifest.encoder.content}),`;
1664
+ }).join("\n");
1665
+ const decFields = fieldManifests.map(({ field: f, manifest }) => {
1666
+ return ` ('${f.name}', ${manifest.decoder.content}),`;
1667
+ }).join("\n");
1668
+ const toMapFields = fields.map(
1669
+ (f) => ` '${f.name}': value.${camelCase(f.name)},`
1670
+ ).join("\n");
1671
+ const fromMapFields = fieldManifests.map(({ field: f, manifest }) => {
1672
+ const typeStr = manifest.type.content;
1673
+ const isNullable = typeStr.endsWith("?");
1674
+ const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
1675
+ return ` ${camelCase(f.name)}: ${accessor} as ${typeStr},`;
1676
+ }).join("\n");
1677
+ const result = fragment`// Auto-generated. Do not edit.
1678
+ // ignore_for_file: type=lint
1679
+
1680
+ ${use("Uint8List", "dartTypedData")}
1681
+ ${use("immutable", "meta")}
1682
+ ${use("Encoder", "solanaCodecsCore")}
1683
+ ${use("Decoder", "solanaCodecsCore")}
1684
+ ${use("Codec", "solanaCodecsCore")}
1685
+ ${use("combineCodec", "solanaCodecsCore")}
1686
+ ${use("transformEncoder", "solanaCodecsCore")}
1687
+ ${use("transformDecoder", "solanaCodecsCore")}
1688
+ ${use("getStructEncoder", "solanaCodecsDataStructures")}
1689
+ ${use("getStructDecoder", "solanaCodecsDataStructures")}
1690
+
1691
+ @immutable
1692
+ class ${fragmentFromString(typeName)} {
1693
+ const ${fragmentFromString(typeName)}({
1694
+ ${fragmentFromString(ctorParams)}
1695
+ });
1696
+
1697
+ ${fragmentFromString(fieldDecls)}
1698
+
1699
+ @override
1700
+ bool operator ==(Object other) =>
1701
+ identical(this, other) ||
1702
+ other is ${fragmentFromString(typeName)} &&
1703
+ runtimeType == other.runtimeType &&
1704
+ ${fragmentFromString(eqChecks)};
1705
+
1706
+ @override
1707
+ int get hashCode => Object.hash(${fragmentFromString(hashFields)});
1708
+
1709
+ @override
1710
+ String toString() => '${fragmentFromString(typeName)}(${fragmentFromString(toStringFields)})';
1711
+ }
1712
+
1713
+ Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
1714
+ final structEncoder = getStructEncoder(<(String, Encoder<Object?>)>[
1715
+ ${fragmentFromString(encFields)}
1716
+ ]);
1717
+
1718
+ return transformEncoder(
1719
+ structEncoder,
1720
+ (${fragmentFromString(typeName)} value) => <String, Object?>{
1721
+ ${fragmentFromString(toMapFields)}
1722
+ },
1723
+ );
1724
+ }
1725
+
1726
+ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
1727
+ final structDecoder = getStructDecoder(<(String, Decoder<Object?>)>[
1728
+ ${fragmentFromString(decFields)}
1729
+ ]);
1730
+
1731
+ return transformDecoder(
1732
+ structDecoder,
1733
+ (Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}(
1734
+ ${fragmentFromString(fromMapFields)}
1735
+ ),
1736
+ );
1737
+ }
1738
+
1739
+ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
1740
+ return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
1741
+ }`;
1742
+ for (const { manifest } of fieldManifests) {
1743
+ result.imports.mergeWith(manifest.encoder.imports);
1744
+ result.imports.mergeWith(manifest.decoder.imports);
1745
+ result.imports.mergeWith(manifest.type.imports);
1746
+ }
1747
+ return result;
1748
+ }
1749
+ function getTypeAliasPageFragment(node, scope) {
1750
+ const name = node.name;
1751
+ const typeName = scope.nameApi.dataType(name);
1752
+ const manifest = visit(node.type, scope.typeManifestVisitor);
1753
+ const encoderName = scope.nameApi.encoderFunction(name);
1754
+ const decoderName = scope.nameApi.decoderFunction(name);
1755
+ const codecName = scope.nameApi.codecFunction(name);
1756
+ return fragment`// Auto-generated. Do not edit.
1757
+ // ignore_for_file: type=lint
1758
+
1759
+ ${use("Encoder", "solanaCodecsCore")}
1760
+ ${use("Decoder", "solanaCodecsCore")}
1761
+ ${use("Codec", "solanaCodecsCore")}
1762
+ ${use("combineCodec", "solanaCodecsCore")}
1763
+
1764
+ typedef ${fragmentFromString(typeName)} = ${manifest.type};
1765
+
1766
+ Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
1767
+ return ${manifest.encoder};
1768
+ }
1769
+
1770
+ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
1771
+ return ${manifest.decoder};
1772
+ }
1773
+
1774
+ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
1775
+ return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
1776
+ }`;
1777
+ }
1778
+ function getNumberCodecName2(format) {
1779
+ switch (format) {
1780
+ case "u8":
1781
+ return "U8";
1782
+ case "u16":
1783
+ return "U16";
1784
+ case "u32":
1785
+ return "U32";
1786
+ case "u64":
1787
+ return "U64";
1788
+ case "u128":
1789
+ return "U128";
1790
+ case "i8":
1791
+ return "I8";
1792
+ case "i16":
1793
+ return "I16";
1794
+ case "i32":
1795
+ return "I32";
1796
+ case "i64":
1797
+ return "I64";
1798
+ case "i128":
1799
+ return "I128";
1800
+ case "f32":
1801
+ return "F32";
1802
+ case "f64":
1803
+ return "F64";
1804
+ case "shortU16":
1805
+ return "ShortU16";
1806
+ default:
1807
+ return "U8";
1808
+ }
1809
+ }
1810
+
1811
+ // src/visitors/getRenderMapVisitor.ts
1812
+ function getRenderMapVisitor(options = {}) {
1813
+ const nameApi = {
1814
+ ...createDartNameApi(),
1815
+ ...options.nameApi
1816
+ };
1817
+ options.dependencyMap ?? {};
1818
+ const stack = new NodeStack();
1819
+ const linkables = new LinkableDictionary();
1820
+ const typeManifestVisitor = getTypeManifestVisitor({
1821
+ nameApi,
1822
+ linkables});
1823
+ const scope = {
1824
+ nameApi,
1825
+ typeManifestVisitor};
1826
+ return pipe(
1827
+ staticVisitor(
1828
+ () => createRenderMap(),
1829
+ {
1830
+ keys: [
1831
+ "rootNode",
1832
+ "programNode",
1833
+ "accountNode",
1834
+ "definedTypeNode",
1835
+ "instructionNode",
1836
+ "pdaNode"
1837
+ ]
1838
+ }
1839
+ ),
1840
+ (v) => extendVisitor(v, {
1841
+ visitRoot(node, { self }) {
1842
+ const programMaps = [
1843
+ visit(node.program, self),
1844
+ ...node.additionalPrograms.map((p) => visit(p, self))
1845
+ ];
1846
+ return mergeRenderMaps(programMaps);
1847
+ },
1848
+ visitProgram(node, { self }) {
1849
+ const programName = node.name;
1850
+ const maps = [];
1851
+ const accountFiles = [];
1852
+ const instructionFiles = [];
1853
+ const typeFiles = [];
1854
+ const pdaFiles = [];
1855
+ const errorFiles = [];
1856
+ const programFiles = [];
1857
+ for (const account of node.accounts ?? []) {
1858
+ maps.push(visit(account, self));
1859
+ accountFiles.push(`${snakeCase(account.name)}.dart`);
1860
+ }
1861
+ for (const instruction of node.instructions ?? []) {
1862
+ maps.push(visit(instruction, self));
1863
+ instructionFiles.push(
1864
+ `${snakeCase(instruction.name)}.dart`
1865
+ );
1866
+ }
1867
+ for (const definedType of node.definedTypes ?? []) {
1868
+ maps.push(visit(definedType, self));
1869
+ typeFiles.push(
1870
+ `${snakeCase(definedType.name)}.dart`
1871
+ );
1872
+ }
1873
+ for (const pda of node.pdas ?? []) {
1874
+ maps.push(visit(pda, self));
1875
+ pdaFiles.push(`${snakeCase(pda.name)}.dart`);
1876
+ }
1877
+ const programFragment = getProgramPageFragment(node, scope);
1878
+ const programFileName = `${snakeCase(programName)}.dart`;
1879
+ programFiles.push(programFileName);
1880
+ let programMap = createRenderMap();
1881
+ programMap = addToRenderMap(programMap, `programs/${programFileName}`, programFragment);
1882
+ maps.push(programMap);
1883
+ const errors = node.errors ?? [];
1884
+ if (errors.length > 0) {
1885
+ const errorFragment = getErrorPageFragment(node, scope);
1886
+ const errorFileName = `${snakeCase(programName)}.dart`;
1887
+ errorFiles.push(errorFileName);
1888
+ let errorMap = createRenderMap();
1889
+ errorMap = addToRenderMap(errorMap, `errors/${errorFileName}`, errorFragment);
1890
+ maps.push(errorMap);
1891
+ }
1892
+ const categories = [];
1893
+ if (accountFiles.length > 0) {
1894
+ categories.push("accounts");
1895
+ let indexMap = createRenderMap();
1896
+ indexMap = addToRenderMap(
1897
+ indexMap,
1898
+ "accounts/accounts.dart",
1899
+ getIndexPageFragment(accountFiles)
1900
+ );
1901
+ maps.push(indexMap);
1902
+ }
1903
+ if (instructionFiles.length > 0) {
1904
+ categories.push("instructions");
1905
+ let indexMap = createRenderMap();
1906
+ indexMap = addToRenderMap(
1907
+ indexMap,
1908
+ "instructions/instructions.dart",
1909
+ getIndexPageFragment(instructionFiles)
1910
+ );
1911
+ maps.push(indexMap);
1912
+ }
1913
+ if (typeFiles.length > 0) {
1914
+ categories.push("types");
1915
+ let indexMap = createRenderMap();
1916
+ indexMap = addToRenderMap(
1917
+ indexMap,
1918
+ "types/types.dart",
1919
+ getIndexPageFragment(typeFiles)
1920
+ );
1921
+ maps.push(indexMap);
1922
+ }
1923
+ if (pdaFiles.length > 0) {
1924
+ categories.push("pdas");
1925
+ let indexMap = createRenderMap();
1926
+ indexMap = addToRenderMap(
1927
+ indexMap,
1928
+ "pdas/pdas.dart",
1929
+ getIndexPageFragment(pdaFiles)
1930
+ );
1931
+ maps.push(indexMap);
1932
+ }
1933
+ if (errorFiles.length > 0) {
1934
+ categories.push("errors");
1935
+ let indexMap = createRenderMap();
1936
+ indexMap = addToRenderMap(
1937
+ indexMap,
1938
+ "errors/errors.dart",
1939
+ getIndexPageFragment(errorFiles)
1940
+ );
1941
+ maps.push(indexMap);
1942
+ }
1943
+ if (programFiles.length > 0) {
1944
+ categories.push("programs");
1945
+ let indexMap = createRenderMap();
1946
+ indexMap = addToRenderMap(
1947
+ indexMap,
1948
+ "programs/programs.dart",
1949
+ getIndexPageFragment(programFiles)
1950
+ );
1951
+ maps.push(indexMap);
1952
+ }
1953
+ if (categories.length > 0) {
1954
+ let rootMap = createRenderMap();
1955
+ rootMap = addToRenderMap(
1956
+ rootMap,
1957
+ `${snakeCase(programName)}.dart`,
1958
+ getRootIndexPageFragment(categories)
1959
+ );
1960
+ maps.push(rootMap);
1961
+ }
1962
+ return mergeRenderMaps(maps);
1963
+ },
1964
+ visitAccount(node, { self }) {
1965
+ const fileName = `${snakeCase(node.name)}.dart`;
1966
+ const frag = getAccountPageFragment(node, scope);
1967
+ let map = createRenderMap();
1968
+ map = addToRenderMap(map, `accounts/${fileName}`, frag);
1969
+ return map;
1970
+ },
1971
+ visitDefinedType(node, { self }) {
1972
+ const fileName = `${snakeCase(node.name)}.dart`;
1973
+ const frag = getTypePageFragment(node, scope);
1974
+ let map = createRenderMap();
1975
+ map = addToRenderMap(map, `types/${fileName}`, frag);
1976
+ return map;
1977
+ },
1978
+ visitInstruction(node, { self }) {
1979
+ const fileName = `${snakeCase(node.name)}.dart`;
1980
+ const frag = getInstructionPageFragment(node, scope);
1981
+ let map = createRenderMap();
1982
+ map = addToRenderMap(map, `instructions/${fileName}`, frag);
1983
+ return map;
1984
+ },
1985
+ visitPda(node, { self }) {
1986
+ const fileName = `${snakeCase(node.name)}.dart`;
1987
+ const frag = getPdaPageFragment(node, scope);
1988
+ let map = createRenderMap();
1989
+ map = addToRenderMap(map, `pdas/${fileName}`, frag);
1990
+ return map;
1991
+ }
1992
+ }),
1993
+ (v) => recordNodeStackVisitor(v, stack),
1994
+ (v) => recordLinkablesOnFirstVisitVisitor(v, linkables)
1995
+ );
1996
+ }
1997
+
1998
+ // src/visitors/renderVisitor.ts
1999
+ function renderVisitor(outputDir, options = {}) {
2000
+ const {
2001
+ deleteFolderBeforeRendering = true,
2002
+ formatCode = false,
2003
+ nameApi,
2004
+ dependencyMap
2005
+ } = options;
2006
+ return rootNodeVisitor((root) => {
2007
+ if (deleteFolderBeforeRendering && existsSync(outputDir)) {
2008
+ deleteDirectory(outputDir);
2009
+ }
2010
+ const renderMap = visit(
2011
+ root,
2012
+ getRenderMapVisitor({ nameApi, dependencyMap })
2013
+ );
2014
+ const typePathMap = {};
2015
+ for (const renderPath of renderMap.keys()) {
2016
+ const match = renderPath.match(/^(?:.*\/)?types\/([a-z_]+)\.dart$/);
2017
+ if (match) {
2018
+ typePathMap[`definedType:${match[1]}`] = renderPath;
2019
+ }
2020
+ }
2021
+ for (const [filePath, frag] of renderMap.entries()) {
2022
+ const fullPath = join(outputDir, filePath);
2023
+ const dir = dirname(fullPath);
2024
+ if (!existsSync(dir)) {
2025
+ mkdirSync(dir, { recursive: true });
2026
+ }
2027
+ const fileDir = dirname(filePath);
2028
+ const internalMap = {};
2029
+ for (const [key, typePath] of Object.entries(typePathMap)) {
2030
+ if (typePath === filePath) continue;
2031
+ let rel = posix.relative(fileDir, typePath);
2032
+ if (!rel.startsWith(".")) {
2033
+ rel = `./${rel}`;
2034
+ }
2035
+ internalMap[key] = rel;
2036
+ }
2037
+ const content = resolveFragmentContent(frag, dependencyMap ?? {}, internalMap);
2038
+ writeFileSync(fullPath, content, "utf-8");
2039
+ }
2040
+ if (formatCode) {
2041
+ formatDartDirectory(outputDir);
2042
+ }
2043
+ });
2044
+ }
2045
+ function resolveFragmentContent(frag, dependencyMap, internalMap = {}) {
2046
+ const { content, imports } = frag;
2047
+ const importStr = imports.toString({
2048
+ ...internalMap,
2049
+ ...dependencyMap
2050
+ });
2051
+ if (!importStr) {
2052
+ return content + "\n";
2053
+ }
2054
+ const lines = content.split("\n");
2055
+ const headerLines = [];
2056
+ let restIndex = 0;
2057
+ for (let i = 0; i < lines.length; i++) {
2058
+ if (lines[i].startsWith("//") || lines[i].trim() === "") {
2059
+ headerLines.push(lines[i]);
2060
+ restIndex = i + 1;
2061
+ } else {
2062
+ break;
2063
+ }
2064
+ }
2065
+ const header = headerLines.join("\n");
2066
+ const rest = lines.slice(restIndex).join("\n");
2067
+ const cleanContent = cleanFragmentContent(rest);
2068
+ return `${header}
2069
+
2070
+ ${importStr}
2071
+
2072
+ ${cleanContent}
2073
+ `;
2074
+ }
2075
+ function cleanFragmentContent(content) {
2076
+ const lines = content.split("\n");
2077
+ const cleanLines = lines.filter((line) => {
2078
+ const trimmed = line.trim();
2079
+ if (/^[a-zA-Z][a-zA-Z0-9]*$/.test(trimmed)) {
2080
+ return false;
2081
+ }
2082
+ return true;
2083
+ });
2084
+ return cleanLines.join("\n");
2085
+ }
2086
+
2087
+ // src/index.ts
2088
+ var src_default = renderVisitor;
2089
+
2090
+ export { DART_EXTERNAL_PACKAGE_MAP, DartImportMap, createDartNameApi, src_default as default, getRenderMapVisitor, getTypeManifestVisitor, renderVisitor };
2091
+ //# sourceMappingURL=index.node.js.map
2092
+ //# sourceMappingURL=index.node.js.map