codama-renderers-dart 0.5.0 → 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.
- package/dist/index.browser.cjs +456 -127
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +456 -128
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +456 -127
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +456 -128
- package/dist/index.node.js.map +1 -1
- package/dist/index.react-native.js +456 -128
- package/dist/index.react-native.js.map +1 -1
- package/dist/types/fragments/accountPage.d.ts.map +1 -1
- package/dist/types/fragments/instructionPage.d.ts.map +1 -1
- package/dist/types/fragments/typePage.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils/discriminators.d.ts +10 -0
- package/dist/types/utils/discriminators.d.ts.map +1 -0
- package/dist/types/utils/exactDecoder.d.ts +17 -0
- package/dist/types/utils/exactDecoder.d.ts.map +1 -0
- package/dist/types/utils/formatCode.d.ts +1 -1
- package/dist/types/utils/formatCode.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +4 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/normalizeRootNode.d.ts +11 -0
- package/dist/types/utils/normalizeRootNode.d.ts.map +1 -0
- package/dist/types/utils/valueNodes.d.ts +16 -0
- package/dist/types/utils/valueNodes.d.ts.map +1 -0
- package/dist/types/visitors/getTypeManifestVisitor.d.ts +1 -1
- package/dist/types/visitors/getTypeManifestVisitor.d.ts.map +1 -1
- package/dist/types/visitors/renderVisitor.d.ts.map +1 -1
- package/package.json +21 -18
- package/readme.md +29 -0
- package/src/fragments/accountPage.ts +90 -17
- package/src/fragments/instructionPage.ts +103 -77
- package/src/fragments/typePage.ts +32 -12
- package/src/index.ts +1 -0
- package/src/utils/discriminators.ts +121 -0
- package/src/utils/exactDecoder.ts +82 -0
- package/src/utils/formatCode.ts +7 -11
- package/src/utils/index.ts +4 -0
- package/src/utils/normalizeRootNode.ts +76 -0
- package/src/utils/valueNodes.ts +87 -0
- package/src/visitors/getRenderMapVisitor.ts +1 -1
- package/src/visitors/getTypeManifestVisitor.ts +14 -8
- package/src/visitors/renderVisitor.ts +4 -1
package/dist/index.browser.cjs
CHANGED
|
@@ -12,13 +12,71 @@ var errors = require('@codama/errors');
|
|
|
12
12
|
|
|
13
13
|
// src/visitors/renderVisitor.ts
|
|
14
14
|
function formatDartDirectory(dir) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
child_process.execSync(`dart format "${dir}"`, {
|
|
16
|
+
encoding: "utf-8",
|
|
17
|
+
timeout: 6e4,
|
|
18
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/utils/normalizeRootNode.ts
|
|
23
|
+
function normalizeRootNode(root) {
|
|
24
|
+
return normalizeNode(root);
|
|
25
|
+
}
|
|
26
|
+
function normalizeNode(value) {
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
return value.map(normalizeNode);
|
|
29
|
+
}
|
|
30
|
+
if (!isRecord(value)) {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
const normalized = Object.fromEntries(
|
|
34
|
+
Object.entries(value).map(([key, child]) => [key, normalizeNode(child)])
|
|
35
|
+
);
|
|
36
|
+
switch (normalized.kind) {
|
|
37
|
+
case "rootNode":
|
|
38
|
+
setEmptyCollection(normalized, "additionalPrograms");
|
|
39
|
+
break;
|
|
40
|
+
case "programNode":
|
|
41
|
+
setEmptyCollection(normalized, "accounts");
|
|
42
|
+
setEmptyCollection(normalized, "constants");
|
|
43
|
+
setEmptyCollection(normalized, "definedTypes");
|
|
44
|
+
setEmptyCollection(normalized, "errors");
|
|
45
|
+
setEmptyCollection(normalized, "events");
|
|
46
|
+
setEmptyCollection(normalized, "instructions");
|
|
47
|
+
setEmptyCollection(normalized, "pdas");
|
|
48
|
+
break;
|
|
49
|
+
case "instructionNode":
|
|
50
|
+
setEmptyCollection(normalized, "accounts");
|
|
51
|
+
setEmptyCollection(normalized, "arguments");
|
|
52
|
+
break;
|
|
53
|
+
case "pdaNode":
|
|
54
|
+
setEmptyCollection(normalized, "seeds");
|
|
55
|
+
break;
|
|
56
|
+
case "structTypeNode":
|
|
57
|
+
setEmptyCollection(normalized, "fields");
|
|
58
|
+
break;
|
|
59
|
+
case "enumTypeNode":
|
|
60
|
+
setEmptyCollection(normalized, "variants");
|
|
61
|
+
break;
|
|
62
|
+
case "tupleTypeNode":
|
|
63
|
+
setEmptyCollection(normalized, "items");
|
|
64
|
+
break;
|
|
65
|
+
case "hiddenPrefixTypeNode":
|
|
66
|
+
setEmptyCollection(normalized, "prefix");
|
|
67
|
+
break;
|
|
68
|
+
case "hiddenSuffixTypeNode":
|
|
69
|
+
setEmptyCollection(normalized, "suffix");
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
return normalized;
|
|
73
|
+
}
|
|
74
|
+
function isRecord(value) {
|
|
75
|
+
return typeof value === "object" && value !== null;
|
|
76
|
+
}
|
|
77
|
+
function setEmptyCollection(record, key) {
|
|
78
|
+
if (record[key] === void 0) {
|
|
79
|
+
record[key] = [];
|
|
22
80
|
}
|
|
23
81
|
}
|
|
24
82
|
|
|
@@ -208,17 +266,6 @@ function use(typeName, module) {
|
|
|
208
266
|
return { content: typeName, imports };
|
|
209
267
|
}
|
|
210
268
|
|
|
211
|
-
// src/utils/typeManifest.ts
|
|
212
|
-
function emptyTypeManifest() {
|
|
213
|
-
return {
|
|
214
|
-
type: emptyFragment(),
|
|
215
|
-
encoder: emptyFragment(),
|
|
216
|
-
decoder: emptyFragment(),
|
|
217
|
-
value: emptyFragment(),
|
|
218
|
-
isEnum: false
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
269
|
// src/utils/wellKnownAddresses.ts
|
|
223
270
|
var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
|
|
224
271
|
// Agave / Solana native programs
|
|
@@ -273,6 +320,207 @@ var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
|
|
|
273
320
|
["Es9vMFrzaCERm6YKXx6bqKr1Rmd9b5v3J8rM5e4rfF4", "usdtAddress"]
|
|
274
321
|
]);
|
|
275
322
|
|
|
323
|
+
// src/utils/valueNodes.ts
|
|
324
|
+
function getDartValueFragment(value, dartType) {
|
|
325
|
+
switch (value.kind) {
|
|
326
|
+
case "numberValueNode":
|
|
327
|
+
return fragmentFromString(
|
|
328
|
+
dartType === "BigInt" ? `BigInt.from(${value.number})` : String(value.number)
|
|
329
|
+
);
|
|
330
|
+
case "booleanValueNode":
|
|
331
|
+
return fragmentFromString(String(value.boolean));
|
|
332
|
+
case "stringValueNode":
|
|
333
|
+
return fragmentFromString(toDartStringLiteral(value.string));
|
|
334
|
+
case "noneValueNode":
|
|
335
|
+
return fragmentFromString("null");
|
|
336
|
+
case "bytesValueNode": {
|
|
337
|
+
if (value.encoding !== "base16") {
|
|
338
|
+
throw new Error(
|
|
339
|
+
`Unsupported deterministic bytes encoding: ${value.encoding}`
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
const clean = value.data.replace(/^0x/, "");
|
|
343
|
+
if (clean.length % 2 !== 0 || !/^[0-9a-f]*$/i.test(clean)) {
|
|
344
|
+
throw new Error(`Invalid hexadecimal bytes value: ${value.data}`);
|
|
345
|
+
}
|
|
346
|
+
const bytes = clean.match(/.{2}/g)?.map((byte) => `0x${byte}`) ?? [];
|
|
347
|
+
return fragment`${use("Uint8List", "dartTypedData")}.fromList([${fragmentFromString(bytes.join(", "))}])`;
|
|
348
|
+
}
|
|
349
|
+
case "publicKeyValueNode": {
|
|
350
|
+
const wellKnownName = WELL_KNOWN_ADDRESSES.get(value.publicKey);
|
|
351
|
+
return wellKnownName ? fragment`${use(wellKnownName, "solanaAddresses")}` : fragment`${use("Address", "solanaAddresses")}(${fragmentFromString(toDartStringLiteral(value.publicKey))})`;
|
|
352
|
+
}
|
|
353
|
+
default:
|
|
354
|
+
throw new Error(
|
|
355
|
+
`Unsupported deterministic Dart value node: ${value.kind}`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function isConstDartValueNode(value) {
|
|
360
|
+
switch (value.kind) {
|
|
361
|
+
case "numberValueNode":
|
|
362
|
+
case "booleanValueNode":
|
|
363
|
+
case "stringValueNode":
|
|
364
|
+
case "noneValueNode":
|
|
365
|
+
case "publicKeyValueNode":
|
|
366
|
+
return true;
|
|
367
|
+
default:
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function toDartStringLiteral(value) {
|
|
372
|
+
return `'${value.replaceAll("\\", "\\\\").replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll(" ", "\\t").replaceAll("\b", "\\b").replaceAll("\f", "\\f").replaceAll("$", "\\$").replaceAll("'", "\\'")}'`;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/utils/discriminators.ts
|
|
376
|
+
function getDiscriminatorValidationFragment(node, scope) {
|
|
377
|
+
const discriminators = node.discriminators ?? [];
|
|
378
|
+
if (discriminators.length === 0) return emptyFragment();
|
|
379
|
+
const fields = getDiscriminatorFields(node);
|
|
380
|
+
const fragments = discriminators.map((discriminator) => {
|
|
381
|
+
switch (discriminator.kind) {
|
|
382
|
+
case "constantDiscriminatorNode":
|
|
383
|
+
return getConstantValidationFragment(
|
|
384
|
+
discriminator.constant,
|
|
385
|
+
discriminator.offset,
|
|
386
|
+
scope
|
|
387
|
+
);
|
|
388
|
+
case "fieldDiscriminatorNode": {
|
|
389
|
+
const field = fields.find(
|
|
390
|
+
(candidate) => candidate.name === discriminator.name
|
|
391
|
+
);
|
|
392
|
+
if (field?.defaultValue == null) {
|
|
393
|
+
throw new Error(
|
|
394
|
+
`Field discriminator "${discriminator.name}" on ${node.kind} "${node.name}" must reference a field with a default value.`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
return getConstantValidationFragment(
|
|
398
|
+
{
|
|
399
|
+
type: field.type,
|
|
400
|
+
value: field.defaultValue
|
|
401
|
+
},
|
|
402
|
+
discriminator.offset,
|
|
403
|
+
scope
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
case "sizeDiscriminatorNode": {
|
|
407
|
+
if (!Number.isSafeInteger(discriminator.size) || discriminator.size < 0) {
|
|
408
|
+
throw new Error(
|
|
409
|
+
`Discriminator size must be a non-negative safe integer, got ${discriminator.size}.`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
return fragment`if (bytes.length - offset != ${fragmentFromString(String(discriminator.size))}) {
|
|
413
|
+
throw ${use("SolanaError", "solanaErrors")}(
|
|
414
|
+
${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
|
|
415
|
+
{
|
|
416
|
+
'codecDescription': '${fragmentFromString(node.name)} discriminator',
|
|
417
|
+
'expected': ${fragmentFromString(String(discriminator.size))},
|
|
418
|
+
'bytesLength': bytes.length - offset,
|
|
419
|
+
},
|
|
420
|
+
);
|
|
421
|
+
}`;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
return mergeFragments(fragments, (contents) => contents.join("\n"));
|
|
426
|
+
}
|
|
427
|
+
function getConstantValidationFragment(constant, discriminatorOffset, scope) {
|
|
428
|
+
if (!Number.isSafeInteger(discriminatorOffset) || discriminatorOffset < 0) {
|
|
429
|
+
throw new Error(
|
|
430
|
+
`Discriminator offset must be a non-negative safe integer, got ${discriminatorOffset}.`
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
const manifest = visitorsCore.visit(constant.type, scope.typeManifestVisitor);
|
|
434
|
+
const value = getDartValueFragment(
|
|
435
|
+
constant.value,
|
|
436
|
+
manifest.type.content
|
|
437
|
+
);
|
|
438
|
+
return fragment`${use("getConstantDecoder", "solanaCodecsDataStructures")}(
|
|
439
|
+
${manifest.encoder}.encode(${value}),
|
|
440
|
+
).read(bytes, offset + ${fragmentFromString(String(discriminatorOffset))});`;
|
|
441
|
+
}
|
|
442
|
+
function getDiscriminatorFields(node) {
|
|
443
|
+
if (node.kind === "accountNode") {
|
|
444
|
+
return nodes.resolveNestedTypeNode(node.data).fields ?? [];
|
|
445
|
+
}
|
|
446
|
+
return (node.arguments ?? []).map(
|
|
447
|
+
(argument) => ({
|
|
448
|
+
...argument,
|
|
449
|
+
kind: "structFieldTypeNode"
|
|
450
|
+
})
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// src/utils/exactDecoder.ts
|
|
455
|
+
function getTopLevelDecoderFragment({
|
|
456
|
+
typeName,
|
|
457
|
+
description,
|
|
458
|
+
discriminatorValidation,
|
|
459
|
+
fromMapFields,
|
|
460
|
+
requireExactConsumption
|
|
461
|
+
}) {
|
|
462
|
+
const validation = discriminatorValidation.content ? ` ${discriminatorValidation.content.replaceAll("\n", "\n ")}
|
|
463
|
+
` : "";
|
|
464
|
+
const consumptionCheck = requireExactConsumption ? ` if (newOffset != bytes.length) {
|
|
465
|
+
throwInvalidByteLength(newOffset - offset, bytes.length - offset);
|
|
466
|
+
}
|
|
467
|
+
` : "";
|
|
468
|
+
const fixedSizeCheck = requireExactConsumption ? "bytesLength != structDecoder.fixedSize" : "bytesLength < structDecoder.fixedSize";
|
|
469
|
+
const result = fragment` Never throwInvalidByteLength(int expected, int bytesLength) {
|
|
470
|
+
throw ${use("SolanaError", "solanaErrors")}(
|
|
471
|
+
${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
|
|
472
|
+
{
|
|
473
|
+
'codecDescription': '${fragmentFromString(description)}',
|
|
474
|
+
'expected': expected,
|
|
475
|
+
'bytesLength': bytesLength,
|
|
476
|
+
},
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
(${fragmentFromString(typeName)}, int) readTopLevel(Uint8List bytes, int offset) {
|
|
481
|
+
${fragmentFromString(validation)} final (map, newOffset) = structDecoder.read(bytes, offset);
|
|
482
|
+
${fragmentFromString(consumptionCheck)}
|
|
483
|
+
return (
|
|
484
|
+
${fragmentFromString(typeName)}(
|
|
485
|
+
${fragmentFromString(fromMapFields)}
|
|
486
|
+
),
|
|
487
|
+
newOffset,
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return switch (structDecoder) {
|
|
492
|
+
${use("FixedSizeDecoder", "solanaCodecsCore")}<Map<String, Object?>>() =>
|
|
493
|
+
${use("FixedSizeDecoder", "solanaCodecsCore")}<${fragmentFromString(typeName)}>(
|
|
494
|
+
fixedSize: structDecoder.fixedSize,
|
|
495
|
+
read: (bytes, offset) {
|
|
496
|
+
final bytesLength = bytes.length - offset;
|
|
497
|
+
if (${fragmentFromString(fixedSizeCheck)}) {
|
|
498
|
+
throwInvalidByteLength(structDecoder.fixedSize, bytesLength);
|
|
499
|
+
}
|
|
500
|
+
return readTopLevel(bytes, offset);
|
|
501
|
+
},
|
|
502
|
+
),
|
|
503
|
+
${use("VariableSizeDecoder", "solanaCodecsCore")}<Map<String, Object?>>() =>
|
|
504
|
+
${use("VariableSizeDecoder", "solanaCodecsCore")}<${fragmentFromString(typeName)}>(
|
|
505
|
+
read: readTopLevel,
|
|
506
|
+
maxSize: structDecoder.maxSize,
|
|
507
|
+
),
|
|
508
|
+
};`;
|
|
509
|
+
result.imports.mergeWith(discriminatorValidation.imports);
|
|
510
|
+
return result;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/utils/typeManifest.ts
|
|
514
|
+
function emptyTypeManifest() {
|
|
515
|
+
return {
|
|
516
|
+
type: emptyFragment(),
|
|
517
|
+
encoder: emptyFragment(),
|
|
518
|
+
decoder: emptyFragment(),
|
|
519
|
+
value: emptyFragment(),
|
|
520
|
+
isEnum: false
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
|
|
276
524
|
// src/visitors/getTypeManifestVisitor.ts
|
|
277
525
|
function getTypeManifestVisitor(input) {
|
|
278
526
|
const { nameApi, linkables, nonScalarEnums = [] } = input;
|
|
@@ -416,12 +664,17 @@ function getTypeManifestVisitor(input) {
|
|
|
416
664
|
const itemManifest = visitorsCore.visit(node.item, self);
|
|
417
665
|
const encoderSizeExpr = getArraySizeExpression(node, "Encoder");
|
|
418
666
|
const decoderSizeExpr = getArraySizeExpression(node, "Decoder");
|
|
667
|
+
const itemType = fragmentFromString(itemManifest.type.content);
|
|
668
|
+
const itemEncoder = fragment`${use(
|
|
669
|
+
"transformEncoder",
|
|
670
|
+
"solanaCodecsCore"
|
|
671
|
+
)}(${itemManifest.encoder}, (${itemType} value) => value)`;
|
|
419
672
|
return {
|
|
420
673
|
type: fragment`List<${itemManifest.type}>`,
|
|
421
674
|
encoder: fragment`${use(
|
|
422
675
|
"getArrayEncoder",
|
|
423
676
|
"solanaCodecsDataStructures"
|
|
424
|
-
)}(${
|
|
677
|
+
)}<${itemType}>(${itemEncoder}${encoderSizeExpr})`,
|
|
425
678
|
decoder: fragment`${use(
|
|
426
679
|
"getArrayDecoder",
|
|
427
680
|
"solanaCodecsDataStructures"
|
|
@@ -468,7 +721,7 @@ function getTypeManifestVisitor(input) {
|
|
|
468
721
|
};
|
|
469
722
|
},
|
|
470
723
|
visitTupleType(node, { self }) {
|
|
471
|
-
const itemManifests = node.items.map((item) => visitorsCore.visit(item, self));
|
|
724
|
+
const itemManifests = (node.items ?? []).map((item) => visitorsCore.visit(item, self));
|
|
472
725
|
const typeList = itemManifests.map((m) => m.type.content).join(", ");
|
|
473
726
|
const encoderList = itemManifests.map((m) => m.encoder);
|
|
474
727
|
const decoderList = itemManifests.map((m) => m.decoder);
|
|
@@ -501,8 +754,9 @@ function getTypeManifestVisitor(input) {
|
|
|
501
754
|
};
|
|
502
755
|
},
|
|
503
756
|
visitStructType(node, { self }) {
|
|
504
|
-
const
|
|
505
|
-
const
|
|
757
|
+
const nodeFields = node.fields ?? [];
|
|
758
|
+
const fields = nodeFields.map((f) => visitorsCore.visit(f, self));
|
|
759
|
+
const fieldNames = nodeFields.map((f) => f.name);
|
|
506
760
|
const typeStr = "Map<String, Object?>";
|
|
507
761
|
const encoderFields = fields.map((f, i) => `('${fieldNames[i]}', ${f.encoder.content})`).join(", ");
|
|
508
762
|
const encoderFrag = fragment`${use(
|
|
@@ -532,7 +786,7 @@ function getTypeManifestVisitor(input) {
|
|
|
532
786
|
return visitorsCore.visit(node.type, self);
|
|
533
787
|
},
|
|
534
788
|
visitEnumType(node, { self }) {
|
|
535
|
-
const isScalar = node.variants.every(
|
|
789
|
+
const isScalar = (node.variants ?? []).every(
|
|
536
790
|
(v) => v.kind === "enumEmptyVariantTypeNode"
|
|
537
791
|
);
|
|
538
792
|
if (isScalar) {
|
|
@@ -624,7 +878,7 @@ function getTypeManifestVisitor(input) {
|
|
|
624
878
|
encoder: fragment`${use(
|
|
625
879
|
"fixEncoderSize",
|
|
626
880
|
"solanaCodecsCore"
|
|
627
|
-
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))})`,
|
|
881
|
+
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))}, allowTruncation: false)`,
|
|
628
882
|
decoder: fragment`${use(
|
|
629
883
|
"fixDecoderSize",
|
|
630
884
|
"solanaCodecsCore"
|
|
@@ -662,7 +916,7 @@ function getTypeManifestVisitor(input) {
|
|
|
662
916
|
},
|
|
663
917
|
visitHiddenPrefixType(node, { self }) {
|
|
664
918
|
const innerManifest = visitorsCore.visit(node.type, self);
|
|
665
|
-
const prefixes = node.prefix.map((p) => getHiddenAffixManifest(p, self));
|
|
919
|
+
const prefixes = (node.prefix ?? []).map((p) => getHiddenAffixManifest(p, self));
|
|
666
920
|
const prefixEncoders = prefixes.map((p) => p.encoder.content).join(", ");
|
|
667
921
|
const prefixDecoders = prefixes.map((p) => p.decoder.content).join(", ");
|
|
668
922
|
const encoderFrag = fragment`${use(
|
|
@@ -689,7 +943,7 @@ function getTypeManifestVisitor(input) {
|
|
|
689
943
|
},
|
|
690
944
|
visitHiddenSuffixType(node, { self }) {
|
|
691
945
|
const innerManifest = visitorsCore.visit(node.type, self);
|
|
692
|
-
const suffixes = node.suffix.map((s) => getHiddenAffixManifest(s, self));
|
|
946
|
+
const suffixes = (node.suffix ?? []).map((s) => getHiddenAffixManifest(s, self));
|
|
693
947
|
const suffixEncoders = suffixes.map((s) => s.encoder.content).join(", ");
|
|
694
948
|
const suffixDecoders = suffixes.map((s) => s.decoder.content).join(", ");
|
|
695
949
|
const encoderFrag = fragment`${use(
|
|
@@ -976,19 +1230,52 @@ function hexToBytes(hex) {
|
|
|
976
1230
|
function getAccountPageFragment(node, scope) {
|
|
977
1231
|
const name = node.name;
|
|
978
1232
|
const typeName = scope.nameApi.dataType(name);
|
|
979
|
-
const
|
|
980
|
-
const fields = dataNode.fields;
|
|
1233
|
+
const fields = nodes.resolveNestedTypeNode(node.data).fields ?? [];
|
|
981
1234
|
const fieldManifests = fields.map((f) => ({
|
|
982
1235
|
field: f,
|
|
983
1236
|
manifest: visitorsCore.visit(f.type, scope.typeManifestVisitor)
|
|
984
1237
|
}));
|
|
1238
|
+
const omittedFields = fields.filter(isOmittedDefaultField);
|
|
1239
|
+
const constructorFields = fields.filter(
|
|
1240
|
+
(field) => !isOmittedDefaultField(field)
|
|
1241
|
+
);
|
|
1242
|
+
const forcedFields = /* @__PURE__ */ new Set([
|
|
1243
|
+
...omittedFields,
|
|
1244
|
+
...fields.filter((field) => isFieldDiscriminator(field, node))
|
|
1245
|
+
]);
|
|
1246
|
+
const fieldDefaults = new Map(
|
|
1247
|
+
fieldManifests.flatMap(({ field, manifest }) => {
|
|
1248
|
+
if (!forcedFields.has(field) || field.defaultValue == null) return [];
|
|
1249
|
+
return [
|
|
1250
|
+
[
|
|
1251
|
+
field,
|
|
1252
|
+
getDartValueFragment(field.defaultValue, manifest.type.content)
|
|
1253
|
+
]
|
|
1254
|
+
];
|
|
1255
|
+
})
|
|
1256
|
+
);
|
|
1257
|
+
for (const field of forcedFields) {
|
|
1258
|
+
if (!fieldDefaults.has(field)) {
|
|
1259
|
+
throw new Error(
|
|
1260
|
+
`Forced field "${field.name}" on account "${node.name}" must have a deterministic default value.`
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
985
1264
|
const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
|
|
986
1265
|
return ` final ${manifest.type.content} ${camelCase(f.name)};`;
|
|
987
1266
|
}).join("\n");
|
|
988
|
-
const ctorParams =
|
|
989
|
-
const
|
|
1267
|
+
const ctorParams = constructorFields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
|
|
1268
|
+
const ctorInitializers = omittedFields.map((field) => {
|
|
1269
|
+
const fieldName = camelCase(field.name);
|
|
1270
|
+
return `${fieldName} = ${fieldDefaults.get(field).content}`;
|
|
1271
|
+
}).join(",\n ");
|
|
1272
|
+
const ctorKeyword = omittedFields.every(
|
|
1273
|
+
(field) => isConstDartValueNode(field.defaultValue)
|
|
1274
|
+
) ? "const " : "";
|
|
1275
|
+
const ctorSignature = constructorFields.length === 0 ? `${ctorKeyword}${typeName}()${ctorInitializers ? ` : ${ctorInitializers}` : ""};` : `${ctorKeyword}${typeName}({
|
|
990
1276
|
${ctorParams}
|
|
991
|
-
})
|
|
1277
|
+
})${ctorInitializers ? ` :
|
|
1278
|
+
${ctorInitializers}` : ""};`;
|
|
992
1279
|
const eqChecks = fields.length === 0 ? "true" : fields.map(
|
|
993
1280
|
(f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`
|
|
994
1281
|
).join(" &&\n ");
|
|
@@ -1003,10 +1290,11 @@ ${ctorParams}
|
|
|
1003
1290
|
const decFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1004
1291
|
return ` ('${f.name}', ${manifest.decoder.content}),`;
|
|
1005
1292
|
}).join("\n");
|
|
1006
|
-
const toMapFields = fields.map(
|
|
1007
|
-
(f)
|
|
1008
|
-
|
|
1009
|
-
|
|
1293
|
+
const toMapFields = fields.map((f) => {
|
|
1294
|
+
const value = forcedFields.has(f) ? fieldDefaults.get(f).content : `value.${camelCase(f.name)}`;
|
|
1295
|
+
return ` '${f.name}': ${value},`;
|
|
1296
|
+
}).join("\n");
|
|
1297
|
+
const fromMapFields = fieldManifests.filter(({ field }) => !isOmittedDefaultField(field)).map(({ field: f, manifest }) => {
|
|
1010
1298
|
const typeStr = manifest.type.content;
|
|
1011
1299
|
const isNullable = typeStr.endsWith("?");
|
|
1012
1300
|
const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
|
|
@@ -1020,6 +1308,19 @@ ${ctorParams}
|
|
|
1020
1308
|
/// The size of the [${fragmentFromString(typeName)}] account data in bytes.
|
|
1021
1309
|
const int ${fragmentFromString(scope.nameApi.accountSizeConstant(name))} = ${fragmentFromString(String(node.size))};` : emptyFragment();
|
|
1022
1310
|
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
1311
|
+
const discriminatorValidation = getDiscriminatorValidationFragment(
|
|
1312
|
+
node,
|
|
1313
|
+
scope
|
|
1314
|
+
);
|
|
1315
|
+
const topLevelDecoder = getTopLevelDecoderFragment({
|
|
1316
|
+
typeName,
|
|
1317
|
+
description: `${name} account decoder`,
|
|
1318
|
+
discriminatorValidation,
|
|
1319
|
+
fromMapFields,
|
|
1320
|
+
requireExactConsumption: (node.discriminators ?? []).some(
|
|
1321
|
+
(discriminator) => discriminator.kind === "sizeDiscriminatorNode"
|
|
1322
|
+
)
|
|
1323
|
+
});
|
|
1023
1324
|
const parts = [
|
|
1024
1325
|
fragment`// Auto-generated. Do not edit.
|
|
1025
1326
|
// ignore_for_file: type=lint
|
|
@@ -1079,12 +1380,7 @@ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
|
1079
1380
|
${fragmentFromString(decFields)}
|
|
1080
1381
|
]);
|
|
1081
1382
|
|
|
1082
|
-
|
|
1083
|
-
structDecoder,
|
|
1084
|
-
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}(
|
|
1085
|
-
${fragmentFromString(fromMapFields)}
|
|
1086
|
-
),
|
|
1087
|
-
);
|
|
1383
|
+
${topLevelDecoder}
|
|
1088
1384
|
}
|
|
1089
1385
|
|
|
1090
1386
|
Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
|
|
@@ -1100,8 +1396,19 @@ Account<${fragmentFromString(typeName)}> ${fragmentFromString(decodeFnName)}(Enc
|
|
|
1100
1396
|
result.imports.mergeWith(manifest.decoder.imports);
|
|
1101
1397
|
result.imports.mergeWith(manifest.type.imports);
|
|
1102
1398
|
}
|
|
1399
|
+
for (const defaultValue of fieldDefaults.values()) {
|
|
1400
|
+
result.imports.mergeWith(defaultValue.imports);
|
|
1401
|
+
}
|
|
1103
1402
|
return result;
|
|
1104
1403
|
}
|
|
1404
|
+
function isOmittedDefaultField(field) {
|
|
1405
|
+
return field.defaultValue != null && field.defaultValueStrategy === "omitted";
|
|
1406
|
+
}
|
|
1407
|
+
function isFieldDiscriminator(field, node) {
|
|
1408
|
+
return (node.discriminators ?? []).some(
|
|
1409
|
+
(discriminator) => discriminator.kind === "fieldDiscriminatorNode" && discriminator.name === field.name
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1105
1412
|
|
|
1106
1413
|
// src/fragments/errorPage.ts
|
|
1107
1414
|
function getErrorPageFragment(programNode, scope) {
|
|
@@ -1162,7 +1469,7 @@ function getIndexPageFragment(fileNames, relativePath = "") {
|
|
|
1162
1469
|
"// Auto-generated. Do not edit.\n// ignore_for_file: type=lint\n"
|
|
1163
1470
|
);
|
|
1164
1471
|
}
|
|
1165
|
-
const exports
|
|
1472
|
+
const exports = fileNames.sort().map((f) => {
|
|
1166
1473
|
const path = relativePath ? `${relativePath}/${f}` : f;
|
|
1167
1474
|
return `export '${path}';`;
|
|
1168
1475
|
}).join("\n");
|
|
@@ -1170,17 +1477,17 @@ function getIndexPageFragment(fileNames, relativePath = "") {
|
|
|
1170
1477
|
`// Auto-generated. Do not edit.
|
|
1171
1478
|
// ignore_for_file: type=lint
|
|
1172
1479
|
|
|
1173
|
-
${exports
|
|
1480
|
+
${exports}
|
|
1174
1481
|
`
|
|
1175
1482
|
);
|
|
1176
1483
|
}
|
|
1177
1484
|
function getRootIndexPageFragment(categories) {
|
|
1178
|
-
const exports
|
|
1485
|
+
const exports = categories.sort().map((cat) => `export '${cat}/${cat}.dart';`).join("\n");
|
|
1179
1486
|
return fragmentFromString(
|
|
1180
1487
|
`// Auto-generated. Do not edit.
|
|
1181
1488
|
// ignore_for_file: type=lint
|
|
1182
1489
|
|
|
1183
|
-
${exports
|
|
1490
|
+
${exports}
|
|
1184
1491
|
`
|
|
1185
1492
|
);
|
|
1186
1493
|
}
|
|
@@ -1190,30 +1497,62 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1190
1497
|
const instrFnName = scope.nameApi.instructionFunction(name);
|
|
1191
1498
|
const parseFnName = scope.nameApi.instructionParseFunction(name);
|
|
1192
1499
|
const accounts = node.accounts ?? [];
|
|
1193
|
-
const args = (node.arguments ?? []).filter(
|
|
1194
|
-
(arg) => !isDiscriminatorArg(arg, node)
|
|
1195
|
-
);
|
|
1196
1500
|
const allArgs = node.arguments ?? [];
|
|
1501
|
+
const optionalAccountStrategy = node.optionalAccountStrategy ?? "programId";
|
|
1502
|
+
if (optionalAccountStrategy !== "programId" && optionalAccountStrategy !== "omitted") {
|
|
1503
|
+
throw new Error(
|
|
1504
|
+
`Unsupported optional account strategy on instruction "${node.name}": ${optionalAccountStrategy}`
|
|
1505
|
+
);
|
|
1506
|
+
}
|
|
1507
|
+
const args = allArgs.filter(
|
|
1508
|
+
(arg) => !isDiscriminatorArg(arg, node) && !isOmittedDefaultArgument(arg)
|
|
1509
|
+
);
|
|
1197
1510
|
const dataClassName = `${typeName}InstructionData`;
|
|
1198
|
-
const allArgManifests =
|
|
1511
|
+
const allArgManifests = (node.arguments ?? []).map((arg) => ({
|
|
1199
1512
|
arg,
|
|
1200
1513
|
manifest: visitorsCore.visit(arg.type, scope.typeManifestVisitor)
|
|
1201
1514
|
}));
|
|
1515
|
+
const argDefaultValues = new Map(
|
|
1516
|
+
allArgManifests.flatMap(({ arg, manifest }) => {
|
|
1517
|
+
if (arg.defaultValue == null) return [];
|
|
1518
|
+
const needsRenderedDefault = isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node) || arg.defaultValue.kind !== "accountBumpValueNode";
|
|
1519
|
+
if (!needsRenderedDefault) return [];
|
|
1520
|
+
return [
|
|
1521
|
+
[
|
|
1522
|
+
arg,
|
|
1523
|
+
getDartValueFragment(arg.defaultValue, manifest.type.content)
|
|
1524
|
+
]
|
|
1525
|
+
];
|
|
1526
|
+
})
|
|
1527
|
+
);
|
|
1528
|
+
for (const arg of allArgs.filter(
|
|
1529
|
+
(candidate) => isDiscriminatorArg(candidate, node)
|
|
1530
|
+
)) {
|
|
1531
|
+
if (!argDefaultValues.has(arg)) {
|
|
1532
|
+
throw new Error(
|
|
1533
|
+
`Field discriminator "${arg.name}" on instruction "${node.name}" must reference a field with a default value.`
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1202
1537
|
const dataFieldDecls = allArgManifests.map(({ arg, manifest }) => {
|
|
1203
1538
|
const fieldName = camelCase(arg.name);
|
|
1204
1539
|
return ` final ${manifest.type.content} ${fieldName};`;
|
|
1205
1540
|
}).join("\n");
|
|
1206
1541
|
const dataCtorParams = allArgManifests.map(({ arg, manifest }) => {
|
|
1207
1542
|
const fieldName = camelCase(arg.name);
|
|
1543
|
+
if (isOmittedDefaultArgument(arg)) return "";
|
|
1208
1544
|
if (isDiscriminatorArg(arg, node)) {
|
|
1209
|
-
return isConstDefaultValue(arg.defaultValue) ? ` this.${fieldName} = ${
|
|
1545
|
+
return isConstDefaultValue(arg.defaultValue) ? ` this.${fieldName} = ${argDefaultValues.get(arg).content},` : ` ${manifest.type.content}? ${fieldName},`;
|
|
1210
1546
|
}
|
|
1211
1547
|
return ` required this.${fieldName},`;
|
|
1212
|
-
}).join("\n");
|
|
1548
|
+
}).filter(Boolean).join("\n");
|
|
1213
1549
|
const dataCtorInitializers = allArgManifests.map(({ arg }) => {
|
|
1214
1550
|
const fieldName = camelCase(arg.name);
|
|
1551
|
+
if (isOmittedDefaultArgument(arg)) {
|
|
1552
|
+
return ` ${fieldName} = ${argDefaultValues.get(arg).content}`;
|
|
1553
|
+
}
|
|
1215
1554
|
if (isDiscriminatorArg(arg, node) && !isConstDefaultValue(arg.defaultValue)) {
|
|
1216
|
-
return ` ${fieldName} = ${fieldName} ?? ${
|
|
1555
|
+
return ` ${fieldName} = ${fieldName} ?? ${argDefaultValues.get(arg).content}`;
|
|
1217
1556
|
}
|
|
1218
1557
|
return null;
|
|
1219
1558
|
}).filter((value) => value !== null).join(",\n");
|
|
@@ -1223,16 +1562,26 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1223
1562
|
const decFields = allArgManifests.map(({ arg, manifest }) => {
|
|
1224
1563
|
return ` ('${arg.name}', ${manifest.decoder.content}),`;
|
|
1225
1564
|
}).join("\n");
|
|
1226
|
-
const toMapFields = allArgs.map(
|
|
1227
|
-
(arg)
|
|
1228
|
-
|
|
1229
|
-
|
|
1565
|
+
const toMapFields = allArgs.map((arg) => {
|
|
1566
|
+
const value = isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node) ? argDefaultValues.get(arg).content : `value.${camelCase(arg.name)}`;
|
|
1567
|
+
return ` '${arg.name}': ${value},`;
|
|
1568
|
+
}).join("\n");
|
|
1569
|
+
const fromMapFields = allArgManifests.filter(({ arg }) => !isOmittedDefaultArgument(arg)).map(({ arg, manifest }) => {
|
|
1230
1570
|
const typeStr = manifest.type.content;
|
|
1231
1571
|
const isNullable = typeStr.endsWith("?");
|
|
1232
1572
|
const accessor = isNullable ? `map['${arg.name}']` : `map['${arg.name}']!`;
|
|
1233
1573
|
return ` ${camelCase(arg.name)}: ${accessor} as ${typeStr},`;
|
|
1234
1574
|
}).join("\n");
|
|
1235
|
-
const dataCtorKeyword =
|
|
1575
|
+
const dataCtorKeyword = allArgs.every(
|
|
1576
|
+
(arg) => !isOmittedDefaultArgument(arg) || isConstDartValueNode(arg.defaultValue)
|
|
1577
|
+
) && allArgs.every(
|
|
1578
|
+
(arg) => !isDiscriminatorArg(arg, node) || isConstDefaultValue(arg.defaultValue)
|
|
1579
|
+
) ? "const " : "";
|
|
1580
|
+
const dataCtorSignature = dataCtorParams ? `${dataCtorKeyword}${dataClassName}({
|
|
1581
|
+
${dataCtorParams}
|
|
1582
|
+
})${dataCtorInitializers ? ` :
|
|
1583
|
+
${dataCtorInitializers}` : ""};` : `${dataCtorKeyword}${dataClassName}()${dataCtorInitializers ? ` :
|
|
1584
|
+
${dataCtorInitializers}` : ""};`;
|
|
1236
1585
|
const dataEncoderName = `get${typeName}InstructionDataEncoder`;
|
|
1237
1586
|
const dataDecoderName = `get${typeName}InstructionDataDecoder`;
|
|
1238
1587
|
const dataCodecName = `get${typeName}InstructionDataCodec`;
|
|
@@ -1262,20 +1611,33 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1262
1611
|
const role = getAccountRole(acc);
|
|
1263
1612
|
const isOptional = acc.isOptional ?? false;
|
|
1264
1613
|
if (isOptional) {
|
|
1265
|
-
|
|
1614
|
+
if (optionalAccountStrategy === "omitted") {
|
|
1615
|
+
return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}),`;
|
|
1616
|
+
}
|
|
1617
|
+
return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}) else AccountMeta(address: ${instrProgramParam}, role: AccountRole.readonly),`;
|
|
1266
1618
|
}
|
|
1267
1619
|
return ` AccountMeta(address: ${fieldName}, role: ${role}),`;
|
|
1268
1620
|
}).join("\n");
|
|
1269
1621
|
const dataConstruction = allArgs.map((arg) => {
|
|
1270
1622
|
const fieldName = camelCase(arg.name);
|
|
1271
|
-
if (isDiscriminatorArg(arg, node)) {
|
|
1623
|
+
if (isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node)) {
|
|
1272
1624
|
return "";
|
|
1273
1625
|
}
|
|
1274
|
-
const typeStr2 = argManifestMap.get(arg)?.type.content;
|
|
1275
1626
|
const skipDefault = arg.defaultValue?.kind === "accountBumpValueNode";
|
|
1276
|
-
return ` ${fieldName}: ${fieldName}${arg.defaultValue != null && !skipDefault ? ` ?? ${
|
|
1627
|
+
return ` ${fieldName}: ${fieldName}${arg.defaultValue != null && !skipDefault ? ` ?? ${argDefaultValues.get(arg).content}` : ""},`;
|
|
1277
1628
|
}).filter(Boolean).join("\n");
|
|
1278
1629
|
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
1630
|
+
const discriminatorValidation = getDiscriminatorValidationFragment(
|
|
1631
|
+
node,
|
|
1632
|
+
scope
|
|
1633
|
+
);
|
|
1634
|
+
const topLevelDecoder = getTopLevelDecoderFragment({
|
|
1635
|
+
typeName: dataClassName,
|
|
1636
|
+
description: `${name} instruction decoder`,
|
|
1637
|
+
discriminatorValidation,
|
|
1638
|
+
fromMapFields,
|
|
1639
|
+
requireExactConsumption: true
|
|
1640
|
+
});
|
|
1279
1641
|
const parts = [
|
|
1280
1642
|
fragment`// Auto-generated. Do not edit.
|
|
1281
1643
|
// ignore_for_file: type=lint
|
|
@@ -1299,10 +1661,7 @@ ${use("AccountRole", "solanaInstructions")}`
|
|
|
1299
1661
|
parts.push(fragment`
|
|
1300
1662
|
@immutable
|
|
1301
1663
|
class ${fragmentFromString(dataClassName)} {
|
|
1302
|
-
${fragmentFromString(
|
|
1303
|
-
${fragmentFromString(dataCtorParams)}
|
|
1304
|
-
})${fragmentFromString(dataCtorInitializers ? ` :
|
|
1305
|
-
${dataCtorInitializers}` : "")};
|
|
1664
|
+
${fragmentFromString(dataCtorSignature)}
|
|
1306
1665
|
|
|
1307
1666
|
${fragmentFromString(dataFieldDecls)}
|
|
1308
1667
|
}`);
|
|
@@ -1325,12 +1684,7 @@ Decoder<${fragmentFromString(dataClassName)}> ${fragmentFromString(dataDecoderNa
|
|
|
1325
1684
|
${fragmentFromString(decFields)}
|
|
1326
1685
|
]);
|
|
1327
1686
|
|
|
1328
|
-
|
|
1329
|
-
structDecoder,
|
|
1330
|
-
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(dataClassName)}(
|
|
1331
|
-
${fragmentFromString(fromMapFields)}
|
|
1332
|
-
),
|
|
1333
|
-
);
|
|
1687
|
+
${topLevelDecoder}
|
|
1334
1688
|
}
|
|
1335
1689
|
|
|
1336
1690
|
Codec<${fragmentFromString(dataClassName)}, ${fragmentFromString(dataClassName)}> ${fragmentFromString(dataCodecName)}() {
|
|
@@ -1366,6 +1720,9 @@ ${fragmentFromString(dataClassName)} ${fragmentFromString(parseFnName)}(Instruct
|
|
|
1366
1720
|
result.imports.mergeWith(manifest.decoder.imports);
|
|
1367
1721
|
result.imports.mergeWith(manifest.type.imports);
|
|
1368
1722
|
}
|
|
1723
|
+
for (const defaultValue of argDefaultValues.values()) {
|
|
1724
|
+
result.imports.mergeWith(defaultValue.imports);
|
|
1725
|
+
}
|
|
1369
1726
|
return result;
|
|
1370
1727
|
}
|
|
1371
1728
|
function getAccountRole(acc) {
|
|
@@ -1382,19 +1739,6 @@ function isDiscriminatorArg(arg, node) {
|
|
|
1382
1739
|
(d) => d.kind === "fieldDiscriminatorNode" && d.name === arg.name
|
|
1383
1740
|
);
|
|
1384
1741
|
}
|
|
1385
|
-
function getDiscriminatorDefault(arg, _node) {
|
|
1386
|
-
if (arg.defaultValue) {
|
|
1387
|
-
if (arg.defaultValue.kind === "numberValueNode") {
|
|
1388
|
-
return String(arg.defaultValue.number);
|
|
1389
|
-
}
|
|
1390
|
-
if (arg.defaultValue.kind === "bytesValueNode") {
|
|
1391
|
-
const data = arg.defaultValue.data;
|
|
1392
|
-
const bytes = data.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? [];
|
|
1393
|
-
return `Uint8List.fromList([${bytes.join(", ")}])`;
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
return "0";
|
|
1397
|
-
}
|
|
1398
1742
|
function isConstDefaultValue(defaultValue) {
|
|
1399
1743
|
if (!defaultValue) return false;
|
|
1400
1744
|
switch (defaultValue.kind) {
|
|
@@ -1407,34 +1751,8 @@ function isConstDefaultValue(defaultValue) {
|
|
|
1407
1751
|
return false;
|
|
1408
1752
|
}
|
|
1409
1753
|
}
|
|
1410
|
-
function
|
|
1411
|
-
|
|
1412
|
-
const isBigInt = typeStr === "BigInt";
|
|
1413
|
-
const dv = arg.defaultValue;
|
|
1414
|
-
switch (dv.kind) {
|
|
1415
|
-
case "numberValueNode":
|
|
1416
|
-
return isBigInt ? `BigInt.from(${dv.number})` : String(dv.number);
|
|
1417
|
-
case "booleanValueNode":
|
|
1418
|
-
return String(dv.boolean);
|
|
1419
|
-
case "stringValueNode":
|
|
1420
|
-
return `'${dv.string}'`;
|
|
1421
|
-
case "publicKeyValueNode": {
|
|
1422
|
-
const wellKnownName = WELL_KNOWN_ADDRESSES.get(dv.publicKey);
|
|
1423
|
-
if (wellKnownName) {
|
|
1424
|
-
use(wellKnownName, "solanaAddresses");
|
|
1425
|
-
return wellKnownName;
|
|
1426
|
-
}
|
|
1427
|
-
return `Address('${dv.publicKey}')`;
|
|
1428
|
-
}
|
|
1429
|
-
case "noneValueNode":
|
|
1430
|
-
return "null";
|
|
1431
|
-
case "bytesValueNode": {
|
|
1432
|
-
const bytes = dv.data.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? [];
|
|
1433
|
-
return `Uint8List.fromList([${bytes.join(", ")}])`;
|
|
1434
|
-
}
|
|
1435
|
-
default:
|
|
1436
|
-
return "null";
|
|
1437
|
-
}
|
|
1754
|
+
function isOmittedDefaultArgument(arg) {
|
|
1755
|
+
return arg.defaultValue != null && arg.defaultValueStrategy === "omitted";
|
|
1438
1756
|
}
|
|
1439
1757
|
function getPdaPageFragment(node, scope) {
|
|
1440
1758
|
const name = node.name;
|
|
@@ -1729,25 +2047,26 @@ function getTypePageFragment(node, scope) {
|
|
|
1729
2047
|
scope.nameApi.dataType(name);
|
|
1730
2048
|
const typeNode = node.type;
|
|
1731
2049
|
if (typeNode.kind === "enumTypeNode") {
|
|
1732
|
-
const
|
|
2050
|
+
const variants = typeNode.variants ?? [];
|
|
2051
|
+
const isScalar = variants.every(
|
|
1733
2052
|
(v) => v.kind === "enumEmptyVariantTypeNode"
|
|
1734
2053
|
);
|
|
1735
2054
|
if (isScalar) {
|
|
1736
|
-
return getScalarEnumPageFragment(node, scope);
|
|
2055
|
+
return getScalarEnumPageFragment(node, variants, scope);
|
|
1737
2056
|
}
|
|
1738
|
-
return getDataEnumPageFragment(node, scope);
|
|
2057
|
+
return getDataEnumPageFragment(node, variants, scope);
|
|
1739
2058
|
}
|
|
1740
2059
|
if (typeNode.kind === "structTypeNode") {
|
|
1741
2060
|
return getStructPageFragment(node, scope);
|
|
1742
2061
|
}
|
|
1743
2062
|
return getTypeAliasPageFragment(node, scope);
|
|
1744
2063
|
}
|
|
1745
|
-
function getScalarEnumPageFragment(node, scope) {
|
|
2064
|
+
function getScalarEnumPageFragment(node, enumVariants, scope) {
|
|
1746
2065
|
const name = node.name;
|
|
1747
2066
|
const typeName = scope.nameApi.dataType(name);
|
|
1748
2067
|
const enumNode = node.type;
|
|
1749
2068
|
if (enumNode.kind !== "enumTypeNode") return emptyFragment();
|
|
1750
|
-
const variants =
|
|
2069
|
+
const variants = enumVariants.map((v) => {
|
|
1751
2070
|
const variantName = scope.nameApi.enumVariant(v.name);
|
|
1752
2071
|
return variantName;
|
|
1753
2072
|
});
|
|
@@ -1758,6 +2077,14 @@ function getScalarEnumPageFragment(node, scope) {
|
|
|
1758
2077
|
const resolvedSize = nodes.resolveNestedTypeNode(enumNode.size);
|
|
1759
2078
|
const sizeType = resolvedSize.format ?? "u8";
|
|
1760
2079
|
const sizeCodecName = getNumberCodecName2(sizeType);
|
|
2080
|
+
const isU64 = sizeType === "u64";
|
|
2081
|
+
const encodedVariantIndex = isU64 ? "BigInt.from(value.index)" : "value.index";
|
|
2082
|
+
const decodedVariant = isU64 ? `(BigInt value, Uint8List bytes, int offset) {
|
|
2083
|
+
if (value.isNegative || value >= BigInt.from(${typeName}.values.length)) {
|
|
2084
|
+
throw RangeError('Invalid ${typeName} discriminator: ' + value.toString());
|
|
2085
|
+
}
|
|
2086
|
+
return ${typeName}.values[value.toInt()];
|
|
2087
|
+
}` : `(int value, Uint8List bytes, int offset) => ${typeName}.values[value]`;
|
|
1761
2088
|
return fragment`// Auto-generated. Do not edit.
|
|
1762
2089
|
// ignore_for_file: type=lint
|
|
1763
2090
|
|
|
@@ -1778,14 +2105,14 @@ ${fragmentFromString(variantLines)}
|
|
|
1778
2105
|
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
1779
2106
|
return transformEncoder(
|
|
1780
2107
|
get${fragmentFromString(sizeCodecName)}Encoder(),
|
|
1781
|
-
(${fragmentFromString(typeName)} value) =>
|
|
2108
|
+
(${fragmentFromString(typeName)} value) => ${fragmentFromString(encodedVariantIndex)},
|
|
1782
2109
|
);
|
|
1783
2110
|
}
|
|
1784
2111
|
|
|
1785
2112
|
Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
1786
2113
|
return transformDecoder(
|
|
1787
2114
|
get${fragmentFromString(sizeCodecName)}Decoder(),
|
|
1788
|
-
|
|
2115
|
+
${fragmentFromString(decodedVariant)},
|
|
1789
2116
|
);
|
|
1790
2117
|
}
|
|
1791
2118
|
|
|
@@ -1793,7 +2120,7 @@ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragme
|
|
|
1793
2120
|
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
1794
2121
|
}`;
|
|
1795
2122
|
}
|
|
1796
|
-
function getDataEnumPageFragment(node, scope) {
|
|
2123
|
+
function getDataEnumPageFragment(node, variants, scope) {
|
|
1797
2124
|
const name = node.name;
|
|
1798
2125
|
const typeName = scope.nameApi.dataType(name);
|
|
1799
2126
|
const enumNode = node.type;
|
|
@@ -1804,8 +2131,8 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1804
2131
|
const encodeCases = [];
|
|
1805
2132
|
const decodeCases = [];
|
|
1806
2133
|
const allVariantManifests = [];
|
|
1807
|
-
for (let i = 0; i <
|
|
1808
|
-
const variant =
|
|
2134
|
+
for (let i = 0; i < variants.length; i++) {
|
|
2135
|
+
const variant = variants[i];
|
|
1809
2136
|
const variantName = pascalCase(variant.name);
|
|
1810
2137
|
const variantClassName = scope.nameApi.sealedClassVariant(
|
|
1811
2138
|
name,
|
|
@@ -1835,7 +2162,7 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1835
2162
|
decodeCases.push(`case ${i}: return const ${variantClassName}();`);
|
|
1836
2163
|
} else if (variant.kind === "enumStructVariantTypeNode") {
|
|
1837
2164
|
const resolvedStruct = nodes.resolveNestedTypeNode(variant.struct);
|
|
1838
|
-
const fields = resolvedStruct.fields;
|
|
2165
|
+
const fields = resolvedStruct.fields ?? [];
|
|
1839
2166
|
const fieldManifests = fields.map((f) => ({
|
|
1840
2167
|
field: f,
|
|
1841
2168
|
manifest: visitorsCore.visit(f.type, scope.typeManifestVisitor)
|
|
@@ -1901,7 +2228,7 @@ ${fieldDecls}
|
|
|
1901
2228
|
decodeCases.push(`case ${i}: return ${variantClassName}(${fromMapFields.replace(/\n/g, " ").replace(/,$/, "")});`);
|
|
1902
2229
|
} else if (variant.kind === "enumTupleVariantTypeNode") {
|
|
1903
2230
|
const resolvedTuple = nodes.resolveNestedTypeNode(variant.tuple);
|
|
1904
|
-
const items = resolvedTuple.items;
|
|
2231
|
+
const items = resolvedTuple.items ?? [];
|
|
1905
2232
|
if (items.length === 1) {
|
|
1906
2233
|
const manifest = visitorsCore.visit(items[0], scope.typeManifestVisitor);
|
|
1907
2234
|
allVariantManifests.push(manifest);
|
|
@@ -2001,7 +2328,7 @@ function getStructPageFragment(node, scope) {
|
|
|
2001
2328
|
const typeName = scope.nameApi.dataType(name);
|
|
2002
2329
|
const structNode = node.type;
|
|
2003
2330
|
if (structNode.kind !== "structTypeNode") return emptyFragment();
|
|
2004
|
-
const fields = structNode.fields;
|
|
2331
|
+
const fields = structNode.fields ?? [];
|
|
2005
2332
|
const fieldManifests = fields.map((f) => ({
|
|
2006
2333
|
field: f,
|
|
2007
2334
|
manifest: visitorsCore.visit(f.type, scope.typeManifestVisitor)
|
|
@@ -2208,7 +2535,7 @@ function getRenderMapVisitor(options = {}) {
|
|
|
2208
2535
|
visitRoot(node, { self }) {
|
|
2209
2536
|
const programMaps = [
|
|
2210
2537
|
visitorsCore.visit(node.program, self),
|
|
2211
|
-
...node.additionalPrograms.map((p) => visitorsCore.visit(p, self))
|
|
2538
|
+
...(node.additionalPrograms ?? []).map((p) => visitorsCore.visit(p, self))
|
|
2212
2539
|
];
|
|
2213
2540
|
const mergedProgramMap = renderersCore.mergeRenderMaps(programMaps);
|
|
2214
2541
|
const categoryMaps = getSharedCategoryIndexMaps(mergedProgramMap);
|
|
@@ -2354,11 +2681,12 @@ function renderVisitor(outputDir, options = {}) {
|
|
|
2354
2681
|
dependencyMap
|
|
2355
2682
|
} = options;
|
|
2356
2683
|
return visitorsCore.rootNodeVisitor((root) => {
|
|
2684
|
+
const normalizedRoot = normalizeRootNode(root);
|
|
2357
2685
|
if (deleteFolderBeforeRendering && fs.existsSync(outputDir)) {
|
|
2358
2686
|
renderersCore.deleteDirectory(outputDir);
|
|
2359
2687
|
}
|
|
2360
2688
|
const renderMap = visitorsCore.visit(
|
|
2361
|
-
|
|
2689
|
+
normalizedRoot,
|
|
2362
2690
|
getRenderMapVisitor({ nameApi, dependencyMap })
|
|
2363
2691
|
);
|
|
2364
2692
|
const typePathMap = {};
|
|
@@ -2446,6 +2774,7 @@ exports.createDartNameApi = createDartNameApi;
|
|
|
2446
2774
|
exports.default = src_default;
|
|
2447
2775
|
exports.getRenderMapVisitor = getRenderMapVisitor;
|
|
2448
2776
|
exports.getTypeManifestVisitor = getTypeManifestVisitor;
|
|
2777
|
+
exports.normalizeRootNode = normalizeRootNode;
|
|
2449
2778
|
exports.renderVisitor = renderVisitor;
|
|
2450
2779
|
//# sourceMappingURL=index.browser.cjs.map
|
|
2451
2780
|
//# sourceMappingURL=index.browser.cjs.map
|