@codama/renderers-js-umi
Version:
JavaScript renderer compatible with the Umi framework
1,147 lines (1,135 loc) • 82.8 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
ImportMap: () => ImportMap,
default: () => renderVisitor,
getRenderMapVisitor: () => getRenderMapVisitor,
getTypeManifestVisitor: () => getTypeManifestVisitor,
renderVisitor: () => renderVisitor
});
module.exports = __toCommonJS(index_exports);
// src/ImportMap.ts
var DEFAULT_MODULE_MAP = {
errors: "../errors",
shared: "../shared",
types: "../types",
umi: "@metaplex-foundation/umi",
umiSerializers: "@metaplex-foundation/umi/serializers"
};
var ImportMap = class {
_imports = /* @__PURE__ */ new Map();
_aliases = /* @__PURE__ */ new Map();
add(module2, imports) {
const currentImports = this._imports.get(module2) ?? /* @__PURE__ */ new Set();
const newImports = typeof imports === "string" ? [imports] : imports;
newImports.forEach((i) => currentImports.add(i));
this._imports.set(module2, currentImports);
return this;
}
remove(module2, imports) {
const currentImports = this._imports.get(module2) ?? /* @__PURE__ */ new Set();
const importsToRemove = typeof imports === "string" ? [imports] : imports;
importsToRemove.forEach((i) => currentImports.delete(i));
if (currentImports.size === 0) {
this._imports.delete(module2);
} else {
this._imports.set(module2, currentImports);
}
return this;
}
mergeWith(...others) {
others.forEach((other) => {
other._imports.forEach((imports, module2) => {
this.add(module2, imports);
});
other._aliases.forEach((aliases, module2) => {
Object.entries(aliases).forEach(([name, alias]) => {
this.addAlias(module2, name, alias);
});
});
});
return this;
}
mergeWithManifest(manifest) {
return this.mergeWith(manifest.strictImports, manifest.looseImports, manifest.serializerImports);
}
addAlias(module2, name, alias) {
const currentAliases = this._aliases.get(module2) ?? {};
currentAliases[name] = alias;
this._aliases.set(module2, currentAliases);
return this;
}
isEmpty() {
return this._imports.size === 0;
}
toString(dependencies) {
const dependencyMap = { ...DEFAULT_MODULE_MAP, ...dependencies };
const importStatements = [...this._imports.entries()].map(([module2, imports]) => {
const mappedModule = dependencyMap[module2] ?? module2;
return [mappedModule, module2, imports];
}).sort(([a], [b]) => {
const aIsRelative = a.startsWith(".");
const bIsRelative = b.startsWith(".");
if (aIsRelative && !bIsRelative) return 1;
if (!aIsRelative && bIsRelative) return -1;
return a.localeCompare(b);
}).map(([mappedModule, module2, imports]) => {
const aliasMap = this._aliases.get(module2) ?? {};
const joinedImports = [...imports].sort().map((i) => aliasMap[i] ? `${i} as ${aliasMap[i]}` : i).join(", ");
return `import { ${joinedImports} } from '${mappedModule}';`;
});
return importStatements.join("\n");
}
};
// src/getRenderMapVisitor.ts
var import_errors3 = require("@codama/errors");
var import_nodes6 = require("@codama/nodes");
var import_renderers_core = require("@codama/renderers-core");
var import_visitors_core4 = require("@codama/visitors-core");
// src/ContextMap.ts
var ContextMap = class {
_interfaces = /* @__PURE__ */ new Set();
add(contextInterface) {
if (Array.isArray(contextInterface)) {
contextInterface.forEach((i) => this._interfaces.add(i));
} else {
this._interfaces.add(contextInterface);
}
return this;
}
remove(contextInterface) {
if (Array.isArray(contextInterface)) {
contextInterface.forEach((i) => this._interfaces.delete(i));
} else {
this._interfaces.delete(contextInterface);
}
return this;
}
mergeWith(...others) {
others.forEach((other) => this.add([...other._interfaces]));
return this;
}
isEmpty() {
return this._interfaces.size === 0;
}
toString() {
const contextInterfaces = [...this._interfaces].sort().map((i) => `"${i}"`).join(" | ");
return `Pick<Context, ${contextInterfaces}>`;
}
};
// src/getTypeManifestVisitor.ts
var import_errors2 = require("@codama/errors");
var import_nodes4 = require("@codama/nodes");
var import_visitors_core2 = require("@codama/visitors-core");
// src/utils/codecs.ts
var import_codecs_strings = require("@solana/codecs-strings");
function getBytesFromBytesValueNode(node) {
switch (node.encoding) {
case "utf8":
return (0, import_codecs_strings.getUtf8Encoder)().encode(node.data);
case "base16":
return (0, import_codecs_strings.getBase16Encoder)().encode(node.data);
case "base58":
return (0, import_codecs_strings.getBase58Encoder)().encode(node.data);
case "base64":
default:
return (0, import_codecs_strings.getBase64Encoder)().encode(node.data);
}
}
// src/utils/customData.ts
var import_nodes = require("@codama/nodes");
var parseCustomDataOptions = (customDataOptions, defaultSuffix) => new Map(
customDataOptions.map((o) => {
const options = typeof o === "string" ? { name: o } : o;
const importAs = (0, import_nodes.camelCase)(options.importAs ?? `${options.name}${defaultSuffix}`);
const importFrom = options.importFrom ?? "hooked";
return [
(0, import_nodes.camelCase)(options.name),
{
extract: options.extract ?? false,
extractAs: options.extractAs ? (0, import_nodes.camelCase)(options.extractAs) : importAs,
importAs,
importFrom,
linkNode: (0, import_nodes.definedTypeLinkNode)(importAs)
}
];
})
);
var getDefinedTypeNodesToExtract = (nodes, parsedCustomDataOptions) => nodes.flatMap((node) => {
const options = parsedCustomDataOptions.get(node.name);
if (!options || !options.extract) return [];
if ((0, import_nodes.isNode)(node, "accountNode")) {
return [(0, import_nodes.definedTypeNode)({ name: options.extractAs, type: { ...node.data } })];
}
return [
(0, import_nodes.definedTypeNode)({
name: options.extractAs,
type: (0, import_nodes.structTypeNodeFromInstructionArgumentNodes)(node.arguments)
})
];
});
// src/utils/gpaField.ts
var import_nodes2 = require("@codama/nodes");
var import_visitors_core = require("@codama/visitors-core");
function getGpaFieldsFromAccount(node, sizeVisitor) {
let offset = 0;
const struct = (0, import_nodes2.resolveNestedTypeNode)(node.data);
return struct.fields.map((field) => {
const fieldOffset = offset;
if (offset !== null) {
const newOffset = (0, import_visitors_core.visit)(field.type, sizeVisitor);
offset = newOffset !== null ? offset + newOffset : null;
}
return { name: field.name, offset: fieldOffset, type: field.type };
});
}
// src/utils/linkOverrides.ts
var import_errors = require("@codama/errors");
function getImportFromFactory(overrides, customAccountData, customInstructionData) {
const customDataOverrides = Object.fromEntries(
[...customAccountData.values(), ...customInstructionData.values()].map(({ importFrom, importAs }) => [
importAs,
importFrom
])
);
const linkOverrides = {
accounts: overrides.accounts ?? {},
definedTypes: { ...customDataOverrides, ...overrides.definedTypes },
instructions: overrides.instructions ?? {},
pdas: overrides.pdas ?? {},
programs: overrides.programs ?? {},
resolvers: overrides.resolvers ?? {}
};
return (node) => {
const kind = node.kind;
switch (kind) {
case "accountLinkNode":
return linkOverrides.accounts[node.name] ?? "generatedAccounts";
case "definedTypeLinkNode":
return linkOverrides.definedTypes[node.name] ?? "generatedTypes";
case "instructionLinkNode":
return linkOverrides.instructions[node.name] ?? "generatedInstructions";
case "pdaLinkNode":
return linkOverrides.pdas[node.name] ?? "generatedAccounts";
case "programLinkNode":
return linkOverrides.programs[node.name] ?? "generatedPrograms";
case "resolverValueNode":
return linkOverrides.resolvers[node.name] ?? "hooked";
default:
throw new import_errors.CodamaError(import_errors.CODAMA_ERROR__UNEXPECTED_NODE_KIND, {
expectedKinds: [
"AccountLinkNode",
"DefinedTypeLinkNode",
"InstructionLinkNode",
"PdaLinkNode",
"ProgramLinkNode",
"resolverValueNode"
],
kind,
node
});
}
};
}
// src/utils/render.ts
var import_node_path = require("path");
var import_node_url = require("url");
var import_nodes3 = require("@codama/nodes");
var import_nunjucks = __toESM(require("nunjucks"));
function jsDocblock(docs) {
if (docs.length <= 0) return "";
if (docs.length === 1) return `/** ${docs[0]} */
`;
const lines = docs.map((doc) => ` * ${doc}`);
return `/**
${lines.join("\n")}
*/
`;
}
var render = (template, context, options) => {
const dirname = false ? pathDirname(fileURLToPath(import_meta.url)) : __dirname;
const templates = false ? (0, import_node_path.join)(dirname, "..", "..", "public", "templates") : (0, import_node_path.join)(dirname, "templates");
const env = import_nunjucks.default.configure(templates, { autoescape: false, trimBlocks: true, ...options });
env.addFilter("pascalCase", import_nodes3.pascalCase);
env.addFilter("camelCase", import_nodes3.camelCase);
env.addFilter("snakeCase", import_nodes3.snakeCase);
env.addFilter("kebabCase", import_nodes3.kebabCase);
env.addFilter("titleCase", import_nodes3.titleCase);
env.addFilter("jsDocblock", jsDocblock);
return env.render(template, context);
};
// src/getTypeManifestVisitor.ts
function typeManifest() {
return {
isEnum: false,
looseImports: new ImportMap(),
looseType: "",
serializer: "",
serializerImports: new ImportMap(),
strictImports: new ImportMap(),
strictType: "",
value: "",
valueImports: new ImportMap()
};
}
function getTypeManifestVisitor(input) {
const { linkables, nonScalarEnums, customAccountData, customInstructionData, getImportFrom } = input;
const stack = input.stack ?? new import_visitors_core2.NodeStack();
let parentName = null;
let parentSize = null;
return (0, import_visitors_core2.pipe)(
(0, import_visitors_core2.staticVisitor)(
() => ({
isEnum: false,
looseImports: new ImportMap(),
looseType: "",
serializer: "",
serializerImports: new ImportMap(),
strictImports: new ImportMap(),
strictType: "",
value: "",
valueImports: new ImportMap()
}),
{
keys: [
...import_nodes4.REGISTERED_TYPE_NODE_KINDS,
...import_nodes4.REGISTERED_VALUE_NODE_KINDS,
"definedTypeLinkNode",
"definedTypeNode",
"accountNode",
"instructionNode"
]
}
),
(v) => (0, import_visitors_core2.extendVisitor)(v, {
visitAccount(account, { self }) {
parentName = {
loose: `${(0, import_nodes4.pascalCase)(account.name)}AccountDataArgs`,
strict: `${(0, import_nodes4.pascalCase)(account.name)}AccountData`
};
const link = customAccountData.get(account.name)?.linkNode;
const manifest = link ? (0, import_visitors_core2.visit)(link, self) : (0, import_visitors_core2.visit)(account.data, self);
parentName = null;
return manifest;
},
visitAmountType(amountType, { self }) {
const numberManifest = (0, import_visitors_core2.visit)(amountType.number, self);
const resolvedNode = (0, import_nodes4.resolveNestedTypeNode)(amountType.number);
if (!(0, import_nodes4.isUnsignedInteger)(resolvedNode)) {
throw new Error(
`Amount wrappers can only be applied to unsigned integer types. Got format [${resolvedNode.format}].`
);
}
const { unit, decimals } = amountType;
const idAndDecimals = `'${unit ?? "Unknown"}', ${decimals}`;
const isSolAmount = unit === "SOL" && decimals === 9;
const amountTypeString = isSolAmount ? "SolAmount" : `Amount<${idAndDecimals}>`;
const amountImport = isSolAmount ? "SolAmount" : "Amount";
numberManifest.strictImports.add("umi", amountImport);
numberManifest.looseImports.add("umi", amountImport);
numberManifest.serializerImports.add("umi", "mapAmountSerializer");
return {
...numberManifest,
looseType: amountTypeString,
serializer: `mapAmountSerializer(${numberManifest.serializer}, ${idAndDecimals})`,
strictType: amountTypeString
};
},
visitArrayType(arrayType, { self }) {
const childManifest = (0, import_visitors_core2.visit)(arrayType.item, self);
childManifest.serializerImports.add("umiSerializers", "array");
const sizeOption = getArrayLikeSizeOption(arrayType.count, childManifest, self);
const options = sizeOption ? `, { ${sizeOption} }` : "";
return {
...childManifest,
looseType: `Array<${childManifest.looseType}>`,
serializer: `array(${childManifest.serializer + options})`,
strictType: `Array<${childManifest.strictType}>`
};
},
visitArrayValue(node, { self }) {
const list = node.items.map((value) => (0, import_visitors_core2.visit)(value, self));
return {
...typeManifest(),
value: `[${list.map((c) => c.value).join(", ")}]`,
valueImports: new ImportMap().mergeWith(...list.map((c) => c.valueImports))
};
},
visitBooleanType(booleanType, { self }) {
const looseImports = new ImportMap();
const strictImports = new ImportMap();
const serializerImports = new ImportMap().add("umiSerializers", "bool");
let sizeSerializer = "";
const resolvedSize = (0, import_nodes4.resolveNestedTypeNode)(booleanType.size);
if (resolvedSize.format !== "u8" || resolvedSize.endian !== "le") {
const size = (0, import_visitors_core2.visit)(booleanType.size, self);
looseImports.mergeWith(size.looseImports);
strictImports.mergeWith(size.strictImports);
serializerImports.mergeWith(size.serializerImports);
sizeSerializer = `{ size: ${size.serializer} }`;
}
return {
isEnum: false,
looseImports,
looseType: "boolean",
serializer: `bool(${sizeSerializer})`,
serializerImports,
strictImports,
strictType: "boolean",
value: "",
valueImports: new ImportMap()
};
},
visitBooleanValue(node) {
return {
...typeManifest(),
value: JSON.stringify(node.boolean)
};
},
visitBytesType(_bytesType, { self }) {
const strictImports = new ImportMap();
const looseImports = new ImportMap();
const serializerImports = new ImportMap().add("umiSerializers", "bytes");
const options = [];
if (typeof parentSize === "number") {
options.push(`size: ${parentSize}`);
} else if (parentSize) {
const prefix = (0, import_visitors_core2.visit)(parentSize, self);
strictImports.mergeWith(prefix.strictImports);
looseImports.mergeWith(prefix.looseImports);
serializerImports.mergeWith(prefix.serializerImports);
options.push(`size: ${prefix.serializer}`);
}
const optionsAsString = options.length > 0 ? `{ ${options.join(", ")} }` : "";
return {
isEnum: false,
looseImports,
looseType: "Uint8Array",
serializer: `bytes(${optionsAsString})`,
serializerImports,
strictImports,
strictType: "Uint8Array",
value: "",
valueImports: new ImportMap()
};
},
visitBytesValue(node) {
const bytes = getBytesFromBytesValueNode(node);
return {
...typeManifest(),
value: `new Uint8Array([${Array.from(bytes).join(", ")}])`
};
},
visitConstantValue(node, { self }) {
if ((0, import_nodes4.isNode)(node.type, "bytesTypeNode") && (0, import_nodes4.isNode)(node.value, "bytesValueNode")) {
return (0, import_visitors_core2.visit)(node.value, self);
}
const imports = new ImportMap();
const value = (0, import_visitors_core2.visit)(node.value, self);
imports.mergeWith(value.valueImports);
const type = (0, import_visitors_core2.visit)(node.type, self);
imports.mergeWith(type.serializerImports);
return {
...typeManifest(),
value: `${type.serializer}.serialize(${value.value})`,
valueImports: imports
};
},
visitDateTimeType(dateTimeType, { self }) {
const numberManifest = (0, import_visitors_core2.visit)(dateTimeType.number, self);
const dateTimeNumber = (0, import_nodes4.resolveNestedTypeNode)(dateTimeType.number);
if (!(0, import_nodes4.isInteger)(dateTimeNumber)) {
throw new Error(
`DateTime wrappers can only be applied to integer types. Got format [${dateTimeNumber.format}].`
);
}
numberManifest.strictImports.add("umi", "DateTime");
numberManifest.looseImports.add("umi", "DateTimeInput");
numberManifest.serializerImports.add("umi", "mapDateTimeSerializer");
return {
...numberManifest,
looseType: `DateTimeInput`,
serializer: `mapDateTimeSerializer(${numberManifest.serializer})`,
strictType: `DateTime`
};
},
visitDefinedType(definedType, { self }) {
parentName = {
loose: `${(0, import_nodes4.pascalCase)(definedType.name)}Args`,
strict: (0, import_nodes4.pascalCase)(definedType.name)
};
const manifest = (0, import_visitors_core2.visit)(definedType.type, self);
parentName = null;
return manifest;
},
visitDefinedTypeLink(node) {
const pascalCaseDefinedType = (0, import_nodes4.pascalCase)(node.name);
const serializerName = `get${pascalCaseDefinedType}Serializer`;
const importFrom = getImportFrom(node);
return {
isEnum: false,
looseImports: new ImportMap().add(importFrom, `${pascalCaseDefinedType}Args`),
looseType: `${pascalCaseDefinedType}Args`,
serializer: `${serializerName}()`,
serializerImports: new ImportMap().add(importFrom, serializerName),
strictImports: new ImportMap().add(importFrom, pascalCaseDefinedType),
strictType: pascalCaseDefinedType,
value: "",
valueImports: new ImportMap()
};
},
visitEnumEmptyVariantType(enumEmptyVariantType) {
const name = (0, import_nodes4.pascalCase)(enumEmptyVariantType.name);
const kindAttribute = `__kind: "${name}"`;
return {
isEnum: false,
looseImports: new ImportMap(),
looseType: `{ ${kindAttribute} }`,
serializer: `['${name}', unit()]`,
serializerImports: new ImportMap().add("umiSerializers", "unit"),
strictImports: new ImportMap(),
strictType: `{ ${kindAttribute} }`,
value: "",
valueImports: new ImportMap()
};
},
visitEnumStructVariantType(enumStructVariantType, { self }) {
const name = (0, import_nodes4.pascalCase)(enumStructVariantType.name);
const kindAttribute = `__kind: "${name}"`;
const type = (0, import_visitors_core2.visit)(enumStructVariantType.struct, self);
return {
...type,
looseType: `{ ${kindAttribute},${type.looseType.slice(1, -1)}}`,
serializer: `['${name}', ${type.serializer}]`,
strictType: `{ ${kindAttribute},${type.strictType.slice(1, -1)}}`
};
},
visitEnumTupleVariantType(enumTupleVariantType, { self }) {
const name = (0, import_nodes4.pascalCase)(enumTupleVariantType.name);
const kindAttribute = `__kind: "${name}"`;
const struct = (0, import_nodes4.structTypeNode)([
(0, import_nodes4.structFieldTypeNode)({
name: "fields",
type: enumTupleVariantType.tuple
})
]);
const type = (0, import_visitors_core2.visit)(struct, self);
return {
...type,
looseType: `{ ${kindAttribute},${type.looseType.slice(1, -1)}}`,
serializer: `['${name}', ${type.serializer}]`,
strictType: `{ ${kindAttribute},${type.strictType.slice(1, -1)}}`,
value: "",
valueImports: new ImportMap()
};
},
visitEnumType(enumType, { self }) {
const strictImports = new ImportMap();
const looseImports = new ImportMap();
const serializerImports = new ImportMap();
const variantNames = enumType.variants.map((variant) => (0, import_nodes4.pascalCase)(variant.name));
const currentParentName = { ...parentName };
parentName = null;
const options = [];
const enumSize = (0, import_nodes4.resolveNestedTypeNode)(enumType.size);
if (enumSize.format !== "u8" || enumSize.endian !== "le") {
const sizeManifest = (0, import_visitors_core2.visit)(enumType.size, self);
strictImports.mergeWith(sizeManifest.strictImports);
looseImports.mergeWith(sizeManifest.looseImports);
serializerImports.mergeWith(sizeManifest.serializerImports);
options.push(`size: ${sizeManifest.serializer}`);
}
if ((0, import_nodes4.isScalarEnum)(enumType)) {
if (currentParentName === null) {
throw new Error(
"Scalar enums cannot be inlined and must be introduced via a defined type. Ensure you are not inlining a defined type that is a scalar enum through a visitor."
);
}
options.push(`description: '${currentParentName.strict}'`);
const optionsAsString2 = options.length > 0 ? `, { ${options.join(", ")} }` : "";
return {
isEnum: true,
looseImports,
looseType: `{ ${variantNames.join(", ")} }`,
serializer: `scalarEnum<${currentParentName.strict}>(${currentParentName.strict + optionsAsString2})`,
serializerImports: serializerImports.add("umiSerializers", "scalarEnum"),
strictImports,
strictType: `{ ${variantNames.join(", ")} }`,
value: "",
valueImports: new ImportMap()
};
}
const variants = enumType.variants.map((variant) => {
const variantName = (0, import_nodes4.pascalCase)(variant.name);
parentName = currentParentName ? {
loose: `GetDataEnumKindContent<${currentParentName.loose}, '${variantName}'>`,
strict: `GetDataEnumKindContent<${currentParentName.strict}, '${variantName}'>`
} : null;
const variantManifest = (0, import_visitors_core2.visit)(variant, self);
parentName = null;
return variantManifest;
});
const mergedManifest = mergeManifests(variants);
mergedManifest.strictImports.mergeWith(strictImports);
mergedManifest.looseImports.mergeWith(looseImports);
mergedManifest.serializerImports.mergeWith(serializerImports);
const variantSerializers = variants.map((variant) => variant.serializer).join(", ");
const serializerTypeParams = currentParentName ? currentParentName.strict : "any";
if (currentParentName?.strict) {
options.push(`description: '${(0, import_nodes4.pascalCase)(currentParentName.strict)}'`);
}
const optionsAsString = options.length > 0 ? `, { ${options.join(", ")} }` : "";
return {
...mergedManifest,
looseType: variants.map((variant) => variant.looseType).join(" | "),
serializer: `dataEnum<${serializerTypeParams}>([${variantSerializers}]${optionsAsString})`,
serializerImports: mergedManifest.serializerImports.add("umiSerializers", [
"GetDataEnumKindContent",
"GetDataEnumKind",
"dataEnum"
]),
strictType: variants.map((variant) => variant.strictType).join(" | "),
value: "",
valueImports: new ImportMap()
};
},
visitEnumValue(node, { self }) {
const imports = new ImportMap();
const enumName = (0, import_nodes4.pascalCase)(node.enum.name);
const variantName = (0, import_nodes4.pascalCase)(node.variant);
const importFrom = getImportFrom(node.enum);
const enumNode = linkables.get([...stack.getPath(), node.enum])?.type;
const isScalar = enumNode && (0, import_nodes4.isNode)(enumNode, "enumTypeNode") ? (0, import_nodes4.isScalarEnum)(enumNode) : !nonScalarEnums.includes(node.enum.name);
if (!node.value && isScalar) {
return {
...typeManifest(),
value: `${enumName}.${variantName}`,
valueImports: imports.add(importFrom, enumName)
};
}
const enumFn = (0, import_nodes4.camelCase)(node.enum.name);
imports.add(importFrom, enumFn);
if (!node.value) {
return {
...typeManifest(),
value: `${enumFn}('${variantName}')`,
valueImports: imports
};
}
const enumValue = (0, import_visitors_core2.visit)(node.value, self);
const fields = enumValue.value;
imports.mergeWith(enumValue.valueImports);
return {
...typeManifest(),
value: `${enumFn}('${variantName}', ${fields})`,
valueImports: imports
};
},
visitFixedSizeType(fixedSizeType, { self }) {
parentSize = fixedSizeType.size;
const manifest = (0, import_visitors_core2.visit)(fixedSizeType.type, self);
parentSize = null;
return manifest;
},
visitInstruction(instruction, { self }) {
parentName = {
loose: `${(0, import_nodes4.pascalCase)(instruction.name)}InstructionDataArgs`,
strict: `${(0, import_nodes4.pascalCase)(instruction.name)}InstructionData`
};
const link = customInstructionData.get(instruction.name)?.linkNode;
const struct = (0, import_nodes4.structTypeNodeFromInstructionArgumentNodes)(instruction.arguments);
const manifest = link ? (0, import_visitors_core2.visit)(link, self) : (0, import_visitors_core2.visit)(struct, self);
parentName = null;
return manifest;
},
visitMapEntryValue(node, { self }) {
const mapKey = (0, import_visitors_core2.visit)(node.key, self);
const mapValue = (0, import_visitors_core2.visit)(node.value, self);
return {
...typeManifest(),
imports: mapKey.valueImports.mergeWith(mapValue.valueImports),
render: `[${mapKey.value}, ${mapValue.value}]`
};
},
visitMapType(mapType, { self }) {
const key = (0, import_visitors_core2.visit)(mapType.key, self);
const value = (0, import_visitors_core2.visit)(mapType.value, self);
const mergedManifest = mergeManifests([key, value]);
mergedManifest.serializerImports.add("umiSerializers", "map");
const sizeOption = getArrayLikeSizeOption(mapType.count, mergedManifest, self);
const options = sizeOption ? `, { ${sizeOption} }` : "";
return {
...mergedManifest,
looseType: `Map<${key.looseType}, ${value.looseType}>`,
serializer: `map(${key.serializer}, ${value.serializer}${options})`,
strictType: `Map<${key.strictType}, ${value.strictType}>`,
value: "",
valueImports: new ImportMap()
};
},
visitMapValue(node, { self }) {
const map = node.entries.map((entry) => (0, import_visitors_core2.visit)(entry, self));
return {
...typeManifest(),
value: `new Map([${map.map((c) => c.value).join(", ")}])`,
valueImports: new ImportMap().mergeWith(...map.map((c) => c.valueImports))
};
},
visitNoneValue() {
return {
...typeManifest(),
value: "none()",
valueImports: new ImportMap().add("umi", "none")
};
},
visitNumberType(numberType) {
const isBigNumber = ["u64", "u128", "i64", "i128"].includes(numberType.format);
const serializerImports = new ImportMap().add("umiSerializers", numberType.format);
let endianness = "";
if (numberType.endian === "be") {
serializerImports.add("umiSerializers", "Endian");
endianness = "{ endian: Endian.Big }";
}
return {
isEnum: false,
looseImports: new ImportMap(),
looseType: isBigNumber ? "number | bigint" : "number",
serializer: `${numberType.format}(${endianness})`,
serializerImports,
strictImports: new ImportMap(),
strictType: isBigNumber ? "bigint" : "number",
value: "",
valueImports: new ImportMap()
};
},
visitNumberValue(node) {
return {
...typeManifest(),
value: JSON.stringify(node.number)
};
},
visitOptionType(optionType, { self }) {
const childManifest = (0, import_visitors_core2.visit)(optionType.item, self);
childManifest.strictImports.add("umi", "Option");
childManifest.looseImports.add("umi", "OptionOrNullable");
childManifest.serializerImports.add("umiSerializers", "option");
const options = [];
const optionPrefix = (0, import_nodes4.resolveNestedTypeNode)(optionType.prefix);
if (optionPrefix.format !== "u8" || optionPrefix.endian !== "le") {
const prefixManifest = (0, import_visitors_core2.visit)(optionType.prefix, self);
childManifest.strictImports.mergeWith(prefixManifest.strictImports);
childManifest.looseImports.mergeWith(prefixManifest.looseImports);
childManifest.serializerImports.mergeWith(prefixManifest.serializerImports);
options.push(`prefix: ${prefixManifest.serializer}`);
}
if (optionType.fixed) {
options.push(`fixed: true`);
}
const optionsAsString = options.length > 0 ? `, { ${options.join(", ")} }` : "";
return {
...childManifest,
looseType: `OptionOrNullable<${childManifest.looseType}>`,
serializer: `option(${childManifest.serializer}${optionsAsString})`,
strictType: `Option<${childManifest.strictType}>`
};
},
visitPublicKeyType() {
const imports = new ImportMap().add("umi", "PublicKey");
return {
isEnum: false,
looseImports: imports,
looseType: "PublicKey",
serializer: `publicKeySerializer()`,
serializerImports: new ImportMap().add("umiSerializers", "publicKey").addAlias("umiSerializers", "publicKey", "publicKeySerializer"),
strictImports: imports,
strictType: "PublicKey",
value: "",
valueImports: new ImportMap()
};
},
visitPublicKeyValue(node) {
return {
...typeManifest(),
value: `publicKey("${node.publicKey}")`,
valueImports: new ImportMap().add("umi", "publicKey")
};
},
visitRemainderOptionType(node) {
throw new import_errors2.CodamaError(import_errors2.CODAMA_ERROR__RENDERERS__UNSUPPORTED_NODE, { kind: node.kind, node });
},
visitSetType(setType, { self }) {
const childManifest = (0, import_visitors_core2.visit)(setType.item, self);
childManifest.serializerImports.add("umiSerializers", "set");
const sizeOption = getArrayLikeSizeOption(setType.count, childManifest, self);
const options = sizeOption ? `, { ${sizeOption} }` : "";
return {
...childManifest,
looseType: `Set<${childManifest.looseType}>`,
serializer: `set(${childManifest.serializer + options})`,
strictType: `Set<${childManifest.strictType}>`,
value: "",
valueImports: new ImportMap()
};
},
visitSetValue(node, { self }) {
const set = node.items.map((value) => (0, import_visitors_core2.visit)(value, self));
return {
...typeManifest(),
value: `new Set([${set.map((c) => c.value).join(", ")}])`,
valueImports: new ImportMap().mergeWith(...set.map((c) => c.valueImports))
};
},
visitSizePrefixType(sizePrefixType, { self }) {
parentSize = (0, import_nodes4.resolveNestedTypeNode)(sizePrefixType.prefix);
const manifest = (0, import_visitors_core2.visit)(sizePrefixType.type, self);
parentSize = null;
return manifest;
},
visitSolAmountType(solAmountType, { self }) {
const numberManifest = (0, import_visitors_core2.visit)(solAmountType.number, self);
const nestedNumber = (0, import_nodes4.resolveNestedTypeNode)(solAmountType.number);
if (!(0, import_nodes4.isUnsignedInteger)(nestedNumber)) {
throw new Error(
`Amount wrappers can only be applied to unsigned integer types. Got format [${nestedNumber.format}].`
);
}
const idAndDecimals = `'SOL', 9`;
numberManifest.strictImports.add("umi", "SolAmount");
numberManifest.looseImports.add("umi", "SolAmount");
numberManifest.serializerImports.add("umi", "mapAmountSerializer");
return {
...numberManifest,
looseType: "SolAmount",
serializer: `mapAmountSerializer(${numberManifest.serializer}, ${idAndDecimals})`,
strictType: "SolAmount"
};
},
visitSomeValue(node, { self }) {
const child = (0, import_visitors_core2.visit)(node.value, self);
return {
...typeManifest(),
value: `some(${child.value})`,
valueImports: child.valueImports.add("umi", "some")
};
},
visitStringType(stringType, { self }) {
const looseImports = new ImportMap();
const strictImports = new ImportMap();
const serializerImports = new ImportMap().add("umiSerializers", "string");
const options = [];
if (stringType.encoding !== "utf8") {
looseImports.add("umiSerializers", stringType.encoding);
strictImports.add("umiSerializers", stringType.encoding);
options.push(`encoding: ${stringType.encoding}`);
}
if (!parentSize) {
options.push(`size: 'variable'`);
} else if (typeof parentSize === "number") {
options.push(`size: ${parentSize}`);
} else if (parentSize.format !== "u32" || parentSize.endian !== "le") {
const prefix = (0, import_visitors_core2.visit)(parentSize, self);
looseImports.mergeWith(prefix.looseImports);
strictImports.mergeWith(prefix.strictImports);
serializerImports.mergeWith(prefix.serializerImports);
options.push(`size: ${prefix.serializer}`);
}
const optionsAsString = options.length > 0 ? `{ ${options.join(", ")} }` : "";
return {
isEnum: false,
looseImports,
looseType: "string",
serializer: `string(${optionsAsString})`,
serializerImports,
strictImports,
strictType: "string",
value: "",
valueImports: new ImportMap()
};
},
visitStringValue(node) {
return {
...typeManifest(),
value: JSON.stringify(node.string)
};
},
visitStructFieldType(structFieldType, { self }) {
const name = (0, import_nodes4.camelCase)(structFieldType.name);
const fieldChild = (0, import_visitors_core2.visit)(structFieldType.type, self);
const structFieldDocs = (0, import_nodes4.parseDocs)(structFieldType.docs);
const docblock = structFieldDocs.length > 0 ? `
${jsDocblock(structFieldDocs)}` : "";
const baseField = {
...fieldChild,
looseType: `${docblock}${name}: ${fieldChild.looseType}; `,
serializer: `['${name}', ${fieldChild.serializer}]`,
strictType: `${docblock}${name}: ${fieldChild.strictType}; `
};
if (!structFieldType.defaultValue) {
return baseField;
}
if (structFieldType.defaultValueStrategy !== "omitted") {
return {
...baseField,
looseType: `${docblock}${name}?: ${fieldChild.looseType}; `
};
}
return {
...baseField,
looseImports: new ImportMap(),
looseType: ""
};
},
visitStructFieldValue(node, { self }) {
const structValue = (0, import_visitors_core2.visit)(node.value, self);
return {
...structValue,
value: `${node.name}: ${structValue.value}`
};
},
visitStructType(structType, { self }) {
const currentParentName = parentName;
parentName = null;
const fields = structType.fields.map((field) => (0, import_visitors_core2.visit)(field, self));
const mergedManifest = mergeManifests(fields);
mergedManifest.serializerImports.add("umiSerializers", "struct");
const fieldSerializers = fields.map((field) => field.serializer).join(", ");
const structDescription = currentParentName?.strict && !currentParentName.strict.match(/['"<>]/) ? `, { description: '${(0, import_nodes4.pascalCase)(currentParentName.strict)}' }` : "";
const serializerTypeParams = currentParentName ? currentParentName.strict : "any";
const baseManifest = {
...mergedManifest,
looseType: `{ ${fields.map((field) => field.looseType).join("")} }`,
serializer: `struct<${serializerTypeParams}>([${fieldSerializers}]${structDescription})`,
strictType: `{ ${fields.map((field) => field.strictType).join("")} }`,
value: "",
valueImports: new ImportMap()
};
const optionalFields = structType.fields.filter((f) => !!f.defaultValue);
if (optionalFields.length === 0) {
return baseManifest;
}
const defaultValues = optionalFields.map((f) => {
const key = (0, import_nodes4.camelCase)(f.name);
const defaultValue = f.defaultValue;
const { value: renderedValue, valueImports } = (0, import_visitors_core2.visit)(defaultValue, self);
baseManifest.serializerImports.mergeWith(valueImports);
if (f.defaultValueStrategy === "omitted") {
return `${key}: ${renderedValue}`;
}
return `${key}: value.${key} ?? ${renderedValue}`;
}).join(", ");
const mapSerializerTypeParams = currentParentName ? `${currentParentName.loose}, any, ${currentParentName.strict}` : "any, any, any";
const mappedSerializer = `mapSerializer<${mapSerializerTypeParams}>(${baseManifest.serializer}, (value) => ({ ...value, ${defaultValues} }) )`;
baseManifest.serializerImports.add("umiSerializers", "mapSerializer");
return { ...baseManifest, serializer: mappedSerializer };
},
visitStructValue(node, { self }) {
const struct = node.fields.map((field) => (0, import_visitors_core2.visit)(field, self));
return {
...typeManifest(),
value: `{ ${struct.map((c) => c.value).join(", ")} }`,
valueImports: new ImportMap().mergeWith(...struct.map((c) => c.valueImports))
};
},
visitTupleType(tupleType, { self }) {
const items = tupleType.items.map((item) => (0, import_visitors_core2.visit)(item, self));
const mergedManifest = mergeManifests(items);
mergedManifest.serializerImports.add("umiSerializers", "tuple");
const itemSerializers = items.map((child) => child.serializer).join(", ");
return {
...mergedManifest,
looseType: `[${items.map((item) => item.looseType).join(", ")}]`,
serializer: `tuple([${itemSerializers}])`,
strictType: `[${items.map((item) => item.strictType).join(", ")}]`,
value: ""
};
},
visitTupleValue(node, { self }) {
const list = node.items.map((value) => (0, import_visitors_core2.visit)(value, self));
return {
...typeManifest(),
value: `[${list.map((c) => c.value).join(", ")}]`,
valueImports: new ImportMap().mergeWith(...list.map((c) => c.valueImports))
};
},
visitZeroableOptionType(node) {
throw new import_errors2.CodamaError(import_errors2.CODAMA_ERROR__RENDERERS__UNSUPPORTED_NODE, { kind: node.kind, node });
}
}),
(v) => (0, import_visitors_core2.recordNodeStackVisitor)(v, stack)
);
}
function mergeManifests(manifests) {
return {
isEnum: false,
looseImports: new ImportMap().mergeWith(...manifests.map((td) => td.looseImports)),
serializerImports: new ImportMap().mergeWith(...manifests.map((td) => td.serializerImports)),
strictImports: new ImportMap().mergeWith(...manifests.map((td) => td.strictImports)),
valueImports: new ImportMap().mergeWith(...manifests.map((td) => td.valueImports))
};
}
function getArrayLikeSizeOption(count, manifest, self) {
if ((0, import_nodes4.isNode)(count, "fixedCountNode")) return `size: ${count.value}`;
if ((0, import_nodes4.isNode)(count, "remainderCountNode")) return `size: 'remainder'`;
const prefixManifest = (0, import_visitors_core2.visit)(count.prefix, self);
if (prefixManifest.serializer === "u32()") return null;
manifest.strictImports.mergeWith(prefixManifest.strictImports);
manifest.looseImports.mergeWith(prefixManifest.looseImports);
manifest.serializerImports.mergeWith(prefixManifest.serializerImports);
return `size: ${prefixManifest.serializer}`;
}
// src/renderInstructionDefaults.ts
var import_nodes5 = require("@codama/nodes");
var import_visitors_core3 = require("@codama/visitors-core");
function renderInstructionDefaults(input, typeManifestVisitor, optionalAccountStrategy, argObject, getImportFrom) {
const imports = new ImportMap();
const interfaces = new ContextMap();
if (!input.defaultValue) {
return { imports, interfaces, render: "" };
}
const { defaultValue } = input;
const render2 = (renderedValue, isWritable) => {
const inputName = (0, import_nodes5.camelCase)(input.name);
if (input.kind === "instructionAccountNode" && (0, import_nodes5.isNode)(defaultValue, "resolverValueNode")) {
return {
imports,
interfaces,
render: `resolvedAccounts.${inputName} = { ...resolvedAccounts.${inputName}, ...${renderedValue} };`
};
}
if (input.kind === "instructionAccountNode" && isWritable === void 0) {
return {
imports,
interfaces,
render: `resolvedAccounts.${inputName}.value = ${renderedValue};`
};
}
if (input.kind === "instructionAccountNode") {
return {
imports,
interfaces,
render: `resolvedAccounts.${inputName}.value = ${renderedValue};
resolvedAccounts.${inputName}.isWritable = ${isWritable ? "true" : "false"}`
};
}
return {
imports,
interfaces,
render: `${argObject}.${inputName} = ${renderedValue};`
};
};
switch (defaultValue.kind) {
case "accountValueNode":
const name = (0, import_nodes5.camelCase)(defaultValue.name);
if (input.kind === "instructionAccountNode") {
imports.add("shared", "expectSome");
if (input.resolvedIsSigner && !input.isSigner) {
return render2(`expectSome(resolvedAccounts.${name}.value).publicKey`);
}
return render2(`expectSome(resolvedAccounts.${name}.value)`);
}
imports.add("shared", "expectPublicKey");
return render2(`expectPublicKey(resolvedAccounts.${name}.value)`);
case "pdaValueNode":
if ((0, import_nodes5.isNode)(defaultValue.pda, "pdaNode")) {
const pdaProgram = defaultValue.pda.programId ? `context.programs.getPublicKey('${defaultValue.pda.programId}', '${defaultValue.pda.programId}')` : "programId";
const pdaSeeds2 = defaultValue.pda.seeds.flatMap((seed) => {
if ((0, import_nodes5.isNode)(seed, "constantPdaSeedNode") && (0, import_nodes5.isNode)(seed.value, "programIdValueNode")) {
imports.add("umiSerializers", "publicKey").addAlias("umiSerializers", "publicKey", "publicKeySerializer");
return [`publicKeySerializer().serialize(${pdaProgram})`];
}
if ((0, import_nodes5.isNode)(seed, "constantPdaSeedNode") && !(0, import_nodes5.isNode)(seed.value, "programIdValueNode")) {
const typeManifest2 = (0, import_visitors_core3.visit)(seed.type, typeManifestVisitor);
const valueManifest2 = (0, import_visitors_core3.visit)(seed.value, typeManifestVisitor);
imports.mergeWith(typeManifest2.serializerImports);
imports.mergeWith(valueManifest2.valueImports);
return [`${typeManifest2.serializer}.serialize(${valueManifest2.value})`];
}
if ((0, import_nodes5.isNode)(seed, "variablePdaSeedNode")) {
const typeManifest2 = (0, import_visitors_core3.visit)(seed.type, typeManifestVisitor);
const valueSeed = defaultValue.seeds.find((s) => s.name === seed.name)?.value;
if (!valueSeed) return [];
if ((0, import_nodes5.isNode)(valueSeed, "accountValueNode")) {
imports.mergeWith(typeManifest2.serializerImports);
imports.add("shared", "expectPublicKey");
return [
`${typeManifest2.serializer}.serialize(expectPublicKey(resolvedAccounts.${(0, import_nodes5.camelCase)(valueSeed.name)}.value))`
];
}
if ((0, import_nodes5.isNode)(valueSeed, "argumentValueNode")) {
imports.mergeWith(typeManifest2.serializerImports);
imports.add("shared", "expectSome");
return [
`${typeManifest2.serializer}.serialize(expectSome(${argObject}.${(0, import_nodes5.camelCase)(valueSeed.name)}))`
];
}
const valueManifest2 = (0, import_visitors_core3.visit)(valueSeed, typeManifestVisitor);
imports.mergeWith(typeManifest2.serializerImports);
imports.mergeWith(valueManifest2.valueImports);
return [`${typeManifest2.serializer}.serialize(${valueManifest2.value})`];
}
return [];
});
interfaces.add("eddsa");
return render2(`context.eddsa.findPda(${pdaProgram}, [${pdaSeeds2.join(", ")}])`);
}
const pdaFunction = `find${(0, import_nodes5.pascalCase)(defaultValue.pda.name)}Pda`;
imports.add(getImportFrom(defaultValue.pda), pdaFunction);
interfaces.add("eddsa");
const pdaArgs = ["context"];
const pdaSeeds = defaultValue.seeds.map((seed) => {
if ((0, import_nodes5.isNode)(seed.value, "accountValueNode")) {
imports.add("shared", "expectPublicKey");
return `${seed.name}: expectPublicKey(resolvedAccounts.${(0, import_nodes5.camelCase)(seed.value.name)}.value)`;
}
if ((0, import_nodes5.isNode)(seed.value, "argumentValueNode")) {
imports.add("shared", "expectSome");
return `${seed.name}: expectSome(${argObject}.${(0, import_nodes5.camelCase)(seed.value.name)})`;
}
const valueManifest2 = (0, import_visitors_core3.visit)(seed.value, typeManifestVisitor);
imports.mergeWith(valueManifest2.valueImports);
return `${seed.name}: ${valueManifest2.value}`;
});
if (pdaSeeds.length > 0) {
pdaArgs.push(`{ ${pdaSeeds.join(", ")} }`);
}
return render2(`${pdaFunction}(${pdaArgs.join(", ")})`);
case "publicKeyValueNode":
if (!defaultValue.identifier) {
imports.add("umi", "publicKey");
return render2(`publicKey('${defaultValue.publicKey}')`);
}
interfaces.add("programs");
return render2(
`context.programs.getPublicKey('${defaultValue.identifier}', '${defaultValue.publicKey}')`,
false
);
case "programLinkNode":
const functionNa