@codama/renderers-rust 1.2.6 → 1.2.8
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.node.cjs +111 -40
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +111 -40
- package/dist/index.node.mjs.map +1 -1
- package/dist/templates/instructionsCpiPage.njk +2 -2
- package/dist/templates/instructionsPage.njk +16 -2
- package/dist/types/getRenderMapVisitor.d.ts +3 -1
- package/dist/types/getRenderMapVisitor.d.ts.map +1 -1
- package/dist/types/getTypeManifestVisitor.d.ts +2 -1
- package/dist/types/getTypeManifestVisitor.d.ts.map +1 -1
- package/dist/types/renderVisitor.d.ts.map +1 -1
- package/dist/types/utils/render.d.ts.map +1 -1
- package/dist/types/utils/traitOptions.d.ts +5 -0
- package/dist/types/utils/traitOptions.d.ts.map +1 -1
- package/package.json +10 -10
package/dist/index.node.mjs
CHANGED
|
@@ -392,6 +392,10 @@ var render = (template, context, options) => {
|
|
|
392
392
|
env.addFilter("kebabCase", kebabCase);
|
|
393
393
|
env.addFilter("titleCase", titleCase);
|
|
394
394
|
env.addFilter("rustDocblock", rustDocblock);
|
|
395
|
+
env.addFilter("hasTrait", (traits, ...traitNames) => {
|
|
396
|
+
if (typeof traits !== "string") return false;
|
|
397
|
+
return traitNames.some((traitName) => traits.includes(traitName));
|
|
398
|
+
});
|
|
395
399
|
return env.render(template, context);
|
|
396
400
|
};
|
|
397
401
|
|
|
@@ -501,14 +505,51 @@ function extractFullyQualifiedNames(traits, imports) {
|
|
|
501
505
|
return trait.slice(index + 2);
|
|
502
506
|
});
|
|
503
507
|
}
|
|
508
|
+
function getSerdeFieldAttribute(serdeWith, node, userOptions = {}) {
|
|
509
|
+
assertIsNode(node, ["accountNode", "definedTypeNode", "instructionNode"]);
|
|
510
|
+
const options = { ...DEFAULT_TRAIT_OPTIONS, ...userOptions };
|
|
511
|
+
const nodeType = getNodeType(node);
|
|
512
|
+
if (nodeType === "alias") {
|
|
513
|
+
return "";
|
|
514
|
+
}
|
|
515
|
+
const sanitizedOverrides = Object.fromEntries(
|
|
516
|
+
Object.entries(options.overrides).map(([key, value]) => [camelCase3(key), value])
|
|
517
|
+
);
|
|
518
|
+
const nodeOverrides = sanitizedOverrides[node.name];
|
|
519
|
+
const allTraits = nodeOverrides === void 0 ? getDefaultTraits(nodeType, options) : nodeOverrides;
|
|
520
|
+
const hasSerdeSerialize = allTraits.some((t) => t === "serde::Serialize" || t === "Serialize");
|
|
521
|
+
const hasSerdeDeserialize = allTraits.some((t) => t === "serde::Deserialize" || t === "Deserialize");
|
|
522
|
+
if (!hasSerdeSerialize && !hasSerdeDeserialize) {
|
|
523
|
+
return "";
|
|
524
|
+
}
|
|
525
|
+
const partitionedTraits = partitionTraitsInFeatures(allTraits, options.featureFlags);
|
|
526
|
+
const featuredTraits = partitionedTraits[1];
|
|
527
|
+
let serdeFeatureName;
|
|
528
|
+
for (const [feature, traits] of Object.entries(featuredTraits)) {
|
|
529
|
+
if (traits.some(
|
|
530
|
+
(t) => t === "serde::Serialize" || t === "serde::Deserialize" || t === "Serialize" || t === "Deserialize"
|
|
531
|
+
)) {
|
|
532
|
+
serdeFeatureName = feature;
|
|
533
|
+
break;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (serdeFeatureName) {
|
|
537
|
+
return `#[cfg_attr(feature = "${serdeFeatureName}", serde(with = "${serdeWith}"))]
|
|
538
|
+
`;
|
|
539
|
+
} else {
|
|
540
|
+
return `#[serde(with = "${serdeWith}")]
|
|
541
|
+
`;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
504
544
|
|
|
505
545
|
// src/getTypeManifestVisitor.ts
|
|
506
546
|
function getTypeManifestVisitor(options) {
|
|
507
|
-
const { getImportFrom, getTraitsFromNode: getTraitsFromNode2 } = options;
|
|
547
|
+
const { getImportFrom, getTraitsFromNode: getTraitsFromNode2, traitOptions } = options;
|
|
508
548
|
let parentName = options.parentName ?? null;
|
|
509
549
|
let nestedStruct = options.nestedStruct ?? false;
|
|
510
550
|
let inlineStruct = false;
|
|
511
551
|
let parentSize = null;
|
|
552
|
+
let parentNode = null;
|
|
512
553
|
return pipe(
|
|
513
554
|
mergeVisitor(
|
|
514
555
|
() => ({ imports: new ImportMap(), nestedStructs: [], type: "" }),
|
|
@@ -521,10 +562,12 @@ function getTypeManifestVisitor(options) {
|
|
|
521
562
|
(v) => extendVisitor(v, {
|
|
522
563
|
visitAccount(account, { self }) {
|
|
523
564
|
parentName = pascalCase3(account.name);
|
|
565
|
+
parentNode = account;
|
|
524
566
|
const manifest = visit3(account.data, self);
|
|
525
567
|
const traits = getTraitsFromNode2(account);
|
|
526
568
|
manifest.imports.mergeWith(traits.imports);
|
|
527
569
|
parentName = null;
|
|
570
|
+
parentNode = null;
|
|
528
571
|
return {
|
|
529
572
|
...manifest,
|
|
530
573
|
type: traits.render + manifest.type
|
|
@@ -599,10 +642,12 @@ function getTypeManifestVisitor(options) {
|
|
|
599
642
|
},
|
|
600
643
|
visitDefinedType(definedType, { self }) {
|
|
601
644
|
parentName = pascalCase3(definedType.name);
|
|
645
|
+
parentNode = definedType;
|
|
602
646
|
const manifest = visit3(definedType.type, self);
|
|
603
647
|
const traits = getTraitsFromNode2(definedType);
|
|
604
648
|
manifest.imports.mergeWith(traits.imports);
|
|
605
649
|
parentName = null;
|
|
650
|
+
parentNode = null;
|
|
606
651
|
const renderedType = isNode4(definedType.type, ["enumTypeNode", "structTypeNode"]) ? manifest.type : `pub type ${pascalCase3(definedType.name)} = ${manifest.type};`;
|
|
607
652
|
return { ...manifest, type: `${traits.render}${renderedType}` };
|
|
608
653
|
},
|
|
@@ -649,10 +694,18 @@ function getTypeManifestVisitor(options) {
|
|
|
649
694
|
const childManifest = visit3(enumTupleVariantType.tuple, self);
|
|
650
695
|
parentName = originalParentName;
|
|
651
696
|
let derive = "";
|
|
652
|
-
if (childManifest.type === "(Pubkey)") {
|
|
653
|
-
derive =
|
|
654
|
-
|
|
655
|
-
|
|
697
|
+
if (parentNode && childManifest.type === "(Pubkey)") {
|
|
698
|
+
derive = getSerdeFieldAttribute(
|
|
699
|
+
"serde_with::As::<serde_with::DisplayFromStr>",
|
|
700
|
+
parentNode,
|
|
701
|
+
traitOptions
|
|
702
|
+
);
|
|
703
|
+
} else if (parentNode && childManifest.type === "(Vec<Pubkey>)") {
|
|
704
|
+
derive = getSerdeFieldAttribute(
|
|
705
|
+
"serde_with::As::<Vec<serde_with::DisplayFromStr>>",
|
|
706
|
+
parentNode,
|
|
707
|
+
traitOptions
|
|
708
|
+
);
|
|
656
709
|
}
|
|
657
710
|
return {
|
|
658
711
|
...childManifest,
|
|
@@ -799,14 +852,28 @@ ${variantNames}
|
|
|
799
852
|
const docblock = rustDocblock(parseDocs(structFieldType.docs));
|
|
800
853
|
const resolvedNestedType = resolveNestedTypeNode(structFieldType.type);
|
|
801
854
|
let derive = "";
|
|
802
|
-
if (
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
855
|
+
if (parentNode) {
|
|
856
|
+
if (fieldManifest.type === "Pubkey") {
|
|
857
|
+
derive = getSerdeFieldAttribute(
|
|
858
|
+
"serde_with::As::<serde_with::DisplayFromStr>",
|
|
859
|
+
parentNode,
|
|
860
|
+
traitOptions
|
|
861
|
+
);
|
|
862
|
+
} else if (fieldManifest.type === "Vec<Pubkey>") {
|
|
863
|
+
derive = getSerdeFieldAttribute(
|
|
864
|
+
"serde_with::As::<Vec<serde_with::DisplayFromStr>>",
|
|
865
|
+
parentNode,
|
|
866
|
+
traitOptions
|
|
867
|
+
);
|
|
868
|
+
} else if (isNode4(resolvedNestedType, "arrayTypeNode") && isNode4(resolvedNestedType.count, "fixedCountNode") && resolvedNestedType.count.value > 32) {
|
|
869
|
+
derive = getSerdeFieldAttribute("serde_big_array::BigArray", parentNode, traitOptions);
|
|
870
|
+
} else if (isNode4(resolvedNestedType, ["bytesTypeNode", "stringTypeNode"]) && isNode4(structFieldType.type, "fixedSizeTypeNode") && structFieldType.type.size > 32) {
|
|
871
|
+
derive = getSerdeFieldAttribute(
|
|
872
|
+
"serde_with::As::<serde_with::Bytes>",
|
|
873
|
+
parentNode,
|
|
874
|
+
traitOptions
|
|
875
|
+
);
|
|
876
|
+
}
|
|
810
877
|
}
|
|
811
878
|
return {
|
|
812
879
|
...fieldManifest,
|
|
@@ -879,7 +946,11 @@ function getRenderMapVisitor(options = {}) {
|
|
|
879
946
|
const dependencyMap = options.dependencyMap ?? {};
|
|
880
947
|
const getImportFrom = getImportFromFactory(options.linkOverrides ?? {});
|
|
881
948
|
const getTraitsFromNode2 = getTraitsFromNodeFactory(options.traitOptions);
|
|
882
|
-
const typeManifestVisitor = getTypeManifestVisitor({
|
|
949
|
+
const typeManifestVisitor = getTypeManifestVisitor({
|
|
950
|
+
getImportFrom,
|
|
951
|
+
getTraitsFromNode: getTraitsFromNode2,
|
|
952
|
+
traitOptions: options.traitOptions
|
|
953
|
+
});
|
|
883
954
|
const anchorTraits = options.anchorTraits ?? true;
|
|
884
955
|
return pipe2(
|
|
885
956
|
staticVisitor(() => createRenderMap(), {
|
|
@@ -921,9 +992,8 @@ function getRenderMapVisitor(options = {}) {
|
|
|
921
992
|
if (hasVariableSeeds) {
|
|
922
993
|
imports.mergeWith(seedsImports);
|
|
923
994
|
}
|
|
924
|
-
return createRenderMap(
|
|
925
|
-
|
|
926
|
-
render("accountsPage.njk", {
|
|
995
|
+
return createRenderMap(`accounts/${snakeCase4(node.name)}.rs`, {
|
|
996
|
+
content: render("accountsPage.njk", {
|
|
927
997
|
account: node,
|
|
928
998
|
anchorTraits,
|
|
929
999
|
constantSeeds,
|
|
@@ -935,19 +1005,18 @@ function getRenderMapVisitor(options = {}) {
|
|
|
935
1005
|
seeds,
|
|
936
1006
|
typeManifest
|
|
937
1007
|
})
|
|
938
|
-
);
|
|
1008
|
+
});
|
|
939
1009
|
},
|
|
940
1010
|
visitDefinedType(node) {
|
|
941
1011
|
const typeManifest = visit4(node, typeManifestVisitor);
|
|
942
1012
|
const imports = new ImportMap().mergeWithManifest(typeManifest);
|
|
943
|
-
return createRenderMap(
|
|
944
|
-
|
|
945
|
-
render("definedTypesPage.njk", {
|
|
1013
|
+
return createRenderMap(`types/${snakeCase4(node.name)}.rs`, {
|
|
1014
|
+
content: render("definedTypesPage.njk", {
|
|
946
1015
|
definedType: node,
|
|
947
1016
|
imports: imports.remove(`generatedTypes::${pascalCase4(node.name)}`).toString(dependencyMap),
|
|
948
1017
|
typeManifest
|
|
949
1018
|
})
|
|
950
|
-
);
|
|
1019
|
+
});
|
|
951
1020
|
},
|
|
952
1021
|
visitInstruction(node) {
|
|
953
1022
|
const imports = new ImportMap();
|
|
@@ -1008,9 +1077,8 @@ function getRenderMapVisitor(options = {}) {
|
|
|
1008
1077
|
const typeManifest = visit4(struct, structVisitor);
|
|
1009
1078
|
const dataTraits = getTraitsFromNode2(node);
|
|
1010
1079
|
imports.mergeWith(dataTraits.imports);
|
|
1011
|
-
return createRenderMap(
|
|
1012
|
-
|
|
1013
|
-
render("instructionsPage.njk", {
|
|
1080
|
+
return createRenderMap(`instructions/${snakeCase4(node.name)}.rs`, {
|
|
1081
|
+
content: render("instructionsPage.njk", {
|
|
1014
1082
|
dataTraits: dataTraits.render,
|
|
1015
1083
|
discriminatorConstants: discriminatorConstants.render,
|
|
1016
1084
|
hasArgs,
|
|
@@ -1021,7 +1089,7 @@ function getRenderMapVisitor(options = {}) {
|
|
|
1021
1089
|
program,
|
|
1022
1090
|
typeManifest
|
|
1023
1091
|
})
|
|
1024
|
-
);
|
|
1092
|
+
});
|
|
1025
1093
|
},
|
|
1026
1094
|
visitProgram(node, { self }) {
|
|
1027
1095
|
program = node;
|
|
@@ -1033,15 +1101,13 @@ function getRenderMapVisitor(options = {}) {
|
|
|
1033
1101
|
}).map((ix) => visit4(ix, self))
|
|
1034
1102
|
]);
|
|
1035
1103
|
if (node.errors.length > 0) {
|
|
1036
|
-
renders = addToRenderMap(
|
|
1037
|
-
|
|
1038
|
-
`errors/${snakeCase4(node.name)}.rs`,
|
|
1039
|
-
render("errorsPage.njk", {
|
|
1104
|
+
renders = addToRenderMap(renders, `errors/${snakeCase4(node.name)}.rs`, {
|
|
1105
|
+
content: render("errorsPage.njk", {
|
|
1040
1106
|
errors: node.errors,
|
|
1041
1107
|
imports: new ImportMap().toString(dependencyMap),
|
|
1042
1108
|
program: node
|
|
1043
1109
|
})
|
|
1044
|
-
);
|
|
1110
|
+
});
|
|
1045
1111
|
}
|
|
1046
1112
|
program = null;
|
|
1047
1113
|
return renders;
|
|
@@ -1064,13 +1130,13 @@ function getRenderMapVisitor(options = {}) {
|
|
|
1064
1130
|
};
|
|
1065
1131
|
return mergeRenderMaps([
|
|
1066
1132
|
createRenderMap({
|
|
1067
|
-
["accounts/mod.rs"]: accountsToExport.length > 0 ? render("accountsMod.njk", ctx) : void 0,
|
|
1068
|
-
["errors/mod.rs"]: programsToExport.length > 0 ? render("errorsMod.njk", ctx) : void 0,
|
|
1069
|
-
["instructions/mod.rs"]: instructionsToExport.length > 0 ? render("instructionsMod.njk", ctx) : void 0,
|
|
1070
|
-
["mod.rs"]: render("rootMod.njk", ctx),
|
|
1071
|
-
["programs.rs"]: programsToExport.length > 0 ? render("programsMod.njk", ctx) : void 0,
|
|
1072
|
-
["shared.rs"]: accountsToExport.length > 0 ? render("sharedPage.njk", ctx) : void 0,
|
|
1073
|
-
["types/mod.rs"]: definedTypesToExport.length > 0 ? render("definedTypesMod.njk", ctx) : void 0
|
|
1133
|
+
["accounts/mod.rs"]: accountsToExport.length > 0 ? { content: render("accountsMod.njk", ctx) } : void 0,
|
|
1134
|
+
["errors/mod.rs"]: programsToExport.length > 0 ? { content: render("errorsMod.njk", ctx) } : void 0,
|
|
1135
|
+
["instructions/mod.rs"]: instructionsToExport.length > 0 ? { content: render("instructionsMod.njk", ctx) } : void 0,
|
|
1136
|
+
["mod.rs"]: { content: render("rootMod.njk", ctx) },
|
|
1137
|
+
["programs.rs"]: programsToExport.length > 0 ? { content: render("programsMod.njk", ctx) } : void 0,
|
|
1138
|
+
["shared.rs"]: accountsToExport.length > 0 ? { content: render("sharedPage.njk", ctx) } : void 0,
|
|
1139
|
+
["types/mod.rs"]: definedTypesToExport.length > 0 ? { content: render("definedTypesMod.njk", ctx) } : void 0
|
|
1074
1140
|
}),
|
|
1075
1141
|
...getAllPrograms(node).map((p) => visit4(p, self))
|
|
1076
1142
|
]);
|
|
@@ -1102,8 +1168,13 @@ function renderVisitor(path, options = {}) {
|
|
|
1102
1168
|
visit5(root, writeRenderMapVisitor(getRenderMapVisitor(options), path));
|
|
1103
1169
|
if (options.formatCode) {
|
|
1104
1170
|
if (options.crateFolder) {
|
|
1105
|
-
const
|
|
1106
|
-
runFormatter(
|
|
1171
|
+
const removeFalsy = (arg) => Boolean(arg);
|
|
1172
|
+
runFormatter(
|
|
1173
|
+
"cargo",
|
|
1174
|
+
[options.toolchain, "fmt", "--manifest-path", `${options.crateFolder}/Cargo.toml`].filter(
|
|
1175
|
+
removeFalsy
|
|
1176
|
+
)
|
|
1177
|
+
);
|
|
1107
1178
|
} else {
|
|
1108
1179
|
logWarn2("No crate folder specified, skipping formatting.");
|
|
1109
1180
|
}
|