UNPKG

@codama/renderers-js-umi

Version:

JavaScript renderer compatible with the Umi framework

1,147 lines (1,135 loc) 82.8 kB
"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