codama-renderers-dart 0.5.0 → 0.5.3
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/{readme.md → README.md} +38 -42
- package/dist/index.browser.cjs +628 -147
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +628 -148
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +628 -147
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +628 -148
- package/dist/index.node.js.map +1 -1
- package/dist/index.react-native.js +628 -148
- 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/nameTransformers.d.ts +5 -0
- package/dist/types/utils/nameTransformers.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/src/fragments/accountPage.ts +90 -17
- package/src/fragments/instructionPage.ts +112 -79
- package/src/fragments/typePage.ts +134 -31
- 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/nameTransformers.ts +28 -1
- 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 +37 -14
- package/src/visitors/renderVisitor.ts +4 -1
package/dist/index.browser.js
CHANGED
|
@@ -8,13 +8,71 @@ import { CodamaError, CODAMA_ERROR__UNEXPECTED_NODE_KIND } from '@codama/errors'
|
|
|
8
8
|
|
|
9
9
|
// src/visitors/renderVisitor.ts
|
|
10
10
|
function formatDartDirectory(dir) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
execSync(`dart format "${dir}"`, {
|
|
12
|
+
encoding: "utf-8",
|
|
13
|
+
timeout: 6e4,
|
|
14
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/utils/normalizeRootNode.ts
|
|
19
|
+
function normalizeRootNode(root) {
|
|
20
|
+
return normalizeNode(root);
|
|
21
|
+
}
|
|
22
|
+
function normalizeNode(value) {
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
return value.map(normalizeNode);
|
|
25
|
+
}
|
|
26
|
+
if (!isRecord(value)) {
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
const normalized = Object.fromEntries(
|
|
30
|
+
Object.entries(value).map(([key, child]) => [key, normalizeNode(child)])
|
|
31
|
+
);
|
|
32
|
+
switch (normalized.kind) {
|
|
33
|
+
case "rootNode":
|
|
34
|
+
setEmptyCollection(normalized, "additionalPrograms");
|
|
35
|
+
break;
|
|
36
|
+
case "programNode":
|
|
37
|
+
setEmptyCollection(normalized, "accounts");
|
|
38
|
+
setEmptyCollection(normalized, "constants");
|
|
39
|
+
setEmptyCollection(normalized, "definedTypes");
|
|
40
|
+
setEmptyCollection(normalized, "errors");
|
|
41
|
+
setEmptyCollection(normalized, "events");
|
|
42
|
+
setEmptyCollection(normalized, "instructions");
|
|
43
|
+
setEmptyCollection(normalized, "pdas");
|
|
44
|
+
break;
|
|
45
|
+
case "instructionNode":
|
|
46
|
+
setEmptyCollection(normalized, "accounts");
|
|
47
|
+
setEmptyCollection(normalized, "arguments");
|
|
48
|
+
break;
|
|
49
|
+
case "pdaNode":
|
|
50
|
+
setEmptyCollection(normalized, "seeds");
|
|
51
|
+
break;
|
|
52
|
+
case "structTypeNode":
|
|
53
|
+
setEmptyCollection(normalized, "fields");
|
|
54
|
+
break;
|
|
55
|
+
case "enumTypeNode":
|
|
56
|
+
setEmptyCollection(normalized, "variants");
|
|
57
|
+
break;
|
|
58
|
+
case "tupleTypeNode":
|
|
59
|
+
setEmptyCollection(normalized, "items");
|
|
60
|
+
break;
|
|
61
|
+
case "hiddenPrefixTypeNode":
|
|
62
|
+
setEmptyCollection(normalized, "prefix");
|
|
63
|
+
break;
|
|
64
|
+
case "hiddenSuffixTypeNode":
|
|
65
|
+
setEmptyCollection(normalized, "suffix");
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
return normalized;
|
|
69
|
+
}
|
|
70
|
+
function isRecord(value) {
|
|
71
|
+
return typeof value === "object" && value !== null;
|
|
72
|
+
}
|
|
73
|
+
function setEmptyCollection(record, key) {
|
|
74
|
+
if (record[key] === void 0) {
|
|
75
|
+
record[key] = [];
|
|
18
76
|
}
|
|
19
77
|
}
|
|
20
78
|
|
|
@@ -22,9 +80,83 @@ function formatDartDirectory(dir) {
|
|
|
22
80
|
function pascalCase(str) {
|
|
23
81
|
return str.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : "").replace(/^(.)/, (c) => c.toUpperCase());
|
|
24
82
|
}
|
|
83
|
+
var DART_RESERVED_WORDS = /* @__PURE__ */ new Set([
|
|
84
|
+
"abstract",
|
|
85
|
+
"as",
|
|
86
|
+
"assert",
|
|
87
|
+
"async",
|
|
88
|
+
"augment",
|
|
89
|
+
"await",
|
|
90
|
+
"base",
|
|
91
|
+
"break",
|
|
92
|
+
"case",
|
|
93
|
+
"catch",
|
|
94
|
+
"class",
|
|
95
|
+
"const",
|
|
96
|
+
"continue",
|
|
97
|
+
"covariant",
|
|
98
|
+
"default",
|
|
99
|
+
"deferred",
|
|
100
|
+
"do",
|
|
101
|
+
"dynamic",
|
|
102
|
+
"else",
|
|
103
|
+
"enum",
|
|
104
|
+
"export",
|
|
105
|
+
"extends",
|
|
106
|
+
"extension",
|
|
107
|
+
"external",
|
|
108
|
+
"factory",
|
|
109
|
+
"false",
|
|
110
|
+
"final",
|
|
111
|
+
"finally",
|
|
112
|
+
"for",
|
|
113
|
+
"get",
|
|
114
|
+
"hide",
|
|
115
|
+
"if",
|
|
116
|
+
"implements",
|
|
117
|
+
"import",
|
|
118
|
+
"in",
|
|
119
|
+
"interface",
|
|
120
|
+
"is",
|
|
121
|
+
"late",
|
|
122
|
+
"library",
|
|
123
|
+
"mixin",
|
|
124
|
+
"native",
|
|
125
|
+
"new",
|
|
126
|
+
"null",
|
|
127
|
+
"of",
|
|
128
|
+
"on",
|
|
129
|
+
"operator",
|
|
130
|
+
"part",
|
|
131
|
+
"required",
|
|
132
|
+
"rethrow",
|
|
133
|
+
"return",
|
|
134
|
+
"sealed",
|
|
135
|
+
"set",
|
|
136
|
+
"show",
|
|
137
|
+
"static",
|
|
138
|
+
"super",
|
|
139
|
+
"switch",
|
|
140
|
+
"sync",
|
|
141
|
+
"this",
|
|
142
|
+
"throw",
|
|
143
|
+
"true",
|
|
144
|
+
"try",
|
|
145
|
+
"typedef",
|
|
146
|
+
"var",
|
|
147
|
+
"void",
|
|
148
|
+
"when",
|
|
149
|
+
"while",
|
|
150
|
+
"with",
|
|
151
|
+
"yield"
|
|
152
|
+
]);
|
|
153
|
+
function escapeDartIdentifier(name) {
|
|
154
|
+
return DART_RESERVED_WORDS.has(name) ? `${name}_` : name;
|
|
155
|
+
}
|
|
25
156
|
function camelCase(str) {
|
|
26
157
|
const pascal = pascalCase(str);
|
|
27
|
-
|
|
158
|
+
const cased = pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
159
|
+
return escapeDartIdentifier(cased);
|
|
28
160
|
}
|
|
29
161
|
function snakeCase(str) {
|
|
30
162
|
return str.replace(/([A-Z])/g, "_$1").replace(/[-\s]+/g, "_").replace(/^_/, "").replace(/_+/g, "_").toLowerCase();
|
|
@@ -204,17 +336,6 @@ function use(typeName, module) {
|
|
|
204
336
|
return { content: typeName, imports };
|
|
205
337
|
}
|
|
206
338
|
|
|
207
|
-
// src/utils/typeManifest.ts
|
|
208
|
-
function emptyTypeManifest() {
|
|
209
|
-
return {
|
|
210
|
-
type: emptyFragment(),
|
|
211
|
-
encoder: emptyFragment(),
|
|
212
|
-
decoder: emptyFragment(),
|
|
213
|
-
value: emptyFragment(),
|
|
214
|
-
isEnum: false
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
339
|
// src/utils/wellKnownAddresses.ts
|
|
219
340
|
var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
|
|
220
341
|
// Agave / Solana native programs
|
|
@@ -269,6 +390,207 @@ var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
|
|
|
269
390
|
["Es9vMFrzaCERm6YKXx6bqKr1Rmd9b5v3J8rM5e4rfF4", "usdtAddress"]
|
|
270
391
|
]);
|
|
271
392
|
|
|
393
|
+
// src/utils/valueNodes.ts
|
|
394
|
+
function getDartValueFragment(value, dartType) {
|
|
395
|
+
switch (value.kind) {
|
|
396
|
+
case "numberValueNode":
|
|
397
|
+
return fragmentFromString(
|
|
398
|
+
dartType === "BigInt" ? `BigInt.from(${value.number})` : String(value.number)
|
|
399
|
+
);
|
|
400
|
+
case "booleanValueNode":
|
|
401
|
+
return fragmentFromString(String(value.boolean));
|
|
402
|
+
case "stringValueNode":
|
|
403
|
+
return fragmentFromString(toDartStringLiteral(value.string));
|
|
404
|
+
case "noneValueNode":
|
|
405
|
+
return fragmentFromString("null");
|
|
406
|
+
case "bytesValueNode": {
|
|
407
|
+
if (value.encoding !== "base16") {
|
|
408
|
+
throw new Error(
|
|
409
|
+
`Unsupported deterministic bytes encoding: ${value.encoding}`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
const clean = value.data.replace(/^0x/, "");
|
|
413
|
+
if (clean.length % 2 !== 0 || !/^[0-9a-f]*$/i.test(clean)) {
|
|
414
|
+
throw new Error(`Invalid hexadecimal bytes value: ${value.data}`);
|
|
415
|
+
}
|
|
416
|
+
const bytes = clean.match(/.{2}/g)?.map((byte) => `0x${byte}`) ?? [];
|
|
417
|
+
return fragment`${use("Uint8List", "dartTypedData")}.fromList([${fragmentFromString(bytes.join(", "))}])`;
|
|
418
|
+
}
|
|
419
|
+
case "publicKeyValueNode": {
|
|
420
|
+
const wellKnownName = WELL_KNOWN_ADDRESSES.get(value.publicKey);
|
|
421
|
+
return wellKnownName ? fragment`${use(wellKnownName, "solanaAddresses")}` : fragment`${use("Address", "solanaAddresses")}(${fragmentFromString(toDartStringLiteral(value.publicKey))})`;
|
|
422
|
+
}
|
|
423
|
+
default:
|
|
424
|
+
throw new Error(
|
|
425
|
+
`Unsupported deterministic Dart value node: ${value.kind}`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
function isConstDartValueNode(value) {
|
|
430
|
+
switch (value.kind) {
|
|
431
|
+
case "numberValueNode":
|
|
432
|
+
case "booleanValueNode":
|
|
433
|
+
case "stringValueNode":
|
|
434
|
+
case "noneValueNode":
|
|
435
|
+
case "publicKeyValueNode":
|
|
436
|
+
return true;
|
|
437
|
+
default:
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function toDartStringLiteral(value) {
|
|
442
|
+
return `'${value.replaceAll("\\", "\\\\").replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll(" ", "\\t").replaceAll("\b", "\\b").replaceAll("\f", "\\f").replaceAll("$", "\\$").replaceAll("'", "\\'")}'`;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// src/utils/discriminators.ts
|
|
446
|
+
function getDiscriminatorValidationFragment(node, scope) {
|
|
447
|
+
const discriminators = node.discriminators ?? [];
|
|
448
|
+
if (discriminators.length === 0) return emptyFragment();
|
|
449
|
+
const fields = getDiscriminatorFields(node);
|
|
450
|
+
const fragments = discriminators.map((discriminator) => {
|
|
451
|
+
switch (discriminator.kind) {
|
|
452
|
+
case "constantDiscriminatorNode":
|
|
453
|
+
return getConstantValidationFragment(
|
|
454
|
+
discriminator.constant,
|
|
455
|
+
discriminator.offset,
|
|
456
|
+
scope
|
|
457
|
+
);
|
|
458
|
+
case "fieldDiscriminatorNode": {
|
|
459
|
+
const field = fields.find(
|
|
460
|
+
(candidate) => candidate.name === discriminator.name
|
|
461
|
+
);
|
|
462
|
+
if (field?.defaultValue == null) {
|
|
463
|
+
throw new Error(
|
|
464
|
+
`Field discriminator "${discriminator.name}" on ${node.kind} "${node.name}" must reference a field with a default value.`
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
return getConstantValidationFragment(
|
|
468
|
+
{
|
|
469
|
+
type: field.type,
|
|
470
|
+
value: field.defaultValue
|
|
471
|
+
},
|
|
472
|
+
discriminator.offset,
|
|
473
|
+
scope
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
case "sizeDiscriminatorNode": {
|
|
477
|
+
if (!Number.isSafeInteger(discriminator.size) || discriminator.size < 0) {
|
|
478
|
+
throw new Error(
|
|
479
|
+
`Discriminator size must be a non-negative safe integer, got ${discriminator.size}.`
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
return fragment`if (bytes.length - offset != ${fragmentFromString(String(discriminator.size))}) {
|
|
483
|
+
throw ${use("SolanaError", "solanaErrors")}(
|
|
484
|
+
${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
|
|
485
|
+
{
|
|
486
|
+
'codecDescription': '${fragmentFromString(node.name)} discriminator',
|
|
487
|
+
'expected': ${fragmentFromString(String(discriminator.size))},
|
|
488
|
+
'bytesLength': bytes.length - offset,
|
|
489
|
+
},
|
|
490
|
+
);
|
|
491
|
+
}`;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
return mergeFragments(fragments, (contents) => contents.join("\n"));
|
|
496
|
+
}
|
|
497
|
+
function getConstantValidationFragment(constant, discriminatorOffset, scope) {
|
|
498
|
+
if (!Number.isSafeInteger(discriminatorOffset) || discriminatorOffset < 0) {
|
|
499
|
+
throw new Error(
|
|
500
|
+
`Discriminator offset must be a non-negative safe integer, got ${discriminatorOffset}.`
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
const manifest = visit(constant.type, scope.typeManifestVisitor);
|
|
504
|
+
const value = getDartValueFragment(
|
|
505
|
+
constant.value,
|
|
506
|
+
manifest.type.content
|
|
507
|
+
);
|
|
508
|
+
return fragment`${use("getConstantDecoder", "solanaCodecsDataStructures")}(
|
|
509
|
+
${manifest.encoder}.encode(${value}),
|
|
510
|
+
).read(bytes, offset + ${fragmentFromString(String(discriminatorOffset))});`;
|
|
511
|
+
}
|
|
512
|
+
function getDiscriminatorFields(node) {
|
|
513
|
+
if (node.kind === "accountNode") {
|
|
514
|
+
return resolveNestedTypeNode(node.data).fields ?? [];
|
|
515
|
+
}
|
|
516
|
+
return (node.arguments ?? []).map(
|
|
517
|
+
(argument) => ({
|
|
518
|
+
...argument,
|
|
519
|
+
kind: "structFieldTypeNode"
|
|
520
|
+
})
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// src/utils/exactDecoder.ts
|
|
525
|
+
function getTopLevelDecoderFragment({
|
|
526
|
+
typeName,
|
|
527
|
+
description,
|
|
528
|
+
discriminatorValidation,
|
|
529
|
+
fromMapFields,
|
|
530
|
+
requireExactConsumption
|
|
531
|
+
}) {
|
|
532
|
+
const validation = discriminatorValidation.content ? ` ${discriminatorValidation.content.replaceAll("\n", "\n ")}
|
|
533
|
+
` : "";
|
|
534
|
+
const consumptionCheck = requireExactConsumption ? ` if (newOffset != bytes.length) {
|
|
535
|
+
throwInvalidByteLength(newOffset - offset, bytes.length - offset);
|
|
536
|
+
}
|
|
537
|
+
` : "";
|
|
538
|
+
const fixedSizeCheck = requireExactConsumption ? "bytesLength != structDecoder.fixedSize" : "bytesLength < structDecoder.fixedSize";
|
|
539
|
+
const result = fragment` Never throwInvalidByteLength(int expected, int bytesLength) {
|
|
540
|
+
throw ${use("SolanaError", "solanaErrors")}(
|
|
541
|
+
${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
|
|
542
|
+
{
|
|
543
|
+
'codecDescription': '${fragmentFromString(description)}',
|
|
544
|
+
'expected': expected,
|
|
545
|
+
'bytesLength': bytesLength,
|
|
546
|
+
},
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
(${fragmentFromString(typeName)}, int) readTopLevel(Uint8List bytes, int offset) {
|
|
551
|
+
${fragmentFromString(validation)} final (map, newOffset) = structDecoder.read(bytes, offset);
|
|
552
|
+
${fragmentFromString(consumptionCheck)}
|
|
553
|
+
return (
|
|
554
|
+
${fragmentFromString(typeName)}(
|
|
555
|
+
${fragmentFromString(fromMapFields)}
|
|
556
|
+
),
|
|
557
|
+
newOffset,
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return switch (structDecoder) {
|
|
562
|
+
${use("FixedSizeDecoder", "solanaCodecsCore")}<Map<String, Object?>>() =>
|
|
563
|
+
${use("FixedSizeDecoder", "solanaCodecsCore")}<${fragmentFromString(typeName)}>(
|
|
564
|
+
fixedSize: structDecoder.fixedSize,
|
|
565
|
+
read: (bytes, offset) {
|
|
566
|
+
final bytesLength = bytes.length - offset;
|
|
567
|
+
if (${fragmentFromString(fixedSizeCheck)}) {
|
|
568
|
+
throwInvalidByteLength(structDecoder.fixedSize, bytesLength);
|
|
569
|
+
}
|
|
570
|
+
return readTopLevel(bytes, offset);
|
|
571
|
+
},
|
|
572
|
+
),
|
|
573
|
+
${use("VariableSizeDecoder", "solanaCodecsCore")}<Map<String, Object?>>() =>
|
|
574
|
+
${use("VariableSizeDecoder", "solanaCodecsCore")}<${fragmentFromString(typeName)}>(
|
|
575
|
+
read: readTopLevel,
|
|
576
|
+
maxSize: structDecoder.maxSize,
|
|
577
|
+
),
|
|
578
|
+
};`;
|
|
579
|
+
result.imports.mergeWith(discriminatorValidation.imports);
|
|
580
|
+
return result;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// src/utils/typeManifest.ts
|
|
584
|
+
function emptyTypeManifest() {
|
|
585
|
+
return {
|
|
586
|
+
type: emptyFragment(),
|
|
587
|
+
encoder: emptyFragment(),
|
|
588
|
+
decoder: emptyFragment(),
|
|
589
|
+
value: emptyFragment(),
|
|
590
|
+
isEnum: false
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
272
594
|
// src/visitors/getTypeManifestVisitor.ts
|
|
273
595
|
function getTypeManifestVisitor(input) {
|
|
274
596
|
const { nameApi, linkables, nonScalarEnums = [] } = input;
|
|
@@ -412,12 +734,17 @@ function getTypeManifestVisitor(input) {
|
|
|
412
734
|
const itemManifest = visit(node.item, self);
|
|
413
735
|
const encoderSizeExpr = getArraySizeExpression(node, "Encoder");
|
|
414
736
|
const decoderSizeExpr = getArraySizeExpression(node, "Decoder");
|
|
737
|
+
const itemType = fragmentFromString(itemManifest.type.content);
|
|
738
|
+
const itemEncoder = fragment`${use(
|
|
739
|
+
"transformEncoder",
|
|
740
|
+
"solanaCodecsCore"
|
|
741
|
+
)}(${itemManifest.encoder}, (${itemType} value) => value)`;
|
|
415
742
|
return {
|
|
416
743
|
type: fragment`List<${itemManifest.type}>`,
|
|
417
744
|
encoder: fragment`${use(
|
|
418
745
|
"getArrayEncoder",
|
|
419
746
|
"solanaCodecsDataStructures"
|
|
420
|
-
)}(${
|
|
747
|
+
)}(${itemEncoder}${encoderSizeExpr})`,
|
|
421
748
|
decoder: fragment`${use(
|
|
422
749
|
"getArrayDecoder",
|
|
423
750
|
"solanaCodecsDataStructures"
|
|
@@ -464,7 +791,7 @@ function getTypeManifestVisitor(input) {
|
|
|
464
791
|
};
|
|
465
792
|
},
|
|
466
793
|
visitTupleType(node, { self }) {
|
|
467
|
-
const itemManifests = node.items.map((item) => visit(item, self));
|
|
794
|
+
const itemManifests = (node.items ?? []).map((item) => visit(item, self));
|
|
468
795
|
const typeList = itemManifests.map((m) => m.type.content).join(", ");
|
|
469
796
|
const encoderList = itemManifests.map((m) => m.encoder);
|
|
470
797
|
const decoderList = itemManifests.map((m) => m.decoder);
|
|
@@ -473,18 +800,28 @@ function getTypeManifestVisitor(input) {
|
|
|
473
800
|
typeFragment.imports.mergeWith(m.type.imports);
|
|
474
801
|
}
|
|
475
802
|
const encoderListStr = encoderList.map((e) => e.content).join(", ");
|
|
803
|
+
const decoderListStr = decoderList.map((d) => d.content).join(", ");
|
|
804
|
+
let tupleEncoderFn = "getTupleEncoder";
|
|
805
|
+
let tupleDecoderFn = "getTupleDecoder";
|
|
806
|
+
let tupleEncoderArgs = `[${encoderListStr}]`;
|
|
807
|
+
let tupleDecoderArgs = `[${decoderListStr}]`;
|
|
808
|
+
if (itemManifests.length === 2) {
|
|
809
|
+
tupleEncoderFn = "getTuple2Encoder";
|
|
810
|
+
tupleDecoderFn = "getTuple2Decoder";
|
|
811
|
+
tupleEncoderArgs = encoderListStr;
|
|
812
|
+
tupleDecoderArgs = decoderListStr;
|
|
813
|
+
}
|
|
476
814
|
const encoderFrag = fragment`${use(
|
|
477
|
-
|
|
815
|
+
tupleEncoderFn,
|
|
478
816
|
"solanaCodecsDataStructures"
|
|
479
|
-
)}(
|
|
817
|
+
)}(${tupleEncoderArgs})`;
|
|
480
818
|
for (const e of encoderList) {
|
|
481
819
|
encoderFrag.imports.mergeWith(e.imports);
|
|
482
820
|
}
|
|
483
|
-
const decoderListStr = decoderList.map((d) => d.content).join(", ");
|
|
484
821
|
const decoderFrag = fragment`${use(
|
|
485
|
-
|
|
822
|
+
tupleDecoderFn,
|
|
486
823
|
"solanaCodecsDataStructures"
|
|
487
|
-
)}(
|
|
824
|
+
)}(${tupleDecoderArgs})`;
|
|
488
825
|
for (const d of decoderList) {
|
|
489
826
|
decoderFrag.imports.mergeWith(d.imports);
|
|
490
827
|
}
|
|
@@ -497,8 +834,9 @@ function getTypeManifestVisitor(input) {
|
|
|
497
834
|
};
|
|
498
835
|
},
|
|
499
836
|
visitStructType(node, { self }) {
|
|
500
|
-
const
|
|
501
|
-
const
|
|
837
|
+
const nodeFields = node.fields ?? [];
|
|
838
|
+
const fields = nodeFields.map((f) => visit(f, self));
|
|
839
|
+
const fieldNames = nodeFields.map((f) => f.name);
|
|
502
840
|
const typeStr = "Map<String, Object?>";
|
|
503
841
|
const encoderFields = fields.map((f, i) => `('${fieldNames[i]}', ${f.encoder.content})`).join(", ");
|
|
504
842
|
const encoderFrag = fragment`${use(
|
|
@@ -528,7 +866,7 @@ function getTypeManifestVisitor(input) {
|
|
|
528
866
|
return visit(node.type, self);
|
|
529
867
|
},
|
|
530
868
|
visitEnumType(node, { self }) {
|
|
531
|
-
const isScalar = node.variants.every(
|
|
869
|
+
const isScalar = (node.variants ?? []).every(
|
|
532
870
|
(v) => v.kind === "enumEmptyVariantTypeNode"
|
|
533
871
|
);
|
|
534
872
|
if (isScalar) {
|
|
@@ -570,7 +908,10 @@ function getTypeManifestVisitor(input) {
|
|
|
570
908
|
encoder: fragment`${use(
|
|
571
909
|
"getNullableEncoder",
|
|
572
910
|
"solanaCodecsDataStructures"
|
|
573
|
-
)}<${fragmentFromString(itemTypeStr)}>(${
|
|
911
|
+
)}<${fragmentFromString(itemTypeStr)}>(${use(
|
|
912
|
+
"transformEncoder",
|
|
913
|
+
"solanaCodecsCore"
|
|
914
|
+
)}(${itemManifest.encoder}, (${fragmentFromString(itemTypeStr)} value) => value)${fragmentFromString(prefixExpr)}${fragmentFromString(noneValueExpr)})`,
|
|
574
915
|
decoder: fragment`${use(
|
|
575
916
|
"getNullableDecoder",
|
|
576
917
|
"solanaCodecsDataStructures"
|
|
@@ -620,7 +961,7 @@ function getTypeManifestVisitor(input) {
|
|
|
620
961
|
encoder: fragment`${use(
|
|
621
962
|
"fixEncoderSize",
|
|
622
963
|
"solanaCodecsCore"
|
|
623
|
-
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))})`,
|
|
964
|
+
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))}, allowTruncation: false)`,
|
|
624
965
|
decoder: fragment`${use(
|
|
625
966
|
"fixDecoderSize",
|
|
626
967
|
"solanaCodecsCore"
|
|
@@ -658,7 +999,7 @@ function getTypeManifestVisitor(input) {
|
|
|
658
999
|
},
|
|
659
1000
|
visitHiddenPrefixType(node, { self }) {
|
|
660
1001
|
const innerManifest = visit(node.type, self);
|
|
661
|
-
const prefixes = node.prefix.map((p) => getHiddenAffixManifest(p, self));
|
|
1002
|
+
const prefixes = (node.prefix ?? []).map((p) => getHiddenAffixManifest(p, self));
|
|
662
1003
|
const prefixEncoders = prefixes.map((p) => p.encoder.content).join(", ");
|
|
663
1004
|
const prefixDecoders = prefixes.map((p) => p.decoder.content).join(", ");
|
|
664
1005
|
const encoderFrag = fragment`${use(
|
|
@@ -685,7 +1026,7 @@ function getTypeManifestVisitor(input) {
|
|
|
685
1026
|
},
|
|
686
1027
|
visitHiddenSuffixType(node, { self }) {
|
|
687
1028
|
const innerManifest = visit(node.type, self);
|
|
688
|
-
const suffixes = node.suffix.map((s) => getHiddenAffixManifest(s, self));
|
|
1029
|
+
const suffixes = (node.suffix ?? []).map((s) => getHiddenAffixManifest(s, self));
|
|
689
1030
|
const suffixEncoders = suffixes.map((s) => s.encoder.content).join(", ");
|
|
690
1031
|
const suffixDecoders = suffixes.map((s) => s.decoder.content).join(", ");
|
|
691
1032
|
const encoderFrag = fragment`${use(
|
|
@@ -972,19 +1313,52 @@ function hexToBytes(hex) {
|
|
|
972
1313
|
function getAccountPageFragment(node, scope) {
|
|
973
1314
|
const name = node.name;
|
|
974
1315
|
const typeName = scope.nameApi.dataType(name);
|
|
975
|
-
const
|
|
976
|
-
const fields = dataNode.fields;
|
|
1316
|
+
const fields = resolveNestedTypeNode(node.data).fields ?? [];
|
|
977
1317
|
const fieldManifests = fields.map((f) => ({
|
|
978
1318
|
field: f,
|
|
979
1319
|
manifest: visit(f.type, scope.typeManifestVisitor)
|
|
980
1320
|
}));
|
|
1321
|
+
const omittedFields = fields.filter(isOmittedDefaultField);
|
|
1322
|
+
const constructorFields = fields.filter(
|
|
1323
|
+
(field) => !isOmittedDefaultField(field)
|
|
1324
|
+
);
|
|
1325
|
+
const forcedFields = /* @__PURE__ */ new Set([
|
|
1326
|
+
...omittedFields,
|
|
1327
|
+
...fields.filter((field) => isFieldDiscriminator(field, node))
|
|
1328
|
+
]);
|
|
1329
|
+
const fieldDefaults = new Map(
|
|
1330
|
+
fieldManifests.flatMap(({ field, manifest }) => {
|
|
1331
|
+
if (!forcedFields.has(field) || field.defaultValue == null) return [];
|
|
1332
|
+
return [
|
|
1333
|
+
[
|
|
1334
|
+
field,
|
|
1335
|
+
getDartValueFragment(field.defaultValue, manifest.type.content)
|
|
1336
|
+
]
|
|
1337
|
+
];
|
|
1338
|
+
})
|
|
1339
|
+
);
|
|
1340
|
+
for (const field of forcedFields) {
|
|
1341
|
+
if (!fieldDefaults.has(field)) {
|
|
1342
|
+
throw new Error(
|
|
1343
|
+
`Forced field "${field.name}" on account "${node.name}" must have a deterministic default value.`
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
981
1347
|
const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
|
|
982
1348
|
return ` final ${manifest.type.content} ${camelCase(f.name)};`;
|
|
983
1349
|
}).join("\n");
|
|
984
|
-
const ctorParams =
|
|
985
|
-
const
|
|
1350
|
+
const ctorParams = constructorFields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
|
|
1351
|
+
const ctorInitializers = omittedFields.map((field) => {
|
|
1352
|
+
const fieldName = camelCase(field.name);
|
|
1353
|
+
return `${fieldName} = ${fieldDefaults.get(field).content}`;
|
|
1354
|
+
}).join(",\n ");
|
|
1355
|
+
const ctorKeyword = omittedFields.every(
|
|
1356
|
+
(field) => isConstDartValueNode(field.defaultValue)
|
|
1357
|
+
) ? "const " : "";
|
|
1358
|
+
const ctorSignature = constructorFields.length === 0 ? `${ctorKeyword}${typeName}()${ctorInitializers ? ` : ${ctorInitializers}` : ""};` : `${ctorKeyword}${typeName}({
|
|
986
1359
|
${ctorParams}
|
|
987
|
-
})
|
|
1360
|
+
})${ctorInitializers ? ` :
|
|
1361
|
+
${ctorInitializers}` : ""};`;
|
|
988
1362
|
const eqChecks = fields.length === 0 ? "true" : fields.map(
|
|
989
1363
|
(f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`
|
|
990
1364
|
).join(" &&\n ");
|
|
@@ -999,10 +1373,11 @@ ${ctorParams}
|
|
|
999
1373
|
const decFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1000
1374
|
return ` ('${f.name}', ${manifest.decoder.content}),`;
|
|
1001
1375
|
}).join("\n");
|
|
1002
|
-
const toMapFields = fields.map(
|
|
1003
|
-
(f)
|
|
1004
|
-
|
|
1005
|
-
|
|
1376
|
+
const toMapFields = fields.map((f) => {
|
|
1377
|
+
const value = forcedFields.has(f) ? fieldDefaults.get(f).content : `value.${camelCase(f.name)}`;
|
|
1378
|
+
return ` '${f.name}': ${value},`;
|
|
1379
|
+
}).join("\n");
|
|
1380
|
+
const fromMapFields = fieldManifests.filter(({ field }) => !isOmittedDefaultField(field)).map(({ field: f, manifest }) => {
|
|
1006
1381
|
const typeStr = manifest.type.content;
|
|
1007
1382
|
const isNullable = typeStr.endsWith("?");
|
|
1008
1383
|
const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
|
|
@@ -1016,6 +1391,19 @@ ${ctorParams}
|
|
|
1016
1391
|
/// The size of the [${fragmentFromString(typeName)}] account data in bytes.
|
|
1017
1392
|
const int ${fragmentFromString(scope.nameApi.accountSizeConstant(name))} = ${fragmentFromString(String(node.size))};` : emptyFragment();
|
|
1018
1393
|
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
1394
|
+
const discriminatorValidation = getDiscriminatorValidationFragment(
|
|
1395
|
+
node,
|
|
1396
|
+
scope
|
|
1397
|
+
);
|
|
1398
|
+
const topLevelDecoder = getTopLevelDecoderFragment({
|
|
1399
|
+
typeName,
|
|
1400
|
+
description: `${name} account decoder`,
|
|
1401
|
+
discriminatorValidation,
|
|
1402
|
+
fromMapFields,
|
|
1403
|
+
requireExactConsumption: (node.discriminators ?? []).some(
|
|
1404
|
+
(discriminator) => discriminator.kind === "sizeDiscriminatorNode"
|
|
1405
|
+
)
|
|
1406
|
+
});
|
|
1019
1407
|
const parts = [
|
|
1020
1408
|
fragment`// Auto-generated. Do not edit.
|
|
1021
1409
|
// ignore_for_file: type=lint
|
|
@@ -1075,12 +1463,7 @@ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
|
1075
1463
|
${fragmentFromString(decFields)}
|
|
1076
1464
|
]);
|
|
1077
1465
|
|
|
1078
|
-
|
|
1079
|
-
structDecoder,
|
|
1080
|
-
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}(
|
|
1081
|
-
${fragmentFromString(fromMapFields)}
|
|
1082
|
-
),
|
|
1083
|
-
);
|
|
1466
|
+
${topLevelDecoder}
|
|
1084
1467
|
}
|
|
1085
1468
|
|
|
1086
1469
|
Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
|
|
@@ -1096,8 +1479,19 @@ Account<${fragmentFromString(typeName)}> ${fragmentFromString(decodeFnName)}(Enc
|
|
|
1096
1479
|
result.imports.mergeWith(manifest.decoder.imports);
|
|
1097
1480
|
result.imports.mergeWith(manifest.type.imports);
|
|
1098
1481
|
}
|
|
1482
|
+
for (const defaultValue of fieldDefaults.values()) {
|
|
1483
|
+
result.imports.mergeWith(defaultValue.imports);
|
|
1484
|
+
}
|
|
1099
1485
|
return result;
|
|
1100
1486
|
}
|
|
1487
|
+
function isOmittedDefaultField(field) {
|
|
1488
|
+
return field.defaultValue != null && field.defaultValueStrategy === "omitted";
|
|
1489
|
+
}
|
|
1490
|
+
function isFieldDiscriminator(field, node) {
|
|
1491
|
+
return (node.discriminators ?? []).some(
|
|
1492
|
+
(discriminator) => discriminator.kind === "fieldDiscriminatorNode" && discriminator.name === field.name
|
|
1493
|
+
);
|
|
1494
|
+
}
|
|
1101
1495
|
|
|
1102
1496
|
// src/fragments/errorPage.ts
|
|
1103
1497
|
function getErrorPageFragment(programNode, scope) {
|
|
@@ -1158,7 +1552,7 @@ function getIndexPageFragment(fileNames, relativePath = "") {
|
|
|
1158
1552
|
"// Auto-generated. Do not edit.\n// ignore_for_file: type=lint\n"
|
|
1159
1553
|
);
|
|
1160
1554
|
}
|
|
1161
|
-
const exports
|
|
1555
|
+
const exports = fileNames.sort().map((f) => {
|
|
1162
1556
|
const path = relativePath ? `${relativePath}/${f}` : f;
|
|
1163
1557
|
return `export '${path}';`;
|
|
1164
1558
|
}).join("\n");
|
|
@@ -1166,17 +1560,17 @@ function getIndexPageFragment(fileNames, relativePath = "") {
|
|
|
1166
1560
|
`// Auto-generated. Do not edit.
|
|
1167
1561
|
// ignore_for_file: type=lint
|
|
1168
1562
|
|
|
1169
|
-
${exports
|
|
1563
|
+
${exports}
|
|
1170
1564
|
`
|
|
1171
1565
|
);
|
|
1172
1566
|
}
|
|
1173
1567
|
function getRootIndexPageFragment(categories) {
|
|
1174
|
-
const exports
|
|
1568
|
+
const exports = categories.sort().map((cat) => `export '${cat}/${cat}.dart';`).join("\n");
|
|
1175
1569
|
return fragmentFromString(
|
|
1176
1570
|
`// Auto-generated. Do not edit.
|
|
1177
1571
|
// ignore_for_file: type=lint
|
|
1178
1572
|
|
|
1179
|
-
${exports
|
|
1573
|
+
${exports}
|
|
1180
1574
|
`
|
|
1181
1575
|
);
|
|
1182
1576
|
}
|
|
@@ -1186,30 +1580,62 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1186
1580
|
const instrFnName = scope.nameApi.instructionFunction(name);
|
|
1187
1581
|
const parseFnName = scope.nameApi.instructionParseFunction(name);
|
|
1188
1582
|
const accounts = node.accounts ?? [];
|
|
1189
|
-
const args = (node.arguments ?? []).filter(
|
|
1190
|
-
(arg) => !isDiscriminatorArg(arg, node)
|
|
1191
|
-
);
|
|
1192
1583
|
const allArgs = node.arguments ?? [];
|
|
1584
|
+
const optionalAccountStrategy = node.optionalAccountStrategy ?? "programId";
|
|
1585
|
+
if (optionalAccountStrategy !== "programId" && optionalAccountStrategy !== "omitted") {
|
|
1586
|
+
throw new Error(
|
|
1587
|
+
`Unsupported optional account strategy on instruction "${node.name}": ${optionalAccountStrategy}`
|
|
1588
|
+
);
|
|
1589
|
+
}
|
|
1590
|
+
const args = allArgs.filter(
|
|
1591
|
+
(arg) => !isDiscriminatorArg(arg, node) && !isOmittedDefaultArgument(arg)
|
|
1592
|
+
);
|
|
1193
1593
|
const dataClassName = `${typeName}InstructionData`;
|
|
1194
|
-
const allArgManifests =
|
|
1594
|
+
const allArgManifests = (node.arguments ?? []).map((arg) => ({
|
|
1195
1595
|
arg,
|
|
1196
1596
|
manifest: visit(arg.type, scope.typeManifestVisitor)
|
|
1197
1597
|
}));
|
|
1598
|
+
const argDefaultValues = new Map(
|
|
1599
|
+
allArgManifests.flatMap(({ arg, manifest }) => {
|
|
1600
|
+
if (arg.defaultValue == null) return [];
|
|
1601
|
+
const needsRenderedDefault = isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node) || arg.defaultValue.kind !== "accountBumpValueNode";
|
|
1602
|
+
if (!needsRenderedDefault) return [];
|
|
1603
|
+
return [
|
|
1604
|
+
[
|
|
1605
|
+
arg,
|
|
1606
|
+
getDartValueFragment(arg.defaultValue, manifest.type.content)
|
|
1607
|
+
]
|
|
1608
|
+
];
|
|
1609
|
+
})
|
|
1610
|
+
);
|
|
1611
|
+
for (const arg of allArgs.filter(
|
|
1612
|
+
(candidate) => isDiscriminatorArg(candidate, node)
|
|
1613
|
+
)) {
|
|
1614
|
+
if (!argDefaultValues.has(arg)) {
|
|
1615
|
+
throw new Error(
|
|
1616
|
+
`Field discriminator "${arg.name}" on instruction "${node.name}" must reference a field with a default value.`
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1198
1620
|
const dataFieldDecls = allArgManifests.map(({ arg, manifest }) => {
|
|
1199
1621
|
const fieldName = camelCase(arg.name);
|
|
1200
1622
|
return ` final ${manifest.type.content} ${fieldName};`;
|
|
1201
1623
|
}).join("\n");
|
|
1202
1624
|
const dataCtorParams = allArgManifests.map(({ arg, manifest }) => {
|
|
1203
1625
|
const fieldName = camelCase(arg.name);
|
|
1626
|
+
if (isOmittedDefaultArgument(arg)) return "";
|
|
1204
1627
|
if (isDiscriminatorArg(arg, node)) {
|
|
1205
|
-
return isConstDefaultValue(arg.defaultValue) ? ` this.${fieldName} = ${
|
|
1628
|
+
return isConstDefaultValue(arg.defaultValue) ? ` this.${fieldName} = ${argDefaultValues.get(arg).content},` : ` ${manifest.type.content}? ${fieldName},`;
|
|
1206
1629
|
}
|
|
1207
1630
|
return ` required this.${fieldName},`;
|
|
1208
|
-
}).join("\n");
|
|
1631
|
+
}).filter(Boolean).join("\n");
|
|
1209
1632
|
const dataCtorInitializers = allArgManifests.map(({ arg }) => {
|
|
1210
1633
|
const fieldName = camelCase(arg.name);
|
|
1634
|
+
if (isOmittedDefaultArgument(arg)) {
|
|
1635
|
+
return ` ${fieldName} = ${argDefaultValues.get(arg).content}`;
|
|
1636
|
+
}
|
|
1211
1637
|
if (isDiscriminatorArg(arg, node) && !isConstDefaultValue(arg.defaultValue)) {
|
|
1212
|
-
return ` ${fieldName} = ${fieldName} ?? ${
|
|
1638
|
+
return ` ${fieldName} = ${fieldName} ?? ${argDefaultValues.get(arg).content}`;
|
|
1213
1639
|
}
|
|
1214
1640
|
return null;
|
|
1215
1641
|
}).filter((value) => value !== null).join(",\n");
|
|
@@ -1219,16 +1645,26 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1219
1645
|
const decFields = allArgManifests.map(({ arg, manifest }) => {
|
|
1220
1646
|
return ` ('${arg.name}', ${manifest.decoder.content}),`;
|
|
1221
1647
|
}).join("\n");
|
|
1222
|
-
const toMapFields = allArgs.map(
|
|
1223
|
-
(arg)
|
|
1224
|
-
|
|
1225
|
-
|
|
1648
|
+
const toMapFields = allArgs.map((arg) => {
|
|
1649
|
+
const value = isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node) ? argDefaultValues.get(arg).content : `value.${camelCase(arg.name)}`;
|
|
1650
|
+
return ` '${arg.name}': ${value},`;
|
|
1651
|
+
}).join("\n");
|
|
1652
|
+
const fromMapFields = allArgManifests.filter(({ arg }) => !isOmittedDefaultArgument(arg)).map(({ arg, manifest }) => {
|
|
1226
1653
|
const typeStr = manifest.type.content;
|
|
1227
1654
|
const isNullable = typeStr.endsWith("?");
|
|
1228
1655
|
const accessor = isNullable ? `map['${arg.name}']` : `map['${arg.name}']!`;
|
|
1229
1656
|
return ` ${camelCase(arg.name)}: ${accessor} as ${typeStr},`;
|
|
1230
1657
|
}).join("\n");
|
|
1231
|
-
const dataCtorKeyword =
|
|
1658
|
+
const dataCtorKeyword = allArgs.every(
|
|
1659
|
+
(arg) => !isOmittedDefaultArgument(arg) || isConstDartValueNode(arg.defaultValue)
|
|
1660
|
+
) && allArgs.every(
|
|
1661
|
+
(arg) => !isDiscriminatorArg(arg, node) || isConstDefaultValue(arg.defaultValue)
|
|
1662
|
+
) ? "const " : "";
|
|
1663
|
+
const dataCtorSignature = dataCtorParams ? `${dataCtorKeyword}${dataClassName}({
|
|
1664
|
+
${dataCtorParams}
|
|
1665
|
+
})${dataCtorInitializers ? ` :
|
|
1666
|
+
${dataCtorInitializers}` : ""};` : `${dataCtorKeyword}${dataClassName}()${dataCtorInitializers ? ` :
|
|
1667
|
+
${dataCtorInitializers}` : ""};`;
|
|
1232
1668
|
const dataEncoderName = `get${typeName}InstructionDataEncoder`;
|
|
1233
1669
|
const dataDecoderName = `get${typeName}InstructionDataDecoder`;
|
|
1234
1670
|
const dataCodecName = `get${typeName}InstructionDataCodec`;
|
|
@@ -1236,6 +1672,10 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1236
1672
|
const accountNames = new Set(accounts.map((a) => camelCase(a.name)));
|
|
1237
1673
|
const hasProgramAddressCollision = argNames.has("programAddress") || accountNames.has("programAddress");
|
|
1238
1674
|
const instrProgramParam = hasProgramAddressCollision ? "instructionProgramAddress" : "programAddress";
|
|
1675
|
+
let instructionDataLocal = "instructionData";
|
|
1676
|
+
while (argNames.has(instructionDataLocal) || accountNames.has(instructionDataLocal)) {
|
|
1677
|
+
instructionDataLocal = `${instructionDataLocal}_`;
|
|
1678
|
+
}
|
|
1239
1679
|
const accountParams = accounts.map((acc) => {
|
|
1240
1680
|
const fieldName = camelCase(acc.name);
|
|
1241
1681
|
const isRequired = !(acc.isOptional ?? false);
|
|
@@ -1258,20 +1698,33 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1258
1698
|
const role = getAccountRole(acc);
|
|
1259
1699
|
const isOptional = acc.isOptional ?? false;
|
|
1260
1700
|
if (isOptional) {
|
|
1261
|
-
|
|
1701
|
+
if (optionalAccountStrategy === "omitted") {
|
|
1702
|
+
return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}),`;
|
|
1703
|
+
}
|
|
1704
|
+
return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}) else AccountMeta(address: ${instrProgramParam}, role: AccountRole.readonly),`;
|
|
1262
1705
|
}
|
|
1263
1706
|
return ` AccountMeta(address: ${fieldName}, role: ${role}),`;
|
|
1264
1707
|
}).join("\n");
|
|
1265
1708
|
const dataConstruction = allArgs.map((arg) => {
|
|
1266
1709
|
const fieldName = camelCase(arg.name);
|
|
1267
|
-
if (isDiscriminatorArg(arg, node)) {
|
|
1710
|
+
if (isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node)) {
|
|
1268
1711
|
return "";
|
|
1269
1712
|
}
|
|
1270
|
-
const typeStr2 = argManifestMap.get(arg)?.type.content;
|
|
1271
1713
|
const skipDefault = arg.defaultValue?.kind === "accountBumpValueNode";
|
|
1272
|
-
return ` ${fieldName}: ${fieldName}${arg.defaultValue != null && !skipDefault ? ` ?? ${
|
|
1714
|
+
return ` ${fieldName}: ${fieldName}${arg.defaultValue != null && !skipDefault ? ` ?? ${argDefaultValues.get(arg).content}` : ""},`;
|
|
1273
1715
|
}).filter(Boolean).join("\n");
|
|
1274
1716
|
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
1717
|
+
const discriminatorValidation = getDiscriminatorValidationFragment(
|
|
1718
|
+
node,
|
|
1719
|
+
scope
|
|
1720
|
+
);
|
|
1721
|
+
const topLevelDecoder = getTopLevelDecoderFragment({
|
|
1722
|
+
typeName: dataClassName,
|
|
1723
|
+
description: `${name} instruction decoder`,
|
|
1724
|
+
discriminatorValidation,
|
|
1725
|
+
fromMapFields,
|
|
1726
|
+
requireExactConsumption: true
|
|
1727
|
+
});
|
|
1275
1728
|
const parts = [
|
|
1276
1729
|
fragment`// Auto-generated. Do not edit.
|
|
1277
1730
|
// ignore_for_file: type=lint
|
|
@@ -1295,10 +1748,7 @@ ${use("AccountRole", "solanaInstructions")}`
|
|
|
1295
1748
|
parts.push(fragment`
|
|
1296
1749
|
@immutable
|
|
1297
1750
|
class ${fragmentFromString(dataClassName)} {
|
|
1298
|
-
${fragmentFromString(
|
|
1299
|
-
${fragmentFromString(dataCtorParams)}
|
|
1300
|
-
})${fragmentFromString(dataCtorInitializers ? ` :
|
|
1301
|
-
${dataCtorInitializers}` : "")};
|
|
1751
|
+
${fragmentFromString(dataCtorSignature)}
|
|
1302
1752
|
|
|
1303
1753
|
${fragmentFromString(dataFieldDecls)}
|
|
1304
1754
|
}`);
|
|
@@ -1321,12 +1771,7 @@ Decoder<${fragmentFromString(dataClassName)}> ${fragmentFromString(dataDecoderNa
|
|
|
1321
1771
|
${fragmentFromString(decFields)}
|
|
1322
1772
|
]);
|
|
1323
1773
|
|
|
1324
|
-
|
|
1325
|
-
structDecoder,
|
|
1326
|
-
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(dataClassName)}(
|
|
1327
|
-
${fragmentFromString(fromMapFields)}
|
|
1328
|
-
),
|
|
1329
|
-
);
|
|
1774
|
+
${topLevelDecoder}
|
|
1330
1775
|
}
|
|
1331
1776
|
|
|
1332
1777
|
Codec<${fragmentFromString(dataClassName)}, ${fragmentFromString(dataClassName)}> ${fragmentFromString(dataCodecName)}() {
|
|
@@ -1339,7 +1784,7 @@ Instruction ${fragmentFromString(instrFnName)}({
|
|
|
1339
1784
|
${fragmentFromString(accountParams)}
|
|
1340
1785
|
${fragmentFromString(argParams)}
|
|
1341
1786
|
}) {
|
|
1342
|
-
final
|
|
1787
|
+
final ${instructionDataLocal} = ${fragmentFromString(dataClassName)}(
|
|
1343
1788
|
${fragmentFromString(dataConstruction)}
|
|
1344
1789
|
);
|
|
1345
1790
|
|
|
@@ -1348,7 +1793,7 @@ ${fragmentFromString(dataConstruction)}
|
|
|
1348
1793
|
accounts: [
|
|
1349
1794
|
${fragmentFromString(accountMetas)}
|
|
1350
1795
|
],
|
|
1351
|
-
data: ${fragmentFromString(dataEncoderName)}().encode(
|
|
1796
|
+
data: ${fragmentFromString(dataEncoderName)}().encode(${instructionDataLocal}),
|
|
1352
1797
|
);
|
|
1353
1798
|
}`);
|
|
1354
1799
|
parts.push(fragment`
|
|
@@ -1362,6 +1807,9 @@ ${fragmentFromString(dataClassName)} ${fragmentFromString(parseFnName)}(Instruct
|
|
|
1362
1807
|
result.imports.mergeWith(manifest.decoder.imports);
|
|
1363
1808
|
result.imports.mergeWith(manifest.type.imports);
|
|
1364
1809
|
}
|
|
1810
|
+
for (const defaultValue of argDefaultValues.values()) {
|
|
1811
|
+
result.imports.mergeWith(defaultValue.imports);
|
|
1812
|
+
}
|
|
1365
1813
|
return result;
|
|
1366
1814
|
}
|
|
1367
1815
|
function getAccountRole(acc) {
|
|
@@ -1378,19 +1826,6 @@ function isDiscriminatorArg(arg, node) {
|
|
|
1378
1826
|
(d) => d.kind === "fieldDiscriminatorNode" && d.name === arg.name
|
|
1379
1827
|
);
|
|
1380
1828
|
}
|
|
1381
|
-
function getDiscriminatorDefault(arg, _node) {
|
|
1382
|
-
if (arg.defaultValue) {
|
|
1383
|
-
if (arg.defaultValue.kind === "numberValueNode") {
|
|
1384
|
-
return String(arg.defaultValue.number);
|
|
1385
|
-
}
|
|
1386
|
-
if (arg.defaultValue.kind === "bytesValueNode") {
|
|
1387
|
-
const data = arg.defaultValue.data;
|
|
1388
|
-
const bytes = data.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? [];
|
|
1389
|
-
return `Uint8List.fromList([${bytes.join(", ")}])`;
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
return "0";
|
|
1393
|
-
}
|
|
1394
1829
|
function isConstDefaultValue(defaultValue) {
|
|
1395
1830
|
if (!defaultValue) return false;
|
|
1396
1831
|
switch (defaultValue.kind) {
|
|
@@ -1403,34 +1838,8 @@ function isConstDefaultValue(defaultValue) {
|
|
|
1403
1838
|
return false;
|
|
1404
1839
|
}
|
|
1405
1840
|
}
|
|
1406
|
-
function
|
|
1407
|
-
|
|
1408
|
-
const isBigInt = typeStr === "BigInt";
|
|
1409
|
-
const dv = arg.defaultValue;
|
|
1410
|
-
switch (dv.kind) {
|
|
1411
|
-
case "numberValueNode":
|
|
1412
|
-
return isBigInt ? `BigInt.from(${dv.number})` : String(dv.number);
|
|
1413
|
-
case "booleanValueNode":
|
|
1414
|
-
return String(dv.boolean);
|
|
1415
|
-
case "stringValueNode":
|
|
1416
|
-
return `'${dv.string}'`;
|
|
1417
|
-
case "publicKeyValueNode": {
|
|
1418
|
-
const wellKnownName = WELL_KNOWN_ADDRESSES.get(dv.publicKey);
|
|
1419
|
-
if (wellKnownName) {
|
|
1420
|
-
use(wellKnownName, "solanaAddresses");
|
|
1421
|
-
return wellKnownName;
|
|
1422
|
-
}
|
|
1423
|
-
return `Address('${dv.publicKey}')`;
|
|
1424
|
-
}
|
|
1425
|
-
case "noneValueNode":
|
|
1426
|
-
return "null";
|
|
1427
|
-
case "bytesValueNode": {
|
|
1428
|
-
const bytes = dv.data.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? [];
|
|
1429
|
-
return `Uint8List.fromList([${bytes.join(", ")}])`;
|
|
1430
|
-
}
|
|
1431
|
-
default:
|
|
1432
|
-
return "null";
|
|
1433
|
-
}
|
|
1841
|
+
function isOmittedDefaultArgument(arg) {
|
|
1842
|
+
return arg.defaultValue != null && arg.defaultValueStrategy === "omitted";
|
|
1434
1843
|
}
|
|
1435
1844
|
function getPdaPageFragment(node, scope) {
|
|
1436
1845
|
const name = node.name;
|
|
@@ -1725,25 +2134,26 @@ function getTypePageFragment(node, scope) {
|
|
|
1725
2134
|
scope.nameApi.dataType(name);
|
|
1726
2135
|
const typeNode = node.type;
|
|
1727
2136
|
if (typeNode.kind === "enumTypeNode") {
|
|
1728
|
-
const
|
|
2137
|
+
const variants = typeNode.variants ?? [];
|
|
2138
|
+
const isScalar = variants.every(
|
|
1729
2139
|
(v) => v.kind === "enumEmptyVariantTypeNode"
|
|
1730
2140
|
);
|
|
1731
2141
|
if (isScalar) {
|
|
1732
|
-
return getScalarEnumPageFragment(node, scope);
|
|
2142
|
+
return getScalarEnumPageFragment(node, variants, scope);
|
|
1733
2143
|
}
|
|
1734
|
-
return getDataEnumPageFragment(node, scope);
|
|
2144
|
+
return getDataEnumPageFragment(node, variants, scope);
|
|
1735
2145
|
}
|
|
1736
2146
|
if (typeNode.kind === "structTypeNode") {
|
|
1737
2147
|
return getStructPageFragment(node, scope);
|
|
1738
2148
|
}
|
|
1739
2149
|
return getTypeAliasPageFragment(node, scope);
|
|
1740
2150
|
}
|
|
1741
|
-
function getScalarEnumPageFragment(node, scope) {
|
|
2151
|
+
function getScalarEnumPageFragment(node, enumVariants, scope) {
|
|
1742
2152
|
const name = node.name;
|
|
1743
2153
|
const typeName = scope.nameApi.dataType(name);
|
|
1744
2154
|
const enumNode = node.type;
|
|
1745
2155
|
if (enumNode.kind !== "enumTypeNode") return emptyFragment();
|
|
1746
|
-
const variants =
|
|
2156
|
+
const variants = enumVariants.map((v) => {
|
|
1747
2157
|
const variantName = scope.nameApi.enumVariant(v.name);
|
|
1748
2158
|
return variantName;
|
|
1749
2159
|
});
|
|
@@ -1754,6 +2164,14 @@ function getScalarEnumPageFragment(node, scope) {
|
|
|
1754
2164
|
const resolvedSize = resolveNestedTypeNode(enumNode.size);
|
|
1755
2165
|
const sizeType = resolvedSize.format ?? "u8";
|
|
1756
2166
|
const sizeCodecName = getNumberCodecName2(sizeType);
|
|
2167
|
+
const isU64 = sizeType === "u64";
|
|
2168
|
+
const encodedVariantIndex = isU64 ? "BigInt.from(value.index)" : "value.index";
|
|
2169
|
+
const decodedVariant = isU64 ? `(BigInt value, Uint8List bytes, int offset) {
|
|
2170
|
+
if (value.isNegative || value >= BigInt.from(${typeName}.values.length)) {
|
|
2171
|
+
throw RangeError('Invalid ${typeName} discriminator: ' + value.toString());
|
|
2172
|
+
}
|
|
2173
|
+
return ${typeName}.values[value.toInt()];
|
|
2174
|
+
}` : `(int value, Uint8List bytes, int offset) => ${typeName}.values[value]`;
|
|
1757
2175
|
return fragment`// Auto-generated. Do not edit.
|
|
1758
2176
|
// ignore_for_file: type=lint
|
|
1759
2177
|
|
|
@@ -1774,14 +2192,14 @@ ${fragmentFromString(variantLines)}
|
|
|
1774
2192
|
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
1775
2193
|
return transformEncoder(
|
|
1776
2194
|
get${fragmentFromString(sizeCodecName)}Encoder(),
|
|
1777
|
-
(${fragmentFromString(typeName)} value) =>
|
|
2195
|
+
(${fragmentFromString(typeName)} value) => ${fragmentFromString(encodedVariantIndex)},
|
|
1778
2196
|
);
|
|
1779
2197
|
}
|
|
1780
2198
|
|
|
1781
2199
|
Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
1782
2200
|
return transformDecoder(
|
|
1783
2201
|
get${fragmentFromString(sizeCodecName)}Decoder(),
|
|
1784
|
-
|
|
2202
|
+
${fragmentFromString(decodedVariant)},
|
|
1785
2203
|
);
|
|
1786
2204
|
}
|
|
1787
2205
|
|
|
@@ -1789,7 +2207,7 @@ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragme
|
|
|
1789
2207
|
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
1790
2208
|
}`;
|
|
1791
2209
|
}
|
|
1792
|
-
function getDataEnumPageFragment(node, scope) {
|
|
2210
|
+
function getDataEnumPageFragment(node, variants, scope) {
|
|
1793
2211
|
const name = node.name;
|
|
1794
2212
|
const typeName = scope.nameApi.dataType(name);
|
|
1795
2213
|
const enumNode = node.type;
|
|
@@ -1799,9 +2217,10 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1799
2217
|
const decoderVariants = [];
|
|
1800
2218
|
const encodeCases = [];
|
|
1801
2219
|
const decodeCases = [];
|
|
2220
|
+
let pageHasListEnums = false;
|
|
1802
2221
|
const allVariantManifests = [];
|
|
1803
|
-
for (let i = 0; i <
|
|
1804
|
-
const variant =
|
|
2222
|
+
for (let i = 0; i < variants.length; i++) {
|
|
2223
|
+
const variant = variants[i];
|
|
1805
2224
|
const variantName = pascalCase(variant.name);
|
|
1806
2225
|
const variantClassName = scope.nameApi.sealedClassVariant(
|
|
1807
2226
|
name,
|
|
@@ -1831,7 +2250,7 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1831
2250
|
decodeCases.push(`case ${i}: return const ${variantClassName}();`);
|
|
1832
2251
|
} else if (variant.kind === "enumStructVariantTypeNode") {
|
|
1833
2252
|
const resolvedStruct = resolveNestedTypeNode(variant.struct);
|
|
1834
|
-
const fields = resolvedStruct.fields;
|
|
2253
|
+
const fields = resolvedStruct.fields ?? [];
|
|
1835
2254
|
const fieldManifests = fields.map((f) => ({
|
|
1836
2255
|
field: f,
|
|
1837
2256
|
manifest: visit(f.type, scope.typeManifestVisitor)
|
|
@@ -1846,10 +2265,14 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1846
2265
|
const ctorSignature = fields.length === 0 ? ` const ${variantClassName}();` : ` const ${variantClassName}({
|
|
1847
2266
|
${ctorParams}
|
|
1848
2267
|
});`;
|
|
1849
|
-
const eqChecks = fields.length === 0 ? "true" : fields.map((f) =>
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
);
|
|
2268
|
+
const eqChecks = fields.length === 0 ? "true" : fields.map((f, index) => {
|
|
2269
|
+
const fieldName = camelCase(f.name);
|
|
2270
|
+
return isListManifest(fieldManifests[index].manifest) ? `_listEquals(${fieldName}, other.${fieldName})` : `${fieldName} == other.${fieldName}`;
|
|
2271
|
+
}).join(" &&\n ");
|
|
2272
|
+
const hashExpression = getValueHashExpression(fields, fieldManifests);
|
|
2273
|
+
if (fieldManifests.some(({ manifest }) => isListManifest(manifest))) {
|
|
2274
|
+
pageHasListEnums = true;
|
|
2275
|
+
}
|
|
1853
2276
|
const toStringFields = fields.map((f) => `${camelCase(f.name)}: $${camelCase(f.name)}`).join(", ");
|
|
1854
2277
|
variantClasses.push(`final class ${variantClassName} extends ${typeName} {
|
|
1855
2278
|
${ctorSignature}
|
|
@@ -1897,7 +2320,7 @@ ${fieldDecls}
|
|
|
1897
2320
|
decodeCases.push(`case ${i}: return ${variantClassName}(${fromMapFields.replace(/\n/g, " ").replace(/,$/, "")});`);
|
|
1898
2321
|
} else if (variant.kind === "enumTupleVariantTypeNode") {
|
|
1899
2322
|
const resolvedTuple = resolveNestedTypeNode(variant.tuple);
|
|
1900
|
-
const items = resolvedTuple.items;
|
|
2323
|
+
const items = resolvedTuple.items ?? [];
|
|
1901
2324
|
if (items.length === 1) {
|
|
1902
2325
|
const manifest = visit(items[0], scope.typeManifestVisitor);
|
|
1903
2326
|
allVariantManifests.push(manifest);
|
|
@@ -1955,7 +2378,7 @@ sealed class ${fragmentFromString(typeName)} {
|
|
|
1955
2378
|
const ${fragmentFromString(typeName)}();
|
|
1956
2379
|
}
|
|
1957
2380
|
|
|
1958
|
-
${fragmentFromString(variantClasses.join("\n\n"))}
|
|
2381
|
+
${fragmentFromString(variantClasses.join("\n\n"))}${pageHasListEnums ? LIST_VALUE_HELPERS : ""}
|
|
1959
2382
|
|
|
1960
2383
|
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
1961
2384
|
return transformEncoder<Map<String, Object?>, ${fragmentFromString(typeName)}>(
|
|
@@ -1997,7 +2420,8 @@ function getStructPageFragment(node, scope) {
|
|
|
1997
2420
|
const typeName = scope.nameApi.dataType(name);
|
|
1998
2421
|
const structNode = node.type;
|
|
1999
2422
|
if (structNode.kind !== "structTypeNode") return emptyFragment();
|
|
2000
|
-
const fields = structNode.fields;
|
|
2423
|
+
const fields = structNode.fields ?? [];
|
|
2424
|
+
let pageHasListStructs = false;
|
|
2001
2425
|
const fieldManifests = fields.map((f) => ({
|
|
2002
2426
|
field: f,
|
|
2003
2427
|
manifest: visit(f.type, scope.typeManifestVisitor)
|
|
@@ -2009,10 +2433,13 @@ function getStructPageFragment(node, scope) {
|
|
|
2009
2433
|
const ctorSignature = fields.length === 0 ? ` const ${typeName}();` : ` const ${typeName}({
|
|
2010
2434
|
${ctorParams}
|
|
2011
2435
|
});`;
|
|
2012
|
-
const eqChecks = fields.length === 0 ? "true" :
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2436
|
+
const eqChecks = fields.length === 0 ? "true" : fieldManifests.map(({ field: f, manifest }, index) => {
|
|
2437
|
+
const fieldName = camelCase(f.name);
|
|
2438
|
+
return isListManifest(manifest) ? `_listEquals(${fieldName}, other.${fieldName})` : `${fieldName} == other.${fieldName}`;
|
|
2439
|
+
}).join(" &&\n ");
|
|
2440
|
+
if (fieldManifests.some(({ manifest }) => isListManifest(manifest))) {
|
|
2441
|
+
pageHasListStructs = true;
|
|
2442
|
+
}
|
|
2016
2443
|
const toStringFields = fields.map(
|
|
2017
2444
|
(f) => `${camelCase(f.name)}: $${camelCase(f.name)}`
|
|
2018
2445
|
).join(", ");
|
|
@@ -2062,12 +2489,14 @@ ${fragmentFromString(fieldDecls)}
|
|
|
2062
2489
|
${fragmentFromString(eqChecks)};
|
|
2063
2490
|
|
|
2064
2491
|
@override
|
|
2065
|
-
int get hashCode => ${fragmentFromString(
|
|
2492
|
+
int get hashCode => ${fragmentFromString(
|
|
2493
|
+
getValueHashExpression(fields, fieldManifests)
|
|
2494
|
+
)};
|
|
2066
2495
|
|
|
2067
2496
|
@override
|
|
2068
2497
|
String toString() => '${fragmentFromString(typeName)}(${fragmentFromString(toStringFields)})';
|
|
2069
2498
|
}
|
|
2070
|
-
|
|
2499
|
+
${pageHasListStructs ? LIST_VALUE_HELPERS : ""}
|
|
2071
2500
|
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
2072
2501
|
final structEncoder = getStructEncoder(<(String, Encoder<Object?>)>[
|
|
2073
2502
|
${fragmentFromString(encFields)}
|
|
@@ -2133,6 +2562,56 @@ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragme
|
|
|
2133
2562
|
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
2134
2563
|
}`;
|
|
2135
2564
|
}
|
|
2565
|
+
function isListManifest(manifest) {
|
|
2566
|
+
return manifest.type.content.startsWith("List<") || manifest.type.content === "Uint8List";
|
|
2567
|
+
}
|
|
2568
|
+
var LIST_VALUE_HELPERS = `
|
|
2569
|
+
bool _listEquals<T>(List<T>? a, List<T>? b) {
|
|
2570
|
+
if (identical(a, b)) return true;
|
|
2571
|
+
if (a == null || b == null) return a == b;
|
|
2572
|
+
if (a.length != b.length) return false;
|
|
2573
|
+
for (var i = 0; i < a.length; i++) {
|
|
2574
|
+
final left = a[i];
|
|
2575
|
+
final right = b[i];
|
|
2576
|
+
if (left is List<Object?> && right is List<Object?>) {
|
|
2577
|
+
if (!_listEquals(left, right)) return false;
|
|
2578
|
+
} else if (left != right) {
|
|
2579
|
+
return false;
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
return true;
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
Object? _deepHash(Object? value) {
|
|
2586
|
+
if (value is List<Object?>) {
|
|
2587
|
+
return Object.hashAll(value.map(_deepHash));
|
|
2588
|
+
}
|
|
2589
|
+
return value;
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
int _listHashCode<T>(List<T>? a) {
|
|
2593
|
+
if (a == null) return 0;
|
|
2594
|
+
return Object.hashAll(a.map(_deepHash));
|
|
2595
|
+
}
|
|
2596
|
+
`;
|
|
2597
|
+
function getValueHashExpression(fields, fieldManifests) {
|
|
2598
|
+
const fieldNames = fields.map(
|
|
2599
|
+
(f) => camelCase(f.name)
|
|
2600
|
+
);
|
|
2601
|
+
const hasListFields = fieldManifests.some(
|
|
2602
|
+
({ manifest }) => isListManifest(manifest)
|
|
2603
|
+
);
|
|
2604
|
+
if (!hasListFields) {
|
|
2605
|
+
return getHashExpression(fieldNames);
|
|
2606
|
+
}
|
|
2607
|
+
if (fieldNames.length === 1) {
|
|
2608
|
+
return `_listHashCode(${fieldNames[0]})`;
|
|
2609
|
+
}
|
|
2610
|
+
const hashArgs = fields.map(
|
|
2611
|
+
(f, index) => isListManifest(fieldManifests[index].manifest) ? `_listHashCode(${camelCase(f.name)})` : camelCase(f.name)
|
|
2612
|
+
);
|
|
2613
|
+
return `Object.hash(${hashArgs.join(", ")})`;
|
|
2614
|
+
}
|
|
2136
2615
|
function getHashExpression(fields) {
|
|
2137
2616
|
if (fields.length === 0) return "runtimeType.hashCode";
|
|
2138
2617
|
if (fields.length === 1) return `${fields[0]}.hashCode`;
|
|
@@ -2204,7 +2683,7 @@ function getRenderMapVisitor(options = {}) {
|
|
|
2204
2683
|
visitRoot(node, { self }) {
|
|
2205
2684
|
const programMaps = [
|
|
2206
2685
|
visit(node.program, self),
|
|
2207
|
-
...node.additionalPrograms.map((p) => visit(p, self))
|
|
2686
|
+
...(node.additionalPrograms ?? []).map((p) => visit(p, self))
|
|
2208
2687
|
];
|
|
2209
2688
|
const mergedProgramMap = mergeRenderMaps(programMaps);
|
|
2210
2689
|
const categoryMaps = getSharedCategoryIndexMaps(mergedProgramMap);
|
|
@@ -2350,11 +2829,12 @@ function renderVisitor(outputDir, options = {}) {
|
|
|
2350
2829
|
dependencyMap
|
|
2351
2830
|
} = options;
|
|
2352
2831
|
return rootNodeVisitor((root) => {
|
|
2832
|
+
const normalizedRoot = normalizeRootNode(root);
|
|
2353
2833
|
if (deleteFolderBeforeRendering && existsSync(outputDir)) {
|
|
2354
2834
|
deleteDirectory(outputDir);
|
|
2355
2835
|
}
|
|
2356
2836
|
const renderMap = visit(
|
|
2357
|
-
|
|
2837
|
+
normalizedRoot,
|
|
2358
2838
|
getRenderMapVisitor({ nameApi, dependencyMap })
|
|
2359
2839
|
);
|
|
2360
2840
|
const typePathMap = {};
|
|
@@ -2436,6 +2916,6 @@ function cleanFragmentContent(content) {
|
|
|
2436
2916
|
// src/index.ts
|
|
2437
2917
|
var src_default = renderVisitor;
|
|
2438
2918
|
|
|
2439
|
-
export { DART_EXTERNAL_PACKAGE_MAP, DartImportMap, createDartNameApi, src_default as default, getRenderMapVisitor, getTypeManifestVisitor, renderVisitor };
|
|
2919
|
+
export { DART_EXTERNAL_PACKAGE_MAP, DartImportMap, createDartNameApi, src_default as default, getRenderMapVisitor, getTypeManifestVisitor, normalizeRootNode, renderVisitor };
|
|
2440
2920
|
//# sourceMappingURL=index.browser.js.map
|
|
2441
2921
|
//# sourceMappingURL=index.browser.js.map
|