codama-renderers-dart 0.4.3 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.browser.cjs +634 -159
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +635 -161
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +634 -159
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +635 -161
- package/dist/index.node.js.map +1 -1
- package/dist/index.react-native.js +635 -161
- 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/programPage.d.ts +1 -1
- package/dist/types/fragments/programPage.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/importMap.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 +1 -1
- 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 +31 -23
- package/readme.md +30 -3
- package/src/fragments/accountPage.ts +90 -17
- package/src/fragments/instructionPage.ts +109 -72
- package/src/fragments/programPage.ts +165 -6
- package/src/fragments/typePage.ts +36 -15
- 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/importMap.ts +16 -3
- package/src/utils/index.ts +4 -0
- package/src/utils/nameTransformers.ts +3 -2
- package/src/utils/normalizeRootNode.ts +76 -0
- package/src/utils/valueNodes.ts +87 -0
- package/src/utils/wellKnownAddresses.ts +4 -4
- package/src/visitors/getRenderMapVisitor.ts +1 -1
- package/src/visitors/getTypeManifestVisitor.ts +48 -29
- package/src/visitors/renderVisitor.ts +11 -4
|
@@ -226,18 +226,24 @@ export function getTypeManifestVisitor(input: {
|
|
|
226
226
|
|
|
227
227
|
visitArrayType(node: ArrayTypeNode, { self }) {
|
|
228
228
|
const itemManifest = visit(node.item, self);
|
|
229
|
-
const
|
|
229
|
+
const encoderSizeExpr = getArraySizeExpression(node, "Encoder");
|
|
230
|
+
const decoderSizeExpr = getArraySizeExpression(node, "Decoder");
|
|
231
|
+
const itemType = fragmentFromString(itemManifest.type.content);
|
|
232
|
+
const itemEncoder = fragment`${use(
|
|
233
|
+
"transformEncoder",
|
|
234
|
+
"solanaCodecsCore",
|
|
235
|
+
)}(${itemManifest.encoder}, (${itemType} value) => value)`;
|
|
230
236
|
|
|
231
237
|
return {
|
|
232
238
|
type: fragment`List<${itemManifest.type}>`,
|
|
233
239
|
encoder: fragment`${use(
|
|
234
240
|
"getArrayEncoder",
|
|
235
241
|
"solanaCodecsDataStructures",
|
|
236
|
-
)}(${
|
|
242
|
+
)}<${itemType}>(${itemEncoder}${encoderSizeExpr})`,
|
|
237
243
|
decoder: fragment`${use(
|
|
238
244
|
"getArrayDecoder",
|
|
239
245
|
"solanaCodecsDataStructures",
|
|
240
|
-
)}(${itemManifest.decoder}${
|
|
246
|
+
)}(${itemManifest.decoder}${decoderSizeExpr})`,
|
|
241
247
|
value: emptyTypeManifest().value,
|
|
242
248
|
isEnum: false,
|
|
243
249
|
};
|
|
@@ -246,18 +252,19 @@ export function getTypeManifestVisitor(input: {
|
|
|
246
252
|
visitMapType(node: MapTypeNode, { self }) {
|
|
247
253
|
const keyManifest = visit(node.key, self);
|
|
248
254
|
const valueManifest = visit(node.value, self);
|
|
249
|
-
const
|
|
255
|
+
const encoderSizeExpr = getMapSizeExpression(node, "Encoder");
|
|
256
|
+
const decoderSizeExpr = getMapSizeExpression(node, "Decoder");
|
|
250
257
|
|
|
251
258
|
return {
|
|
252
259
|
type: fragment`Map<${keyManifest.type}, ${valueManifest.type}>`,
|
|
253
260
|
encoder: fragment`${use(
|
|
254
261
|
"getMapEncoder",
|
|
255
262
|
"solanaCodecsDataStructures",
|
|
256
|
-
)}(${keyManifest.encoder}, ${valueManifest.encoder}${
|
|
263
|
+
)}(${keyManifest.encoder}, ${valueManifest.encoder}${encoderSizeExpr})`,
|
|
257
264
|
decoder: fragment`${use(
|
|
258
265
|
"getMapDecoder",
|
|
259
266
|
"solanaCodecsDataStructures",
|
|
260
|
-
)}(${keyManifest.decoder}, ${valueManifest.decoder}${
|
|
267
|
+
)}(${keyManifest.decoder}, ${valueManifest.decoder}${decoderSizeExpr})`,
|
|
261
268
|
value: emptyTypeManifest().value,
|
|
262
269
|
isEnum: false,
|
|
263
270
|
};
|
|
@@ -265,25 +272,26 @@ export function getTypeManifestVisitor(input: {
|
|
|
265
272
|
|
|
266
273
|
visitSetType(node: SetTypeNode, { self }) {
|
|
267
274
|
const itemManifest = visit(node.item, self);
|
|
268
|
-
const
|
|
275
|
+
const encoderSizeExpr = getSetSizeExpression(node, "Encoder");
|
|
276
|
+
const decoderSizeExpr = getSetSizeExpression(node, "Decoder");
|
|
269
277
|
|
|
270
278
|
return {
|
|
271
279
|
type: fragment`Set<${itemManifest.type}>`,
|
|
272
280
|
encoder: fragment`${use(
|
|
273
281
|
"getSetEncoder",
|
|
274
282
|
"solanaCodecsDataStructures",
|
|
275
|
-
)}(${itemManifest.encoder}${
|
|
283
|
+
)}(${itemManifest.encoder}${encoderSizeExpr})`,
|
|
276
284
|
decoder: fragment`${use(
|
|
277
285
|
"getSetDecoder",
|
|
278
286
|
"solanaCodecsDataStructures",
|
|
279
|
-
)}(${itemManifest.decoder}${
|
|
287
|
+
)}(${itemManifest.decoder}${decoderSizeExpr})`,
|
|
280
288
|
value: emptyTypeManifest().value,
|
|
281
289
|
isEnum: false,
|
|
282
290
|
};
|
|
283
291
|
},
|
|
284
292
|
|
|
285
293
|
visitTupleType(node: TupleTypeNode, { self }) {
|
|
286
|
-
const itemManifests = node.items.map((item) => visit(item, self));
|
|
294
|
+
const itemManifests = (node.items ?? []).map((item) => visit(item, self));
|
|
287
295
|
const typeList = itemManifests
|
|
288
296
|
.map((m) => m.type.content)
|
|
289
297
|
.join(", ");
|
|
@@ -324,8 +332,9 @@ export function getTypeManifestVisitor(input: {
|
|
|
324
332
|
},
|
|
325
333
|
|
|
326
334
|
visitStructType(node: StructTypeNode, { self }) {
|
|
327
|
-
const
|
|
328
|
-
const
|
|
335
|
+
const nodeFields = node.fields ?? [];
|
|
336
|
+
const fields = nodeFields.map((f) => visit(f, self));
|
|
337
|
+
const fieldNames = nodeFields.map((f) => f.name as string);
|
|
329
338
|
|
|
330
339
|
// Type: Map<String, Object?> (for inline structs without a name)
|
|
331
340
|
const typeStr = "Map<String, Object?>";
|
|
@@ -368,7 +377,7 @@ export function getTypeManifestVisitor(input: {
|
|
|
368
377
|
|
|
369
378
|
visitEnumType(node: EnumTypeNode, { self }) {
|
|
370
379
|
// Check if this is a scalar enum (all empty variants)
|
|
371
|
-
const isScalar = node.variants.every(
|
|
380
|
+
const isScalar = (node.variants ?? []).every(
|
|
372
381
|
(v) => v.kind === "enumEmptyVariantTypeNode",
|
|
373
382
|
);
|
|
374
383
|
|
|
@@ -495,7 +504,7 @@ export function getTypeManifestVisitor(input: {
|
|
|
495
504
|
encoder: fragment`${use(
|
|
496
505
|
"fixEncoderSize",
|
|
497
506
|
"solanaCodecsCore",
|
|
498
|
-
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))})`,
|
|
507
|
+
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))}, allowTruncation: false)`,
|
|
499
508
|
decoder: fragment`${use(
|
|
500
509
|
"fixDecoderSize",
|
|
501
510
|
"solanaCodecsCore",
|
|
@@ -509,20 +518,21 @@ export function getTypeManifestVisitor(input: {
|
|
|
509
518
|
const innerManifest = visit(node.type, self);
|
|
510
519
|
|
|
511
520
|
// The Dart addEncoderSizePrefix / addDecoderSizePrefix APIs require
|
|
512
|
-
// Encoder<num> / Decoder<num> for the prefix
|
|
513
|
-
// (u64, u128, i64, i128) return Encoder<BigInt> which is
|
|
514
|
-
//
|
|
515
|
-
//
|
|
521
|
+
// Encoder<num> / Decoder<num> for the prefix, but BigInt-width number
|
|
522
|
+
// types (u64, u128, i64, i128) return Encoder<BigInt> which is
|
|
523
|
+
// incompatible. Transform the BigInt codec to int so it satisfies the
|
|
524
|
+
// num constraint while preserving the on-chain byte width (e.g. the
|
|
525
|
+
// system program's bincode u64 string-length prefix).
|
|
516
526
|
const bigIntFormats = new Set(["u64", "u128", "i64", "i128"]);
|
|
517
527
|
let prefixManifest;
|
|
518
528
|
if (
|
|
519
529
|
node.prefix.kind === "numberTypeNode" &&
|
|
520
530
|
bigIntFormats.has((node.prefix as any).format)
|
|
521
531
|
) {
|
|
522
|
-
|
|
532
|
+
const codecName = getNumberCodecName((node.prefix as any).format);
|
|
523
533
|
prefixManifest = {
|
|
524
|
-
encoder: fragment
|
|
525
|
-
decoder: fragment
|
|
534
|
+
encoder: fragment`transformEncoder(${use(`get${codecName}Encoder`, "solanaCodecsNumbers")}(), (size) => BigInt.from(size))`,
|
|
535
|
+
decoder: fragment`transformDecoder(${use(`get${codecName}Decoder`, "solanaCodecsNumbers")}(), (size, _, __) => size.toInt())`,
|
|
526
536
|
};
|
|
527
537
|
} else {
|
|
528
538
|
prefixManifest = visit(node.prefix, self);
|
|
@@ -545,7 +555,7 @@ export function getTypeManifestVisitor(input: {
|
|
|
545
555
|
|
|
546
556
|
visitHiddenPrefixType(node: HiddenPrefixTypeNode, { self }) {
|
|
547
557
|
const innerManifest = visit(node.type, self);
|
|
548
|
-
const prefixes = node.prefix.map((p) => getHiddenAffixManifest(p, self));
|
|
558
|
+
const prefixes = (node.prefix ?? []).map((p) => getHiddenAffixManifest(p, self));
|
|
549
559
|
const prefixEncoders = prefixes
|
|
550
560
|
.map((p) => p.encoder.content)
|
|
551
561
|
.join(", ");
|
|
@@ -580,7 +590,7 @@ export function getTypeManifestVisitor(input: {
|
|
|
580
590
|
|
|
581
591
|
visitHiddenSuffixType(node: HiddenSuffixTypeNode, { self }) {
|
|
582
592
|
const innerManifest = visit(node.type, self);
|
|
583
|
-
const suffixes = node.suffix.map((s) => getHiddenAffixManifest(s, self));
|
|
593
|
+
const suffixes = (node.suffix ?? []).map((s) => getHiddenAffixManifest(s, self));
|
|
584
594
|
const suffixEncoders = suffixes
|
|
585
595
|
.map((s) => s.encoder.content)
|
|
586
596
|
.join(", ");
|
|
@@ -757,7 +767,10 @@ function getNumberCodecExpression(
|
|
|
757
767
|
return `get${name}${codecType}()`;
|
|
758
768
|
}
|
|
759
769
|
|
|
760
|
-
function getArraySizeExpression(
|
|
770
|
+
function getArraySizeExpression(
|
|
771
|
+
node: ArrayTypeNode,
|
|
772
|
+
codecType: "Encoder" | "Decoder",
|
|
773
|
+
): string {
|
|
761
774
|
if (!("count" in node) || !node.count) return "";
|
|
762
775
|
const count = node.count;
|
|
763
776
|
switch (count.kind) {
|
|
@@ -770,14 +783,17 @@ function getArraySizeExpression(node: ArrayTypeNode): string {
|
|
|
770
783
|
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
771
784
|
return ""; // Default
|
|
772
785
|
}
|
|
773
|
-
return `, size: PrefixedArraySize(
|
|
786
|
+
return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
|
|
774
787
|
}
|
|
775
788
|
default:
|
|
776
789
|
return "";
|
|
777
790
|
}
|
|
778
791
|
}
|
|
779
792
|
|
|
780
|
-
function getMapSizeExpression(
|
|
793
|
+
function getMapSizeExpression(
|
|
794
|
+
node: MapTypeNode,
|
|
795
|
+
codecType: "Encoder" | "Decoder",
|
|
796
|
+
): string {
|
|
781
797
|
if (!("count" in node) || !node.count) return "";
|
|
782
798
|
const count = node.count;
|
|
783
799
|
switch (count.kind) {
|
|
@@ -790,14 +806,17 @@ function getMapSizeExpression(node: MapTypeNode): string {
|
|
|
790
806
|
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
791
807
|
return "";
|
|
792
808
|
}
|
|
793
|
-
return `, size: PrefixedArraySize(
|
|
809
|
+
return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
|
|
794
810
|
}
|
|
795
811
|
default:
|
|
796
812
|
return "";
|
|
797
813
|
}
|
|
798
814
|
}
|
|
799
815
|
|
|
800
|
-
function getSetSizeExpression(
|
|
816
|
+
function getSetSizeExpression(
|
|
817
|
+
node: SetTypeNode,
|
|
818
|
+
codecType: "Encoder" | "Decoder",
|
|
819
|
+
): string {
|
|
801
820
|
if (!("count" in node) || !node.count) return "";
|
|
802
821
|
const count = node.count;
|
|
803
822
|
switch (count.kind) {
|
|
@@ -810,7 +829,7 @@ function getSetSizeExpression(node: SetTypeNode): string {
|
|
|
810
829
|
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
811
830
|
return "";
|
|
812
831
|
}
|
|
813
|
-
return `, size: PrefixedArraySize(
|
|
832
|
+
return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
|
|
814
833
|
}
|
|
815
834
|
default:
|
|
816
835
|
return "";
|
|
@@ -9,6 +9,7 @@ import type { Fragment } from "../utils/fragment.js";
|
|
|
9
9
|
import type { RenderOptions } from "../utils/options.js";
|
|
10
10
|
import { DartImportMap, DART_EXTERNAL_PACKAGE_MAP } from "../utils/importMap.js";
|
|
11
11
|
import { formatDartDirectory } from "../utils/formatCode.js";
|
|
12
|
+
import { normalizeRootNode } from "../utils/normalizeRootNode.js";
|
|
12
13
|
import { getRenderMapVisitor } from "./getRenderMapVisitor.js";
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -29,6 +30,8 @@ export function renderVisitor(
|
|
|
29
30
|
} = options;
|
|
30
31
|
|
|
31
32
|
return rootNodeVisitor((root: RootNode) => {
|
|
33
|
+
const normalizedRoot = normalizeRootNode(root);
|
|
34
|
+
|
|
32
35
|
// 1. Optionally delete the output directory
|
|
33
36
|
if (deleteFolderBeforeRendering && existsSync(outputDir)) {
|
|
34
37
|
deleteDirectory(outputDir);
|
|
@@ -36,14 +39,14 @@ export function renderVisitor(
|
|
|
36
39
|
|
|
37
40
|
// 2. Build the render map
|
|
38
41
|
const renderMap = visit(
|
|
39
|
-
|
|
42
|
+
normalizedRoot,
|
|
40
43
|
getRenderMapVisitor({ nameApi, dependencyMap }),
|
|
41
44
|
);
|
|
42
45
|
|
|
43
46
|
// 3. Build a map of definedType module keys to their render map paths
|
|
44
47
|
const typePathMap: Record<string, string> = {};
|
|
45
48
|
for (const renderPath of renderMap.keys()) {
|
|
46
|
-
const match = renderPath.match(/^(?:.*\/)?types\/([a-
|
|
49
|
+
const match = renderPath.match(/^(?:.*\/)?types\/([a-z0-9_]+)\.dart$/);
|
|
47
50
|
if (match) {
|
|
48
51
|
typePathMap[`definedType:${match[1]}`] = renderPath;
|
|
49
52
|
}
|
|
@@ -63,8 +66,12 @@ export function renderVisitor(
|
|
|
63
66
|
const fileDir = dirname(filePath);
|
|
64
67
|
const internalMap: Record<string, string> = {};
|
|
65
68
|
for (const [key, typePath] of Object.entries(typePathMap)) {
|
|
66
|
-
//
|
|
67
|
-
if (typePath === filePath)
|
|
69
|
+
// Keep the key resolved without generating a self-import.
|
|
70
|
+
if (typePath === filePath) {
|
|
71
|
+
internalMap[key] = "";
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
68
75
|
let rel = posix.relative(fileDir, typePath);
|
|
69
76
|
if (!rel.startsWith(".")) {
|
|
70
77
|
rel = `./${rel}`;
|