@codama/renderers-js 1.3.4 → 1.4.0

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.
Files changed (160) hide show
  1. package/LICENSE +1 -1
  2. package/dist/index.browser.cjs +3247 -0
  3. package/dist/index.browser.cjs.map +1 -0
  4. package/dist/index.browser.mjs +3300 -0
  5. package/dist/index.browser.mjs.map +1 -0
  6. package/dist/index.node.cjs +2081 -1718
  7. package/dist/index.node.cjs.map +1 -1
  8. package/dist/index.node.mjs +2015 -1657
  9. package/dist/index.node.mjs.map +1 -1
  10. package/dist/index.react-native.mjs +3300 -0
  11. package/dist/index.react-native.mjs.map +1 -0
  12. package/dist/types/fragments/accountFetchHelpers.d.ts +2 -4
  13. package/dist/types/fragments/accountFetchHelpers.d.ts.map +1 -1
  14. package/dist/types/fragments/accountPage.d.ts +8 -0
  15. package/dist/types/fragments/accountPage.d.ts.map +1 -0
  16. package/dist/types/fragments/accountPdaHelpers.d.ts +3 -5
  17. package/dist/types/fragments/accountPdaHelpers.d.ts.map +1 -1
  18. package/dist/types/fragments/accountSizeHelpers.d.ts +3 -4
  19. package/dist/types/fragments/accountSizeHelpers.d.ts.map +1 -1
  20. package/dist/types/fragments/accountType.d.ts +3 -5
  21. package/dist/types/fragments/accountType.d.ts.map +1 -1
  22. package/dist/types/fragments/discriminatorCondition.d.ts +2 -3
  23. package/dist/types/fragments/discriminatorCondition.d.ts.map +1 -1
  24. package/dist/types/fragments/discriminatorConstants.d.ts +5 -6
  25. package/dist/types/fragments/discriminatorConstants.d.ts.map +1 -1
  26. package/dist/types/fragments/errorPage.d.ts +6 -0
  27. package/dist/types/fragments/errorPage.d.ts.map +1 -0
  28. package/dist/types/fragments/index.d.ts +11 -4
  29. package/dist/types/fragments/index.d.ts.map +1 -1
  30. package/dist/types/fragments/indexPage.d.ts +6 -0
  31. package/dist/types/fragments/indexPage.d.ts.map +1 -0
  32. package/dist/types/fragments/instructionAccountMeta.d.ts +1 -1
  33. package/dist/types/fragments/instructionAccountMeta.d.ts.map +1 -1
  34. package/dist/types/fragments/instructionAccountTypeParam.d.ts +2 -3
  35. package/dist/types/fragments/instructionAccountTypeParam.d.ts.map +1 -1
  36. package/dist/types/fragments/instructionByteDelta.d.ts +3 -4
  37. package/dist/types/fragments/instructionByteDelta.d.ts.map +1 -1
  38. package/dist/types/fragments/instructionData.d.ts +3 -5
  39. package/dist/types/fragments/instructionData.d.ts.map +1 -1
  40. package/dist/types/fragments/instructionExtraArgs.d.ts +3 -5
  41. package/dist/types/fragments/instructionExtraArgs.d.ts.map +1 -1
  42. package/dist/types/fragments/instructionFunction.d.ts +3 -5
  43. package/dist/types/fragments/instructionFunction.d.ts.map +1 -1
  44. package/dist/types/fragments/instructionInputDefault.d.ts +2 -3
  45. package/dist/types/fragments/instructionInputDefault.d.ts.map +1 -1
  46. package/dist/types/fragments/instructionInputResolved.d.ts +2 -3
  47. package/dist/types/fragments/instructionInputResolved.d.ts.map +1 -1
  48. package/dist/types/fragments/instructionInputType.d.ts +2 -4
  49. package/dist/types/fragments/instructionInputType.d.ts.map +1 -1
  50. package/dist/types/fragments/instructionPage.d.ts +9 -0
  51. package/dist/types/fragments/instructionPage.d.ts.map +1 -0
  52. package/dist/types/fragments/instructionParseFunction.d.ts +2 -4
  53. package/dist/types/fragments/instructionParseFunction.d.ts.map +1 -1
  54. package/dist/types/fragments/instructionRemainingAccounts.d.ts +3 -4
  55. package/dist/types/fragments/instructionRemainingAccounts.d.ts.map +1 -1
  56. package/dist/types/fragments/instructionType.d.ts +2 -3
  57. package/dist/types/fragments/instructionType.d.ts.map +1 -1
  58. package/dist/types/fragments/pdaFunction.d.ts +2 -3
  59. package/dist/types/fragments/pdaFunction.d.ts.map +1 -1
  60. package/dist/types/fragments/pdaPage.d.ts +7 -0
  61. package/dist/types/fragments/pdaPage.d.ts.map +1 -0
  62. package/dist/types/fragments/programAccounts.d.ts +3 -4
  63. package/dist/types/fragments/programAccounts.d.ts.map +1 -1
  64. package/dist/types/fragments/programConstant.d.ts +6 -0
  65. package/dist/types/fragments/programConstant.d.ts.map +1 -0
  66. package/dist/types/fragments/programInstructions.d.ts +3 -4
  67. package/dist/types/fragments/programInstructions.d.ts.map +1 -1
  68. package/dist/types/fragments/programPage.d.ts +6 -0
  69. package/dist/types/fragments/programPage.d.ts.map +1 -0
  70. package/dist/types/fragments/rootIndexPage.d.ts +10 -0
  71. package/dist/types/fragments/rootIndexPage.d.ts.map +1 -0
  72. package/dist/types/fragments/sharedPage.d.ts +3 -0
  73. package/dist/types/fragments/sharedPage.d.ts.map +1 -0
  74. package/dist/types/fragments/type.d.ts +2 -4
  75. package/dist/types/fragments/type.d.ts.map +1 -1
  76. package/dist/types/fragments/typeCodec.d.ts +2 -4
  77. package/dist/types/fragments/typeCodec.d.ts.map +1 -1
  78. package/dist/types/fragments/typeDecoder.d.ts +2 -4
  79. package/dist/types/fragments/typeDecoder.d.ts.map +1 -1
  80. package/dist/types/fragments/typeDiscriminatedUnionHelpers.d.ts +3 -4
  81. package/dist/types/fragments/typeDiscriminatedUnionHelpers.d.ts.map +1 -1
  82. package/dist/types/fragments/typeEncoder.d.ts +2 -4
  83. package/dist/types/fragments/typeEncoder.d.ts.map +1 -1
  84. package/dist/types/fragments/typePage.d.ts +7 -0
  85. package/dist/types/fragments/typePage.d.ts.map +1 -0
  86. package/dist/types/fragments/typeWithCodec.d.ts +2 -4
  87. package/dist/types/fragments/typeWithCodec.d.ts.map +1 -1
  88. package/dist/types/index.d.ts +5 -7
  89. package/dist/types/index.d.ts.map +1 -1
  90. package/dist/types/utils/fragment.d.ts +24 -0
  91. package/dist/types/utils/fragment.d.ts.map +1 -0
  92. package/dist/types/utils/importMap.d.ts +17 -0
  93. package/dist/types/utils/importMap.d.ts.map +1 -0
  94. package/dist/types/utils/index.d.ts +5 -1
  95. package/dist/types/utils/index.d.ts.map +1 -1
  96. package/dist/types/utils/nameTransformers.d.ts.map +1 -0
  97. package/dist/types/utils/options.d.ts +40 -0
  98. package/dist/types/utils/options.d.ts.map +1 -0
  99. package/dist/types/{TypeManifest.d.ts → utils/typeManifest.d.ts} +6 -6
  100. package/dist/types/utils/typeManifest.d.ts.map +1 -0
  101. package/dist/types/visitors/getRenderMapVisitor.d.ts +3 -0
  102. package/dist/types/visitors/getRenderMapVisitor.d.ts.map +1 -0
  103. package/dist/types/visitors/getTypeManifestVisitor.d.ts +21 -0
  104. package/dist/types/visitors/getTypeManifestVisitor.d.ts.map +1 -0
  105. package/dist/types/visitors/index.d.ts +4 -0
  106. package/dist/types/visitors/index.d.ts.map +1 -0
  107. package/dist/types/visitors/renderVisitor.d.ts +3 -0
  108. package/dist/types/visitors/renderVisitor.d.ts.map +1 -0
  109. package/package.json +22 -13
  110. package/dist/templates/fragments/accountFetchHelpers.njk +0 -43
  111. package/dist/templates/fragments/accountPdaHelpers.njk +0 -25
  112. package/dist/templates/fragments/accountSizeHelpers.njk +0 -3
  113. package/dist/templates/fragments/instructionExtraArgs.njk +0 -4
  114. package/dist/templates/fragments/instructionFunction.njk +0 -62
  115. package/dist/templates/fragments/instructionInputType.njk +0 -16
  116. package/dist/templates/fragments/instructionParseFunction.njk +0 -81
  117. package/dist/templates/fragments/instructionType.njk +0 -18
  118. package/dist/templates/fragments/pdaFunction.njk +0 -33
  119. package/dist/templates/fragments/program.njk +0 -3
  120. package/dist/templates/fragments/programErrors.njk +0 -36
  121. package/dist/templates/fragments/type.njk +0 -12
  122. package/dist/templates/fragments/typeCodec.njk +0 -6
  123. package/dist/templates/fragments/typeDecoder.njk +0 -6
  124. package/dist/templates/fragments/typeDiscriminatedUnionHelpers.njk +0 -23
  125. package/dist/templates/fragments/typeEncoder.njk +0 -6
  126. package/dist/templates/layout.njk +0 -9
  127. package/dist/templates/macros.njk +0 -12
  128. package/dist/templates/pages/accountsIndex.njk +0 -9
  129. package/dist/templates/pages/accountsPage.njk +0 -12
  130. package/dist/templates/pages/definedTypesIndex.njk +0 -9
  131. package/dist/templates/pages/definedTypesPage.njk +0 -9
  132. package/dist/templates/pages/errorsIndex.njk +0 -9
  133. package/dist/templates/pages/errorsPage.njk +0 -8
  134. package/dist/templates/pages/instructionsIndex.njk +0 -9
  135. package/dist/templates/pages/instructionsPage.njk +0 -14
  136. package/dist/templates/pages/pdasIndex.njk +0 -9
  137. package/dist/templates/pages/pdasPage.njk +0 -8
  138. package/dist/templates/pages/programsIndex.njk +0 -9
  139. package/dist/templates/pages/programsPage.njk +0 -10
  140. package/dist/templates/pages/rootIndex.njk +0 -26
  141. package/dist/templates/pages/sharedPage.njk +0 -106
  142. package/dist/types/ImportMap.d.ts +0 -15
  143. package/dist/types/ImportMap.d.ts.map +0 -1
  144. package/dist/types/TypeManifest.d.ts.map +0 -1
  145. package/dist/types/fragments/common.d.ts +0 -25
  146. package/dist/types/fragments/common.d.ts.map +0 -1
  147. package/dist/types/fragments/program.d.ts +0 -7
  148. package/dist/types/fragments/program.d.ts.map +0 -1
  149. package/dist/types/fragments/programErrors.d.ts +0 -7
  150. package/dist/types/fragments/programErrors.d.ts.map +0 -1
  151. package/dist/types/getRenderMapVisitor.d.ts +0 -31
  152. package/dist/types/getRenderMapVisitor.d.ts.map +0 -1
  153. package/dist/types/getTypeManifestVisitor.d.ts +0 -16
  154. package/dist/types/getTypeManifestVisitor.d.ts.map +0 -1
  155. package/dist/types/nameTransformers.d.ts.map +0 -1
  156. package/dist/types/renderVisitor.d.ts +0 -11
  157. package/dist/types/renderVisitor.d.ts.map +0 -1
  158. package/dist/types/utils/render.d.ts +0 -4
  159. package/dist/types/utils/render.d.ts.map +0 -1
  160. /package/dist/types/{nameTransformers.d.ts → utils/nameTransformers.d.ts} +0 -0
@@ -1,4 +1,4 @@
1
- // src/ImportMap.ts
1
+ // src/utils/importMap.ts
2
2
  var DEFAULT_EXTERNAL_MODULE_MAP = {
3
3
  solanaAccounts: "@solana/kit",
4
4
  solanaAddresses: "@solana/kit",
@@ -40,102 +40,255 @@ var DEFAULT_INTERNAL_MODULE_MAP = {
40
40
  shared: "../shared",
41
41
  types: "../types"
42
42
  };
43
- var ImportMap = class {
44
- _imports = /* @__PURE__ */ new Map();
45
- _aliases = /* @__PURE__ */ new Map();
46
- add(module, imports) {
47
- const newImports = new Set(typeof imports === "string" ? [imports] : imports);
48
- if (newImports.size === 0) return this;
49
- const currentImports = this._imports.get(module) ?? /* @__PURE__ */ new Set();
50
- newImports.forEach((i) => currentImports.add(i));
51
- this._imports.set(module, currentImports);
52
- return this;
53
- }
54
- remove(module, imports) {
55
- const importsToRemove = new Set(typeof imports === "string" ? [imports] : imports);
56
- if (importsToRemove.size === 0) return this;
57
- const currentImports = this._imports.get(module) ?? /* @__PURE__ */ new Set();
58
- importsToRemove.forEach((i) => currentImports.delete(i));
59
- if (currentImports.size === 0) {
60
- this._imports.delete(module);
61
- } else {
62
- this._imports.set(module, currentImports);
63
- }
64
- return this;
65
- }
66
- mergeWith(...others) {
67
- others.forEach((rawOther) => {
68
- const other = "imports" in rawOther ? rawOther.imports : rawOther;
69
- other._imports.forEach((imports, module) => {
70
- this.add(module, imports);
71
- });
72
- other._aliases.forEach((aliases, module) => {
73
- Object.entries(aliases).forEach(([name, alias]) => {
74
- this.addAlias(module, name, alias);
75
- });
76
- });
77
- });
78
- return this;
79
- }
80
- mergeWithManifest(manifest) {
81
- return this.mergeWith(manifest.strictType, manifest.looseType, manifest.encoder, manifest.decoder);
82
- }
83
- addAlias(module, name, alias) {
84
- const currentAliases = this._aliases.get(module) ?? {};
85
- currentAliases[name] = alias;
86
- this._aliases.set(module, currentAliases);
87
- return this;
88
- }
89
- isEmpty() {
90
- return this._imports.size === 0;
91
- }
92
- resolve(dependencies = {}, useGranularImports = false) {
93
- const aliasedMap = new Map(
94
- [...this._imports.entries()].map(([module, imports]) => {
95
- const aliasMap = this._aliases.get(module) ?? {};
96
- const joinedImports = [...imports].map((i) => aliasMap[i] ? `${i} as ${aliasMap[i]}` : i);
97
- return [module, new Set(joinedImports)];
98
- })
99
- );
100
- const dependencyMap = {
101
- ...useGranularImports ? DEFAULT_GRANULAR_EXTERNAL_MODULE_MAP : DEFAULT_EXTERNAL_MODULE_MAP,
102
- ...DEFAULT_INTERNAL_MODULE_MAP,
103
- ...dependencies
104
- };
105
- const resolvedMap = /* @__PURE__ */ new Map();
106
- aliasedMap.forEach((imports, module) => {
107
- const resolvedModule = dependencyMap[module] ?? module;
108
- const currentImports = resolvedMap.get(resolvedModule) ?? /* @__PURE__ */ new Set();
109
- imports.forEach((i) => currentImports.add(i));
110
- resolvedMap.set(resolvedModule, currentImports);
111
- });
112
- return resolvedMap;
113
- }
114
- toString(dependencies = {}, useGranularImports = false) {
115
- return [...this.resolve(dependencies, useGranularImports).entries()].sort(([a], [b]) => {
116
- const aIsRelative = a.startsWith(".");
117
- const bIsRelative = b.startsWith(".");
118
- if (aIsRelative && !bIsRelative) return 1;
119
- if (!aIsRelative && bIsRelative) return -1;
120
- return a.localeCompare(b);
121
- }).map(([module, imports]) => {
122
- const joinedImports = [...imports].sort().filter((i) => {
123
- const name = i.split(" ");
124
- if (name.length > 1) {
125
- return !imports.has(name[1]);
43
+ function createImportMap() {
44
+ return Object.freeze(/* @__PURE__ */ new Map());
45
+ }
46
+ function parseImportInput(input) {
47
+ const matches = input.match(/^(type )?([^ ]+)(?: as (.+))?$/);
48
+ if (!matches) return Object.freeze({ importedIdentifier: input, isType: false, usedIdentifier: input });
49
+ const [_, isType, name, alias] = matches;
50
+ return Object.freeze({
51
+ importedIdentifier: name,
52
+ isType: !!isType,
53
+ usedIdentifier: alias ?? name
54
+ });
55
+ }
56
+ function addToImportMap(importMap, module, imports) {
57
+ const parsedImports = imports.map(parseImportInput).map((i) => [i.usedIdentifier, i]);
58
+ return mergeImportMaps([importMap, /* @__PURE__ */ new Map([[module, new Map(parsedImports)]])]);
59
+ }
60
+ function removeFromImportMap(importMap, module, usedIdentifiers) {
61
+ const newMap = new Map(importMap);
62
+ const newModuleMap = new Map(newMap.get(module));
63
+ usedIdentifiers.forEach((usedIdentifier) => {
64
+ newModuleMap.delete(usedIdentifier);
65
+ });
66
+ if (newModuleMap.size === 0) {
67
+ newMap.delete(module);
68
+ } else {
69
+ newMap.set(module, newModuleMap);
70
+ }
71
+ return Object.freeze(newMap);
72
+ }
73
+ function mergeImportMaps(importMaps) {
74
+ if (importMaps.length === 0) return createImportMap();
75
+ if (importMaps.length === 1) return importMaps[0];
76
+ const mergedMap = new Map(importMaps[0]);
77
+ for (const map of importMaps.slice(1)) {
78
+ for (const [module, imports] of map) {
79
+ const mergedModuleMap = mergedMap.get(module) ?? /* @__PURE__ */ new Map();
80
+ for (const [usedIdentifier, importInfo] of imports) {
81
+ const existingImportInfo = mergedModuleMap.get(usedIdentifier);
82
+ const shouldOverwriteTypeOnly = existingImportInfo && existingImportInfo.importedIdentifier === importInfo.importedIdentifier && existingImportInfo.isType && !importInfo.isType;
83
+ if (!existingImportInfo || shouldOverwriteTypeOnly) {
84
+ mergedModuleMap.set(usedIdentifier, importInfo);
126
85
  }
127
- return true;
128
- }).join(", ");
129
- return `import { ${joinedImports} } from '${module}';`;
130
- }).join("\n");
86
+ }
87
+ mergedMap.set(module, mergedModuleMap);
88
+ }
131
89
  }
90
+ return Object.freeze(mergedMap);
91
+ }
92
+ function importMapToString(importMap, dependencyMap = {}, useGranularImports = false) {
93
+ const resolvedMap = resolveImportMapModules(importMap, dependencyMap, useGranularImports);
94
+ return [...resolvedMap.entries()].sort(([a], [b]) => {
95
+ const relative = Number(a.startsWith(".")) - Number(b.startsWith("."));
96
+ if (relative !== 0) return relative;
97
+ return a.localeCompare(b);
98
+ }).map(([module, imports]) => {
99
+ const innerImports = [...imports.values()].map(importInfoToString).sort((a, b) => a.localeCompare(b)).join(", ");
100
+ return `import { ${innerImports} } from '${module}';`;
101
+ }).join("\n");
102
+ }
103
+ function resolveImportMapModules(importMap, dependencyMap, useGranularImports) {
104
+ const dependencyMapWithDefaults = {
105
+ ...useGranularImports ? DEFAULT_GRANULAR_EXTERNAL_MODULE_MAP : DEFAULT_EXTERNAL_MODULE_MAP,
106
+ ...DEFAULT_INTERNAL_MODULE_MAP,
107
+ ...dependencyMap
108
+ };
109
+ return mergeImportMaps(
110
+ [...importMap.entries()].map(([module, imports]) => {
111
+ const resolvedModule = dependencyMapWithDefaults[module] ?? module;
112
+ return /* @__PURE__ */ new Map([[resolvedModule, imports]]);
113
+ })
114
+ );
115
+ }
116
+ function importInfoToString({ importedIdentifier, isType, usedIdentifier }) {
117
+ const alias = importedIdentifier !== usedIdentifier ? ` as ${usedIdentifier}` : "";
118
+ return `${isType ? "type " : ""}${importedIdentifier}${alias}`;
119
+ }
120
+
121
+ // src/utils/nameTransformers.ts
122
+ import { camelCase, capitalize, kebabCase, pascalCase, snakeCase, titleCase } from "@codama/nodes";
123
+ function getNameApi(transformers) {
124
+ const helpers = {
125
+ camelCase,
126
+ capitalize,
127
+ kebabCase,
128
+ pascalCase,
129
+ snakeCase,
130
+ titleCase
131
+ };
132
+ return Object.fromEntries(
133
+ Object.entries(transformers).map(([key, transformer]) => [key, (name) => transformer(name, helpers)])
134
+ );
135
+ }
136
+ var DEFAULT_NAME_TRANSFORMERS = {
137
+ accountDecodeFunction: (name) => `decode${pascalCase(name)}`,
138
+ accountFetchAllFunction: (name) => `fetchAll${pascalCase(name)}`,
139
+ accountFetchAllMaybeFunction: (name) => `fetchAllMaybe${pascalCase(name)}`,
140
+ accountFetchFromSeedsFunction: (name) => `fetch${pascalCase(name)}FromSeeds`,
141
+ accountFetchFunction: (name) => `fetch${pascalCase(name)}`,
142
+ accountFetchMaybeFromSeedsFunction: (name) => `fetchMaybe${pascalCase(name)}FromSeeds`,
143
+ accountFetchMaybeFunction: (name) => `fetchMaybe${pascalCase(name)}`,
144
+ accountGetSizeFunction: (name) => `get${pascalCase(name)}Size`,
145
+ codecFunction: (name) => `get${pascalCase(name)}Codec`,
146
+ constant: (name) => snakeCase(name).toUpperCase(),
147
+ constantFunction: (name) => `get${pascalCase(name)}Bytes`,
148
+ dataArgsType: (name) => `${pascalCase(name)}Args`,
149
+ dataType: (name) => `${pascalCase(name)}`,
150
+ decoderFunction: (name) => `get${pascalCase(name)}Decoder`,
151
+ discriminatedUnionDiscriminator: () => "__kind",
152
+ discriminatedUnionFunction: (name) => `${camelCase(name)}`,
153
+ discriminatedUnionVariant: (name) => `${pascalCase(name)}`,
154
+ encoderFunction: (name) => `get${pascalCase(name)}Encoder`,
155
+ enumVariant: (name) => `${pascalCase(name)}`,
156
+ instructionAsyncFunction: (name) => `get${pascalCase(name)}InstructionAsync`,
157
+ instructionAsyncInputType: (name) => `${pascalCase(name)}AsyncInput`,
158
+ instructionDataType: (name) => `${pascalCase(name)}InstructionData`,
159
+ instructionExtraType: (name) => `${pascalCase(name)}InstructionExtra`,
160
+ instructionParseFunction: (name) => `parse${pascalCase(name)}Instruction`,
161
+ instructionParsedType: (name) => `Parsed${pascalCase(name)}Instruction`,
162
+ instructionSyncFunction: (name) => `get${pascalCase(name)}Instruction`,
163
+ instructionSyncInputType: (name) => `${pascalCase(name)}Input`,
164
+ instructionType: (name) => `${pascalCase(name)}Instruction`,
165
+ isDiscriminatedUnionFunction: (name) => `is${pascalCase(name)}`,
166
+ pdaFindFunction: (name) => `find${pascalCase(name)}Pda`,
167
+ pdaSeedsType: (name) => `${pascalCase(name)}Seeds`,
168
+ programAccountsEnum: (name) => `${pascalCase(name)}Account`,
169
+ programAccountsEnumVariant: (name) => `${pascalCase(name)}`,
170
+ programAccountsIdentifierFunction: (name) => `identify${pascalCase(name)}Account`,
171
+ programAddressConstant: (name) => `${snakeCase(name).toUpperCase()}_PROGRAM_ADDRESS`,
172
+ programErrorConstant: (name) => snakeCase(name).toUpperCase(),
173
+ programErrorConstantPrefix: (name) => `${snakeCase(name).toUpperCase()}_ERROR__`,
174
+ programErrorMessagesMap: (name) => `${camelCase(name)}ErrorMessages`,
175
+ programErrorUnion: (name) => `${pascalCase(name)}Error`,
176
+ programGetErrorMessageFunction: (name) => `get${pascalCase(name)}ErrorMessage`,
177
+ programInstructionsEnum: (name) => `${pascalCase(name)}Instruction`,
178
+ programInstructionsEnumVariant: (name) => `${pascalCase(name)}`,
179
+ programInstructionsIdentifierFunction: (name) => `identify${pascalCase(name)}Instruction`,
180
+ programInstructionsParsedUnionType: (name) => `Parsed${pascalCase(name)}Instruction`,
181
+ programIsErrorFunction: (name) => `is${pascalCase(name)}Error`,
182
+ resolverFunction: (name) => `${camelCase(name)}`
132
183
  };
133
184
 
134
- // src/fragments/accountFetchHelpers.ts
135
- import { getLastNodeFromPath } from "@codama/visitors-core";
185
+ // src/utils/fragment.ts
186
+ import { createFragmentTemplate } from "@codama/renderers-core";
187
+ function createFragment(content) {
188
+ return Object.freeze({ content, features: /* @__PURE__ */ new Set(), imports: createImportMap() });
189
+ }
190
+ function isFragment(value) {
191
+ return typeof value === "object" && value !== null && "content" in value;
192
+ }
193
+ function fragment(template, ...items) {
194
+ return createFragmentTemplate(template, items, isFragment, mergeFragments);
195
+ }
196
+ function mergeFragments(fragments, mergeContent) {
197
+ const filteredFragments = fragments.filter((f) => f !== void 0);
198
+ return Object.freeze({
199
+ content: mergeContent(filteredFragments.map((fragment2) => fragment2.content)),
200
+ features: new Set(filteredFragments.flatMap((f) => [...f.features])),
201
+ imports: mergeImportMaps(filteredFragments.map((f) => f.imports))
202
+ });
203
+ }
204
+ function use(importInput, module) {
205
+ const importInfo = parseImportInput(importInput);
206
+ return addFragmentImports(createFragment(importInfo.usedIdentifier), module, [importInput]);
207
+ }
208
+ function mergeFragmentImports(fragment2, importMaps) {
209
+ return Object.freeze({ ...fragment2, imports: mergeImportMaps([fragment2.imports, ...importMaps]) });
210
+ }
211
+ function addFragmentImports(fragment2, module, importInputs) {
212
+ return Object.freeze({ ...fragment2, imports: addToImportMap(fragment2.imports, module, importInputs) });
213
+ }
214
+ function removeFragmentImports(fragment2, module, usedIdentifiers) {
215
+ return Object.freeze({ ...fragment2, imports: removeFromImportMap(fragment2.imports, module, usedIdentifiers) });
216
+ }
217
+ function addFragmentFeatures(fragment2, features) {
218
+ return Object.freeze({ ...fragment2, features: /* @__PURE__ */ new Set([...fragment2.features, ...features]) });
219
+ }
220
+ function getExportAllFragment(module) {
221
+ return fragment`export * from '${module}';`;
222
+ }
223
+ function getDocblockFragment(lines, withLineJump = false) {
224
+ const lineJump = withLineJump ? "\n" : "";
225
+ if (lines.length === 0) return;
226
+ if (lines.length === 1) return fragment`/** ${lines[0]} */${lineJump}`;
227
+ const prefixedLines = lines.map((line) => line ? ` * ${line}` : " *");
228
+ return fragment`/**\n${prefixedLines.join("\n")}\n */${lineJump}`;
229
+ }
230
+ function getPageFragment(page, scope) {
231
+ const header = getDocblockFragment([
232
+ "This code was AUTOGENERATED using the Codama library.",
233
+ "Please DO NOT EDIT THIS FILE, instead use visitors",
234
+ "to add features, then rerun Codama to update it.",
235
+ "",
236
+ "@see https://github.com/codama-idl/codama"
237
+ ]);
238
+ const imports = page.imports.size === 0 ? void 0 : fragment`${importMapToString(page.imports, scope.dependencyMap, scope.useGranularImports)}`;
239
+ return mergeFragments([header, imports, page], (cs) => cs.join("\n\n"));
240
+ }
241
+
242
+ // src/utils/typeManifest.ts
243
+ function typeManifest(input = {}) {
244
+ return Object.freeze({
245
+ decoder: fragment``,
246
+ encoder: fragment``,
247
+ isEnum: false,
248
+ looseType: fragment``,
249
+ strictType: fragment``,
250
+ value: fragment``,
251
+ ...input
252
+ });
253
+ }
254
+ function mergeTypeManifests(manifests, options = {}) {
255
+ const { mergeTypes, mergeCodecs, mergeValues } = options;
256
+ const merge = (fragmentFn, mergeFn) => mergeFn ? mergeFragments(manifests.map(fragmentFn), mergeFn) : fragment``;
257
+ return Object.freeze({
258
+ decoder: merge((m) => m.decoder, mergeCodecs),
259
+ encoder: merge((m) => m.encoder, mergeCodecs),
260
+ isEnum: false,
261
+ looseType: merge((m) => m.looseType, mergeTypes),
262
+ strictType: merge((m) => m.strictType, mergeTypes),
263
+ value: merge((m) => m.value, mergeValues)
264
+ });
265
+ }
266
+
267
+ // src/visitors/getRenderMapVisitor.ts
268
+ import {
269
+ camelCase as camelCase14,
270
+ getAllAccounts,
271
+ getAllDefinedTypes,
272
+ getAllInstructionsWithSubs as getAllInstructionsWithSubs2,
273
+ getAllPdas,
274
+ getAllPrograms
275
+ } from "@codama/nodes";
276
+ import { createRenderMap, mergeRenderMaps } from "@codama/renderers-core";
277
+ import {
278
+ extendVisitor as extendVisitor2,
279
+ getByteSizeVisitor,
280
+ getResolvedInstructionInputsVisitor,
281
+ LinkableDictionary as LinkableDictionary3,
282
+ NodeStack as NodeStack2,
283
+ pipe as pipe16,
284
+ recordLinkablesOnFirstVisitVisitor,
285
+ recordNodeStackVisitor as recordNodeStackVisitor2,
286
+ staticVisitor as staticVisitor2,
287
+ visit as visit9
288
+ } from "@codama/visitors-core";
136
289
 
137
- // src/fragments/common.ts
138
- import { join as join2 } from "path";
290
+ // src/fragments/accountFetchHelpers.ts
291
+ import { getLastNodeFromPath, pipe } from "@codama/visitors-core";
139
292
 
140
293
  // src/utils/async.ts
141
294
  import {
@@ -232,7 +385,7 @@ function getBytesFromBytesValueNode(node) {
232
385
 
233
386
  // src/utils/customData.ts
234
387
  import {
235
- camelCase,
388
+ camelCase as camelCase2,
236
389
  definedTypeLinkNode,
237
390
  definedTypeNode,
238
391
  isNode as isNode2,
@@ -241,13 +394,13 @@ import {
241
394
  var parseCustomDataOptions = (customDataOptions, defaultSuffix) => new Map(
242
395
  customDataOptions.map((o) => {
243
396
  const options = typeof o === "string" ? { name: o } : o;
244
- const importAs = camelCase(options.importAs ?? `${options.name}${defaultSuffix}`);
397
+ const importAs = camelCase2(options.importAs ?? `${options.name}${defaultSuffix}`);
245
398
  const importFrom = options.importFrom ?? "hooked";
246
399
  return [
247
- camelCase(options.name),
400
+ camelCase2(options.name),
248
401
  {
249
402
  extract: options.extract ?? false,
250
- extractAs: options.extractAs ? camelCase(options.extractAs) : importAs,
403
+ extractAs: options.extractAs ? camelCase2(options.extractAs) : importAs,
251
404
  importAs,
252
405
  importFrom,
253
406
  linkNode: definedTypeLinkNode(importAs)
@@ -318,169 +471,128 @@ function getImportFromFactory(overrides, customAccountData, customInstructionDat
318
471
  };
319
472
  }
320
473
 
321
- // src/utils/render.ts
322
- import { dirname as pathDirname, join } from "path";
323
- import { fileURLToPath } from "url";
324
- import { camelCase as camelCase2, kebabCase, pascalCase, snakeCase, titleCase } from "@codama/nodes";
325
- import nunjucks from "nunjucks";
326
- function jsDocblock(docs) {
327
- if (docs.length <= 0) return "";
328
- if (docs.length === 1) return `/** ${docs[0]} */
329
- `;
330
- const lines = docs.map((doc) => ` * ${doc}`);
331
- return `/**
332
- ${lines.join("\n")}
333
- */
334
- `;
474
+ // src/fragments/accountFetchHelpers.ts
475
+ function getAccountFetchHelpersFragment(scope) {
476
+ const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
477
+ const accountNode = getLastNodeFromPath(accountPath);
478
+ const decodeFunction = nameApi.accountDecodeFunction(accountNode.name);
479
+ const fetchAllFunction = nameApi.accountFetchAllFunction(accountNode.name);
480
+ const fetchAllMaybeFunction = nameApi.accountFetchAllMaybeFunction(accountNode.name);
481
+ const fetchFunction = nameApi.accountFetchFunction(accountNode.name);
482
+ const fetchMaybeFunction = nameApi.accountFetchMaybeFunction(accountNode.name);
483
+ const hasCustomData = customAccountData.has(accountNode.name);
484
+ const accountType = hasCustomData ? typeManifest2.strictType : nameApi.dataType(accountNode.name);
485
+ const decoderFunction = hasCustomData ? typeManifest2.decoder : `${nameApi.decoderFunction(accountNode.name)}()`;
486
+ return pipe(
487
+ fragment`export function ${decodeFunction}<TAddress extends string = string>(encodedAccount: EncodedAccount<TAddress>): Account<${accountType}, TAddress>;
488
+ export function ${decodeFunction}<TAddress extends string = string>(encodedAccount: MaybeEncodedAccount<TAddress>): MaybeAccount<${accountType}, TAddress>;
489
+ export function ${decodeFunction}<TAddress extends string = string>(encodedAccount: EncodedAccount<TAddress> | MaybeEncodedAccount<TAddress>): Account<${accountType}, TAddress> | MaybeAccount<${accountType}, TAddress> {
490
+ return decodeAccount(encodedAccount as MaybeEncodedAccount<TAddress>, ${decoderFunction});
335
491
  }
336
- var render = (template, context, options) => {
337
- const dirname = true ? pathDirname(fileURLToPath(import.meta.url)) : __dirname;
338
- const templates = false ? join(dirname, "..", "..", "public", "templates") : join(dirname, "templates");
339
- const env = nunjucks.configure(templates, { autoescape: false, trimBlocks: true, ...options });
340
- env.addFilter("pascalCase", pascalCase);
341
- env.addFilter("camelCase", camelCase2);
342
- env.addFilter("snakeCase", snakeCase);
343
- env.addFilter("kebabCase", kebabCase);
344
- env.addFilter("titleCase", titleCase);
345
- env.addFilter("jsDocblock", jsDocblock);
346
- return env.render(template, context);
347
- };
348
492
 
349
- // src/fragments/common.ts
350
- function fragment(render2, imports) {
351
- return new Fragment(render2, imports);
493
+ export async function ${fetchFunction}<TAddress extends string = string>(
494
+ rpc: Parameters<typeof fetchEncodedAccount>[0],
495
+ address: Address<TAddress>,
496
+ config?: FetchAccountConfig,
497
+ ): Promise<Account<${accountType}, TAddress>> {
498
+ const maybeAccount = await ${fetchMaybeFunction}(rpc, address, config);
499
+ assertAccountExists(maybeAccount);
500
+ return maybeAccount;
352
501
  }
353
- function fragmentFromTemplate(fragmentFile, context, options) {
354
- return fragment(render(join2("fragments", fragmentFile), context, options));
502
+
503
+ export async function ${fetchMaybeFunction}<TAddress extends string = string>(
504
+ rpc: Parameters<typeof fetchEncodedAccount>[0],
505
+ address: Address<TAddress>,
506
+ config?: FetchAccountConfig,
507
+ ): Promise<MaybeAccount<${accountType}, TAddress>> {
508
+ const maybeAccount = await fetchEncodedAccount(rpc, address, config);
509
+ return ${decodeFunction}(maybeAccount);
355
510
  }
356
- function mergeFragments(fragments, mergeRenders) {
357
- return new Fragment(
358
- mergeRenders(fragments.map((f) => f.render)),
359
- new ImportMap().mergeWith(...fragments),
360
- new Set(fragments.flatMap((f) => [...f.features]))
361
- );
511
+
512
+ export async function ${fetchAllFunction}(
513
+ rpc: Parameters<typeof fetchEncodedAccounts>[0],
514
+ addresses: Array<Address>,
515
+ config?: FetchAccountsConfig,
516
+ ): Promise<Account<${accountType}>[]> {
517
+ const maybeAccounts = await ${fetchAllMaybeFunction}(rpc, addresses, config);
518
+ assertAccountsExist(maybeAccounts);
519
+ return maybeAccounts;
362
520
  }
363
- var Fragment = class _Fragment {
364
- render;
365
- imports;
366
- features;
367
- constructor(render2, imports, features) {
368
- this.render = render2;
369
- this.imports = imports ? new ImportMap().mergeWith(imports) : new ImportMap();
370
- this.features = /* @__PURE__ */ new Set([...features ?? []]);
371
- }
372
- setRender(render2) {
373
- this.render = render2;
374
- return this;
375
- }
376
- mapRender(fn) {
377
- this.render = fn(this.render);
378
- return this;
379
- }
380
- addImports(module, imports) {
381
- this.imports.add(module, imports);
382
- return this;
383
- }
384
- removeImports(module, imports) {
385
- this.imports.remove(module, imports);
386
- return this;
387
- }
388
- mergeImportsWith(...others) {
389
- this.imports.mergeWith(...others);
390
- return this;
391
- }
392
- addImportAlias(module, name, alias) {
393
- this.imports.addAlias(module, name, alias);
394
- return this;
395
- }
396
- addFeatures(features) {
397
- const featureArray = typeof features === "string" ? [features] : features;
398
- featureArray.forEach((f) => this.features.add(f));
399
- return this;
400
- }
401
- removeFeatures(features) {
402
- const featureArray = typeof features === "string" ? [features] : features;
403
- featureArray.forEach((f) => this.features.delete(f));
404
- return this;
405
- }
406
- hasFeatures(features) {
407
- const featureArray = typeof features === "string" ? [features] : features;
408
- return featureArray.every((f) => this.features.has(f));
409
- }
410
- mergeFeaturesWith(...others) {
411
- others.forEach((f) => this.addFeatures([...f.features]));
412
- return this;
413
- }
414
- clone() {
415
- return new _Fragment(this.render).mergeImportsWith(this.imports);
416
- }
417
- toString() {
418
- return this.render;
419
- }
420
- };
421
521
 
422
- // src/fragments/accountFetchHelpers.ts
423
- function getAccountFetchHelpersFragment(scope) {
424
- const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
425
- const accountNode = getLastNodeFromPath(accountPath);
426
- const hasCustomData = customAccountData.has(accountNode.name);
427
- const accountTypeFragment = hasCustomData ? typeManifest2.strictType.clone() : fragment(nameApi.dataType(accountNode.name));
428
- const decoderFunctionFragment = hasCustomData ? typeManifest2.decoder.clone() : fragment(`${nameApi.decoderFunction(accountNode.name)}()`);
429
- return fragmentFromTemplate("accountFetchHelpers.njk", {
430
- accountType: accountTypeFragment.render,
431
- decodeFunction: nameApi.accountDecodeFunction(accountNode.name),
432
- decoderFunction: decoderFunctionFragment.render,
433
- fetchAllFunction: nameApi.accountFetchAllFunction(accountNode.name),
434
- fetchAllMaybeFunction: nameApi.accountFetchAllMaybeFunction(accountNode.name),
435
- fetchFunction: nameApi.accountFetchFunction(accountNode.name),
436
- fetchMaybeFunction: nameApi.accountFetchMaybeFunction(accountNode.name)
437
- }).mergeImportsWith(accountTypeFragment, decoderFunctionFragment).addImports("solanaAddresses", ["type Address"]).addImports("solanaAccounts", [
438
- "type Account",
439
- "assertAccountExists",
440
- "assertAccountsExist",
441
- "decodeAccount",
442
- "type EncodedAccount",
443
- "fetchEncodedAccount",
444
- "fetchEncodedAccounts",
445
- "type FetchAccountConfig",
446
- "type FetchAccountsConfig",
447
- "type MaybeAccount",
448
- "type MaybeEncodedAccount"
449
- ]);
522
+ export async function ${fetchAllMaybeFunction}(
523
+ rpc: Parameters<typeof fetchEncodedAccounts>[0],
524
+ addresses: Array<Address>,
525
+ config?: FetchAccountsConfig,
526
+ ): Promise<MaybeAccount<${accountType}>[]> {
527
+ const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config);
528
+ return maybeAccounts.map((maybeAccount) => ${decodeFunction}(maybeAccount));
529
+ }`,
530
+ (f) => addFragmentImports(f, "solanaAddresses", ["type Address"]),
531
+ (f) => addFragmentImports(f, "solanaAccounts", [
532
+ "type Account",
533
+ "assertAccountExists",
534
+ "assertAccountsExist",
535
+ "decodeAccount",
536
+ "type EncodedAccount",
537
+ "fetchEncodedAccount",
538
+ "fetchEncodedAccounts",
539
+ "type FetchAccountConfig",
540
+ "type FetchAccountsConfig",
541
+ "type MaybeAccount",
542
+ "type MaybeEncodedAccount"
543
+ ])
544
+ );
450
545
  }
451
546
 
547
+ // src/fragments/accountPage.ts
548
+ import { resolveNestedTypeNode as resolveNestedTypeNode2 } from "@codama/nodes";
549
+ import { findProgramNodeFromPath, getLastNodeFromPath as getLastNodeFromPath5, visit as visit2 } from "@codama/visitors-core";
550
+
452
551
  // src/fragments/accountPdaHelpers.ts
453
552
  import { isNodeFilter } from "@codama/nodes";
454
- import { findProgramNodeFromPath, getLastNodeFromPath as getLastNodeFromPath2 } from "@codama/visitors-core";
553
+ import { getLastNodeFromPath as getLastNodeFromPath2, pipe as pipe2 } from "@codama/visitors-core";
455
554
  function getAccountPdaHelpersFragment(scope) {
456
555
  const { accountPath, nameApi, linkables, customAccountData, typeManifest: typeManifest2 } = scope;
457
556
  const accountNode = getLastNodeFromPath2(accountPath);
458
- const programNode = findProgramNodeFromPath(accountPath);
459
557
  const pdaNode = accountNode.pda ? linkables.get([...accountPath, accountNode.pda]) : void 0;
460
- if (!pdaNode) {
461
- return fragment("");
462
- }
463
- const accountTypeFragment = customAccountData.has(accountNode.name) ? typeManifest2.strictType.clone() : fragment(nameApi.dataType(accountNode.name));
558
+ if (!pdaNode) return;
559
+ const accountType = customAccountData.has(accountNode.name) ? typeManifest2.strictType : nameApi.dataType(accountNode.name);
464
560
  const importFrom = "generatedPdas";
465
561
  const pdaSeedsType = nameApi.pdaSeedsType(pdaNode.name);
466
562
  const findPdaFunction = nameApi.pdaFindFunction(pdaNode.name);
467
563
  const hasVariableSeeds = pdaNode.seeds.filter(isNodeFilter("variablePdaSeedNode")).length > 0;
468
- return fragmentFromTemplate("accountPdaHelpers.njk", {
469
- accountType: accountTypeFragment.render,
470
- fetchFromSeedsFunction: nameApi.accountFetchFromSeedsFunction(accountNode.name),
471
- fetchFunction: nameApi.accountFetchFunction(accountNode.name),
472
- fetchMaybeFromSeedsFunction: nameApi.accountFetchMaybeFromSeedsFunction(accountNode.name),
473
- fetchMaybeFunction: nameApi.accountFetchMaybeFunction(accountNode.name),
474
- findPdaFunction,
475
- hasVariableSeeds,
476
- pdaSeedsType,
477
- program: programNode
478
- }).mergeImportsWith(accountTypeFragment).addImports(importFrom, hasVariableSeeds ? [pdaSeedsType, findPdaFunction] : [findPdaFunction]).addImports("solanaAddresses", ["type Address"]).addImports("solanaAccounts", [
479
- "type Account",
480
- "assertAccountExists",
481
- "type FetchAccountConfig",
482
- "type MaybeAccount"
483
- ]);
564
+ const fetchFromSeedsFunction = nameApi.accountFetchFromSeedsFunction(accountNode.name);
565
+ const fetchMaybeFromSeedsFunction = nameApi.accountFetchMaybeFromSeedsFunction(accountNode.name);
566
+ const fetchMaybeFunction = nameApi.accountFetchMaybeFunction(accountNode.name);
567
+ return pipe2(
568
+ fragment`export async function ${fetchFromSeedsFunction}(
569
+ rpc: Parameters<typeof fetchEncodedAccount>[0],
570
+ ${hasVariableSeeds ? `seeds: ${pdaSeedsType},` : ""}
571
+ config: FetchAccountConfig & { programAddress?: Address } = {},
572
+ ): Promise<Account<${accountType}>> {
573
+ const maybeAccount = await ${fetchMaybeFromSeedsFunction}(rpc, ${hasVariableSeeds ? "seeds, " : ""}config);
574
+ assertAccountExists(maybeAccount);
575
+ return maybeAccount;
576
+ }
577
+
578
+ export async function ${fetchMaybeFromSeedsFunction}(
579
+ rpc: Parameters<typeof fetchEncodedAccount>[0],
580
+ ${hasVariableSeeds ? `seeds: ${pdaSeedsType},` : ""}
581
+ config: FetchAccountConfig & { programAddress?: Address } = {},
582
+ ): Promise<MaybeAccount<${accountType}>> {
583
+ const { programAddress, ...fetchConfig } = config;
584
+ const [address] = await ${findPdaFunction}(${hasVariableSeeds ? "seeds, " : ""}{ programAddress });
585
+ return await ${fetchMaybeFunction}(rpc, address, fetchConfig);
586
+ }`,
587
+ (f) => addFragmentImports(f, importFrom, hasVariableSeeds ? [pdaSeedsType, findPdaFunction] : [findPdaFunction]),
588
+ (f) => addFragmentImports(f, "solanaAddresses", ["type Address"]),
589
+ (f) => addFragmentImports(f, "solanaAccounts", [
590
+ "type Account",
591
+ "assertAccountExists",
592
+ "type FetchAccountConfig",
593
+ "type MaybeAccount"
594
+ ])
595
+ );
484
596
  }
485
597
 
486
598
  // src/fragments/accountSizeHelpers.ts
@@ -488,13 +600,11 @@ import { getLastNodeFromPath as getLastNodeFromPath3 } from "@codama/visitors-co
488
600
  function getAccountSizeHelpersFragment(scope) {
489
601
  const { accountPath, nameApi } = scope;
490
602
  const accountNode = getLastNodeFromPath3(accountPath);
491
- if (accountNode.size == null) {
492
- return fragment("");
493
- }
494
- return fragmentFromTemplate("accountSizeHelpers.njk", {
495
- account: accountNode,
496
- getSizeFunction: nameApi.accountGetSizeFunction(accountNode.name)
497
- });
603
+ if (accountNode.size == null) return;
604
+ const getSizeFunction = nameApi.accountGetSizeFunction(accountNode.name);
605
+ return fragment`export function ${getSizeFunction}(): number {
606
+ return ${accountNode.size};
607
+ }`;
498
608
  }
499
609
 
500
610
  // src/fragments/accountType.ts
@@ -504,70 +614,70 @@ import { getLastNodeFromPath as getLastNodeFromPath4 } from "@codama/visitors-co
504
614
  // src/fragments/type.ts
505
615
  function getTypeFragment(scope) {
506
616
  const { name, manifest, nameApi, docs = [] } = scope;
507
- const typeFragment = fragmentFromTemplate("type.njk", {
508
- docs,
509
- looseName: nameApi.dataArgsType(name),
510
- manifest,
511
- strictName: nameApi.dataType(name)
512
- });
513
- if (!manifest.isEnum) {
514
- typeFragment.mergeImportsWith(manifest.strictType, manifest.looseType);
617
+ const docblock = getDocblockFragment(docs, true);
618
+ const strictName = nameApi.dataType(name);
619
+ const looseName = nameApi.dataArgsType(name);
620
+ const aliasedLooseName = `export type ${looseName} = ${strictName};`;
621
+ if (manifest.isEnum) {
622
+ return fragment`${docblock}export enum ${strictName} ${manifest.strictType};\n\n${aliasedLooseName}`;
515
623
  }
516
- return typeFragment;
624
+ const looseExport = manifest.strictType.content === manifest.looseType.content ? aliasedLooseName : fragment`export type ${looseName} = ${manifest.looseType};`;
625
+ return fragment`${docblock}export type ${strictName} = ${manifest.strictType};\n\n${looseExport}`;
517
626
  }
518
627
 
519
628
  // src/fragments/typeDecoder.ts
520
629
  import { isDataEnum, isNode as isNode3 } from "@codama/nodes";
521
630
  function getTypeDecoderFragment(scope) {
522
631
  const { name, node, manifest, nameApi, docs = [] } = scope;
523
- const decoderType = typeof scope.size === "number" ? "FixedSizeDecoder" : "Decoder";
632
+ const decoderFunction = nameApi.decoderFunction(name);
633
+ const strictName = nameApi.dataType(name);
634
+ const docblock = getDocblockFragment(docs, true);
635
+ const decoderType = use(
636
+ typeof scope.size === "number" ? "type FixedSizeDecoder" : "type Decoder",
637
+ "solanaCodecsCore"
638
+ );
524
639
  const useTypeCast = isNode3(node, "enumTypeNode") && isDataEnum(node) && typeof scope.size === "number";
525
- return fragmentFromTemplate("typeDecoder.njk", {
526
- decoderFunction: nameApi.decoderFunction(name),
527
- decoderType,
528
- docs,
529
- looseName: nameApi.dataArgsType(name),
530
- manifest,
531
- strictName: nameApi.dataType(name),
532
- useTypeCast
533
- }).mergeImportsWith(manifest.decoder).addImports("solanaCodecsCore", `type ${decoderType}`);
640
+ const typeCast = useTypeCast ? fragment` as ${decoderType}<${strictName}>` : "";
641
+ return fragment`${docblock}export function ${decoderFunction}(): ${decoderType}<${strictName}> {
642
+ return ${manifest.decoder}${typeCast};
643
+ }`;
534
644
  }
535
645
 
536
646
  // src/fragments/typeEncoder.ts
537
647
  import { isDataEnum as isDataEnum2, isNode as isNode4 } from "@codama/nodes";
538
648
  function getTypeEncoderFragment(scope) {
539
649
  const { name, node, manifest, nameApi, docs = [] } = scope;
540
- const encoderType = typeof scope.size === "number" ? "FixedSizeEncoder" : "Encoder";
650
+ const encoderFunction = nameApi.encoderFunction(name);
651
+ const looseName = nameApi.dataArgsType(name);
652
+ const docblock = getDocblockFragment(docs, true);
653
+ const encoderType = use(
654
+ typeof scope.size === "number" ? "type FixedSizeEncoder" : "type Encoder",
655
+ "solanaCodecsCore"
656
+ );
541
657
  const useTypeCast = isNode4(node, "enumTypeNode") && isDataEnum2(node) && typeof scope.size === "number";
542
- return fragmentFromTemplate("typeEncoder.njk", {
543
- docs,
544
- encoderFunction: nameApi.encoderFunction(name),
545
- encoderType,
546
- looseName: nameApi.dataArgsType(name),
547
- manifest,
548
- strictName: nameApi.dataType(name),
549
- useTypeCast
550
- }).mergeImportsWith(manifest.encoder).addImports("solanaCodecsCore", `type ${encoderType}`);
658
+ const typeCast = useTypeCast ? fragment` as ${encoderType}<${looseName}>` : "";
659
+ return fragment`${docblock}export function ${encoderFunction}(): ${encoderType}<${looseName}> {
660
+ return ${manifest.encoder}${typeCast};
661
+ }`;
551
662
  }
552
663
 
553
664
  // src/fragments/typeCodec.ts
554
665
  function getTypeCodecFragment(scope) {
555
- const { name, manifest, nameApi } = scope;
556
- const codecType = typeof scope.size === "number" ? "FixedSizeCodec" : "Codec";
666
+ const { codecDocs = [], name, nameApi } = scope;
667
+ const codecFunction = nameApi.codecFunction(name);
668
+ const decoderFunction = nameApi.decoderFunction(name);
669
+ const encoderFunction = nameApi.encoderFunction(name);
670
+ const looseName = nameApi.dataArgsType(name);
671
+ const strictName = nameApi.dataType(name);
672
+ const docblock = getDocblockFragment(codecDocs, true);
673
+ const codecType = use(typeof scope.size === "number" ? "type FixedSizeCodec" : "type Codec", "solanaCodecsCore");
557
674
  return mergeFragments(
558
675
  [
559
676
  getTypeEncoderFragment({ ...scope, docs: scope.encoderDocs }),
560
677
  getTypeDecoderFragment({ ...scope, docs: scope.decoderDocs }),
561
- fragmentFromTemplate("typeCodec.njk", {
562
- codecFunction: nameApi.codecFunction(name),
563
- codecType,
564
- decoderFunction: nameApi.decoderFunction(name),
565
- docs: scope.codecDocs,
566
- encoderFunction: nameApi.encoderFunction(name),
567
- looseName: nameApi.dataArgsType(name),
568
- manifest,
569
- strictName: nameApi.dataType(name)
570
- }).addImports("solanaCodecsCore", [`type ${codecType}`, "combineCodec"])
678
+ fragment`${docblock}export function ${codecFunction}(): ${codecType}<${looseName}, ${strictName}> {
679
+ return ${use("combineCodec", "solanaCodecsCore")}(${encoderFunction}(), ${decoderFunction}());
680
+ }`
571
681
  ],
572
682
  (renders) => renders.join("\n\n")
573
683
  );
@@ -585,9 +695,7 @@ function getTypeWithCodecFragment(scope) {
585
695
  function getAccountTypeFragment(scope) {
586
696
  const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
587
697
  const accountNode = getLastNodeFromPath4(accountPath);
588
- if (customAccountData.has(accountNode.name)) {
589
- return fragment("");
590
- }
698
+ if (customAccountData.has(accountNode.name)) return;
591
699
  return getTypeWithCodecFragment({
592
700
  manifest: typeManifest2,
593
701
  name: accountNode.name,
@@ -597,41 +705,119 @@ function getAccountTypeFragment(scope) {
597
705
  });
598
706
  }
599
707
 
708
+ // src/fragments/discriminatorConstants.ts
709
+ import {
710
+ camelCase as camelCase3,
711
+ isNode as isNode5,
712
+ isNodeFilter as isNodeFilter2,
713
+ VALUE_NODES
714
+ } from "@codama/nodes";
715
+ import { visit } from "@codama/visitors-core";
716
+ function getDiscriminatorConstantsFragment(scope) {
717
+ const fragments = scope.discriminatorNodes.map((node) => getDiscriminatorConstantFragment(node, scope)).filter(Boolean);
718
+ return mergeFragments(fragments, (c) => c.join("\n\n"));
719
+ }
720
+ function getDiscriminatorConstantFragment(discriminatorNode, scope) {
721
+ switch (discriminatorNode.kind) {
722
+ case "constantDiscriminatorNode":
723
+ return getConstantDiscriminatorConstantFragment(discriminatorNode, scope);
724
+ case "fieldDiscriminatorNode":
725
+ return getFieldDiscriminatorConstantFragment(discriminatorNode, scope);
726
+ default:
727
+ return null;
728
+ }
729
+ }
730
+ function getConstantDiscriminatorConstantFragment(discriminatorNode, scope) {
731
+ const { discriminatorNodes, typeManifestVisitor, prefix } = scope;
732
+ const index = discriminatorNodes.filter(isNodeFilter2("constantDiscriminatorNode")).indexOf(discriminatorNode);
733
+ const suffix = index <= 0 ? "" : `_${index + 1}`;
734
+ const name = camelCase3(`${prefix}_discriminator${suffix}`);
735
+ const encoder = visit(discriminatorNode.constant.type, typeManifestVisitor).encoder;
736
+ const value = visit(discriminatorNode.constant.value, typeManifestVisitor).value;
737
+ return getConstantFragment({ ...scope, encoder, name, value });
738
+ }
739
+ function getFieldDiscriminatorConstantFragment(discriminatorNode, scope) {
740
+ const { fields, prefix, typeManifestVisitor } = scope;
741
+ const field = fields.find((f) => f.name === discriminatorNode.name);
742
+ if (!field || !field.defaultValue || !isNode5(field.defaultValue, VALUE_NODES)) {
743
+ return null;
744
+ }
745
+ const name = camelCase3(`${prefix}_${discriminatorNode.name}`);
746
+ const encoder = visit(field.type, typeManifestVisitor).encoder;
747
+ const value = visit(field.defaultValue, typeManifestVisitor).value;
748
+ return getConstantFragment({ ...scope, encoder, name, value });
749
+ }
750
+ function getConstantFragment(scope) {
751
+ const { encoder, name, nameApi, value } = scope;
752
+ const constantName = nameApi.constant(name);
753
+ const constantFunction = nameApi.constantFunction(name);
754
+ return fragment`export const ${constantName} = ${value};\n\nexport function ${constantFunction}() { return ${encoder}.encode(${constantName}); }`;
755
+ }
756
+
757
+ // src/fragments/accountPage.ts
758
+ function getAccountPageFragment(scope) {
759
+ const node = getLastNodeFromPath5(scope.accountPath);
760
+ if (!findProgramNodeFromPath(scope.accountPath)) {
761
+ throw new Error("Account must be visited inside a program.");
762
+ }
763
+ const typeManifest2 = visit2(node, scope.typeManifestVisitor);
764
+ const fields = resolveNestedTypeNode2(node.data).fields;
765
+ return mergeFragments(
766
+ [
767
+ getDiscriminatorConstantsFragment({
768
+ ...scope,
769
+ discriminatorNodes: node.discriminators ?? [],
770
+ fields,
771
+ prefix: node.name
772
+ }),
773
+ getAccountTypeFragment({ ...scope, typeManifest: typeManifest2 }),
774
+ getAccountFetchHelpersFragment({ ...scope, typeManifest: typeManifest2 }),
775
+ getAccountSizeHelpersFragment(scope),
776
+ getAccountPdaHelpersFragment({ ...scope, typeManifest: typeManifest2 })
777
+ ],
778
+ (cs) => cs.join("\n\n")
779
+ );
780
+ }
781
+
600
782
  // src/fragments/discriminatorCondition.ts
601
783
  import {
602
784
  constantDiscriminatorNode,
603
785
  constantValueNode,
604
786
  constantValueNodeFromBytes,
605
- isNode as isNode5,
606
- isNodeFilter as isNodeFilter2
787
+ isNode as isNode6,
788
+ isNodeFilter as isNodeFilter3
607
789
  } from "@codama/nodes";
608
- import { visit } from "@codama/visitors-core";
790
+ import { mapFragmentContent } from "@codama/renderers-core";
791
+ import { pipe as pipe3, visit as visit3 } from "@codama/visitors-core";
609
792
  import { getBase64Decoder } from "@solana/codecs-strings";
610
793
  function getDiscriminatorConditionFragment(scope) {
611
- return mergeFragments(
612
- scope.discriminators.flatMap((discriminator) => {
613
- if (isNode5(discriminator, "sizeDiscriminatorNode")) {
614
- return [getSizeConditionFragment(discriminator, scope)];
615
- }
616
- if (isNode5(discriminator, "constantDiscriminatorNode")) {
617
- return [getByteConditionFragment(discriminator, scope)];
618
- }
619
- if (isNode5(discriminator, "fieldDiscriminatorNode")) {
620
- return [getFieldConditionFragment(discriminator, scope)];
621
- }
622
- return [];
623
- }),
624
- (r) => r.join(" && ")
625
- ).mapRender((r) => `if (${r}) { ${scope.ifTrue}; }`);
794
+ return pipe3(
795
+ mergeFragments(
796
+ scope.discriminators.flatMap((discriminator) => {
797
+ if (isNode6(discriminator, "sizeDiscriminatorNode")) {
798
+ return [getSizeConditionFragment(discriminator, scope)];
799
+ }
800
+ if (isNode6(discriminator, "constantDiscriminatorNode")) {
801
+ return [getByteConditionFragment(discriminator, scope)];
802
+ }
803
+ if (isNode6(discriminator, "fieldDiscriminatorNode")) {
804
+ return [getFieldConditionFragment(discriminator, scope)];
805
+ }
806
+ return [];
807
+ }),
808
+ (c) => c.join(" && ")
809
+ ),
810
+ (f) => mapFragmentContent(f, (c) => `if (${c}) { ${scope.ifTrue}; }`)
811
+ );
626
812
  }
627
813
  function getSizeConditionFragment(discriminator, scope) {
628
814
  const { dataName } = scope;
629
- return fragment(`${dataName}.length === ${discriminator.size}`);
815
+ return fragment`${dataName}.length === ${discriminator.size}`;
630
816
  }
631
817
  function getByteConditionFragment(discriminator, scope) {
632
818
  const { dataName, typeManifestVisitor } = scope;
633
- const constant = visit(discriminator.constant, typeManifestVisitor).value;
634
- return constant.mapRender((r) => `containsBytes(${dataName}, ${r}, ${discriminator.offset})`).addImports("solanaCodecsCore", "containsBytes");
819
+ const constant = visit3(discriminator.constant, typeManifestVisitor).value;
820
+ return fragment`${use("containsBytes", "solanaCodecsCore")}(${dataName}, ${constant}, ${discriminator.offset})`;
635
821
  }
636
822
  function getFieldConditionFragment(discriminator, scope) {
637
823
  const field = scope.struct.fields.find((f) => f.name === discriminator.name);
@@ -640,7 +826,7 @@ function getFieldConditionFragment(discriminator, scope) {
640
826
  `Field discriminator "${discriminator.name}" does not have a matching argument with default value.`
641
827
  );
642
828
  }
643
- if (isNode5(field.type, "arrayTypeNode") && isNode5(field.type.item, "numberTypeNode") && field.type.item.format === "u8" && isNode5(field.type.count, "fixedCountNode") && isNode5(field.defaultValue, "arrayValueNode") && field.defaultValue.items.every(isNodeFilter2("numberValueNode"))) {
829
+ if (isNode6(field.type, "arrayTypeNode") && isNode6(field.type.item, "numberTypeNode") && field.type.item.format === "u8" && isNode6(field.type.count, "fixedCountNode") && isNode6(field.defaultValue, "arrayValueNode") && field.defaultValue.items.every(isNodeFilter3("numberValueNode"))) {
644
830
  const base64Bytes = getBase64Decoder().decode(
645
831
  new Uint8Array(field.defaultValue.items.map((node) => node.number))
646
832
  );
@@ -655,20 +841,103 @@ function getFieldConditionFragment(discriminator, scope) {
655
841
  );
656
842
  }
657
843
 
844
+ // src/fragments/errorPage.ts
845
+ function getErrorPageFragment(scope) {
846
+ return mergeFragments(
847
+ [
848
+ getConstantsFragment(scope),
849
+ getConstantUnionTypeFragment(scope),
850
+ getErrorMessagesFragment(scope),
851
+ getErrorMessageFunctionFragment(scope),
852
+ getIsErrorFunctionFragment(scope)
853
+ ],
854
+ (cs) => cs.join("\n\n")
855
+ );
856
+ }
857
+ function getConstantsFragment(scope) {
858
+ const constantPrefix = scope.nameApi.programErrorConstantPrefix(scope.programNode.name);
859
+ return mergeFragments(
860
+ [...scope.programNode.errors].sort((a, b) => a.code - b.code).map((error) => {
861
+ const docs = getDocblockFragment(error.docs ?? [], true);
862
+ const name = constantPrefix + scope.nameApi.programErrorConstant(error.name);
863
+ return fragment`${docs}export const ${name} = 0x${error.code.toString(16)}; // ${error.code}`;
864
+ }),
865
+ (cs) => cs.join("\n")
866
+ );
867
+ }
868
+ function getConstantUnionTypeFragment(scope) {
869
+ const constantPrefix = scope.nameApi.programErrorConstantPrefix(scope.programNode.name);
870
+ const typeName = scope.nameApi.programErrorUnion(scope.programNode.name);
871
+ const errorTypes = mergeFragments(
872
+ [...scope.programNode.errors].sort((a, b) => a.name.localeCompare(b.name)).map((error) => fragment`typeof ${constantPrefix + scope.nameApi.programErrorConstant(error.name)}`),
873
+ (cs) => cs.join(" | ")
874
+ );
875
+ return fragment`export type ${typeName} = ${errorTypes};`;
876
+ }
877
+ function getErrorMessagesFragment(scope) {
878
+ const mapName = scope.nameApi.programErrorMessagesMap(scope.programNode.name);
879
+ const errorUnionType = scope.nameApi.programErrorUnion(scope.programNode.name);
880
+ const constantPrefix = scope.nameApi.programErrorConstantPrefix(scope.programNode.name);
881
+ const messageEntries = mergeFragments(
882
+ [...scope.programNode.errors].sort((a, b) => a.name.localeCompare(b.name)).map((error) => {
883
+ const constantName = constantPrefix + scope.nameApi.programErrorConstant(error.name);
884
+ const escapedMessage = error.message.replace(/`/g, "\\`");
885
+ return fragment`[${constantName}]: \`${escapedMessage}\``;
886
+ }),
887
+ (cs) => cs.join(", ")
888
+ );
889
+ return fragment`let ${mapName}: Record<${errorUnionType}, string> | undefined;
890
+ if (process.env.NODE_ENV !== 'production') {
891
+ ${mapName} = { ${messageEntries} };
892
+ }`;
893
+ }
894
+ function getErrorMessageFunctionFragment(scope) {
895
+ const functionName = scope.nameApi.programGetErrorMessageFunction(scope.programNode.name);
896
+ const errorUnionType = scope.nameApi.programErrorUnion(scope.programNode.name);
897
+ const messageMapName = scope.nameApi.programErrorMessagesMap(scope.programNode.name);
898
+ return fragment`export function ${functionName}(code: ${errorUnionType}): string {
899
+ if (process.env.NODE_ENV !== 'production') {
900
+ return (${messageMapName} as Record<${errorUnionType}, string>)[code];
901
+ }
902
+
903
+ return 'Error message not available in production bundles.';
904
+ }`;
905
+ }
906
+ function getIsErrorFunctionFragment(scope) {
907
+ const { programNode, nameApi } = scope;
908
+ const programAddressConstant = use(nameApi.programAddressConstant(programNode.name), "generatedPrograms");
909
+ const functionName = nameApi.programIsErrorFunction(programNode.name);
910
+ const programErrorUnion = nameApi.programErrorUnion(programNode.name);
911
+ return fragment`export function ${functionName}<TProgramErrorCode extends ${programErrorUnion}>(
912
+ error: unknown,
913
+ transactionMessage: { instructions: Record<number, { programAddress: ${use("type Address", "solanaAddresses")} }> },
914
+ code?: TProgramErrorCode,
915
+ ): error is ${use("type SolanaError", "solanaErrors")}<typeof ${use("type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM", "solanaErrors")}> & Readonly<{ context: Readonly<{ code: TProgramErrorCode }> }> {
916
+ return ${use("isProgramError", "solanaPrograms")}<TProgramErrorCode>(error, transactionMessage, ${programAddressConstant}, code);
917
+ }`;
918
+ }
919
+
920
+ // src/fragments/indexPage.ts
921
+ function getIndexPageFragment(items) {
922
+ if (items.length === 0) return;
923
+ const names = items.map((item) => item.name).sort((a, b) => a.localeCompare(b)).map((name) => getExportAllFragment(`./${name}`));
924
+ return mergeFragments(names, (cs) => cs.join("\n"));
925
+ }
926
+
658
927
  // src/fragments/instructionAccountMeta.ts
659
928
  import { pascalCase as pascalCase2 } from "@codama/nodes";
660
929
  function getInstructionAccountMetaFragment(instructionAccountNode) {
661
930
  const typeParam = `TAccount${pascalCase2(instructionAccountNode.name)}`;
662
931
  if (instructionAccountNode.isSigner === true && instructionAccountNode.isWritable) {
663
- return fragment(`WritableSignerAccount<${typeParam}> & AccountSignerMeta<${typeParam}>`).addImports("solanaInstructions", ["type WritableSignerAccount"]).addImports("solanaSigners", ["type AccountSignerMeta"]);
932
+ return fragment`${use("type WritableSignerAccount", "solanaInstructions")}<${typeParam}> & ${use("type AccountSignerMeta", "solanaSigners")}<${typeParam}>`;
664
933
  }
665
934
  if (instructionAccountNode.isSigner === true) {
666
- return fragment(`ReadonlySignerAccount<${typeParam}> & AccountSignerMeta<${typeParam}>`).addImports("solanaInstructions", ["type ReadonlySignerAccount"]).addImports("solanaSigners", ["type AccountSignerMeta"]);
935
+ return fragment`${use("type ReadonlySignerAccount", "solanaInstructions")}<${typeParam}> & ${use("type AccountSignerMeta", "solanaSigners")}<${typeParam}>`;
667
936
  }
668
937
  if (instructionAccountNode.isWritable) {
669
- return fragment(`WritableAccount<${typeParam}>`).addImports("solanaInstructions", "type WritableAccount");
938
+ return fragment`${use("type WritableAccount", "solanaInstructions")}<${typeParam}>`;
670
939
  }
671
- return fragment(`ReadonlyAccount<${typeParam}>`).addImports("solanaInstructions", "type ReadonlyAccount");
940
+ return fragment`${use("type ReadonlyAccount", "solanaInstructions")}<${typeParam}>`;
672
941
  }
673
942
 
674
943
  // src/fragments/instructionAccountTypeParam.ts
@@ -676,24 +945,20 @@ import { pascalCase as pascalCase3 } from "@codama/nodes";
676
945
  import {
677
946
  findInstructionNodeFromPath,
678
947
  findProgramNodeFromPath as findProgramNodeFromPath2,
679
- getLastNodeFromPath as getLastNodeFromPath5
948
+ getLastNodeFromPath as getLastNodeFromPath6
680
949
  } from "@codama/visitors-core";
681
950
  function getInstructionAccountTypeParamFragment(scope) {
682
951
  const { instructionAccountPath, allowAccountMeta, linkables } = scope;
683
- const instructionAccountNode = getLastNodeFromPath5(instructionAccountPath);
952
+ const instructionAccountNode = getLastNodeFromPath6(instructionAccountPath);
684
953
  const instructionNode = findInstructionNodeFromPath(instructionAccountPath);
685
954
  const programNode = findProgramNodeFromPath2(instructionAccountPath);
686
955
  const typeParam = `TAccount${pascalCase3(instructionAccountNode.name)}`;
687
- const accountMeta = allowAccountMeta ? " | AccountMeta<string>" : "";
688
- const imports = new ImportMap();
689
- if (allowAccountMeta) {
690
- imports.add("solanaInstructions", "type AccountMeta");
691
- }
956
+ const accountMeta = allowAccountMeta ? fragment` | ${use("type AccountMeta", "solanaInstructions")}<string>` : void 0;
692
957
  if (instructionNode.optionalAccountStrategy === "omitted" && instructionAccountNode.isOptional) {
693
- return fragment(`${typeParam} extends string${accountMeta} | undefined = undefined`, imports);
958
+ return fragment`${typeParam} extends string${accountMeta} | undefined = undefined`;
694
959
  }
695
960
  const defaultAddress = getDefaultAddress(instructionAccountNode.defaultValue, programNode.publicKey, linkables);
696
- return fragment(`${typeParam} extends string${accountMeta} = ${defaultAddress}`, imports);
961
+ return fragment`${typeParam} extends string${accountMeta} = ${defaultAddress}`;
697
962
  }
698
963
  function getDefaultAddress(defaultValue, programId, linkables) {
699
964
  switch (defaultValue?.kind) {
@@ -710,75 +975,83 @@ function getDefaultAddress(defaultValue, programId, linkables) {
710
975
  }
711
976
 
712
977
  // src/fragments/instructionByteDelta.ts
713
- import { assertIsNode, camelCase as camelCase3, isNode as isNode6 } from "@codama/nodes";
714
- import { getLastNodeFromPath as getLastNodeFromPath6 } from "@codama/visitors-core";
978
+ import { assertIsNode, camelCase as camelCase4, isNode as isNode7 } from "@codama/nodes";
979
+ import { mapFragmentContent as mapFragmentContent2 } from "@codama/renderers-core";
980
+ import { getLastNodeFromPath as getLastNodeFromPath7, pipe as pipe4 } from "@codama/visitors-core";
715
981
  function getInstructionByteDeltaFragment(scope) {
716
- const { byteDeltas } = getLastNodeFromPath6(scope.instructionPath);
717
- const fragments = (byteDeltas ?? []).flatMap((r) => getByteDeltaFragment(r, scope));
718
- if (fragments.length === 0) return fragment("");
982
+ const { byteDeltas } = getLastNodeFromPath7(scope.instructionPath);
983
+ const fragments = (byteDeltas ?? []).flatMap((c) => getByteDeltaFragment(c, scope));
984
+ if (fragments.length === 0) return;
719
985
  return mergeFragments(
720
986
  fragments,
721
- (r) => `// Bytes created or reallocated by the instruction.
722
- const byteDelta: number = [${r.join(",")}].reduce((a, b) => a + b, 0);`
987
+ (c) => `// Bytes created or reallocated by the instruction.
988
+ const byteDelta: number = [${c.join(",")}].reduce((a, b) => a + b, 0);`
723
989
  );
724
990
  }
725
991
  function getByteDeltaFragment(byteDelta, scope) {
726
- const bytesFragment = (() => {
727
- if (isNode6(byteDelta.value, "numberValueNode")) {
992
+ let bytesFragment = (() => {
993
+ if (isNode7(byteDelta.value, "numberValueNode")) {
728
994
  return getNumberValueNodeFragment(byteDelta);
729
995
  }
730
- if (isNode6(byteDelta.value, "argumentValueNode")) {
996
+ if (isNode7(byteDelta.value, "argumentValueNode")) {
731
997
  return getArgumentValueNodeFragment(byteDelta);
732
998
  }
733
- if (isNode6(byteDelta.value, "accountLinkNode")) {
999
+ if (isNode7(byteDelta.value, "accountLinkNode")) {
734
1000
  return getAccountLinkNodeFragment(byteDelta, scope);
735
1001
  }
736
- if (isNode6(byteDelta.value, "resolverValueNode")) {
1002
+ if (isNode7(byteDelta.value, "resolverValueNode")) {
737
1003
  return getResolverValueNodeFragment(byteDelta, scope);
738
1004
  }
739
1005
  return null;
740
1006
  })();
741
1007
  if (bytesFragment === null) return [];
742
1008
  if (byteDelta.withHeader) {
743
- bytesFragment.mapRender((r) => `${r} + BASE_ACCOUNT_SIZE`).addImports("solanaAccounts", "BASE_ACCOUNT_SIZE");
1009
+ bytesFragment = fragment`${bytesFragment} + ${use("BASE_ACCOUNT_SIZE", "solanaAccounts")}`;
744
1010
  }
745
1011
  if (byteDelta.subtract) {
746
- bytesFragment.mapRender((r) => `- (${r})`);
1012
+ bytesFragment = pipe4(bytesFragment, (f) => mapFragmentContent2(f, (c) => `- (${c})`));
747
1013
  }
748
1014
  return [bytesFragment];
749
1015
  }
750
1016
  function getNumberValueNodeFragment(byteDelta) {
751
1017
  assertIsNode(byteDelta.value, "numberValueNode");
752
- return fragment(byteDelta.value.number.toString());
1018
+ return fragment`${byteDelta.value.number}`;
753
1019
  }
754
1020
  function getArgumentValueNodeFragment(byteDelta) {
755
1021
  assertIsNode(byteDelta.value, "argumentValueNode");
756
- const argumentName = camelCase3(byteDelta.value.name);
757
- return fragment(`Number(args.${argumentName})`);
1022
+ const argumentName = camelCase4(byteDelta.value.name);
1023
+ return fragment`Number(args.${argumentName})`;
758
1024
  }
759
1025
  function getAccountLinkNodeFragment(byteDelta, scope) {
760
1026
  assertIsNode(byteDelta.value, "accountLinkNode");
761
- const functionName = scope.nameApi.accountGetSizeFunction(byteDelta.value.name);
762
- return fragment(`${functionName}()`).addImports(scope.getImportFrom(byteDelta.value), functionName);
1027
+ const functionName = use(
1028
+ scope.nameApi.accountGetSizeFunction(byteDelta.value.name),
1029
+ scope.getImportFrom(byteDelta.value)
1030
+ );
1031
+ return fragment`${functionName}()`;
763
1032
  }
764
1033
  function getResolverValueNodeFragment(byteDelta, scope) {
765
1034
  assertIsNode(byteDelta.value, "resolverValueNode");
766
1035
  const isAsync = scope.asyncResolvers.includes(byteDelta.value.name);
767
1036
  if (!scope.useAsync && isAsync) return null;
768
1037
  const awaitKeyword = scope.useAsync && isAsync ? "await " : "";
769
- const functionName = scope.nameApi.resolverFunction(byteDelta.value.name);
770
- return fragment(`${awaitKeyword}${functionName}(resolverScope)`).addImports(scope.getImportFrom(byteDelta.value), functionName).addFeatures(["instruction:resolverScopeVariable"]);
1038
+ const functionName = use(
1039
+ scope.nameApi.resolverFunction(byteDelta.value.name),
1040
+ scope.getImportFrom(byteDelta.value)
1041
+ );
1042
+ return pipe4(
1043
+ fragment`${awaitKeyword}${functionName}(resolverScope)`,
1044
+ (f) => addFragmentFeatures(f, ["instruction:resolverScopeVariable"])
1045
+ );
771
1046
  }
772
1047
 
773
1048
  // src/fragments/instructionData.ts
774
1049
  import { structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes2 } from "@codama/nodes";
775
- import { getLastNodeFromPath as getLastNodeFromPath7 } from "@codama/visitors-core";
1050
+ import { getLastNodeFromPath as getLastNodeFromPath8 } from "@codama/visitors-core";
776
1051
  function getInstructionDataFragment(scope) {
777
1052
  const { instructionPath, dataArgsManifest, nameApi, customInstructionData } = scope;
778
- const instructionNode = getLastNodeFromPath7(instructionPath);
779
- if (instructionNode.arguments.length === 0 || customInstructionData.has(instructionNode.name)) {
780
- return fragment("");
781
- }
1053
+ const instructionNode = getLastNodeFromPath8(instructionPath);
1054
+ if (instructionNode.arguments.length === 0 || customInstructionData.has(instructionNode.name)) return;
782
1055
  const instructionDataName = nameApi.instructionDataType(instructionNode.name);
783
1056
  return getTypeWithCodecFragment({
784
1057
  manifest: dataArgsManifest,
@@ -789,232 +1062,201 @@ function getInstructionDataFragment(scope) {
789
1062
  });
790
1063
  }
791
1064
 
792
- // src/fragments/discriminatorConstants.ts
793
- import {
794
- camelCase as camelCase4,
795
- isNode as isNode7,
796
- isNodeFilter as isNodeFilter3,
797
- VALUE_NODES
798
- } from "@codama/nodes";
799
- import { visit as visit2 } from "@codama/visitors-core";
800
- function getDiscriminatorConstantsFragment(scope) {
801
- const fragments = scope.discriminatorNodes.map((node) => getDiscriminatorConstantFragment(node, scope)).filter(Boolean);
802
- return mergeFragments(fragments, (r) => r.join("\n\n"));
1065
+ // src/fragments/instructionExtraArgs.ts
1066
+ import { mapFragmentContent as mapFragmentContent3 } from "@codama/renderers-core";
1067
+ import { getLastNodeFromPath as getLastNodeFromPath9 } from "@codama/visitors-core";
1068
+ function getInstructionExtraArgsFragment(scope) {
1069
+ const { instructionPath, extraArgsManifest, nameApi } = scope;
1070
+ const instructionNode = getLastNodeFromPath9(instructionPath);
1071
+ if ((instructionNode.extraArguments ?? []).length === 0) return;
1072
+ const instructionExtraName = nameApi.instructionExtraType(instructionNode.name);
1073
+ const looseName = nameApi.dataArgsType(instructionExtraName);
1074
+ return mapFragmentContent3(extraArgsManifest.looseType, (c) => `export type ${looseName} = ${c};`);
803
1075
  }
804
- function getDiscriminatorConstantFragment(discriminatorNode, scope) {
805
- switch (discriminatorNode.kind) {
806
- case "constantDiscriminatorNode":
807
- return getConstantDiscriminatorConstantFragment(discriminatorNode, scope);
808
- case "fieldDiscriminatorNode":
809
- return getFieldDiscriminatorConstantFragment(discriminatorNode, scope);
810
- default:
811
- return null;
812
- }
813
- }
814
- function getConstantDiscriminatorConstantFragment(discriminatorNode, scope) {
815
- const { discriminatorNodes, typeManifestVisitor, prefix } = scope;
816
- const index = discriminatorNodes.filter(isNodeFilter3("constantDiscriminatorNode")).indexOf(discriminatorNode);
817
- const suffix = index <= 0 ? "" : `_${index + 1}`;
818
- const name = camelCase4(`${prefix}_discriminator${suffix}`);
819
- const encoder = visit2(discriminatorNode.constant.type, typeManifestVisitor).encoder;
820
- const value = visit2(discriminatorNode.constant.value, typeManifestVisitor).value;
821
- return getConstantFragment({ ...scope, encoder, name, value });
822
- }
823
- function getFieldDiscriminatorConstantFragment(discriminatorNode, scope) {
824
- const { fields, prefix, typeManifestVisitor } = scope;
825
- const field = fields.find((f) => f.name === discriminatorNode.name);
826
- if (!field || !field.defaultValue || !isNode7(field.defaultValue, VALUE_NODES)) {
827
- return null;
828
- }
829
- const name = camelCase4(`${prefix}_${discriminatorNode.name}`);
830
- const encoder = visit2(field.type, typeManifestVisitor).encoder;
831
- const value = visit2(field.defaultValue, typeManifestVisitor).value;
832
- return getConstantFragment({ ...scope, encoder, name, value });
833
- }
834
- function getConstantFragment(scope) {
835
- const { encoder, name, nameApi, value } = scope;
836
- const constantName = nameApi.constant(name);
837
- const constantFunction = nameApi.constantFunction(name);
838
- return mergeFragments(
839
- [
840
- value.mapRender((r) => `export const ${constantName} = ${r};`),
841
- encoder.mapRender((r) => `export function ${constantFunction}() { return ${r}.encode(${constantName}); }`)
842
- ],
843
- (r) => r.join("\n\n")
844
- );
845
- }
846
-
847
- // src/fragments/instructionExtraArgs.ts
848
- import { getLastNodeFromPath as getLastNodeFromPath8 } from "@codama/visitors-core";
849
- function getInstructionExtraArgsFragment(scope) {
850
- const { instructionPath, extraArgsManifest, nameApi } = scope;
851
- const instructionNode = getLastNodeFromPath8(instructionPath);
852
- if ((instructionNode.extraArguments ?? []).length === 0) {
853
- return fragment("");
854
- }
855
- const instructionExtraName = nameApi.instructionExtraType(instructionNode.name);
856
- return fragmentFromTemplate("instructionExtraArgs.njk", {
857
- looseName: nameApi.dataArgsType(instructionExtraName),
858
- manifest: extraArgsManifest,
859
- strictName: nameApi.dataType(instructionExtraName)
860
- }).mergeImportsWith(extraArgsManifest.looseType);
861
- }
862
-
863
- // src/fragments/instructionFunction.ts
864
- import { camelCase as camelCase9, isNode as isNode12, isNodeFilter as isNodeFilter4, pascalCase as pascalCase5 } from "@codama/nodes";
865
- import {
866
- findProgramNodeFromPath as findProgramNodeFromPath3,
867
- getLastNodeFromPath as getLastNodeFromPath12
868
- } from "@codama/visitors-core";
869
-
870
- // src/fragments/instructionInputResolved.ts
871
- import { camelCase as camelCase6, isNode as isNode9, parseOptionalAccountStrategy } from "@codama/nodes";
872
- import { getLastNodeFromPath as getLastNodeFromPath9 } from "@codama/visitors-core";
873
-
874
- // src/fragments/instructionInputDefault.ts
875
- import { camelCase as camelCase5, isNode as isNode8 } from "@codama/nodes";
876
- import { visit as visit3 } from "@codama/visitors-core";
877
- function getInstructionInputDefaultFragment(scope) {
878
- const { input, optionalAccountStrategy, asyncResolvers, useAsync, nameApi, typeManifestVisitor, getImportFrom } = scope;
879
- if (!input.defaultValue) {
880
- return fragment("");
1076
+
1077
+ // src/fragments/instructionFunction.ts
1078
+ import { camelCase as camelCase9, isNode as isNode12, isNodeFilter as isNodeFilter4, pascalCase as pascalCase5 } from "@codama/nodes";
1079
+ import { mapFragmentContent as mapFragmentContent7 } from "@codama/renderers-core";
1080
+ import {
1081
+ findProgramNodeFromPath as findProgramNodeFromPath3,
1082
+ getLastNodeFromPath as getLastNodeFromPath13,
1083
+ pipe as pipe8
1084
+ } from "@codama/visitors-core";
1085
+
1086
+ // src/fragments/instructionInputResolved.ts
1087
+ import { camelCase as camelCase6, isNode as isNode9, parseOptionalAccountStrategy } from "@codama/nodes";
1088
+ import { mapFragmentContent as mapFragmentContent5 } from "@codama/renderers-core";
1089
+ import { getLastNodeFromPath as getLastNodeFromPath10 } from "@codama/visitors-core";
1090
+
1091
+ // src/fragments/instructionInputDefault.ts
1092
+ import { camelCase as camelCase5, isNode as isNode8 } from "@codama/nodes";
1093
+ import { mapFragmentContent as mapFragmentContent4, setFragmentContent } from "@codama/renderers-core";
1094
+ import { pipe as pipe5, visit as visit4 } from "@codama/visitors-core";
1095
+ function getInstructionInputDefaultFragment(scope) {
1096
+ const { input, optionalAccountStrategy, asyncResolvers, useAsync, nameApi, typeManifestVisitor, getImportFrom } = scope;
1097
+ if (!input.defaultValue) {
1098
+ return fragment``;
881
1099
  }
882
1100
  if (!useAsync && isAsyncDefaultValue(input.defaultValue, asyncResolvers)) {
883
- return fragment("");
1101
+ return fragment``;
884
1102
  }
885
1103
  const { defaultValue } = input;
886
1104
  const defaultFragment = (renderedValue, isWritable) => {
887
1105
  const inputName = camelCase5(input.name);
888
1106
  if (input.kind === "instructionAccountNode" && isNode8(defaultValue, "resolverValueNode")) {
889
- return fragment(`accounts.${inputName} = { ...accounts.${inputName}, ...${renderedValue} };`);
1107
+ return fragment`accounts.${inputName} = { ...accounts.${inputName}, ...${renderedValue} };`;
890
1108
  }
891
1109
  if (input.kind === "instructionAccountNode" && isWritable === void 0) {
892
- return fragment(`accounts.${inputName}.value = ${renderedValue};`);
1110
+ return fragment`accounts.${inputName}.value = ${renderedValue};`;
893
1111
  }
894
1112
  if (input.kind === "instructionAccountNode") {
895
- return fragment(
896
- `accounts.${inputName}.value = ${renderedValue};
897
- accounts.${inputName}.isWritable = ${isWritable ? "true" : "false"}`
898
- );
1113
+ return fragment`accounts.${inputName}.value = ${renderedValue};\naccounts.${inputName}.isWritable = ${isWritable ? "true" : "false"}`;
899
1114
  }
900
- return fragment(`args.${inputName} = ${renderedValue};`);
1115
+ return fragment`args.${inputName} = ${renderedValue};`;
901
1116
  };
902
1117
  switch (defaultValue.kind) {
903
1118
  case "accountValueNode":
904
1119
  const name = camelCase5(defaultValue.name);
905
1120
  if (input.kind === "instructionAccountNode" && input.resolvedIsSigner && !input.isSigner) {
906
- return defaultFragment(`expectTransactionSigner(accounts.${name}.value).address`).addImports(
907
- "shared",
908
- "expectTransactionSigner"
1121
+ return pipe5(
1122
+ defaultFragment(`expectTransactionSigner(accounts.${name}.value).address`),
1123
+ (f) => addFragmentImports(f, "shared", ["expectTransactionSigner"])
909
1124
  );
910
1125
  }
911
1126
  if (input.kind === "instructionAccountNode") {
912
- return defaultFragment(`expectSome(accounts.${name}.value)`).addImports("shared", "expectSome");
1127
+ return pipe5(
1128
+ defaultFragment(`expectSome(accounts.${name}.value)`),
1129
+ (f) => addFragmentImports(f, "shared", ["expectSome"])
1130
+ );
913
1131
  }
914
- return defaultFragment(`expectAddress(accounts.${name}.value)`).addImports("shared", "expectAddress");
1132
+ return pipe5(
1133
+ defaultFragment(`expectAddress(accounts.${name}.value)`),
1134
+ (f) => addFragmentImports(f, "shared", ["expectAddress"])
1135
+ );
915
1136
  case "pdaValueNode":
916
1137
  if (isNode8(defaultValue.pda, "pdaNode")) {
917
- const pdaProgram = defaultValue.pda.programId ? fragment(
918
- `'${defaultValue.pda.programId}' as Address<'${defaultValue.pda.programId}'>`
919
- ).addImports("solanaAddresses", "type Address") : fragment("programAddress");
1138
+ const pdaProgram = defaultValue.pda.programId ? pipe5(
1139
+ fragment`'${defaultValue.pda.programId}' as Address<'${defaultValue.pda.programId}'>`,
1140
+ (f) => addFragmentImports(f, "solanaAddresses", ["type Address"])
1141
+ ) : fragment`programAddress`;
920
1142
  const pdaSeeds2 = defaultValue.pda.seeds.flatMap((seed) => {
921
1143
  if (isNode8(seed, "constantPdaSeedNode") && isNode8(seed.value, "programIdValueNode")) {
922
1144
  return [
923
- fragment(`getAddressEncoder().encode(${pdaProgram.render})`).mergeImportsWith(pdaProgram).addImports("solanaAddresses", "getAddressEncoder")
1145
+ pipe5(
1146
+ fragment`getAddressEncoder().encode(${pdaProgram})`,
1147
+ (f) => addFragmentImports(f, "solanaAddresses", ["getAddressEncoder"])
1148
+ )
924
1149
  ];
925
1150
  }
926
1151
  if (isNode8(seed, "constantPdaSeedNode") && !isNode8(seed.value, "programIdValueNode")) {
927
- const typeManifest2 = visit3(seed.type, typeManifestVisitor);
928
- const valueManifest2 = visit3(seed.value, typeManifestVisitor);
929
- return [
930
- fragment(
931
- `${typeManifest2.encoder.render}.encode(${valueManifest2.value.render})`
932
- ).mergeImportsWith(typeManifest2.encoder, valueManifest2.value)
933
- ];
1152
+ const typeManifest2 = visit4(seed.type, typeManifestVisitor);
1153
+ const valueManifest2 = visit4(seed.value, typeManifestVisitor);
1154
+ return [fragment`${typeManifest2.encoder}.encode(${valueManifest2.value})`];
934
1155
  }
935
1156
  if (isNode8(seed, "variablePdaSeedNode")) {
936
- const typeManifest2 = visit3(seed.type, typeManifestVisitor);
1157
+ const typeManifest2 = visit4(seed.type, typeManifestVisitor);
937
1158
  const valueSeed = defaultValue.seeds.find((s) => s.name === seed.name)?.value;
938
1159
  if (!valueSeed) return [];
939
1160
  if (isNode8(valueSeed, "accountValueNode")) {
940
1161
  return [
941
- fragment(
942
- `${typeManifest2.encoder.render}.encode(expectAddress(accounts.${camelCase5(valueSeed.name)}.value))`
943
- ).mergeImportsWith(typeManifest2.encoder).addImports("shared", "expectAddress")
1162
+ pipe5(
1163
+ fragment`${typeManifest2.encoder}.encode(expectAddress(accounts.${camelCase5(valueSeed.name)}.value))`,
1164
+ (f) => addFragmentImports(f, "shared", ["expectAddress"])
1165
+ )
944
1166
  ];
945
1167
  }
946
1168
  if (isNode8(valueSeed, "argumentValueNode")) {
947
1169
  return [
948
- fragment(
949
- `${typeManifest2.encoder.render}.encode(expectSome(args.${camelCase5(valueSeed.name)}))`
950
- ).mergeImportsWith(typeManifest2.encoder).addImports("shared", "expectSome")
1170
+ pipe5(
1171
+ fragment`${typeManifest2.encoder}.encode(expectSome(args.${camelCase5(valueSeed.name)}))`,
1172
+ (f) => addFragmentImports(f, "shared", ["expectSome"])
1173
+ )
951
1174
  ];
952
1175
  }
953
- const valueManifest2 = visit3(valueSeed, typeManifestVisitor);
954
- return [
955
- fragment(
956
- `${typeManifest2.encoder.render}.encode(${valueManifest2.value.render})`
957
- ).mergeImportsWith(typeManifest2.encoder, valueManifest2.value)
958
- ];
1176
+ const valueManifest2 = visit4(valueSeed, typeManifestVisitor);
1177
+ return [fragment`${typeManifest2.encoder}.encode(${valueManifest2.value})`];
959
1178
  }
960
1179
  return [];
961
1180
  });
962
- const pdaStatement = mergeFragments([pdaProgram, ...pdaSeeds2], ([p, ...s]) => {
963
- const programAddress2 = p === "programAddress" ? p : `programAddress: ${p}`;
964
- return `await getProgramDerivedAddress({ ${programAddress2}, seeds: [${s.join(", ")}] })`;
965
- }).addImports("solanaAddresses", "getProgramDerivedAddress");
966
- return defaultFragment(pdaStatement.render).mergeImportsWith(pdaStatement);
1181
+ return pipe5(
1182
+ mergeFragments([pdaProgram, ...pdaSeeds2], ([p, ...s]) => {
1183
+ const programAddress2 = p === "programAddress" ? p : `programAddress: ${p}`;
1184
+ return `await getProgramDerivedAddress({ ${programAddress2}, seeds: [${s.join(", ")}] })`;
1185
+ }),
1186
+ (f) => addFragmentImports(f, "solanaAddresses", ["getProgramDerivedAddress"]),
1187
+ (f) => mapFragmentContent4(f, (c) => defaultFragment(c).content)
1188
+ );
967
1189
  }
968
1190
  const pdaFunction = nameApi.pdaFindFunction(defaultValue.pda.name);
969
1191
  const pdaArgs = [];
970
1192
  const pdaSeeds = defaultValue.seeds.map((seed) => {
971
1193
  if (isNode8(seed.value, "accountValueNode")) {
972
- return fragment(
973
- `${seed.name}: expectAddress(accounts.${camelCase5(seed.value.name)}.value)`
974
- ).addImports("shared", "expectAddress");
1194
+ return pipe5(
1195
+ fragment`${seed.name}: expectAddress(accounts.${camelCase5(seed.value.name)}.value)`,
1196
+ (f) => addFragmentImports(f, "shared", ["expectAddress"])
1197
+ );
975
1198
  }
976
1199
  if (isNode8(seed.value, "argumentValueNode")) {
977
- return fragment(`${seed.name}: expectSome(args.${camelCase5(seed.value.name)})`).addImports(
978
- "shared",
979
- "expectSome"
1200
+ return pipe5(
1201
+ fragment`${seed.name}: expectSome(args.${camelCase5(seed.value.name)})`,
1202
+ (f) => addFragmentImports(f, "shared", ["expectSome"])
980
1203
  );
981
1204
  }
982
- return visit3(seed.value, typeManifestVisitor).value.mapRender((r) => `${seed.name}: ${r}`);
1205
+ return pipe5(
1206
+ visit4(seed.value, typeManifestVisitor).value,
1207
+ (f) => mapFragmentContent4(f, (c) => `${seed.name}: ${c}`)
1208
+ );
983
1209
  });
984
- const pdaSeedsFragment = mergeFragments(pdaSeeds, (renders) => renders.join(", ")).mapRender((r) => `{ ${r} }`);
1210
+ const pdaSeedsFragment = pipe5(
1211
+ mergeFragments(pdaSeeds, (renders) => renders.join(", ")),
1212
+ (f) => mapFragmentContent4(f, (c) => `{ ${c} }`)
1213
+ );
985
1214
  if (pdaSeeds.length > 0) {
986
- pdaArgs.push(pdaSeedsFragment.render);
1215
+ pdaArgs.push(pdaSeedsFragment.content);
987
1216
  }
988
- return defaultFragment(`await ${pdaFunction}(${pdaArgs.join(", ")})`).mergeImportsWith(pdaSeedsFragment).addImports(getImportFrom(defaultValue.pda), pdaFunction);
1217
+ const module = getImportFrom(defaultValue.pda);
1218
+ return pipe5(
1219
+ defaultFragment(`await ${pdaFunction}(${pdaArgs.join(", ")})`),
1220
+ (f) => mergeFragmentImports(f, [pdaSeedsFragment.imports]),
1221
+ (f) => addFragmentImports(f, module, [pdaFunction])
1222
+ );
989
1223
  case "publicKeyValueNode":
990
- return defaultFragment(`'${defaultValue.publicKey}' as Address<'${defaultValue.publicKey}'>`).addImports(
991
- "solanaAddresses",
992
- "type Address"
1224
+ return pipe5(
1225
+ defaultFragment(`'${defaultValue.publicKey}' as Address<'${defaultValue.publicKey}'>`),
1226
+ (f) => addFragmentImports(f, "solanaAddresses", ["type Address"])
993
1227
  );
994
1228
  case "programLinkNode":
995
1229
  const programAddress = nameApi.programAddressConstant(defaultValue.name);
996
- return defaultFragment(programAddress, false).addImports(getImportFrom(defaultValue), programAddress);
1230
+ return pipe5(
1231
+ defaultFragment(programAddress, false),
1232
+ (f) => addFragmentImports(f, getImportFrom(defaultValue), [programAddress])
1233
+ );
997
1234
  case "programIdValueNode":
998
1235
  if (optionalAccountStrategy === "programId" && input.kind === "instructionAccountNode" && input.isOptional) {
999
- return fragment("");
1236
+ return fragment``;
1000
1237
  }
1001
1238
  return defaultFragment("programAddress", false);
1002
1239
  case "identityValueNode":
1003
1240
  case "payerValueNode":
1004
- return fragment("");
1241
+ return fragment``;
1005
1242
  case "accountBumpValueNode":
1006
- return defaultFragment(
1007
- `expectProgramDerivedAddress(accounts.${camelCase5(defaultValue.name)}.value)[1]`
1008
- ).addImports("shared", "expectProgramDerivedAddress");
1243
+ return pipe5(
1244
+ defaultFragment(`expectProgramDerivedAddress(accounts.${camelCase5(defaultValue.name)}.value)[1]`),
1245
+ (f) => addFragmentImports(f, "shared", ["expectProgramDerivedAddress"])
1246
+ );
1009
1247
  case "argumentValueNode":
1010
- return defaultFragment(`expectSome(args.${camelCase5(defaultValue.name)})`).addImports(
1011
- "shared",
1012
- "expectSome"
1248
+ return pipe5(
1249
+ defaultFragment(`expectSome(args.${camelCase5(defaultValue.name)})`),
1250
+ (f) => addFragmentImports(f, "shared", ["expectSome"])
1013
1251
  );
1014
1252
  case "resolverValueNode":
1015
1253
  const resolverFunction = nameApi.resolverFunction(defaultValue.name);
1016
1254
  const resolverAwait = useAsync && asyncResolvers.includes(defaultValue.name) ? "await " : "";
1017
- return defaultFragment(`${resolverAwait}${resolverFunction}(resolverScope)`).addImports(getImportFrom(defaultValue), resolverFunction).addFeatures(["instruction:resolverScopeVariable"]);
1255
+ return pipe5(
1256
+ defaultFragment(`${resolverAwait}${resolverFunction}(resolverScope)`),
1257
+ (f) => addFragmentImports(f, getImportFrom(defaultValue), [resolverFunction]),
1258
+ (f) => addFragmentFeatures(f, ["instruction:resolverScopeVariable"])
1259
+ );
1018
1260
  case "conditionalValueNode":
1019
1261
  const ifTrueRenderer = renderNestedInstructionDefault({
1020
1262
  ...scope,
@@ -1025,51 +1267,58 @@ accounts.${inputName}.isWritable = ${isWritable ? "true" : "false"}`
1025
1267
  defaultValue: defaultValue.ifFalse
1026
1268
  });
1027
1269
  if (!ifTrueRenderer && !ifFalseRenderer) {
1028
- return fragment("");
1270
+ return fragment``;
1029
1271
  }
1030
- const conditionalFragment = fragment("");
1272
+ let conditionalFragment = fragment``;
1031
1273
  if (ifTrueRenderer) {
1032
- conditionalFragment.mergeImportsWith(ifTrueRenderer).mergeFeaturesWith(ifTrueRenderer);
1274
+ conditionalFragment = mergeFragments([conditionalFragment, ifTrueRenderer], (c) => c[0]);
1033
1275
  }
1034
1276
  if (ifFalseRenderer) {
1035
- conditionalFragment.mergeImportsWith(ifFalseRenderer).mergeFeaturesWith(ifFalseRenderer);
1277
+ conditionalFragment = mergeFragments([conditionalFragment, ifFalseRenderer], (c) => c[0]);
1036
1278
  }
1037
1279
  const negatedCondition = !ifTrueRenderer;
1038
1280
  let condition = "true";
1039
1281
  if (isNode8(defaultValue.condition, "resolverValueNode")) {
1040
1282
  const conditionalResolverFunction = nameApi.resolverFunction(defaultValue.condition.name);
1041
- conditionalFragment.addImports(getImportFrom(defaultValue.condition), conditionalResolverFunction).addFeatures(["instruction:resolverScopeVariable"]);
1283
+ const module2 = getImportFrom(defaultValue.condition);
1284
+ conditionalFragment = pipe5(
1285
+ conditionalFragment,
1286
+ (f) => addFragmentImports(f, module2, [conditionalResolverFunction]),
1287
+ (f) => addFragmentFeatures(f, ["instruction:resolverScopeVariable"])
1288
+ );
1042
1289
  const conditionalResolverAwait = useAsync && asyncResolvers.includes(defaultValue.condition.name) ? "await " : "";
1043
1290
  condition = `${conditionalResolverAwait}${conditionalResolverFunction}(resolverScope)`;
1044
1291
  condition = negatedCondition ? `!${condition}` : condition;
1045
1292
  } else {
1046
1293
  const comparedInputName = isNode8(defaultValue.condition, "accountValueNode") ? `accounts.${camelCase5(defaultValue.condition.name)}.value` : `args.${camelCase5(defaultValue.condition.name)}`;
1047
1294
  if (defaultValue.value) {
1048
- const comparedValue = visit3(defaultValue.value, typeManifestVisitor).value;
1049
- conditionalFragment.mergeImportsWith(comparedValue).mergeFeaturesWith(comparedValue);
1295
+ const comparedValue = visit4(defaultValue.value, typeManifestVisitor).value;
1296
+ conditionalFragment = mergeFragments([conditionalFragment, comparedValue], (c) => c[0]);
1050
1297
  const operator = negatedCondition ? "!==" : "===";
1051
- condition = `${comparedInputName} ${operator} ${comparedValue.render}`;
1298
+ condition = `${comparedInputName} ${operator} ${comparedValue.content}`;
1052
1299
  } else {
1053
1300
  condition = negatedCondition ? `!${comparedInputName}` : comparedInputName;
1054
1301
  }
1055
1302
  }
1056
1303
  if (ifTrueRenderer && ifFalseRenderer) {
1057
- return conditionalFragment.setRender(
1304
+ return setFragmentContent(
1305
+ conditionalFragment,
1058
1306
  `if (${condition}) {
1059
- ${ifTrueRenderer.render}
1307
+ ${ifTrueRenderer.content}
1060
1308
  } else {
1061
- ${ifFalseRenderer.render}
1309
+ ${ifFalseRenderer.content}
1062
1310
  }`
1063
1311
  );
1064
1312
  }
1065
- return conditionalFragment.setRender(
1313
+ return setFragmentContent(
1314
+ conditionalFragment,
1066
1315
  `if (${condition}) {
1067
- ${ifTrueRenderer ? ifTrueRenderer.render : ifFalseRenderer?.render}
1316
+ ${ifTrueRenderer ? ifTrueRenderer.content : ifFalseRenderer?.content}
1068
1317
  }`
1069
1318
  );
1070
1319
  default:
1071
- const valueManifest = visit3(defaultValue, typeManifestVisitor).value;
1072
- return defaultFragment(valueManifest.render).mergeImportsWith(valueManifest);
1320
+ const valueManifest = visit4(defaultValue, typeManifestVisitor).value;
1321
+ return pipe5(valueManifest, (f) => mapFragmentContent4(f, (c) => defaultFragment(c).content));
1073
1322
  }
1074
1323
  }
1075
1324
  function renderNestedInstructionDefault(scope) {
@@ -1083,32 +1332,30 @@ function renderNestedInstructionDefault(scope) {
1083
1332
 
1084
1333
  // src/fragments/instructionInputResolved.ts
1085
1334
  function getInstructionInputResolvedFragment(scope) {
1086
- const instructionNode = getLastNodeFromPath9(scope.instructionPath);
1335
+ const instructionNode = getLastNodeFromPath10(scope.instructionPath);
1087
1336
  const resolvedInputFragments = scope.resolvedInputs.flatMap((input) => {
1088
1337
  const inputFragment = getInstructionInputDefaultFragment({
1089
1338
  ...scope,
1090
1339
  input,
1091
1340
  optionalAccountStrategy: parseOptionalAccountStrategy(instructionNode.optionalAccountStrategy)
1092
1341
  });
1093
- if (!inputFragment.render) return [];
1342
+ if (!inputFragment.content) return [];
1094
1343
  const camelName = camelCase6(input.name);
1095
1344
  return [
1096
- inputFragment.mapRender(
1097
- (r) => isNode9(input, "instructionArgumentNode") ? `if (!args.${camelName}) {
1098
- ${r}
1345
+ mapFragmentContent5(
1346
+ inputFragment,
1347
+ (c) => isNode9(input, "instructionArgumentNode") ? `if (!args.${camelName}) {
1348
+ ${c}
1099
1349
  }` : `if (!accounts.${camelName}.value) {
1100
- ${r}
1350
+ ${c}
1101
1351
  }`
1102
1352
  )
1103
1353
  ];
1104
1354
  });
1105
1355
  if (resolvedInputFragments.length === 0) {
1106
- return fragment("");
1356
+ return fragment``;
1107
1357
  }
1108
- return mergeFragments(
1109
- [fragment("// Resolve default values."), ...resolvedInputFragments],
1110
- (renders) => renders.join("\n")
1111
- );
1358
+ return mergeFragments([fragment`// Resolve default values.`, ...resolvedInputFragments], (c) => c.join("\n"));
1112
1359
  }
1113
1360
 
1114
1361
  // src/fragments/instructionInputType.ts
@@ -1116,99 +1363,94 @@ import {
1116
1363
  camelCase as camelCase7,
1117
1364
  getAllInstructionArguments,
1118
1365
  isNode as isNode10,
1119
- parseDocs,
1120
1366
  pascalCase as pascalCase4
1121
1367
  } from "@codama/nodes";
1368
+ import { mapFragmentContent as mapFragmentContent6 } from "@codama/renderers-core";
1122
1369
  import {
1123
- getLastNodeFromPath as getLastNodeFromPath10
1370
+ getLastNodeFromPath as getLastNodeFromPath11,
1371
+ pipe as pipe6
1124
1372
  } from "@codama/visitors-core";
1125
1373
  function getInstructionInputTypeFragment(scope) {
1126
1374
  const { instructionPath, useAsync, nameApi } = scope;
1127
- const instructionNode = getLastNodeFromPath10(instructionPath);
1375
+ const instructionNode = getLastNodeFromPath11(instructionPath);
1128
1376
  const instructionInputType = useAsync ? nameApi.instructionAsyncInputType(instructionNode.name) : nameApi.instructionSyncInputType(instructionNode.name);
1129
- const accountsFragment = getAccountsFragment(scope);
1130
1377
  const [dataArgumentsFragment, customDataArgumentsFragment] = getDataArgumentsFragments(scope);
1131
- const extraArgumentsFragment = getExtraArgumentsFragment(scope);
1132
- const remainingAccountsFragment = getRemainingAccountsFragment(instructionNode);
1133
- return fragmentFromTemplate("instructionInputType.njk", {
1134
- accountsFragment,
1135
- customDataArgumentsFragment,
1136
- dataArgumentsFragment,
1137
- extraArgumentsFragment,
1138
- instruction: instructionNode,
1139
- instructionInputType,
1140
- remainingAccountsFragment
1141
- }).mergeImportsWith(
1142
- accountsFragment,
1143
- dataArgumentsFragment,
1144
- customDataArgumentsFragment,
1145
- extraArgumentsFragment,
1146
- remainingAccountsFragment
1147
- ).addImports("solanaAddresses", ["type Address"]);
1378
+ let accountTypeParams = "";
1379
+ if (instructionNode.accounts.length > 0) {
1380
+ accountTypeParams = instructionNode.accounts.map((account) => `TAccount${pascalCase4(account.name)} extends string = string`).join(", ");
1381
+ accountTypeParams = `<${accountTypeParams}>`;
1382
+ }
1383
+ const typeBodyFragment = mergeFragments(
1384
+ [
1385
+ getAccountsFragment(scope),
1386
+ dataArgumentsFragment,
1387
+ getExtraArgumentsFragment(scope),
1388
+ getRemainingAccountsFragment(instructionNode)
1389
+ ],
1390
+ (c) => c.join("\n")
1391
+ );
1392
+ return fragment`export type ${instructionInputType}${accountTypeParams} = ${customDataArgumentsFragment} {
1393
+ ${typeBodyFragment}
1394
+ }`;
1148
1395
  }
1149
1396
  function getAccountsFragment(scope) {
1150
1397
  const { instructionPath, resolvedInputs, useAsync, asyncResolvers } = scope;
1151
- const instructionNode = getLastNodeFromPath10(instructionPath);
1398
+ const instructionNode = getLastNodeFromPath11(instructionPath);
1152
1399
  const fragments = instructionNode.accounts.map((account) => {
1153
1400
  const resolvedAccount = resolvedInputs.find(
1154
1401
  (input) => input.kind === "instructionAccountNode" && input.name === account.name
1155
1402
  );
1156
1403
  const hasDefaultValue = !!resolvedAccount.defaultValue && !isNode10(resolvedAccount.defaultValue, ["identityValueNode", "payerValueNode"]) && (useAsync || !isAsyncDefaultValue(resolvedAccount.defaultValue, asyncResolvers));
1157
- const accountDocs = parseDocs(account.docs);
1158
- const docblock = accountDocs.length > 0 ? jsDocblock(accountDocs) : "";
1404
+ const docs = getDocblockFragment(account.docs ?? [], true);
1159
1405
  const optionalSign = hasDefaultValue || resolvedAccount.isOptional ? "?" : "";
1160
- return getAccountTypeFragment2(resolvedAccount).mapRender(
1161
- (r) => `${docblock}${camelCase7(account.name)}${optionalSign}: ${r};`
1162
- );
1406
+ return fragment`${docs}${camelCase7(account.name)}${optionalSign}: ${getAccountTypeFragment2(resolvedAccount)};`;
1163
1407
  });
1164
- return mergeFragments(fragments, (r) => r.join("\n"));
1408
+ return mergeFragments(fragments, (c) => c.join("\n"));
1165
1409
  }
1166
1410
  function getAccountTypeFragment2(account) {
1167
1411
  const typeParam = `TAccount${pascalCase4(account.name)}`;
1168
- if (account.isPda && account.isSigner === false) {
1169
- return fragment(`ProgramDerivedAddress<${typeParam}>`).addImports("solanaAddresses", [
1170
- "type ProgramDerivedAddress"
1171
- ]);
1172
- }
1173
- if (account.isPda && account.isSigner === "either") {
1174
- return fragment(`ProgramDerivedAddress<${typeParam}> | TransactionSigner<${typeParam}>`).addImports("solanaAddresses", ["type ProgramDerivedAddress"]).addImports("solanaSigners", ["type TransactionSigner"]);
1175
- }
1176
- if (account.isSigner === "either") {
1177
- return fragment(`Address<${typeParam}> | TransactionSigner<${typeParam}>`).addImports("solanaAddresses", ["type Address"]).addImports("solanaSigners", ["type TransactionSigner"]);
1178
- }
1179
- if (account.isSigner) {
1180
- return fragment(`TransactionSigner<${typeParam}>`).addImports("solanaSigners", ["type TransactionSigner"]);
1181
- }
1182
- return fragment(`Address<${typeParam}>`).addImports("solanaAddresses", ["type Address"]);
1412
+ const address = use("type Address", "solanaAddresses");
1413
+ const signer = use("type TransactionSigner", "solanaSigners");
1414
+ const pda = use("type ProgramDerivedAddress", "solanaAddresses");
1415
+ if (account.isPda && account.isSigner === false) return fragment`${pda}<${typeParam}>`;
1416
+ if (account.isPda && account.isSigner === "either") return fragment`${pda}<${typeParam}> | ${signer}<${typeParam}>`;
1417
+ if (account.isSigner === "either") return fragment`${address}<${typeParam}> | ${signer}<${typeParam}>`;
1418
+ if (account.isSigner) return fragment`${signer}<${typeParam}>`;
1419
+ return fragment`${address}<${typeParam}>`;
1183
1420
  }
1184
1421
  function getDataArgumentsFragments(scope) {
1185
1422
  const { instructionPath, nameApi } = scope;
1186
- const instructionNode = getLastNodeFromPath10(instructionPath);
1423
+ const instructionNode = getLastNodeFromPath11(instructionPath);
1187
1424
  const customData = scope.customInstructionData.get(instructionNode.name);
1188
1425
  if (customData) {
1189
1426
  return [
1190
- fragment(""),
1191
- fragment(nameApi.dataArgsType(customData.importAs)).mergeImportsWith(scope.dataArgsManifest.looseType).mapRender((r) => `${r} & `)
1427
+ void 0,
1428
+ pipe6(
1429
+ fragment`${nameApi.dataArgsType(customData.importAs)}`,
1430
+ (f) => mergeFragmentImports(f, [scope.dataArgsManifest.looseType.imports]),
1431
+ (f) => mapFragmentContent6(f, (c) => `${c} & `)
1432
+ )
1192
1433
  ];
1193
1434
  }
1194
1435
  const instructionDataName = nameApi.instructionDataType(instructionNode.name);
1195
1436
  const dataArgsType = nameApi.dataArgsType(instructionDataName);
1196
1437
  const fragments = instructionNode.arguments.flatMap((arg) => {
1197
- const argFragment = getArgumentFragment(arg, fragment(dataArgsType), scope.resolvedInputs, scope.renamedArgs);
1438
+ const argFragment = getArgumentFragment(arg, dataArgsType, scope.resolvedInputs, scope.renamedArgs);
1198
1439
  return argFragment ? [argFragment] : [];
1199
1440
  });
1200
- return [mergeFragments(fragments, (r) => r.join("\n")), fragment("")];
1441
+ return [fragments.length === 0 ? void 0 : mergeFragments(fragments, (c) => c.join("\n")), fragment``];
1201
1442
  }
1202
1443
  function getExtraArgumentsFragment(scope) {
1203
1444
  const { instructionPath, nameApi } = scope;
1204
- const instructionNode = getLastNodeFromPath10(instructionPath);
1445
+ const instructionNode = getLastNodeFromPath11(instructionPath);
1205
1446
  const instructionExtraName = nameApi.instructionExtraType(instructionNode.name);
1206
1447
  const extraArgsType = nameApi.dataArgsType(instructionExtraName);
1207
1448
  const fragments = (instructionNode.extraArguments ?? []).flatMap((arg) => {
1208
- const argFragment = getArgumentFragment(arg, fragment(extraArgsType), scope.resolvedInputs, scope.renamedArgs);
1449
+ const argFragment = getArgumentFragment(arg, extraArgsType, scope.resolvedInputs, scope.renamedArgs);
1209
1450
  return argFragment ? [argFragment] : [];
1210
1451
  });
1211
- return mergeFragments(fragments, (r) => r.join("\n"));
1452
+ if (fragments.length === 0) return;
1453
+ return mergeFragments(fragments, (c) => c.join("\n"));
1212
1454
  }
1213
1455
  function getArgumentFragment(arg, argsType, resolvedInputs, renamedArgs) {
1214
1456
  const resolvedArg = resolvedInputs.find(
@@ -1217,7 +1459,7 @@ function getArgumentFragment(arg, argsType, resolvedInputs, renamedArgs) {
1217
1459
  if (arg.defaultValue && arg.defaultValueStrategy === "omitted") return null;
1218
1460
  const renamedName = renamedArgs.get(arg.name) ?? arg.name;
1219
1461
  const optionalSign = arg.defaultValue || resolvedArg?.defaultValue ? "?" : "";
1220
- return argsType.mapRender((r) => `${camelCase7(renamedName)}${optionalSign}: ${r}["${camelCase7(arg.name)}"];`);
1462
+ return fragment`${camelCase7(renamedName)}${optionalSign}: ${argsType}["${camelCase7(arg.name)}"];`;
1221
1463
  }
1222
1464
  function getRemainingAccountsFragment(instructionNode) {
1223
1465
  const fragments = (instructionNode.remainingAccounts ?? []).flatMap((remainingAccountsNode) => {
@@ -1228,16 +1470,16 @@ function getRemainingAccountsFragment(instructionNode) {
1228
1470
  if (argumentExists) return [];
1229
1471
  const isSigner = remainingAccountsNode.isSigner ?? false;
1230
1472
  const optionalSign = remainingAccountsNode.isOptional ?? false ? "?" : "";
1231
- const signerFragment = fragment(`TransactionSigner`).addImports("solanaSigners", ["type TransactionSigner"]);
1232
- const addressFragment = fragment(`Address`).addImports("solanaAddresses", ["type Address"]);
1233
- return (() => {
1234
- if (isSigner === "either") {
1235
- return mergeFragments([signerFragment, addressFragment], (r) => r.join(" | "));
1236
- }
1473
+ const signerFragment = use("type TransactionSigner", "solanaSigners");
1474
+ const addressFragment = use("type Address", "solanaAddresses");
1475
+ const typeFragment = (() => {
1476
+ if (isSigner === "either") return fragment`${signerFragment} | ${addressFragment}`;
1237
1477
  return isSigner ? signerFragment : addressFragment;
1238
- })().mapRender((r) => `${camelCase7(name)}${optionalSign}: Array<${r}>;`);
1478
+ })();
1479
+ return fragment`${camelCase7(name)}${optionalSign}: Array<${typeFragment}>;`;
1239
1480
  });
1240
- return mergeFragments(fragments, (r) => r.join("\n"));
1481
+ if (fragments.length === 0) return;
1482
+ return mergeFragments(fragments, (c) => c.join("\n"));
1241
1483
  }
1242
1484
 
1243
1485
  // src/fragments/instructionRemainingAccounts.ts
@@ -1247,16 +1489,19 @@ import {
1247
1489
  getAllInstructionArguments as getAllInstructionArguments2,
1248
1490
  isNode as isNode11
1249
1491
  } from "@codama/nodes";
1250
- import { getLastNodeFromPath as getLastNodeFromPath11 } from "@codama/visitors-core";
1492
+ import { getLastNodeFromPath as getLastNodeFromPath12, pipe as pipe7 } from "@codama/visitors-core";
1251
1493
  function getInstructionRemainingAccountsFragment(scope) {
1252
- const { remainingAccounts } = getLastNodeFromPath11(scope.instructionPath);
1253
- const fragments = (remainingAccounts ?? []).flatMap((r) => getRemainingAccountsFragment2(r, scope));
1254
- if (fragments.length === 0) return fragment("");
1255
- return mergeFragments(
1256
- fragments,
1257
- (r) => `// Remaining accounts.
1258
- const remainingAccounts: AccountMeta[] = ${r.length === 1 ? r[0] : `[...${r.join(", ...")}]`}`
1259
- ).addImports("solanaInstructions", ["type AccountMeta"]);
1494
+ const { remainingAccounts } = getLastNodeFromPath12(scope.instructionPath);
1495
+ const fragments = (remainingAccounts ?? []).flatMap((a) => getRemainingAccountsFragment2(a, scope));
1496
+ if (fragments.length === 0) return;
1497
+ return pipe7(
1498
+ mergeFragments(
1499
+ fragments,
1500
+ (c) => `// Remaining accounts.
1501
+ const remainingAccounts: AccountMeta[] = ${c.length === 1 ? c[0] : `[...${c.join(", ...")}]`}`
1502
+ ),
1503
+ (f) => addFragmentImports(f, "solanaInstructions", ["type AccountMeta"])
1504
+ );
1260
1505
  }
1261
1506
  function getRemainingAccountsFragment2(remainingAccounts, scope) {
1262
1507
  const remainingAccountsFragment = (() => {
@@ -1272,65 +1517,50 @@ function getRemainingAccountsFragment2(remainingAccounts, scope) {
1272
1517
  return [remainingAccountsFragment];
1273
1518
  }
1274
1519
  function getArgumentValueNodeFragment2(remainingAccounts, scope) {
1275
- const instructionNode = getLastNodeFromPath11(scope.instructionPath);
1520
+ const instructionNode = getLastNodeFromPath12(scope.instructionPath);
1276
1521
  assertIsNode2(remainingAccounts.value, "argumentValueNode");
1277
1522
  const argumentName = camelCase8(remainingAccounts.value.name);
1278
1523
  const isOptional = remainingAccounts.isOptional ?? false;
1279
1524
  const isSigner = remainingAccounts.isSigner ?? false;
1280
1525
  const isWritable = remainingAccounts.isWritable ?? false;
1281
- const nonSignerRole = isWritable ? "AccountRole.WRITABLE" : "AccountRole.READONLY";
1282
- const signerRole = isWritable ? "AccountRole.WRITABLE_SIGNER" : "AccountRole.READONLY_SIGNER";
1526
+ const accountRole = use("AccountRole", "solanaInstructions");
1527
+ const nonSignerRole = isWritable ? fragment`${accountRole}.WRITABLE` : fragment`${accountRole}.READONLY`;
1528
+ const signerRole = isWritable ? fragment`${accountRole}.WRITABLE_SIGNER` : fragment`${accountRole}.READONLY_SIGNER`;
1283
1529
  const role = isSigner === true ? signerRole : nonSignerRole;
1284
1530
  const argumentArray = isOptional ? `(args.${argumentName} ?? [])` : `args.${argumentName}`;
1285
1531
  const allArguments = getAllInstructionArguments2(instructionNode);
1286
1532
  const argumentExists = allArguments.some((arg) => arg.name === remainingAccounts.value.name);
1287
1533
  if (argumentExists || isSigner === false) {
1288
- return fragment(`${argumentArray}.map((address) => ({ address, role: ${role} }))`).addImports(
1289
- "solanaInstructions",
1290
- ["AccountRole"]
1291
- );
1534
+ return fragment`${argumentArray}.map((address) => ({ address, role: ${role} }))`;
1292
1535
  }
1293
1536
  if (isSigner === "either") {
1294
- return fragment(
1295
- `${argumentArray}.map((addressOrSigner) => (isTransactionSigner(addressOrSigner)
1296
- ? { address: addressOrSigner.address, role: ${role}, signer: addressOrSigner }
1297
- : { address: addressOrSigner, role: ${role} }
1298
- ))`
1299
- ).addImports("solanaInstructions", ["AccountRole"]).addImports("shared", ["isTransactionSigner"]);
1537
+ return fragment`${argumentArray}.map((addressOrSigner) => (${use("isTransactionSigner", "shared")}(addressOrSigner) ? { address: addressOrSigner.address, role: ${role}, signer: addressOrSigner } : { address: addressOrSigner, role: ${role} }))`;
1300
1538
  }
1301
- return fragment(
1302
- `${argumentArray}.map((signer) => ({ address: signer.address, role: ${signerRole}, signer }))`
1303
- ).addImports("solanaInstructions", ["AccountRole"]);
1539
+ return fragment`${argumentArray}.map((signer) => ({ address: signer.address, role: ${signerRole}, signer }))`;
1304
1540
  }
1305
1541
  function getResolverValueNodeFragment2(remainingAccounts, scope) {
1306
1542
  assertIsNode2(remainingAccounts.value, "resolverValueNode");
1307
1543
  const isAsync = scope.asyncResolvers.includes(remainingAccounts.value.name);
1308
1544
  if (!scope.useAsync && isAsync) return null;
1309
1545
  const awaitKeyword = scope.useAsync && isAsync ? "await " : "";
1310
- const functionName = scope.nameApi.resolverFunction(remainingAccounts.value.name);
1311
- return fragment(`${awaitKeyword}${functionName}(resolverScope)`).addImports(scope.getImportFrom(remainingAccounts.value), functionName).addFeatures(["instruction:resolverScopeVariable"]);
1546
+ const functionName = use(
1547
+ scope.nameApi.resolverFunction(remainingAccounts.value.name),
1548
+ scope.getImportFrom(remainingAccounts.value)
1549
+ );
1550
+ return pipe7(
1551
+ fragment`${awaitKeyword}${functionName}(resolverScope)`,
1552
+ (f) => addFragmentFeatures(f, ["instruction:resolverScopeVariable"])
1553
+ );
1312
1554
  }
1313
1555
 
1314
1556
  // src/fragments/instructionFunction.ts
1315
1557
  function getInstructionFunctionFragment(scope) {
1316
- const {
1317
- useAsync,
1318
- instructionPath,
1319
- resolvedInputs,
1320
- renamedArgs,
1321
- dataArgsManifest,
1322
- asyncResolvers,
1323
- nameApi,
1324
- customInstructionData
1325
- } = scope;
1326
- const instructionNode = getLastNodeFromPath12(instructionPath);
1558
+ const { useAsync, instructionPath, resolvedInputs, renamedArgs, asyncResolvers, nameApi, customInstructionData } = scope;
1559
+ const instructionNode = getLastNodeFromPath13(instructionPath);
1327
1560
  const programNode = findProgramNodeFromPath3(instructionPath);
1328
- if (useAsync && !hasAsyncFunction(instructionNode, resolvedInputs, asyncResolvers)) {
1329
- return fragment("");
1330
- }
1561
+ if (useAsync && !hasAsyncFunction(instructionNode, resolvedInputs, asyncResolvers)) return;
1331
1562
  const customData = customInstructionData.get(instructionNode.name);
1332
1563
  const hasAccounts = instructionNode.accounts.length > 0;
1333
- const hasLegacyOptionalAccounts = instructionNode.optionalAccountStrategy === "omitted" && instructionNode.accounts.some((account) => account.isOptional);
1334
1564
  const instructionDependencies = getInstructionDependencies(instructionNode, asyncResolvers, useAsync);
1335
1565
  const argDependencies = instructionDependencies.filter(isNodeFilter4("argumentValueNode")).map((node) => node.name);
1336
1566
  const hasData = !!customData || instructionNode.arguments.length > 0;
@@ -1348,161 +1578,297 @@ function getInstructionFunctionFragment(scope) {
1348
1578
  const hasRemainingAccountArgs = (instructionNode.remainingAccounts ?? []).filter(({ value }) => isNode12(value, "argumentValueNode")).length > 0;
1349
1579
  const hasAnyArgs = hasDataArgs || hasExtraArgs || hasRemainingAccountArgs;
1350
1580
  const hasInput = hasAccounts || hasAnyArgs;
1351
- const instructionDataName = nameApi.instructionDataType(instructionNode.name);
1352
- const programAddressConstant = nameApi.programAddressConstant(programNode.name);
1353
- const encoderFunction = customData ? dataArgsManifest.encoder.render : `${nameApi.encoderFunction(instructionDataName)}()`;
1354
- const argsTypeFragment = fragment(
1355
- customData ? dataArgsManifest.looseType.render : nameApi.dataArgsType(instructionDataName)
1356
- );
1357
- if (customData) {
1358
- argsTypeFragment.mergeImportsWith(dataArgsManifest.looseType, dataArgsManifest.encoder);
1359
- }
1581
+ const programAddressConstant = use(nameApi.programAddressConstant(programNode.name), "generatedPrograms");
1360
1582
  const functionName = useAsync ? nameApi.instructionAsyncFunction(instructionNode.name) : nameApi.instructionSyncFunction(instructionNode.name);
1361
- const typeParamsFragment = getTypeParams(instructionNode, programAddressConstant);
1362
- const instructionTypeFragment = getInstructionType(scope);
1363
- const inputTypeFragment = getInstructionInputTypeFragment(scope);
1364
- const inputTypeCallFragment = getInputTypeCall(scope);
1365
- const renamedArgsText = [...renamedArgs.entries()].map(([k, v]) => `${k}: input.${v}`).join(", ");
1366
1583
  const resolvedInputsFragment = getInstructionInputResolvedFragment(scope);
1367
1584
  const remainingAccountsFragment = getInstructionRemainingAccountsFragment(scope);
1368
1585
  const byteDeltaFragment = getInstructionByteDeltaFragment(scope);
1369
- const resolvedFragment = mergeFragments(
1586
+ const resolvedInputFragment = mergeFragments(
1370
1587
  [resolvedInputsFragment, remainingAccountsFragment, byteDeltaFragment],
1371
- (renders) => renders.join("\n\n")
1588
+ (content) => content.join("\n\n")
1372
1589
  );
1373
- const hasRemainingAccounts = remainingAccountsFragment.render !== "";
1374
- const hasByteDeltas = byteDeltaFragment.render !== "";
1375
- const hasResolver = resolvedFragment.hasFeatures("instruction:resolverScopeVariable");
1376
- const getReturnType = (instructionType) => {
1377
- let returnType = instructionType;
1378
- if (hasByteDeltas) {
1379
- returnType = `${returnType} & InstructionWithByteDelta`;
1380
- }
1381
- return useAsync ? `Promise<${returnType}>` : returnType;
1382
- };
1383
- const functionFragment = fragmentFromTemplate("instructionFunction.njk", {
1384
- argsTypeFragment,
1385
- encoderFunction,
1386
- functionName,
1387
- getReturnType,
1388
- hasAccounts,
1389
- hasAnyArgs,
1390
- hasByteDeltas,
1391
- hasData,
1392
- hasDataArgs,
1393
- hasExtraArgs,
1394
- hasInput,
1395
- hasLegacyOptionalAccounts,
1396
- hasRemainingAccounts,
1397
- hasResolver,
1398
- inputTypeCallFragment,
1399
- inputTypeFragment,
1400
- instruction: instructionNode,
1401
- instructionTypeFragment,
1402
- programAddressConstant,
1403
- renamedArgs: renamedArgsText,
1404
- resolvedFragment,
1405
- typeParamsFragment,
1406
- useAsync
1407
- }).mergeImportsWith(
1408
- typeParamsFragment,
1409
- instructionTypeFragment,
1410
- inputTypeFragment,
1411
- inputTypeCallFragment,
1412
- resolvedFragment,
1413
- argsTypeFragment
1414
- ).addImports("generatedPrograms", [programAddressConstant]).addImports("solanaAddresses", ["type Address"]);
1415
- if (hasAccounts) {
1416
- functionFragment.addImports("solanaInstructions", ["type AccountMeta"]).addImports("shared", ["getAccountMetaFactory", "type ResolvedAccount"]);
1417
- }
1418
- if (hasByteDeltas) {
1419
- functionFragment.addImports("shared", ["type InstructionWithByteDelta"]);
1590
+ const hasRemainingAccounts = !!remainingAccountsFragment;
1591
+ const hasByteDeltas = !!byteDeltaFragment;
1592
+ const hasResolver = resolvedInputFragment.features.has("instruction:resolverScopeVariable");
1593
+ const instructionTypeFragment = getInstructionTypeFragment(scope);
1594
+ const typeParams = getTypeParamsFragment(instructionNode, programAddressConstant);
1595
+ const returnType = getReturnTypeFragment(instructionTypeFragment, hasByteDeltas, useAsync);
1596
+ const inputType = getInstructionInputTypeFragment(scope);
1597
+ const inputArg = mapFragmentContent7(getInputTypeCallFragment(scope), (c) => hasInput ? `input: ${c}, ` : "");
1598
+ const functionBody = mergeFragments(
1599
+ [
1600
+ getProgramAddressInitializationFragment(programAddressConstant),
1601
+ getAccountsInitializationFragment(instructionNode),
1602
+ getArgumentsInitializationFragment(hasAnyArgs, renamedArgs),
1603
+ getResolverScopeInitializationFragment(hasResolver, hasAccounts, hasAnyArgs),
1604
+ resolvedInputFragment,
1605
+ getReturnStatementFragment({
1606
+ ...scope,
1607
+ hasByteDeltas,
1608
+ hasData,
1609
+ hasDataArgs,
1610
+ hasRemainingAccounts,
1611
+ instructionNode,
1612
+ syncReturnTypeFragment: getReturnTypeFragment(instructionTypeFragment, hasByteDeltas, false)
1613
+ })
1614
+ ],
1615
+ (cs) => cs.join("\n\n")
1616
+ );
1617
+ return fragment`${inputType}\n\nexport ${useAsync ? "async " : ""}function ${functionName}${typeParams}(${inputArg}config?: { programAddress?: TProgramAddress } ): ${returnType} {
1618
+ ${functionBody}
1619
+ }`;
1620
+ }
1621
+ function getProgramAddressInitializationFragment(programAddressConstant) {
1622
+ return fragment`// Program address.
1623
+ const programAddress = config?.programAddress ?? ${programAddressConstant};`;
1624
+ }
1625
+ function getAccountsInitializationFragment(instructionNode) {
1626
+ if (instructionNode.accounts.length === 0) return;
1627
+ const accounts = mergeFragments(
1628
+ instructionNode.accounts.map((account) => {
1629
+ const name = camelCase9(account.name);
1630
+ const isWritable = account.isWritable ? "true" : "false";
1631
+ return fragment`${name}: { value: input.${name} ?? null, isWritable: ${isWritable} }`;
1632
+ }),
1633
+ (cs) => cs.join(", ")
1634
+ );
1635
+ return fragment` // Original accounts.
1636
+ const originalAccounts = { ${accounts} }
1637
+ const accounts = originalAccounts as Record<keyof typeof originalAccounts, ${use("type ResolvedAccount", "shared")}>;
1638
+ `;
1639
+ }
1640
+ function getArgumentsInitializationFragment(hasAnyArgs, renamedArgs) {
1641
+ if (!hasAnyArgs) return;
1642
+ const renamedArgsText = [...renamedArgs.entries()].map(([k, v]) => `${k}: input.${v}`).join(", ");
1643
+ return fragment`// Original args.
1644
+ const args = { ...input, ${renamedArgsText} };
1645
+ `;
1646
+ }
1647
+ function getResolverScopeInitializationFragment(hasResolver, hasAccounts, hasAnyArgs) {
1648
+ if (!hasResolver) return;
1649
+ const resolverAttributes = [
1650
+ "programAddress",
1651
+ ...hasAccounts ? ["accounts"] : [],
1652
+ ...hasAnyArgs ? ["args"] : []
1653
+ ].join(", ");
1654
+ return fragment`// Resolver scope.
1655
+ const resolverScope = { ${resolverAttributes} };`;
1656
+ }
1657
+ function getReturnStatementFragment(scope) {
1658
+ const { instructionNode, hasByteDeltas, hasData, hasDataArgs, hasRemainingAccounts, nameApi } = scope;
1659
+ const optionalAccountStrategy = instructionNode.optionalAccountStrategy ?? "programId";
1660
+ const hasAccounts = instructionNode.accounts.length > 0;
1661
+ const hasLegacyOptionalAccounts = instructionNode.optionalAccountStrategy === "omitted" && instructionNode.accounts.some((account) => account.isOptional);
1662
+ const getAccountMeta = hasAccounts ? fragment`const getAccountMeta = ${use("getAccountMetaFactory", "shared")}(programAddress, '${optionalAccountStrategy}');` : "";
1663
+ const accountItems = [
1664
+ ...instructionNode.accounts.map((account) => `getAccountMeta(accounts.${camelCase9(account.name)})`),
1665
+ ...hasRemainingAccounts ? ["...remainingAccounts"] : []
1666
+ ].join(", ");
1667
+ let accounts;
1668
+ if (hasAccounts && hasLegacyOptionalAccounts) {
1669
+ accounts = fragment`accounts: [${accountItems}].filter(<T>(x: T | undefined): x is T => x !== undefined)`;
1670
+ } else if (hasAccounts) {
1671
+ accounts = fragment`accounts: [${accountItems}]`;
1672
+ } else if (hasRemainingAccounts) {
1673
+ accounts = fragment`accounts: remainingAccounts`;
1420
1674
  }
1421
- return functionFragment;
1675
+ const customData = scope.customInstructionData.get(instructionNode.name);
1676
+ const instructionDataName = nameApi.instructionDataType(instructionNode.name);
1677
+ const encoderFunctionFragment = customData ? scope.dataArgsManifest.encoder : `${nameApi.encoderFunction(instructionDataName)}()`;
1678
+ const argsTypeFragment = customData ? scope.dataArgsManifest.looseType : nameApi.dataArgsType(instructionDataName);
1679
+ let data;
1680
+ if (hasDataArgs) {
1681
+ data = fragment`data: ${encoderFunctionFragment}.encode(args as ${argsTypeFragment})`;
1682
+ } else if (hasData) {
1683
+ data = fragment`data: ${encoderFunctionFragment}.encode({})`;
1684
+ }
1685
+ const instructionAttributes = pipe8(
1686
+ [accounts, hasByteDeltas ? fragment`byteDelta` : void 0, data, fragment`programAddress`],
1687
+ (fs) => mergeFragments(fs, (cs) => cs.join(", "))
1688
+ );
1689
+ return fragment`${getAccountMeta}\nreturn Object.freeze({ ${instructionAttributes} } as ${scope.syncReturnTypeFragment});`;
1690
+ }
1691
+ function getReturnTypeFragment(instructionTypeFragment, hasByteDeltas, useAsync) {
1692
+ return pipe8(
1693
+ instructionTypeFragment,
1694
+ (f) => hasByteDeltas ? fragment`${f} & ${use("type InstructionWithByteDelta", "shared")}` : f,
1695
+ (f) => useAsync ? fragment`Promise<${f}>` : f
1696
+ );
1422
1697
  }
1423
- function getTypeParams(instructionNode, programAddressConstant) {
1424
- const typeParams = instructionNode.accounts.map((account) => `TAccount${pascalCase5(account.name)} extends string`);
1425
- typeParams.push(`TProgramAddress extends Address = typeof ${programAddressConstant}`);
1426
- return fragment(typeParams.filter((x) => !!x).join(", ")).mapRender((r) => `<${r}>`).addImports("generatedPrograms", [programAddressConstant]);
1698
+ function getTypeParamsFragment(instructionNode, programAddressConstant) {
1699
+ return mergeFragments(
1700
+ [
1701
+ ...instructionNode.accounts.map((account) => fragment`TAccount${pascalCase5(account.name)} extends string`),
1702
+ fragment`TProgramAddress extends ${use("type Address", "solanaAddresses")} = typeof ${programAddressConstant}`
1703
+ ],
1704
+ (cs) => `<${cs.join(", ")}>`
1705
+ );
1427
1706
  }
1428
- function getInstructionType(scope) {
1707
+ function getInstructionTypeFragment(scope) {
1429
1708
  const { instructionPath, nameApi } = scope;
1430
- const instructionNode = getLastNodeFromPath12(instructionPath);
1709
+ const instructionNode = getLastNodeFromPath13(instructionPath);
1431
1710
  const instructionTypeName = nameApi.instructionType(instructionNode.name);
1432
- const programAddressFragment = fragment("TProgramAddress");
1433
1711
  const accountTypeParamsFragments = instructionNode.accounts.map((account) => {
1434
- const typeParam = `TAccount${pascalCase5(account.name)}`;
1712
+ const typeParam = fragment`TAccount${pascalCase5(account.name)}`;
1435
1713
  const camelName = camelCase9(account.name);
1436
1714
  if (account.isSigner === "either") {
1437
- const signerRole = account.isWritable ? "WritableSignerAccount" : "ReadonlySignerAccount";
1438
- return fragment(
1439
- `typeof input["${camelName}"] extends TransactionSigner<${typeParam}> ? ${signerRole}<${typeParam}> & AccountSignerMeta<${typeParam}> : ${typeParam}`
1440
- ).addImports("solanaInstructions", [`type ${signerRole}`]).addImports("solanaSigners", ["type AccountSignerMeta"]);
1715
+ const signerRole = use(
1716
+ account.isWritable ? "type WritableSignerAccount" : "type ReadonlySignerAccount",
1717
+ "solanaInstructions"
1718
+ );
1719
+ return pipe8(
1720
+ fragment`typeof input["${camelName}"] extends TransactionSigner<${typeParam}> ? ${signerRole}<${typeParam}> & AccountSignerMeta<${typeParam}> : ${typeParam}`,
1721
+ (f) => addFragmentImports(f, "solanaSigners", ["type AccountSignerMeta", "type TransactionSigner"])
1722
+ );
1441
1723
  }
1442
- return fragment(typeParam);
1724
+ return typeParam;
1443
1725
  });
1444
- return mergeFragments(
1445
- [programAddressFragment, ...accountTypeParamsFragments],
1446
- (renders) => renders.join(", ")
1447
- ).mapRender((r) => `${instructionTypeName}<${r}>`);
1726
+ return pipe8(
1727
+ mergeFragments([fragment`TProgramAddress`, ...accountTypeParamsFragments], (c) => c.join(", ")),
1728
+ (f) => mapFragmentContent7(f, (c) => `${instructionTypeName}<${c}>`)
1729
+ );
1448
1730
  }
1449
- function getInputTypeCall(scope) {
1731
+ function getInputTypeCallFragment(scope) {
1450
1732
  const { instructionPath, useAsync, nameApi } = scope;
1451
- const instructionNode = getLastNodeFromPath12(instructionPath);
1733
+ const instructionNode = getLastNodeFromPath13(instructionPath);
1452
1734
  const inputTypeName = useAsync ? nameApi.instructionAsyncInputType(instructionNode.name) : nameApi.instructionSyncInputType(instructionNode.name);
1453
- if (instructionNode.accounts.length === 0) return fragment(inputTypeName);
1735
+ if (instructionNode.accounts.length === 0) return fragment`${inputTypeName}`;
1454
1736
  const accountTypeParams = instructionNode.accounts.map((account) => `TAccount${pascalCase5(account.name)}`).join(", ");
1455
- return fragment(`${inputTypeName}<${accountTypeParams}>`);
1737
+ return fragment`${inputTypeName}<${accountTypeParams}>`;
1456
1738
  }
1457
1739
 
1740
+ // src/fragments/instructionPage.ts
1741
+ import { logWarn } from "@codama/errors";
1742
+ import { camelCase as camelCase11, definedTypeNode as definedTypeNode2, structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes3 } from "@codama/nodes";
1743
+ import {
1744
+ findProgramNodeFromPath as findProgramNodeFromPath6,
1745
+ getLastNodeFromPath as getLastNodeFromPath16,
1746
+ visit as visit5
1747
+ } from "@codama/visitors-core";
1748
+
1458
1749
  // src/fragments/instructionParseFunction.ts
1459
- import { findProgramNodeFromPath as findProgramNodeFromPath4, getLastNodeFromPath as getLastNodeFromPath13 } from "@codama/visitors-core";
1750
+ import { camelCase as camelCase10 } from "@codama/nodes";
1751
+ import { findProgramNodeFromPath as findProgramNodeFromPath4, getLastNodeFromPath as getLastNodeFromPath14, pipe as pipe9 } from "@codama/visitors-core";
1460
1752
  function getInstructionParseFunctionFragment(scope) {
1461
- const { instructionPath, dataArgsManifest, nameApi, customInstructionData } = scope;
1462
- const instructionNode = getLastNodeFromPath13(instructionPath);
1463
- const programNode = findProgramNodeFromPath4(instructionPath);
1464
- const customData = customInstructionData.get(instructionNode.name);
1465
- const hasAccounts = instructionNode.accounts.length > 0;
1466
- const hasOptionalAccounts = instructionNode.accounts.some((account) => account.isOptional);
1467
- const minimumNumberOfAccounts = instructionNode.optionalAccountStrategy === "omitted" ? instructionNode.accounts.filter((account) => !account.isOptional).length : instructionNode.accounts.length;
1468
- const hasData = !!customData || instructionNode.arguments.length > 0;
1469
- const instructionDataName = nameApi.instructionDataType(instructionNode.name);
1470
- const programAddressConstant = nameApi.programAddressConstant(programNode.name);
1471
- const dataTypeFragment = fragment(
1472
- customData ? dataArgsManifest.strictType.render : nameApi.dataType(instructionDataName)
1753
+ const instructionNode = getLastNodeFromPath14(scope.instructionPath);
1754
+ const programNode = findProgramNodeFromPath4(scope.instructionPath);
1755
+ const programAddressConstant = use(scope.nameApi.programAddressConstant(programNode.name), "generatedPrograms");
1756
+ const childScope = { ...scope, instructionNode, programAddressConstant };
1757
+ return mergeFragments([getTypeFragment2(childScope), getFunctionFragment(childScope)], (cs) => cs.join("\n\n"));
1758
+ }
1759
+ function getTypeFragment2(scope) {
1760
+ const customData = scope.customInstructionData.get(scope.instructionNode.name);
1761
+ const instructionParsedType = scope.nameApi.instructionParsedType(scope.instructionNode.name);
1762
+ const instructionDataName = scope.nameApi.instructionDataType(scope.instructionNode.name);
1763
+ const hasData = !!customData || scope.instructionNode.arguments.length > 0;
1764
+ const hasAccounts = scope.instructionNode.accounts.length > 0;
1765
+ const typeParamDeclarations = mergeFragments(
1766
+ [
1767
+ fragment`TProgram extends string = typeof ${scope.programAddressConstant}`,
1768
+ hasAccounts ? fragment`TAccountMetas extends readonly ${use("type AccountMeta", "solanaInstructions")}[] = readonly AccountMeta[]` : void 0
1769
+ ],
1770
+ (cs) => cs.join(", ")
1473
1771
  );
1474
- const decoderFunction = customData ? dataArgsManifest.decoder.render : `${nameApi.decoderFunction(instructionDataName)}()`;
1475
- if (customData) {
1476
- dataTypeFragment.mergeImportsWith(dataArgsManifest.strictType, dataArgsManifest.decoder);
1477
- }
1478
- return fragmentFromTemplate("instructionParseFunction.njk", {
1479
- dataTypeFragment,
1480
- decoderFunction,
1481
- hasAccounts,
1482
- hasData,
1483
- hasOptionalAccounts,
1484
- instruction: instructionNode,
1485
- instructionParseFunction: nameApi.instructionParseFunction(instructionNode.name),
1486
- instructionParsedType: nameApi.instructionParsedType(instructionNode.name),
1487
- minimumNumberOfAccounts,
1488
- programAddressConstant
1489
- }).mergeImportsWith(dataTypeFragment).addImports("generatedPrograms", [programAddressConstant]).addImports("solanaInstructions", ["type Instruction"]).addImports("solanaInstructions", hasAccounts ? ["type InstructionWithAccounts", "type AccountMeta"] : []).addImports("solanaInstructions", hasData ? ["type InstructionWithData"] : []).addImports("solanaCodecsCore", hasData ? ["type ReadonlyUint8Array"] : []);
1772
+ const accounts = mergeFragments(
1773
+ scope.instructionNode.accounts.map((account, i) => {
1774
+ const docs = getDocblockFragment(account.docs ?? [], true);
1775
+ const name = camelCase10(account.name);
1776
+ return fragment`${docs}${name}${account.isOptional ? "?" : ""}: TAccountMetas[${i}]${account.isOptional ? " | undefined" : ""};`;
1777
+ }),
1778
+ (cs) => hasAccounts ? `
1779
+ accounts: {
1780
+ ${cs.join("\n")}
1781
+ };` : ""
1782
+ );
1783
+ const dataTypeFragment = customData ? scope.dataArgsManifest.strictType : fragment`${scope.nameApi.dataType(instructionDataName)}`;
1784
+ const data = hasData ? fragment`\ndata: ${dataTypeFragment};` : fragment``;
1785
+ return fragment`export type ${instructionParsedType}<${typeParamDeclarations}> = { programAddress: ${use("type Address", "solanaAddresses")}<TProgram>;${accounts}${data} };`;
1786
+ }
1787
+ function getFunctionFragment(scope) {
1788
+ const customData = scope.customInstructionData.get(scope.instructionNode.name);
1789
+ const instructionParsedType = scope.nameApi.instructionParsedType(scope.instructionNode.name);
1790
+ const instructionParseFunction = scope.nameApi.instructionParseFunction(scope.instructionNode.name);
1791
+ const instructionDataName = scope.nameApi.instructionDataType(scope.instructionNode.name);
1792
+ const decoderFunction = customData ? scope.dataArgsManifest.decoder : fragment`${scope.nameApi.decoderFunction(instructionDataName)}()`;
1793
+ const hasData = !!customData || scope.instructionNode.arguments.length > 0;
1794
+ const hasAccounts = scope.instructionNode.accounts.length > 0;
1795
+ const hasOptionalAccounts = scope.instructionNode.accounts.some((account) => account.isOptional);
1796
+ const minimumNumberOfAccounts = scope.instructionNode.optionalAccountStrategy === "omitted" ? scope.instructionNode.accounts.filter((account) => !account.isOptional).length : scope.instructionNode.accounts.length;
1797
+ const typeParams = ["TProgram", hasAccounts ? "TAccountMetas" : void 0].filter(Boolean).join(", ");
1798
+ const typeParamDeclarations = mergeFragments(
1799
+ [
1800
+ fragment`TProgram extends string`,
1801
+ hasAccounts ? fragment`TAccountMetas extends readonly ${use("type AccountMeta", "solanaInstructions")}[]` : void 0
1802
+ ],
1803
+ (cs) => cs.join(", ")
1804
+ );
1805
+ const instructionType = mergeFragments(
1806
+ [
1807
+ fragment`${use("type Instruction", "solanaInstructions")}<TProgram>`,
1808
+ hasAccounts ? fragment`${use("type InstructionWithAccounts", "solanaInstructions")}<TAccountMetas>` : void 0,
1809
+ hasData ? pipe9(
1810
+ fragment`InstructionWithData<ReadonlyUint8Array>`,
1811
+ (f) => addFragmentImports(f, "solanaInstructions", ["type InstructionWithData"]),
1812
+ (f) => addFragmentImports(f, "solanaCodecsCore", ["type ReadonlyUint8Array"])
1813
+ ) : void 0
1814
+ ],
1815
+ (cs) => cs.join(" & ")
1816
+ );
1817
+ let accountHelpers;
1818
+ if (hasAccounts) {
1819
+ accountHelpers = fragment`if (instruction.accounts.length < ${minimumNumberOfAccounts}) {
1820
+ // TODO: Coded error.
1821
+ throw new Error('Not enough accounts');
1822
+ }
1823
+ let accountIndex = 0;
1824
+ const getNextAccount = () => {
1825
+ const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!;
1826
+ accountIndex += 1;
1827
+ return accountMeta;
1828
+ }`;
1829
+ }
1830
+ if (hasOptionalAccounts && scope.instructionNode.optionalAccountStrategy === "omitted") {
1831
+ accountHelpers = fragment`${accountHelpers}
1832
+ let optionalAccountsRemaining = instruction.accounts.length - ${minimumNumberOfAccounts};
1833
+ const getNextOptionalAccount = () => {
1834
+ if (optionalAccountsRemaining === 0) return undefined;
1835
+ optionalAccountsRemaining -= 1;
1836
+ return getNextAccount();
1837
+ };`;
1838
+ } else if (hasOptionalAccounts) {
1839
+ accountHelpers = fragment`${accountHelpers}
1840
+ const getNextOptionalAccount = () => {
1841
+ const accountMeta = getNextAccount();
1842
+ return accountMeta.address === ${scope.programAddressConstant} ? undefined : accountMeta;
1843
+ };`;
1844
+ }
1845
+ const accounts = mergeFragments(
1846
+ scope.instructionNode.accounts.map(
1847
+ (account) => account.isOptional ? fragment`${camelCase10(account.name)}: getNextOptionalAccount()` : fragment`${camelCase10(account.name)}: getNextAccount()`
1848
+ ),
1849
+ (cs) => hasAccounts ? `, accounts: { ${cs.join(", ")} }` : ""
1850
+ );
1851
+ const data = hasData ? fragment`, data: ${decoderFunction}.decode(instruction.data)` : fragment``;
1852
+ return fragment`export function ${instructionParseFunction}<${typeParamDeclarations}>(instruction: ${instructionType}): ${instructionParsedType}<${typeParams}> {
1853
+ ${accountHelpers}
1854
+ return { programAddress: instruction.programAddress${accounts}${data} };
1855
+ }`;
1490
1856
  }
1491
1857
 
1492
1858
  // src/fragments/instructionType.ts
1493
1859
  import { pascalCase as pascalCase6 } from "@codama/nodes";
1494
- import { findProgramNodeFromPath as findProgramNodeFromPath5, getLastNodeFromPath as getLastNodeFromPath14 } from "@codama/visitors-core";
1495
- function getInstructionTypeFragment(scope) {
1860
+ import { mapFragmentContent as mapFragmentContent8 } from "@codama/renderers-core";
1861
+ import { findProgramNodeFromPath as findProgramNodeFromPath5, getLastNodeFromPath as getLastNodeFromPath15 } from "@codama/visitors-core";
1862
+ function getInstructionTypeFragment2(scope) {
1496
1863
  const { instructionPath, nameApi, customInstructionData } = scope;
1497
- const instructionNode = getLastNodeFromPath14(instructionPath);
1864
+ const instructionNode = getLastNodeFromPath15(instructionPath);
1498
1865
  const programNode = findProgramNodeFromPath5(instructionPath);
1499
1866
  const hasAccounts = instructionNode.accounts.length > 0;
1500
1867
  const customData = customInstructionData.get(instructionNode.name);
1501
1868
  const hasData = !!customData || instructionNode.arguments.length > 0;
1502
- const instructionDataName = nameApi.instructionDataType(instructionNode.name);
1503
- const programAddressConstant = nameApi.programAddressConstant(programNode.name);
1504
- const dataType = customData ? pascalCase6(customData.importAs) : pascalCase6(instructionDataName);
1505
- const accountTypeParamsFragment = mergeFragments(
1869
+ const instructionType = nameApi.instructionType(instructionNode.name);
1870
+ const programAddressConstant = use(nameApi.programAddressConstant(programNode.name), "generatedPrograms");
1871
+ const accountTypeParams = mergeFragments(
1506
1872
  instructionNode.accounts.map(
1507
1873
  (account) => getInstructionAccountTypeParamFragment({
1508
1874
  ...scope,
@@ -1510,91 +1876,165 @@ function getInstructionTypeFragment(scope) {
1510
1876
  instructionAccountPath: [...instructionPath, account]
1511
1877
  })
1512
1878
  ),
1513
- (renders) => renders.join(", ")
1879
+ (cs) => cs.length > 0 ? `${cs.join(", ")}, ` : ""
1514
1880
  );
1881
+ const data = hasData ? fragment` & ${use("type InstructionWithData", "solanaInstructions")}<${use("type ReadonlyUint8Array", "solanaCodecsCore")}>` : void 0;
1515
1882
  const usesLegacyOptionalAccounts = instructionNode.optionalAccountStrategy === "omitted";
1516
1883
  const accountMetasFragment = mergeFragments(
1517
1884
  instructionNode.accounts.map(
1518
- (account) => getInstructionAccountMetaFragment(account).mapRender((r) => {
1885
+ (account) => mapFragmentContent8(getInstructionAccountMetaFragment(account), (c) => {
1519
1886
  const typeParam = `TAccount${pascalCase6(account.name)}`;
1520
1887
  const isLegacyOptional = account.isOptional && usesLegacyOptionalAccounts;
1521
- const type = `${typeParam} extends string ? ${r} : ${typeParam}`;
1888
+ const type = `${typeParam} extends string ? ${c} : ${typeParam}`;
1522
1889
  if (!isLegacyOptional) return type;
1523
1890
  return `...(${typeParam} extends undefined ? [] : [${type}])`;
1524
1891
  })
1525
1892
  ),
1526
- (renders) => renders.join(", ")
1527
- );
1528
- const fragment2 = fragmentFromTemplate("instructionType.njk", {
1529
- accountMetas: accountMetasFragment.render,
1530
- accountTypeParams: accountTypeParamsFragment.render,
1531
- dataType,
1532
- hasAccounts,
1533
- hasData,
1534
- instruction: instructionNode,
1535
- instructionType: nameApi.instructionType(instructionNode.name),
1536
- programAddressConstant
1537
- }).mergeImportsWith(accountTypeParamsFragment, accountMetasFragment).addImports("generatedPrograms", [programAddressConstant]).addImports("solanaCodecsCore", hasData ? ["type ReadonlyUint8Array"] : []).addImports("solanaInstructions", [
1538
- "type AccountMeta",
1539
- "type Instruction",
1540
- "type InstructionWithAccounts",
1541
- ...hasData ? ["type InstructionWithData"] : []
1542
- ]);
1543
- return fragment2;
1893
+ (c) => c.join(", ")
1894
+ );
1895
+ const instructionWithAccounts = use("type InstructionWithAccounts", "solanaInstructions");
1896
+ const accounts = hasAccounts ? fragment` & ${instructionWithAccounts}<[${accountMetasFragment}, ...TRemainingAccounts]>` : fragment` & ${instructionWithAccounts}<TRemainingAccounts>`;
1897
+ return fragment`export type ${instructionType}<TProgram extends string = typeof ${programAddressConstant}, ${accountTypeParams}TRemainingAccounts extends readonly ${use("type AccountMeta", "solanaInstructions")}<string>[] = []> =
1898
+ ${use("type Instruction", "solanaInstructions")}<TProgram>${data}${accounts};`;
1899
+ }
1900
+
1901
+ // src/fragments/instructionPage.ts
1902
+ function getInstructionPageFragment(scope) {
1903
+ const node = getLastNodeFromPath16(scope.instructionPath);
1904
+ if (!findProgramNodeFromPath6(scope.instructionPath)) {
1905
+ throw new Error("Instruction must be visited inside a program.");
1906
+ }
1907
+ const childScope = {
1908
+ ...scope,
1909
+ dataArgsManifest: visit5(node, scope.typeManifestVisitor),
1910
+ extraArgsManifest: visit5(
1911
+ definedTypeNode2({
1912
+ name: scope.nameApi.instructionExtraType(node.name),
1913
+ type: structTypeNodeFromInstructionArgumentNodes3(node.extraArguments ?? [])
1914
+ }),
1915
+ scope.typeManifestVisitor
1916
+ ),
1917
+ renamedArgs: getRenamedArgsMap(node)
1918
+ };
1919
+ return mergeFragments(
1920
+ [
1921
+ getDiscriminatorConstantsFragment({
1922
+ ...childScope,
1923
+ discriminatorNodes: node.discriminators ?? [],
1924
+ fields: node.arguments,
1925
+ prefix: node.name
1926
+ }),
1927
+ getInstructionTypeFragment2(childScope),
1928
+ getInstructionDataFragment(childScope),
1929
+ getInstructionExtraArgsFragment(childScope),
1930
+ getInstructionFunctionFragment({ ...childScope, useAsync: true }),
1931
+ getInstructionFunctionFragment({ ...childScope, useAsync: false }),
1932
+ getInstructionParseFunctionFragment(childScope)
1933
+ ],
1934
+ (cs) => cs.join("\n\n")
1935
+ );
1936
+ }
1937
+ function getRenamedArgsMap(instruction) {
1938
+ const argNames = [
1939
+ ...instruction.arguments.map((a) => a.name),
1940
+ ...(instruction.extraArguments ?? []).map((a) => a.name)
1941
+ ];
1942
+ const duplicateArgs = argNames.filter((e, i, a) => a.indexOf(e) !== i);
1943
+ if (duplicateArgs.length > 0) {
1944
+ throw new Error(`Duplicate args found: [${duplicateArgs.join(", ")}] in instruction [${instruction.name}].`);
1945
+ }
1946
+ const allNames = [...instruction.accounts.map((account) => account.name), ...argNames];
1947
+ const duplicates = allNames.filter((e, i, a) => a.indexOf(e) !== i);
1948
+ if (duplicates.length === 0) return /* @__PURE__ */ new Map();
1949
+ logWarn(
1950
+ `[JavaScript] Accounts and args of instruction [${instruction.name}] have the following conflicting attributes [${duplicates.join(", ")}]. Thus, the arguments have been renamed to avoid conflicts in the input type.`
1951
+ );
1952
+ return new Map(duplicates.map((name) => [camelCase11(name), camelCase11(`${name}Arg`)]));
1544
1953
  }
1545
1954
 
1546
1955
  // src/fragments/pdaFunction.ts
1547
- import { isNode as isNode13, isNodeFilter as isNodeFilter5 } from "@codama/nodes";
1548
- import { findProgramNodeFromPath as findProgramNodeFromPath6, getLastNodeFromPath as getLastNodeFromPath15, visit as visit4 } from "@codama/visitors-core";
1956
+ import { camelCase as camelCase12, isNode as isNode13, isNodeFilter as isNodeFilter5 } from "@codama/nodes";
1957
+ import { findProgramNodeFromPath as findProgramNodeFromPath7, getLastNodeFromPath as getLastNodeFromPath17, visit as visit6 } from "@codama/visitors-core";
1549
1958
  function getPdaFunctionFragment(scope) {
1550
- const { pdaPath, typeManifestVisitor, nameApi } = scope;
1551
- const pdaNode = getLastNodeFromPath15(pdaPath);
1552
- const programNode = findProgramNodeFromPath6(pdaPath);
1553
- const imports = new ImportMap();
1554
- const seeds = pdaNode.seeds.map((seed) => {
1959
+ const pdaNode = getLastNodeFromPath17(scope.pdaPath);
1960
+ const seeds = parsePdaSeedNodes(pdaNode.seeds, scope);
1961
+ return mergeFragments(
1962
+ [getSeedInputTypeFragment(seeds, scope), getFunctionFragment2(seeds, scope)],
1963
+ (cs) => cs.join("\n\n")
1964
+ );
1965
+ }
1966
+ function getSeedInputTypeFragment(seeds, scope) {
1967
+ const variableSeeds = seeds.filter(isNodeFilter5("variablePdaSeedNode"));
1968
+ if (variableSeeds.length === 0) return;
1969
+ const pdaNode = getLastNodeFromPath17(scope.pdaPath);
1970
+ const seedTypeName = scope.nameApi.pdaSeedsType(pdaNode.name);
1971
+ const seedAttributes = mergeFragments(
1972
+ variableSeeds.map((seed) => seed.inputAttribute),
1973
+ (cs) => cs.join("\n")
1974
+ );
1975
+ return fragment`export type ${seedTypeName} = {\n${seedAttributes}\n};`;
1976
+ }
1977
+ function getFunctionFragment2(seeds, scope) {
1978
+ const pdaNode = getLastNodeFromPath17(scope.pdaPath);
1979
+ const programNode = findProgramNodeFromPath7(scope.pdaPath);
1980
+ const addressType = use("type Address", "solanaAddresses");
1981
+ const pdaType = use("type ProgramDerivedAddress", "solanaAddresses");
1982
+ const getPdaFunction = use("getProgramDerivedAddress", "solanaAddresses");
1983
+ const seedTypeName = scope.nameApi.pdaSeedsType(pdaNode.name);
1984
+ const findPdaFunction = scope.nameApi.pdaFindFunction(pdaNode.name);
1985
+ const docs = getDocblockFragment(pdaNode.docs ?? [], true);
1986
+ const hasVariableSeeds = seeds.filter(isNodeFilter5("variablePdaSeedNode")).length > 0;
1987
+ const seedArgument = hasVariableSeeds ? `seeds: ${seedTypeName}, ` : "";
1988
+ const programAddress = pdaNode.programId ?? programNode.publicKey;
1989
+ const encodedSeeds = mergeFragments(
1990
+ seeds.map((s) => s.encodedValue),
1991
+ (cs) => cs.join(", ")
1992
+ );
1993
+ return fragment`${docs}export async function ${findPdaFunction}(${seedArgument}config: { programAddress?: ${addressType} | undefined } = {}): Promise<${pdaType}> {
1994
+ const { programAddress = '${programAddress}' as ${addressType}<'${programAddress}'> } = config;
1995
+ return await ${getPdaFunction}({ programAddress, seeds: [${encodedSeeds}]});
1996
+ }`;
1997
+ }
1998
+ function parsePdaSeedNodes(seeds, scope) {
1999
+ return seeds.map((seed) => {
1555
2000
  if (isNode13(seed, "variablePdaSeedNode")) {
1556
- const seedManifest2 = visit4(seed.type, typeManifestVisitor);
1557
- imports.mergeWith(seedManifest2.looseType, seedManifest2.encoder);
1558
- return { ...seed, typeManifest: seedManifest2 };
2001
+ const name = camelCase12(seed.name);
2002
+ const docs = getDocblockFragment(seed.docs ?? [], true);
2003
+ const { encoder: encoder2, looseType } = visit6(seed.type, scope.typeManifestVisitor);
2004
+ return {
2005
+ ...seed,
2006
+ encodedValue: fragment`${encoder2}.encode(seeds.${name})`,
2007
+ inputAttribute: fragment`${docs}${name}: ${looseType};`
2008
+ };
1559
2009
  }
1560
2010
  if (isNode13(seed.value, "programIdValueNode")) {
1561
- imports.add("solanaAddresses", "getAddressEncoder");
1562
- return seed;
2011
+ const addressEncoder = use("getAddressEncoder", "solanaAddresses");
2012
+ return { ...seed, encodedValue: fragment`${addressEncoder}().encode(programAddress)` };
1563
2013
  }
1564
- const seedManifest = visit4(seed.type, typeManifestVisitor);
1565
- imports.mergeWith(seedManifest.encoder);
1566
- const valueManifest = visit4(seed.value, typeManifestVisitor).value;
1567
- imports.mergeWith(valueManifest.imports);
1568
- return { ...seed, typeManifest: seedManifest, valueManifest };
2014
+ const { encoder } = visit6(seed.type, scope.typeManifestVisitor);
2015
+ const { value } = visit6(seed.value, scope.typeManifestVisitor);
2016
+ return { ...seed, encodedValue: fragment`${encoder}.encode(${value})` };
1569
2017
  });
1570
- const hasVariableSeeds = pdaNode.seeds.filter(isNodeFilter5("variablePdaSeedNode")).length > 0;
1571
- return fragmentFromTemplate("pdaFunction.njk", {
1572
- findPdaFunction: nameApi.pdaFindFunction(pdaNode.name),
1573
- hasVariableSeeds,
1574
- pdaDocs: pdaNode.docs,
1575
- pdaSeedsType: nameApi.pdaSeedsType(pdaNode.name),
1576
- programAddress: pdaNode.programId ?? programNode.publicKey,
1577
- seeds
1578
- }).mergeImportsWith(imports).addImports("solanaAddresses", ["type Address", "getProgramDerivedAddress", "type ProgramDerivedAddress"]);
1579
- }
1580
-
1581
- // src/fragments/program.ts
1582
- function getProgramFragment(scope) {
1583
- const { programNode, nameApi } = scope;
1584
- return fragmentFromTemplate("program.njk", {
1585
- program: programNode,
1586
- programAddressConstant: nameApi.programAddressConstant(programNode.name)
1587
- }).addImports("solanaAddresses", ["type Address"]);
2018
+ }
2019
+
2020
+ // src/fragments/pdaPage.ts
2021
+ import { findProgramNodeFromPath as findProgramNodeFromPath8 } from "@codama/visitors-core";
2022
+ function getPdaPageFragment(scope) {
2023
+ if (!findProgramNodeFromPath8(scope.pdaPath)) {
2024
+ throw new Error("PDA must be visited inside a program.");
2025
+ }
2026
+ return getPdaFunctionFragment(scope);
1588
2027
  }
1589
2028
 
1590
2029
  // src/fragments/programAccounts.ts
1591
- import { resolveNestedTypeNode as resolveNestedTypeNode2 } from "@codama/nodes";
2030
+ import { resolveNestedTypeNode as resolveNestedTypeNode3 } from "@codama/nodes";
2031
+ import { mapFragmentContent as mapFragmentContent9 } from "@codama/renderers-core";
2032
+ import { pipe as pipe10 } from "@codama/visitors-core";
1592
2033
  function getProgramAccountsFragment(scope) {
1593
- if (scope.programNode.accounts.length === 0) return fragment("");
2034
+ if (scope.programNode.accounts.length === 0) return;
1594
2035
  return mergeFragments(
1595
2036
  [getProgramAccountsEnumFragment(scope), getProgramAccountsIdentifierFunctionFragment(scope)],
1596
- (r) => `${r.join("\n\n")}
1597
- `
2037
+ (c) => c.join("\n\n")
1598
2038
  );
1599
2039
  }
1600
2040
  function getProgramAccountsEnumFragment(scope) {
@@ -1603,7 +2043,7 @@ function getProgramAccountsEnumFragment(scope) {
1603
2043
  const programAccountsEnumVariants = programNode.accounts.map(
1604
2044
  (account) => nameApi.programAccountsEnumVariant(account.name)
1605
2045
  );
1606
- return fragment(`export enum ${programAccountsEnum} { ${programAccountsEnumVariants.join(", ")} }`);
2046
+ return fragment`export enum ${programAccountsEnum} { ${programAccountsEnumVariants.join(", ")} }`;
1607
2047
  }
1608
2048
  function getProgramAccountsIdentifierFunctionFragment(scope) {
1609
2049
  const { programNode, nameApi } = scope;
@@ -1611,54 +2051,55 @@ function getProgramAccountsIdentifierFunctionFragment(scope) {
1611
2051
  (account) => (account.discriminators ?? []).length > 0
1612
2052
  );
1613
2053
  const hasAccountDiscriminators = accountsWithDiscriminators.length > 0;
1614
- if (!hasAccountDiscriminators) return fragment("");
2054
+ if (!hasAccountDiscriminators) return;
1615
2055
  const programAccountsEnum = nameApi.programAccountsEnum(programNode.name);
1616
2056
  const programAccountsIdentifierFunction = nameApi.programAccountsIdentifierFunction(programNode.name);
1617
- const discriminatorsFragment = mergeFragments(
1618
- accountsWithDiscriminators.map((account) => {
1619
- const variant = nameApi.programAccountsEnumVariant(account.name);
1620
- return getDiscriminatorConditionFragment({
1621
- ...scope,
1622
- dataName: "data",
1623
- discriminators: account.discriminators ?? [],
1624
- ifTrue: `return ${programAccountsEnum}.${variant};`,
1625
- struct: resolveNestedTypeNode2(account.data)
1626
- });
1627
- }),
1628
- (r) => r.join("\n")
1629
- );
1630
- return discriminatorsFragment.mapRender(
1631
- (discriminators) => `export function ${programAccountsIdentifierFunction}(account: { data: ReadonlyUint8Array } | ReadonlyUint8Array): ${programAccountsEnum} {
2057
+ return pipe10(
2058
+ mergeFragments(
2059
+ accountsWithDiscriminators.map((account) => {
2060
+ const variant = nameApi.programAccountsEnumVariant(account.name);
2061
+ return getDiscriminatorConditionFragment({
2062
+ ...scope,
2063
+ dataName: "data",
2064
+ discriminators: account.discriminators ?? [],
2065
+ ifTrue: `return ${programAccountsEnum}.${variant};`,
2066
+ struct: resolveNestedTypeNode3(account.data)
2067
+ });
2068
+ }),
2069
+ (c) => c.join("\n")
2070
+ ),
2071
+ (f) => mapFragmentContent9(
2072
+ f,
2073
+ (discriminators) => `export function ${programAccountsIdentifierFunction}(account: { data: ReadonlyUint8Array } | ReadonlyUint8Array): ${programAccountsEnum} {
1632
2074
  const data = 'data' in account ? account.data : account;
1633
2075
  ${discriminators}
1634
2076
  throw new Error("The provided account could not be identified as a ${programNode.name} account.")
1635
2077
  }`
1636
- ).addImports("solanaCodecsCore", "type ReadonlyUint8Array");
2078
+ ),
2079
+ (f) => addFragmentImports(f, "solanaCodecsCore", ["type ReadonlyUint8Array"])
2080
+ );
1637
2081
  }
1638
2082
 
1639
- // src/fragments/programErrors.ts
1640
- function getProgramErrorsFragment(scope) {
2083
+ // src/fragments/programConstant.ts
2084
+ import { pipe as pipe11 } from "@codama/visitors-core";
2085
+ function getProgramConstantFragment(scope) {
1641
2086
  const { programNode, nameApi } = scope;
1642
2087
  const programAddressConstant = nameApi.programAddressConstant(programNode.name);
1643
- return fragmentFromTemplate("programErrors.njk", {
1644
- errors: programNode.errors,
1645
- escapeProgramErrorMessage: (message) => message.replace(/`/g, "\\`"),
1646
- getProgramErrorConstant: (name) => nameApi.programErrorConstantPrefix(programNode.name) + nameApi.programErrorConstant(name),
1647
- programAddressConstant,
1648
- programErrorMessagesMap: nameApi.programErrorMessagesMap(programNode.name),
1649
- programErrorUnion: nameApi.programErrorUnion(programNode.name),
1650
- programGetErrorMessageFunction: nameApi.programGetErrorMessageFunction(programNode.name),
1651
- programIsErrorFunction: nameApi.programIsErrorFunction(programNode.name)
1652
- }).addImports("generatedPrograms", [programAddressConstant]).addImports("solanaPrograms", ["isProgramError"]).addImports("solanaErrors", ["type SolanaError", "type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM"]).addImports("solanaAddresses", ["type Address"]);
2088
+ return pipe11(
2089
+ fragment`export const ${programAddressConstant} = '${programNode.publicKey}' as Address<'${programNode.publicKey}'>;`,
2090
+ (f) => addFragmentImports(f, "solanaAddresses", ["type Address"])
2091
+ );
1653
2092
  }
1654
2093
 
1655
2094
  // src/fragments/programInstructions.ts
1656
2095
  import {
1657
2096
  getAllInstructionsWithSubs,
1658
- structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes3
2097
+ structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes4
1659
2098
  } from "@codama/nodes";
2099
+ import { mapFragmentContent as mapFragmentContent10 } from "@codama/renderers-core";
2100
+ import { pipe as pipe12 } from "@codama/visitors-core";
1660
2101
  function getProgramInstructionsFragment(scope) {
1661
- if (scope.programNode.instructions.length === 0) return fragment("");
2102
+ if (scope.programNode.instructions.length === 0) return;
1662
2103
  const allInstructions = getAllInstructionsWithSubs(scope.programNode, {
1663
2104
  leavesOnly: !scope.renderParentInstructions,
1664
2105
  subInstructionsFirst: true
@@ -1670,8 +2111,7 @@ function getProgramInstructionsFragment(scope) {
1670
2111
  getProgramInstructionsIdentifierFunctionFragment(scopeWithInstructions),
1671
2112
  getProgramInstructionsParsedUnionTypeFragment(scopeWithInstructions)
1672
2113
  ],
1673
- (r) => `${r.join("\n\n")}
1674
- `
2114
+ (c) => c.join("\n\n")
1675
2115
  );
1676
2116
  }
1677
2117
  function getProgramInstructionsEnumFragment(scope) {
@@ -1680,9 +2120,7 @@ function getProgramInstructionsEnumFragment(scope) {
1680
2120
  const programInstructionsEnumVariants = allInstructions.map(
1681
2121
  (instruction) => nameApi.programInstructionsEnumVariant(instruction.name)
1682
2122
  );
1683
- return fragment(
1684
- `export enum ${programInstructionsEnum} { ${programInstructionsEnumVariants.join(", ")} }`
1685
- );
2123
+ return fragment`export enum ${programInstructionsEnum} { ${programInstructionsEnumVariants.join(", ")} }`;
1686
2124
  }
1687
2125
  function getProgramInstructionsIdentifierFunctionFragment(scope) {
1688
2126
  const { programNode, nameApi, allInstructions } = scope;
@@ -1690,7 +2128,7 @@ function getProgramInstructionsIdentifierFunctionFragment(scope) {
1690
2128
  (instruction) => (instruction.discriminators ?? []).length > 0
1691
2129
  );
1692
2130
  const hasInstructionDiscriminators = instructionsWithDiscriminators.length > 0;
1693
- if (!hasInstructionDiscriminators) return fragment("");
2131
+ if (!hasInstructionDiscriminators) return;
1694
2132
  const programInstructionsEnum = nameApi.programInstructionsEnum(programNode.name);
1695
2133
  const programInstructionsIdentifierFunction = nameApi.programInstructionsIdentifierFunction(programNode.name);
1696
2134
  const discriminatorsFragment = mergeFragments(
@@ -1701,18 +2139,23 @@ function getProgramInstructionsIdentifierFunctionFragment(scope) {
1701
2139
  dataName: "data",
1702
2140
  discriminators: instruction.discriminators ?? [],
1703
2141
  ifTrue: `return ${programInstructionsEnum}.${variant};`,
1704
- struct: structTypeNodeFromInstructionArgumentNodes3(instruction.arguments)
2142
+ struct: structTypeNodeFromInstructionArgumentNodes4(instruction.arguments)
1705
2143
  });
1706
2144
  }),
1707
- (r) => r.join("\n")
2145
+ (c) => c.join("\n")
1708
2146
  );
1709
- return discriminatorsFragment.mapRender(
1710
- (discriminators) => `export function ${programInstructionsIdentifierFunction}(instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array): ${programInstructionsEnum} {
2147
+ return pipe12(
2148
+ discriminatorsFragment,
2149
+ (f) => mapFragmentContent10(
2150
+ f,
2151
+ (discriminators) => `export function ${programInstructionsIdentifierFunction}(instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array): ${programInstructionsEnum} {
1711
2152
  const data = 'data' in instruction ? instruction.data : instruction;
1712
2153
  ${discriminators}
1713
2154
  throw new Error("The provided instruction could not be identified as a ${programNode.name} instruction.")
1714
2155
  }`
1715
- ).addImports("solanaCodecsCore", "type ReadonlyUint8Array");
2156
+ ),
2157
+ (f) => addFragmentImports(f, "solanaCodecsCore", ["type ReadonlyUint8Array"])
2158
+ );
1716
2159
  }
1717
2160
  function getProgramInstructionsParsedUnionTypeFragment(scope) {
1718
2161
  const { programNode, allInstructions, nameApi } = scope;
@@ -1721,17 +2164,164 @@ function getProgramInstructionsParsedUnionTypeFragment(scope) {
1721
2164
  const programInstructionsEnum = nameApi.programInstructionsEnum(programNode.name);
1722
2165
  const typeVariants = allInstructions.map((instruction) => {
1723
2166
  const instructionEnumVariant = nameApi.programInstructionsEnumVariant(instruction.name);
1724
- const parsedInstructionType = nameApi.instructionParsedType(instruction.name);
1725
- return fragment(
1726
- `| { instructionType: ${programInstructionsEnum}.${instructionEnumVariant} } & ${parsedInstructionType}<TProgram>`
1727
- ).addImports("generatedInstructions", `type ${parsedInstructionType}`);
2167
+ const parsedInstructionType = use(
2168
+ `type ${nameApi.instructionParsedType(instruction.name)}`,
2169
+ "generatedInstructions"
2170
+ );
2171
+ return fragment`| { instructionType: ${programInstructionsEnum}.${instructionEnumVariant} } & ${parsedInstructionType}<TProgram>`;
1728
2172
  });
1729
2173
  return mergeFragments(
1730
2174
  [
1731
- fragment(`export type ${programInstructionsType}<TProgram extends string = '${programAddress}'> =`),
2175
+ fragment`export type ${programInstructionsType}<TProgram extends string = '${programAddress}'> =`,
1732
2176
  ...typeVariants
1733
2177
  ],
1734
- (r) => r.join("\n")
2178
+ (c) => c.join("\n")
2179
+ );
2180
+ }
2181
+
2182
+ // src/fragments/programPage.ts
2183
+ function getProgramPageFragment(scope) {
2184
+ return mergeFragments(
2185
+ [getProgramConstantFragment(scope), getProgramAccountsFragment(scope), getProgramInstructionsFragment(scope)],
2186
+ (cs) => cs.join("\n\n")
2187
+ );
2188
+ }
2189
+
2190
+ // src/fragments/rootIndexPage.ts
2191
+ function getRootIndexPageFragment(scope) {
2192
+ const hasAnythingToExport = scope.programsToExport.length > 0 || scope.accountsToExport.length > 0 || scope.instructionsToExport.length > 0 || scope.definedTypesToExport.length > 0;
2193
+ if (!hasAnythingToExport) {
2194
+ return fragment`export default {};`;
2195
+ }
2196
+ const programsWithErrorsToExport = scope.programsToExport.filter((p) => p.errors.length > 0);
2197
+ return mergeFragments(
2198
+ [
2199
+ scope.accountsToExport.length > 0 ? getExportAllFragment("./accounts") : void 0,
2200
+ programsWithErrorsToExport.length > 0 ? getExportAllFragment("./errors") : void 0,
2201
+ scope.instructionsToExport.length > 0 ? getExportAllFragment("./instructions") : void 0,
2202
+ scope.pdasToExport.length > 0 ? getExportAllFragment("./pdas") : void 0,
2203
+ scope.programsToExport.length > 0 ? getExportAllFragment("./programs") : void 0,
2204
+ scope.definedTypesToExport.length > 0 ? getExportAllFragment("./types") : void 0
2205
+ ],
2206
+ (cs) => cs.join("\n")
2207
+ );
2208
+ }
2209
+
2210
+ // src/fragments/sharedPage.ts
2211
+ import { pipe as pipe13 } from "@codama/visitors-core";
2212
+ function getSharedPageFragment() {
2213
+ const sharedPage = fragment`/**
2214
+ * Asserts that the given value is not null or undefined.
2215
+ * @internal
2216
+ */
2217
+ export function expectSome<T>(value: T | null | undefined): T {
2218
+ if (value === null || value === undefined) {
2219
+ throw new Error('Expected a value but received null or undefined.');
2220
+ }
2221
+ return value;
2222
+ }
2223
+
2224
+ /**
2225
+ * Asserts that the given value is a PublicKey.
2226
+ * @internal
2227
+ */
2228
+ export function expectAddress<T extends string = string>(
2229
+ value: Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null | undefined
2230
+ ): Address<T> {
2231
+ if (!value) {
2232
+ throw new Error('Expected a Address.');
2233
+ }
2234
+ if (typeof value === 'object' && "address" in value) {
2235
+ return value.address;
2236
+ }
2237
+ if (Array.isArray(value)) {
2238
+ return value[0] as Address<T>;
2239
+ }
2240
+ return value as Address<T>;
2241
+ }
2242
+
2243
+ /**
2244
+ * Asserts that the given value is a PDA.
2245
+ * @internal
2246
+ */
2247
+ export function expectProgramDerivedAddress<T extends string = string>(
2248
+ value: Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null | undefined
2249
+ ): ProgramDerivedAddress<T> {
2250
+ if (!value || !Array.isArray(value) || !isProgramDerivedAddress(value)) {
2251
+ throw new Error('Expected a ProgramDerivedAddress.');
2252
+ }
2253
+ return value;
2254
+ }
2255
+
2256
+ /**
2257
+ * Asserts that the given value is a TransactionSigner.
2258
+ * @internal
2259
+ */
2260
+ export function expectTransactionSigner<T extends string = string>(
2261
+ value: Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null | undefined
2262
+ ): TransactionSigner<T> {
2263
+ if (!value || !isTransactionSigner(value)) {
2264
+ throw new Error('Expected a TransactionSigner.');
2265
+ }
2266
+ return value;
2267
+ }
2268
+
2269
+ /**
2270
+ * Defines an instruction account to resolve.
2271
+ * @internal
2272
+ */
2273
+ export type ResolvedAccount<T extends string = string, U extends Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null = Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null> = {
2274
+ isWritable: boolean;
2275
+ value: U;
2276
+ };
2277
+
2278
+ /**
2279
+ * Defines an instruction that stores additional bytes on-chain.
2280
+ * @internal
2281
+ */
2282
+ export type InstructionWithByteDelta = {
2283
+ byteDelta: number;
2284
+ };
2285
+
2286
+ /**
2287
+ * Get account metas and signers from resolved accounts.
2288
+ * @internal
2289
+ */
2290
+ export function getAccountMetaFactory(
2291
+ programAddress: Address,
2292
+ optionalAccountStrategy: 'omitted' | 'programId',
2293
+ ) {
2294
+ return (account: ResolvedAccount): AccountMeta | AccountSignerMeta | undefined => {
2295
+ if (!account.value) {
2296
+ if (optionalAccountStrategy === 'omitted') return;
2297
+ return Object.freeze({ address: programAddress, role: AccountRole.READONLY });
2298
+ }
2299
+
2300
+ const writableRole = account.isWritable ? AccountRole.WRITABLE : AccountRole.READONLY;
2301
+ return Object.freeze({
2302
+ address: expectAddress(account.value),
2303
+ role: isTransactionSigner(account.value) ? upgradeRoleToSigner(writableRole) : writableRole,
2304
+ ...(isTransactionSigner(account.value) ? { signer: account.value } : {})
2305
+ });
2306
+ };
2307
+ }
2308
+
2309
+ export function isTransactionSigner<TAddress extends string = string>(value: Address<TAddress> | ProgramDerivedAddress<TAddress> | TransactionSigner<TAddress>): value is TransactionSigner<TAddress> {
2310
+ return !!value && typeof value === 'object' && 'address' in value && kitIsTransactionSigner(value);
2311
+ }`;
2312
+ return pipe13(
2313
+ sharedPage,
2314
+ (f) => addFragmentImports(f, "solanaAddresses", [
2315
+ "type Address",
2316
+ "isProgramDerivedAddress",
2317
+ "type ProgramDerivedAddress"
2318
+ ]),
2319
+ (f) => addFragmentImports(f, "solanaInstructions", ["AccountRole", "type AccountMeta", "upgradeRoleToSigner"]),
2320
+ (f) => addFragmentImports(f, "solanaSigners", [
2321
+ "type AccountSignerMeta",
2322
+ "isTransactionSigner as kitIsTransactionSigner",
2323
+ "type TransactionSigner"
2324
+ ])
1735
2325
  );
1736
2326
  }
1737
2327
 
@@ -1740,124 +2330,100 @@ import { isDataEnum as isDataEnum3, isNode as isNode14 } from "@codama/nodes";
1740
2330
  function getTypeDiscriminatedUnionHelpersFragment(scope) {
1741
2331
  const { name, typeNode, nameApi } = scope;
1742
2332
  const isDiscriminatedUnion = isNode14(typeNode, "enumTypeNode") && isDataEnum3(typeNode);
1743
- if (!isDiscriminatedUnion) {
1744
- return fragment("");
1745
- }
1746
- return fragmentFromTemplate("typeDiscriminatedUnionHelpers.njk", {
1747
- discriminatedUnionDiscriminator: nameApi.discriminatedUnionDiscriminator(name),
1748
- discriminatedUnionFunction: nameApi.discriminatedUnionFunction(name),
1749
- getVariant: (variant) => nameApi.discriminatedUnionVariant(variant),
1750
- isDiscriminatedUnionFunction: nameApi.isDiscriminatedUnionFunction(name),
1751
- looseName: nameApi.dataArgsType(name),
1752
- strictName: nameApi.dataType(name),
1753
- typeNode
1754
- }).addImports("solanaCodecsDataStructures", [
1755
- "type GetDiscriminatedUnionVariantContent",
1756
- "type GetDiscriminatedUnionVariant"
1757
- ]);
2333
+ if (!isDiscriminatedUnion) return;
2334
+ const functionName = nameApi.discriminatedUnionFunction(name);
2335
+ const isDiscriminatedUnionFunctionName = nameApi.isDiscriminatedUnionFunction(name);
2336
+ const discriminatorName = nameApi.discriminatedUnionDiscriminator(name);
2337
+ const strictName = nameApi.dataType(name);
2338
+ const looseName = nameApi.dataArgsType(name);
2339
+ const getVariantContentType = use("type GetDiscriminatedUnionVariantContent", "solanaCodecsDataStructures");
2340
+ const getVariantType = use("type GetDiscriminatedUnionVariant", "solanaCodecsDataStructures");
2341
+ const variantSignatures = mergeFragments(
2342
+ typeNode.variants.map((variant) => {
2343
+ const variantName = nameApi.discriminatedUnionVariant(variant.name);
2344
+ if (isNode14(variant, "enumStructVariantTypeNode")) {
2345
+ return fragment`export function ${functionName}(kind: '${variantName}', data: ${getVariantContentType}<${looseName}, '${discriminatorName}', '${variantName}'>): ${getVariantType}<${looseName}, '${discriminatorName}', '${variantName}'>;`;
2346
+ }
2347
+ if (isNode14(variant, "enumTupleVariantTypeNode")) {
2348
+ return fragment`export function ${functionName}(kind: '${variantName}', data: ${getVariantContentType}<${looseName}, '${discriminatorName}', '${variantName}'>['fields']): ${getVariantType}<${looseName}, '${discriminatorName}', '${variantName}'>;`;
2349
+ }
2350
+ return fragment`export function ${functionName}(kind: '${variantName}'): ${getVariantType}<${looseName}, '${discriminatorName}', '${variantName}'>;`;
2351
+ }),
2352
+ (cs) => cs.length > 0 ? `${cs.join("\n")}
2353
+ ` : ""
2354
+ );
2355
+ return fragment`// Data Enum Helpers.
2356
+ ${variantSignatures}export function ${functionName}<K extends ${looseName}['${discriminatorName}'], Data>(kind: K, data?: Data) {
2357
+ return Array.isArray(data) ? { ${discriminatorName}: kind, fields: data } : { ${discriminatorName}: kind, ...(data ?? {}) };
1758
2358
  }
1759
2359
 
1760
- // src/TypeManifest.ts
1761
- function typeManifest() {
1762
- return {
1763
- decoder: fragment(""),
1764
- encoder: fragment(""),
1765
- isEnum: false,
1766
- looseType: fragment(""),
1767
- strictType: fragment(""),
1768
- value: fragment("")
1769
- };
1770
- }
1771
- function mergeManifests(manifests, options = {}) {
1772
- const { mergeTypes, mergeCodecs, mergeValues } = options;
1773
- const merge = (fragmentFn, mergeFn) => mergeFn ? mergeFragments(manifests.map(fragmentFn), mergeFn) : fragment("");
1774
- return {
1775
- decoder: merge((m) => m.decoder, mergeCodecs),
1776
- encoder: merge((m) => m.encoder, mergeCodecs),
1777
- isEnum: false,
1778
- looseType: merge((m) => m.looseType, mergeTypes),
1779
- strictType: merge((m) => m.strictType, mergeTypes),
1780
- value: merge((m) => m.value, mergeValues)
1781
- };
2360
+ export function ${isDiscriminatedUnionFunctionName}<K extends ${strictName}['${discriminatorName}']>(kind: K, value: ${strictName}): value is ${strictName} & { ${discriminatorName}: K } {
2361
+ return value.${discriminatorName} === kind;
2362
+ };
2363
+ `;
1782
2364
  }
1783
2365
 
1784
- // src/getRenderMapVisitor.ts
1785
- import { join as join3 } from "path";
1786
- import { logWarn } from "@codama/errors";
1787
- import {
1788
- camelCase as camelCase12,
1789
- definedTypeNode as definedTypeNode2,
1790
- getAllAccounts,
1791
- getAllDefinedTypes,
1792
- getAllInstructionsWithSubs as getAllInstructionsWithSubs2,
1793
- getAllPdas,
1794
- getAllPrograms,
1795
- resolveNestedTypeNode as resolveNestedTypeNode4,
1796
- structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes5
1797
- } from "@codama/nodes";
1798
- import { RenderMap } from "@codama/renderers-core";
1799
- import {
1800
- extendVisitor as extendVisitor2,
1801
- findProgramNodeFromPath as findProgramNodeFromPath7,
1802
- getByteSizeVisitor,
1803
- getResolvedInstructionInputsVisitor,
1804
- LinkableDictionary as LinkableDictionary3,
1805
- NodeStack as NodeStack2,
1806
- pipe as pipe2,
1807
- recordLinkablesOnFirstVisitVisitor,
1808
- recordNodeStackVisitor as recordNodeStackVisitor2,
1809
- staticVisitor as staticVisitor2,
1810
- visit as visit6
1811
- } from "@codama/visitors-core";
2366
+ // src/fragments/typePage.ts
2367
+ import { pipe as pipe14, visit as visit7 } from "@codama/visitors-core";
2368
+ function getTypePageFragment(scope) {
2369
+ const node = scope.node;
2370
+ const manifest = visit7(node, scope.typeManifestVisitor);
2371
+ return pipe14(
2372
+ mergeFragments(
2373
+ [
2374
+ getTypeWithCodecFragment({ ...scope, manifest, name: node.name, node: node.type, typeDocs: node.docs }),
2375
+ getTypeDiscriminatedUnionHelpersFragment({ ...scope, name: node.name, typeNode: node.type })
2376
+ ],
2377
+ (cs) => cs.join("\n\n")
2378
+ ),
2379
+ (f) => removeFragmentImports(f, "generatedTypes", [
2380
+ scope.nameApi.dataType(node.name),
2381
+ scope.nameApi.dataArgsType(node.name),
2382
+ scope.nameApi.encoderFunction(node.name),
2383
+ scope.nameApi.decoderFunction(node.name),
2384
+ scope.nameApi.codecFunction(node.name)
2385
+ ])
2386
+ );
2387
+ }
1812
2388
 
1813
- // src/getTypeManifestVisitor.ts
2389
+ // src/visitors/getTypeManifestVisitor.ts
1814
2390
  import {
1815
- camelCase as camelCase10,
2391
+ camelCase as camelCase13,
1816
2392
  isNode as isNode15,
1817
2393
  isNodeFilter as isNodeFilter6,
1818
2394
  isScalarEnum,
1819
- parseDocs as parseDocs2,
1820
2395
  REGISTERED_TYPE_NODE_KINDS,
1821
2396
  REGISTERED_VALUE_NODE_KINDS,
1822
- resolveNestedTypeNode as resolveNestedTypeNode3,
2397
+ resolveNestedTypeNode as resolveNestedTypeNode4,
1823
2398
  structFieldTypeNode,
1824
2399
  structTypeNode,
1825
- structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes4
2400
+ structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes5
1826
2401
  } from "@codama/nodes";
2402
+ import { mapFragmentContent as mapFragmentContent11, setFragmentContent as setFragmentContent2 } from "@codama/renderers-core";
1827
2403
  import {
1828
2404
  extendVisitor,
1829
2405
  findLastNodeFromPath,
1830
2406
  NodeStack,
1831
- pipe,
2407
+ pipe as pipe15,
1832
2408
  recordNodeStackVisitor,
1833
2409
  staticVisitor,
1834
- visit as visit5
2410
+ visit as visit8
1835
2411
  } from "@codama/visitors-core";
1836
2412
  function getTypeManifestVisitor(input) {
1837
2413
  const { nameApi, linkables, nonScalarEnums, customAccountData, customInstructionData, getImportFrom } = input;
1838
2414
  const stack = input.stack ?? new NodeStack();
1839
2415
  let parentName = null;
1840
- return pipe(
1841
- staticVisitor(
1842
- () => ({
1843
- decoder: fragment(""),
1844
- encoder: fragment(""),
1845
- isEnum: false,
1846
- looseType: fragment(""),
1847
- strictType: fragment(""),
1848
- value: fragment("")
1849
- }),
1850
- {
1851
- keys: [
1852
- ...REGISTERED_TYPE_NODE_KINDS,
1853
- ...REGISTERED_VALUE_NODE_KINDS,
1854
- "definedTypeLinkNode",
1855
- "definedTypeNode",
1856
- "accountNode",
1857
- "instructionNode"
1858
- ]
1859
- }
1860
- ),
2416
+ return pipe15(
2417
+ staticVisitor(() => typeManifest(), {
2418
+ keys: [
2419
+ ...REGISTERED_TYPE_NODE_KINDS,
2420
+ ...REGISTERED_VALUE_NODE_KINDS,
2421
+ "definedTypeLinkNode",
2422
+ "definedTypeNode",
2423
+ "accountNode",
2424
+ "instructionNode"
2425
+ ]
2426
+ }),
1861
2427
  (visitor) => extendVisitor(visitor, {
1862
2428
  visitAccount(account, { self }) {
1863
2429
  parentName = {
@@ -1865,106 +2431,81 @@ function getTypeManifestVisitor(input) {
1865
2431
  strict: nameApi.dataType(account.name)
1866
2432
  };
1867
2433
  const link = customAccountData.get(account.name)?.linkNode;
1868
- const manifest = link ? visit5(link, self) : visit5(account.data, self);
2434
+ const manifest = link ? visit8(link, self) : visit8(account.data, self);
1869
2435
  parentName = null;
1870
2436
  return manifest;
1871
2437
  },
1872
2438
  visitAmountType(amountType, { self }) {
1873
- return visit5(amountType.number, self);
2439
+ return visit8(amountType.number, self);
1874
2440
  },
1875
2441
  visitArrayType(arrayType, { self }) {
1876
- const childManifest = visit5(arrayType.item, self);
1877
- childManifest.looseType.mapRender((r) => `Array<${r}>`);
1878
- childManifest.strictType.mapRender((r) => `Array<${r}>`);
2442
+ const childManifest = visit8(arrayType.item, self);
1879
2443
  const sizeManifest = getArrayLikeSizeOption(arrayType.count, self);
1880
- const encoderOptions = sizeManifest.encoder.render ? `, { ${sizeManifest.encoder.render} }` : "";
1881
- const decoderOptions = sizeManifest.decoder.render ? `, { ${sizeManifest.decoder.render} }` : "";
1882
- childManifest.encoder.mapRender((r) => `getArrayEncoder(${r + encoderOptions})`).mergeImportsWith(sizeManifest.encoder).addImports("solanaCodecsDataStructures", "getArrayEncoder");
1883
- childManifest.decoder.mapRender((r) => `getArrayDecoder(${r + decoderOptions})`).mergeImportsWith(sizeManifest.decoder).addImports("solanaCodecsDataStructures", "getArrayDecoder");
1884
- return childManifest;
2444
+ const encoderOptions = sizeManifest.encoder ? fragment`, { ${sizeManifest.encoder} }` : "";
2445
+ const decoderOptions = sizeManifest.decoder ? fragment`, { ${sizeManifest.decoder} }` : "";
2446
+ return typeManifest({
2447
+ ...childManifest,
2448
+ decoder: fragment`${use("getArrayDecoder", "solanaCodecsDataStructures")}(${childManifest.decoder}${decoderOptions})`,
2449
+ encoder: fragment`${use("getArrayEncoder", "solanaCodecsDataStructures")}(${childManifest.encoder}${encoderOptions})`,
2450
+ looseType: fragment`Array<${childManifest.looseType}>`,
2451
+ strictType: fragment`Array<${childManifest.strictType}>`
2452
+ });
1885
2453
  },
1886
2454
  visitArrayValue(node, { self }) {
1887
- return mergeManifests(
1888
- node.items.map((v) => visit5(v, self)),
2455
+ return mergeTypeManifests(
2456
+ node.items.map((v) => visit8(v, self)),
1889
2457
  { mergeValues: (renders) => `[${renders.join(", ")}]` }
1890
2458
  );
1891
2459
  },
1892
2460
  visitBooleanType(booleanType, { self }) {
1893
- const encoderImports = new ImportMap().add("solanaCodecsDataStructures", "getBooleanEncoder");
1894
- const decoderImports = new ImportMap().add("solanaCodecsDataStructures", "getBooleanDecoder");
1895
- let sizeEncoder = "";
1896
- let sizeDecoder = "";
1897
- const resolvedSize = resolveNestedTypeNode3(booleanType.size);
2461
+ let sizeEncoder = fragment``;
2462
+ let sizeDecoder = fragment``;
2463
+ const resolvedSize = resolveNestedTypeNode4(booleanType.size);
1898
2464
  if (resolvedSize.format !== "u8" || resolvedSize.endian !== "le") {
1899
- const size = visit5(booleanType.size, self);
1900
- encoderImports.mergeWith(size.encoder);
1901
- decoderImports.mergeWith(size.decoder);
1902
- sizeEncoder = `{ size: ${size.encoder.render} }`;
1903
- sizeDecoder = `{ size: ${size.decoder.render} }`;
2465
+ const size = visit8(booleanType.size, self);
2466
+ sizeEncoder = fragment`{ size: ${size.encoder} }`;
2467
+ sizeDecoder = fragment`{ size: ${size.decoder} }`;
1904
2468
  }
1905
- return {
1906
- decoder: fragment(`getBooleanDecoder(${sizeDecoder})`, decoderImports),
1907
- encoder: fragment(`getBooleanEncoder(${sizeEncoder})`, encoderImports),
1908
- isEnum: false,
1909
- looseType: fragment("boolean"),
1910
- strictType: fragment("boolean"),
1911
- value: fragment("")
1912
- };
2469
+ return typeManifest({
2470
+ decoder: fragment`${use("getBooleanDecoder", "solanaCodecsDataStructures")}(${sizeDecoder})`,
2471
+ encoder: fragment`${use("getBooleanEncoder", "solanaCodecsDataStructures")}(${sizeEncoder})`,
2472
+ looseType: fragment`boolean`,
2473
+ strictType: fragment`boolean`
2474
+ });
1913
2475
  },
1914
2476
  visitBooleanValue(node) {
1915
- const manifest = typeManifest();
1916
- manifest.value.setRender(JSON.stringify(node.boolean));
1917
- return manifest;
2477
+ return typeManifest({ value: fragment`${JSON.stringify(node.boolean)}` });
1918
2478
  },
1919
2479
  visitBytesType() {
1920
- return {
1921
- decoder: fragment(`getBytesDecoder()`).addImports(
1922
- "solanaCodecsDataStructures",
1923
- "getBytesDecoder"
1924
- ),
1925
- encoder: fragment(`getBytesEncoder()`).addImports(
1926
- "solanaCodecsDataStructures",
1927
- "getBytesEncoder"
1928
- ),
1929
- isEnum: false,
1930
- looseType: fragment("ReadonlyUint8Array").addImports(
1931
- "solanaCodecsCore",
1932
- "type ReadonlyUint8Array"
1933
- ),
1934
- strictType: fragment("ReadonlyUint8Array").addImports(
1935
- "solanaCodecsCore",
1936
- "type ReadonlyUint8Array"
1937
- ),
1938
- value: fragment("")
1939
- };
2480
+ const readonlyUint8Array = use("type ReadonlyUint8Array", "solanaCodecsCore");
2481
+ return typeManifest({
2482
+ decoder: fragment`${use("getBytesDecoder", "solanaCodecsDataStructures")}()`,
2483
+ encoder: fragment`${use("getBytesEncoder", "solanaCodecsDataStructures")}()`,
2484
+ looseType: readonlyUint8Array,
2485
+ strictType: readonlyUint8Array
2486
+ });
1940
2487
  },
1941
2488
  visitBytesValue(node) {
1942
- const manifest = typeManifest();
1943
2489
  const bytes = getBytesFromBytesValueNode(node);
1944
- manifest.value.setRender(`new Uint8Array([${Array.from(bytes).join(", ")}])`);
1945
- return manifest;
2490
+ return typeManifest({ value: fragment`new Uint8Array([${Array.from(bytes).join(", ")}])` });
1946
2491
  },
1947
2492
  visitConstantValue(node, { self }) {
1948
2493
  if (isNode15(node.type, "bytesTypeNode") && isNode15(node.value, "bytesValueNode")) {
1949
- return visit5(node.value, self);
2494
+ return visit8(node.value, self);
1950
2495
  }
1951
- return {
1952
- ...typeManifest(),
1953
- value: mergeFragments(
1954
- [visit5(node.type, self).encoder, visit5(node.value, self).value],
1955
- ([encoderFunction, value]) => `${encoderFunction}.encode(${value})`
1956
- )
1957
- };
2496
+ return typeManifest({
2497
+ value: fragment`${visit8(node.type, self).encoder}.encode(${visit8(node.value, self).value})`
2498
+ });
1958
2499
  },
1959
2500
  visitDateTimeType(dateTimeType, { self }) {
1960
- return visit5(dateTimeType.number, self);
2501
+ return visit8(dateTimeType.number, self);
1961
2502
  },
1962
2503
  visitDefinedType(definedType, { self }) {
1963
2504
  parentName = {
1964
2505
  loose: nameApi.dataArgsType(definedType.name),
1965
2506
  strict: nameApi.dataType(definedType.name)
1966
2507
  };
1967
- const manifest = visit5(definedType.type, self);
2508
+ const manifest = visit8(definedType.type, self);
1968
2509
  parentName = null;
1969
2510
  return manifest;
1970
2511
  },
@@ -1974,54 +2515,52 @@ function getTypeManifestVisitor(input) {
1974
2515
  const encoderFunction = nameApi.encoderFunction(node.name);
1975
2516
  const decoderFunction = nameApi.decoderFunction(node.name);
1976
2517
  const importFrom = getImportFrom(node);
1977
- return {
1978
- decoder: fragment(`${decoderFunction}()`).addImports(importFrom, decoderFunction),
1979
- encoder: fragment(`${encoderFunction}()`).addImports(importFrom, encoderFunction),
1980
- isEnum: false,
1981
- looseType: fragment(looseName).addImports(importFrom, `type ${looseName}`),
1982
- strictType: fragment(strictName).addImports(importFrom, `type ${strictName}`),
1983
- value: fragment("")
1984
- };
2518
+ return typeManifest({
2519
+ decoder: fragment`${use(decoderFunction, importFrom)}()`,
2520
+ encoder: fragment`${use(encoderFunction, importFrom)}()`,
2521
+ looseType: use(`type ${looseName}`, importFrom),
2522
+ strictType: use(`type ${strictName}`, importFrom)
2523
+ });
1985
2524
  },
1986
2525
  visitEnumEmptyVariantType(enumEmptyVariantType) {
1987
- const discriminator = nameApi.discriminatedUnionDiscriminator(camelCase10(parentName?.strict ?? ""));
2526
+ const discriminator = nameApi.discriminatedUnionDiscriminator(camelCase13(parentName?.strict ?? ""));
1988
2527
  const name = nameApi.discriminatedUnionVariant(enumEmptyVariantType.name);
1989
2528
  const kindAttribute = `${discriminator}: "${name}"`;
1990
- return {
1991
- decoder: fragment(`['${name}', getUnitDecoder()]`).addImports(
1992
- "solanaCodecsDataStructures",
1993
- "getUnitDecoder"
1994
- ),
1995
- encoder: fragment(`['${name}', getUnitEncoder()]`).addImports(
1996
- "solanaCodecsDataStructures",
1997
- "getUnitEncoder"
1998
- ),
1999
- isEnum: false,
2000
- looseType: fragment(`{ ${kindAttribute} }`),
2001
- strictType: fragment(`{ ${kindAttribute} }`),
2002
- value: fragment("")
2003
- };
2529
+ return typeManifest({
2530
+ decoder: fragment`['${name}', ${use("getUnitDecoder", "solanaCodecsDataStructures")}()]`,
2531
+ encoder: fragment`['${name}', ${use("getUnitEncoder", "solanaCodecsDataStructures")}()]`,
2532
+ looseType: fragment`{ ${kindAttribute} }`,
2533
+ strictType: fragment`{ ${kindAttribute} }`
2534
+ });
2004
2535
  },
2005
2536
  visitEnumStructVariantType(enumStructVariantType, { self }) {
2006
2537
  const currentParentName = parentName;
2007
2538
  const discriminator = nameApi.discriminatedUnionDiscriminator(
2008
- camelCase10(currentParentName?.strict ?? "")
2539
+ camelCase13(currentParentName?.strict ?? "")
2009
2540
  );
2010
2541
  const name = nameApi.discriminatedUnionVariant(enumStructVariantType.name);
2011
2542
  const kindAttribute = `${discriminator}: "${name}"`;
2012
2543
  parentName = null;
2013
- const structManifest = visit5(enumStructVariantType.struct, self);
2544
+ const structManifest = visit8(enumStructVariantType.struct, self);
2014
2545
  parentName = currentParentName;
2015
- structManifest.strictType.mapRender((r) => `{ ${kindAttribute},${r.slice(1, -1)}}`);
2016
- structManifest.looseType.mapRender((r) => `{ ${kindAttribute},${r.slice(1, -1)}}`);
2017
- structManifest.encoder.mapRender((r) => `['${name}', ${r}]`);
2018
- structManifest.decoder.mapRender((r) => `['${name}', ${r}]`);
2019
- return structManifest;
2546
+ return typeManifest({
2547
+ ...structManifest,
2548
+ decoder: fragment`['${name}', ${structManifest.decoder}]`,
2549
+ encoder: fragment`['${name}', ${structManifest.encoder}]`,
2550
+ looseType: pipe15(
2551
+ structManifest.looseType,
2552
+ (f) => mapFragmentContent11(f, (c) => `{ ${kindAttribute},${c.slice(1, -1)}}`)
2553
+ ),
2554
+ strictType: pipe15(
2555
+ structManifest.strictType,
2556
+ (f) => mapFragmentContent11(f, (c) => `{ ${kindAttribute},${c.slice(1, -1)}}`)
2557
+ )
2558
+ });
2020
2559
  },
2021
2560
  visitEnumTupleVariantType(enumTupleVariantType, { self }) {
2022
2561
  const currentParentName = parentName;
2023
2562
  const discriminator = nameApi.discriminatedUnionDiscriminator(
2024
- camelCase10(currentParentName?.strict ?? "")
2563
+ camelCase13(currentParentName?.strict ?? "")
2025
2564
  );
2026
2565
  const name = nameApi.discriminatedUnionVariant(enumTupleVariantType.name);
2027
2566
  const kindAttribute = `${discriminator}: "${name}"`;
@@ -2032,37 +2571,47 @@ function getTypeManifestVisitor(input) {
2032
2571
  })
2033
2572
  ]);
2034
2573
  parentName = null;
2035
- const structManifest = visit5(struct, self);
2574
+ const structManifest = visit8(struct, self);
2036
2575
  parentName = currentParentName;
2037
- structManifest.strictType.mapRender((r) => `{ ${kindAttribute},${r.slice(1, -1)}}`);
2038
- structManifest.looseType.mapRender((r) => `{ ${kindAttribute},${r.slice(1, -1)}}`);
2039
- structManifest.encoder.mapRender((r) => `['${name}', ${r}]`);
2040
- structManifest.decoder.mapRender((r) => `['${name}', ${r}]`);
2041
- return structManifest;
2576
+ return typeManifest({
2577
+ ...structManifest,
2578
+ decoder: fragment`['${name}', ${structManifest.decoder}]`,
2579
+ encoder: fragment`['${name}', ${structManifest.encoder}]`,
2580
+ looseType: pipe15(
2581
+ structManifest.looseType,
2582
+ (f) => mapFragmentContent11(f, (c) => `{ ${kindAttribute},${c.slice(1, -1)}}`)
2583
+ ),
2584
+ strictType: pipe15(
2585
+ structManifest.strictType,
2586
+ (f) => mapFragmentContent11(f, (c) => `{ ${kindAttribute},${c.slice(1, -1)}}`)
2587
+ )
2588
+ });
2042
2589
  },
2043
2590
  visitEnumType(enumType, { self }) {
2044
2591
  const currentParentName = parentName;
2045
- const encoderImports = new ImportMap();
2046
- const decoderImports = new ImportMap();
2047
2592
  const encoderOptions = [];
2048
2593
  const decoderOptions = [];
2049
- const enumSize = resolveNestedTypeNode3(enumType.size);
2594
+ const enumSize = resolveNestedTypeNode4(enumType.size);
2050
2595
  if (enumSize.format !== "u8" || enumSize.endian !== "le") {
2051
- const sizeManifest = visit5(enumType.size, self);
2052
- encoderImports.mergeWith(sizeManifest.encoder);
2053
- decoderImports.mergeWith(sizeManifest.decoder);
2054
- encoderOptions.push(`size: ${sizeManifest.encoder.render}`);
2055
- decoderOptions.push(`size: ${sizeManifest.decoder.render}`);
2596
+ const sizeManifest = visit8(enumType.size, self);
2597
+ encoderOptions.push(fragment`size: ${sizeManifest.encoder}`);
2598
+ decoderOptions.push(fragment`size: ${sizeManifest.decoder}`);
2056
2599
  }
2057
2600
  const discriminator = nameApi.discriminatedUnionDiscriminator(
2058
- camelCase10(currentParentName?.strict ?? "")
2601
+ camelCase13(currentParentName?.strict ?? "")
2059
2602
  );
2060
2603
  if (!isScalarEnum(enumType) && discriminator !== "__kind") {
2061
- encoderOptions.push(`discriminator: '${discriminator}'`);
2062
- decoderOptions.push(`discriminator: '${discriminator}'`);
2604
+ encoderOptions.push(fragment`discriminator: '${discriminator}'`);
2605
+ decoderOptions.push(fragment`discriminator: '${discriminator}'`);
2063
2606
  }
2064
- const encoderOptionsAsString = encoderOptions.length > 0 ? `, { ${encoderOptions.join(", ")} }` : "";
2065
- const decoderOptionsAsString = decoderOptions.length > 0 ? `, { ${decoderOptions.join(", ")} }` : "";
2607
+ const encoderOptionsFragment = mergeFragments(
2608
+ encoderOptions,
2609
+ (cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
2610
+ );
2611
+ const decoderOptionsFragment = mergeFragments(
2612
+ decoderOptions,
2613
+ (cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
2614
+ );
2066
2615
  if (isScalarEnum(enumType)) {
2067
2616
  if (currentParentName === null) {
2068
2617
  throw new Error(
@@ -2070,31 +2619,26 @@ function getTypeManifestVisitor(input) {
2070
2619
  );
2071
2620
  }
2072
2621
  const variantNames = enumType.variants.map(({ name }) => nameApi.enumVariant(name));
2073
- return {
2074
- decoder: fragment(
2075
- `getEnumDecoder(${currentParentName.strict + decoderOptionsAsString})`,
2076
- decoderImports.add("solanaCodecsDataStructures", "getEnumDecoder")
2077
- ),
2078
- encoder: fragment(
2079
- `getEnumEncoder(${currentParentName.strict + encoderOptionsAsString})`,
2080
- encoderImports.add("solanaCodecsDataStructures", "getEnumEncoder")
2081
- ),
2622
+ return typeManifest({
2623
+ decoder: fragment`${use("getEnumDecoder", "solanaCodecsDataStructures")}(${currentParentName.strict}${decoderOptionsFragment})`,
2624
+ encoder: fragment`${use("getEnumEncoder", "solanaCodecsDataStructures")}(${currentParentName.strict}${encoderOptionsFragment})`,
2082
2625
  isEnum: true,
2083
- looseType: fragment(`{ ${variantNames.join(", ")} }`),
2084
- strictType: fragment(`{ ${variantNames.join(", ")} }`),
2085
- value: fragment("")
2086
- };
2626
+ looseType: fragment`{ ${variantNames.join(", ")} }`,
2627
+ strictType: fragment`{ ${variantNames.join(", ")} }`
2628
+ });
2087
2629
  }
2088
- const mergedManifest = mergeManifests(
2089
- enumType.variants.map((variant) => visit5(variant, self)),
2630
+ const mergedManifest = mergeTypeManifests(
2631
+ enumType.variants.map((variant) => visit8(variant, self)),
2090
2632
  {
2091
2633
  mergeCodecs: (renders) => renders.join(", "),
2092
2634
  mergeTypes: (renders) => renders.join(" | ")
2093
2635
  }
2094
2636
  );
2095
- mergedManifest.encoder.mapRender((r) => `getDiscriminatedUnionEncoder([${r}]${encoderOptionsAsString})`).mergeImportsWith(encoderImports).addImports("solanaCodecsDataStructures", ["getDiscriminatedUnionEncoder"]);
2096
- mergedManifest.decoder.mapRender((r) => `getDiscriminatedUnionDecoder([${r}]${decoderOptionsAsString})`).mergeImportsWith(decoderImports).addImports("solanaCodecsDataStructures", ["getDiscriminatedUnionDecoder"]);
2097
- return mergedManifest;
2637
+ return typeManifest({
2638
+ ...mergedManifest,
2639
+ decoder: fragment`${use("getDiscriminatedUnionDecoder", "solanaCodecsDataStructures")}([${mergedManifest.decoder}]${decoderOptionsFragment})`,
2640
+ encoder: fragment`${use("getDiscriminatedUnionEncoder", "solanaCodecsDataStructures")}([${mergedManifest.encoder}]${encoderOptionsFragment})`
2641
+ });
2098
2642
  },
2099
2643
  visitEnumValue(node, { self }) {
2100
2644
  const manifest = typeManifest();
@@ -2105,40 +2649,76 @@ function getTypeManifestVisitor(input) {
2105
2649
  const isScalar = enumNode && isNode15(enumNode, "enumTypeNode") ? isScalarEnum(enumNode) : !nonScalarEnums.includes(node.enum.name);
2106
2650
  if (!node.value && isScalar) {
2107
2651
  const variantName2 = nameApi.enumVariant(node.variant);
2108
- manifest.value.setRender(`${enumName}.${variantName2}`).addImports(importFrom, enumName);
2109
- return manifest;
2652
+ return typeManifest({
2653
+ ...manifest,
2654
+ value: pipe15(
2655
+ manifest.value,
2656
+ (f) => setFragmentContent2(f, `${enumName}.${variantName2}`),
2657
+ (f) => addFragmentImports(f, importFrom, [enumName])
2658
+ )
2659
+ });
2110
2660
  }
2111
2661
  const variantName = nameApi.discriminatedUnionVariant(node.variant);
2112
2662
  if (!node.value) {
2113
- manifest.value.setRender(`${enumFunction}('${variantName}')`).addImports(importFrom, enumFunction);
2114
- return manifest;
2663
+ return typeManifest({
2664
+ ...manifest,
2665
+ value: pipe15(
2666
+ manifest.value,
2667
+ (f) => setFragmentContent2(f, `${enumFunction}('${variantName}')`),
2668
+ (f) => addFragmentImports(f, importFrom, [enumFunction])
2669
+ )
2670
+ });
2115
2671
  }
2116
- manifest.value = visit5(node.value, self).value.mapRender((r) => `${enumFunction}('${variantName}', ${r})`).addImports(importFrom, enumFunction);
2117
- return manifest;
2672
+ return typeManifest({
2673
+ ...manifest,
2674
+ value: pipe15(
2675
+ visit8(node.value, self).value,
2676
+ (f) => mapFragmentContent11(f, (c) => `${enumFunction}('${variantName}', ${c})`),
2677
+ (f) => addFragmentImports(f, importFrom, [enumFunction])
2678
+ )
2679
+ });
2118
2680
  },
2119
2681
  visitFixedSizeType(node, { self }) {
2120
- const manifest = visit5(node.type, self);
2121
- manifest.encoder.mapRender((r) => `fixEncoderSize(${r}, ${node.size})`).addImports("solanaCodecsCore", "fixEncoderSize");
2122
- manifest.decoder.mapRender((r) => `fixDecoderSize(${r}, ${node.size})`).addImports("solanaCodecsCore", "fixDecoderSize");
2123
- return manifest;
2682
+ const manifest = visit8(node.type, self);
2683
+ return typeManifest({
2684
+ ...manifest,
2685
+ decoder: fragment`${use("fixDecoderSize", "solanaCodecsCore")}(${manifest.decoder}, ${node.size})`,
2686
+ encoder: fragment`${use("fixEncoderSize", "solanaCodecsCore")}(${manifest.encoder}, ${node.size})`
2687
+ });
2124
2688
  },
2125
2689
  visitHiddenPrefixType(node, { self }) {
2126
- const manifest = visit5(node.type, self);
2127
- const prefixes = node.prefix.map((c) => visit5(c, self).value);
2128
- const prefixEncoders = fragment(prefixes.map((c) => `getConstantEncoder(${c.render})`).join(", ")).addImports("solanaCodecsCore", "getConstantEncoder").mergeImportsWith(...prefixes);
2129
- const prefixDecoders = fragment(prefixes.map((c) => `getConstantDecoder(${c.render})`).join(", ")).addImports("solanaCodecsCore", "getConstantDecoder").mergeImportsWith(...prefixes);
2130
- manifest.encoder.mapRender((r) => `getHiddenPrefixEncoder(${r}, [${prefixEncoders.render}])`).mergeImportsWith(prefixEncoders).addImports("solanaCodecsDataStructures", "getHiddenPrefixEncoder");
2131
- manifest.decoder.mapRender((r) => `getHiddenPrefixDecoder(${r}, [${prefixDecoders.render}])`).mergeImportsWith(prefixDecoders).addImports("solanaCodecsDataStructures", "getHiddenPrefixDecoder");
2132
- return manifest;
2690
+ const manifest = visit8(node.type, self);
2691
+ const prefixes = node.prefix.map((c) => visit8(c, self).value);
2692
+ const prefixEncoders = pipe15(
2693
+ mergeFragments(prefixes, (cs) => cs.map((c) => `getConstantEncoder(${c})`).join(", ")),
2694
+ (f) => addFragmentImports(f, "solanaCodecsCore", ["getConstantEncoder"])
2695
+ );
2696
+ const prefixDecoders = pipe15(
2697
+ mergeFragments(prefixes, (cs) => cs.map((c) => `getConstantDecoder(${c})`).join(", ")),
2698
+ (f) => addFragmentImports(f, "solanaCodecsCore", ["getConstantDecoder"])
2699
+ );
2700
+ return typeManifest({
2701
+ ...manifest,
2702
+ decoder: fragment`${use("getHiddenPrefixDecoder", "solanaCodecsDataStructures")}(${manifest.decoder}, [${prefixDecoders}])`,
2703
+ encoder: fragment`${use("getHiddenPrefixEncoder", "solanaCodecsDataStructures")}(${manifest.encoder}, [${prefixEncoders}])`
2704
+ });
2133
2705
  },
2134
2706
  visitHiddenSuffixType(node, { self }) {
2135
- const manifest = visit5(node.type, self);
2136
- const suffixes = node.suffix.map((c) => visit5(c, self).value);
2137
- const suffixEncoders = fragment(suffixes.map((c) => `getConstantEncoder(${c.render})`).join(", ")).addImports("solanaCodecsCore", "getConstantEncoder").mergeImportsWith(...suffixes);
2138
- const suffixDecoders = fragment(suffixes.map((c) => `getConstantDecoder(${c.render})`).join(", ")).addImports("solanaCodecsCore", "getConstantDecoder").mergeImportsWith(...suffixes);
2139
- manifest.encoder.mapRender((r) => `getHiddenSuffixEncoder(${r}, [${suffixEncoders.render}])`).mergeImportsWith(suffixEncoders).addImports("solanaCodecsDataStructures", "getHiddenSuffixEncoder");
2140
- manifest.decoder.mapRender((r) => `getHiddenSuffixDecoder(${r}, [${suffixDecoders.render}])`).mergeImportsWith(suffixDecoders).addImports("solanaCodecsDataStructures", "getHiddenSuffixDecoder");
2141
- return manifest;
2707
+ const manifest = visit8(node.type, self);
2708
+ const suffixes = node.suffix.map((c) => visit8(c, self).value);
2709
+ const suffixEncoders = pipe15(
2710
+ mergeFragments(suffixes, (cs) => cs.map((c) => `getConstantEncoder(${c})`).join(", ")),
2711
+ (f) => addFragmentImports(f, "solanaCodecsCore", ["getConstantEncoder"])
2712
+ );
2713
+ const suffixDecoders = pipe15(
2714
+ mergeFragments(suffixes, (cs) => cs.map((c) => `getConstantDecoder(${c})`).join(", ")),
2715
+ (f) => addFragmentImports(f, "solanaCodecsCore", ["getConstantDecoder"])
2716
+ );
2717
+ return typeManifest({
2718
+ ...manifest,
2719
+ decoder: fragment`${use("getHiddenSuffixDecoder", "solanaCodecsDataStructures")}(${manifest.decoder}, [${suffixDecoders}])`,
2720
+ encoder: fragment`${use("getHiddenSuffixEncoder", "solanaCodecsDataStructures")}(${manifest.encoder}, [${suffixEncoders}])`
2721
+ });
2142
2722
  },
2143
2723
  visitInstruction(instruction, { self }) {
2144
2724
  const instructionDataName = nameApi.instructionDataType(instruction.name);
@@ -2147,97 +2727,96 @@ function getTypeManifestVisitor(input) {
2147
2727
  strict: nameApi.dataType(instructionDataName)
2148
2728
  };
2149
2729
  const link = customInstructionData.get(instruction.name)?.linkNode;
2150
- const struct = structTypeNodeFromInstructionArgumentNodes4(instruction.arguments);
2151
- const manifest = link ? visit5(link, self) : visit5(struct, self);
2730
+ const struct = structTypeNodeFromInstructionArgumentNodes5(instruction.arguments);
2731
+ const manifest = link ? visit8(link, self) : visit8(struct, self);
2152
2732
  parentName = null;
2153
2733
  return manifest;
2154
2734
  },
2155
2735
  visitMapEntryValue(node, { self }) {
2156
- return mergeManifests([visit5(node.key, self), visit5(node.value, self)], {
2736
+ return mergeTypeManifests([visit8(node.key, self), visit8(node.value, self)], {
2157
2737
  mergeValues: (renders) => `[${renders.join(", ")}]`
2158
2738
  });
2159
2739
  },
2160
2740
  visitMapType(mapType, { self }) {
2161
- const key = visit5(mapType.key, self);
2162
- const value = visit5(mapType.value, self);
2163
- const mergedManifest = mergeManifests([key, value], {
2741
+ const key = visit8(mapType.key, self);
2742
+ const value = visit8(mapType.value, self);
2743
+ const mergedManifest = mergeTypeManifests([key, value], {
2164
2744
  mergeCodecs: ([k, v]) => `${k}, ${v}`,
2165
2745
  mergeTypes: ([k, v]) => `Map<${k}, ${v}>`
2166
2746
  });
2167
2747
  const sizeManifest = getArrayLikeSizeOption(mapType.count, self);
2168
- const encoderOptions = sizeManifest.encoder.render ? `, { ${sizeManifest.encoder.render} }` : "";
2169
- const decoderOptions = sizeManifest.decoder.render ? `, { ${sizeManifest.decoder.render} }` : "";
2170
- mergedManifest.encoder.mapRender((r) => `getMapEncoder(${r}${encoderOptions})`).addImports("solanaCodecsDataStructures", "getMapEncoder");
2171
- mergedManifest.decoder.mapRender((r) => `getMapDecoder(${r}${decoderOptions})`).addImports("solanaCodecsDataStructures", "getMapDecoder");
2172
- return mergedManifest;
2748
+ const encoderOptions = sizeManifest.encoder ? fragment`, { ${sizeManifest.encoder} }` : "";
2749
+ const decoderOptions = sizeManifest.decoder ? fragment`, { ${sizeManifest.decoder} }` : "";
2750
+ return typeManifest({
2751
+ ...mergedManifest,
2752
+ decoder: fragment`${use("getMapDecoder", "solanaCodecsDataStructures")}(${mergedManifest.decoder}${decoderOptions})`,
2753
+ encoder: fragment`${use("getMapEncoder", "solanaCodecsDataStructures")}(${mergedManifest.encoder}${encoderOptions})`
2754
+ });
2173
2755
  },
2174
2756
  visitMapValue(node, { self }) {
2175
- const entryFragments = node.entries.map((entry) => visit5(entry, self));
2176
- return mergeManifests(entryFragments, {
2757
+ const entryFragments = node.entries.map((entry) => visit8(entry, self));
2758
+ return mergeTypeManifests(entryFragments, {
2177
2759
  mergeValues: (renders) => `new Map([${renders.join(", ")}])`
2178
2760
  });
2179
2761
  },
2180
2762
  visitNoneValue() {
2181
- const manifest = typeManifest();
2182
- manifest.value.setRender("none()").addImports("solanaOptions", "none");
2183
- return manifest;
2763
+ return typeManifest({
2764
+ value: fragment`${use("none", "solanaOptions")}()`
2765
+ });
2184
2766
  },
2185
2767
  visitNumberType(numberType) {
2186
- const encoderFunction = nameApi.encoderFunction(numberType.format);
2187
- const decoderFunction = nameApi.decoderFunction(numberType.format);
2768
+ const encoderFunction = use(nameApi.encoderFunction(numberType.format), "solanaCodecsNumbers");
2769
+ const decoderFunction = use(nameApi.decoderFunction(numberType.format), "solanaCodecsNumbers");
2188
2770
  const isBigNumber = ["u64", "u128", "i64", "i128"].includes(numberType.format);
2189
- const encoderImports = new ImportMap().add("solanaCodecsNumbers", encoderFunction);
2190
- const decoderImports = new ImportMap().add("solanaCodecsNumbers", decoderFunction);
2191
- let endianness = "";
2192
- if (numberType.endian === "be") {
2193
- encoderImports.add("solanaCodecsNumbers", "Endian");
2194
- decoderImports.add("solanaCodecsNumbers", "Endian");
2195
- endianness = "{ endian: Endian.Big }";
2196
- }
2197
- return {
2198
- decoder: fragment(`${decoderFunction}(${endianness})`, decoderImports),
2199
- encoder: fragment(`${encoderFunction}(${endianness})`, encoderImports),
2200
- isEnum: false,
2201
- looseType: fragment(isBigNumber ? "number | bigint" : "number"),
2202
- strictType: fragment(isBigNumber ? "bigint" : "number"),
2203
- value: fragment("")
2204
- };
2771
+ const endianness = numberType.endian === "be" ? fragment`{ endian: ${use("Endian", "solanaCodecsNumbers")}.Big }` : "";
2772
+ return typeManifest({
2773
+ decoder: fragment`${decoderFunction}(${endianness})`,
2774
+ encoder: fragment`${encoderFunction}(${endianness})`,
2775
+ looseType: fragment`${isBigNumber ? "number | bigint" : "number"}`,
2776
+ strictType: fragment`${isBigNumber ? "bigint" : "number"}`
2777
+ });
2205
2778
  },
2206
2779
  visitNumberValue(node) {
2207
- const manifest = typeManifest();
2208
- manifest.value.setRender(JSON.stringify(node.number));
2209
- return manifest;
2780
+ return typeManifest({ value: fragment`${JSON.stringify(node.number)}` });
2210
2781
  },
2211
2782
  visitOptionType(optionType, { self }) {
2212
- const childManifest = visit5(optionType.item, self);
2213
- childManifest.strictType.mapRender((r) => `Option<${r}>`).addImports("solanaOptions", "type Option");
2214
- childManifest.looseType.mapRender((r) => `OptionOrNullable<${r}>`).addImports("solanaOptions", "type OptionOrNullable");
2783
+ const childManifest = visit8(optionType.item, self);
2215
2784
  const encoderOptions = [];
2216
2785
  const decoderOptions = [];
2217
- const optionPrefix = resolveNestedTypeNode3(optionType.prefix);
2786
+ const optionPrefix = resolveNestedTypeNode4(optionType.prefix);
2218
2787
  if (optionPrefix.format !== "u8" || optionPrefix.endian !== "le") {
2219
- const prefixManifest = visit5(optionType.prefix, self);
2220
- childManifest.encoder.mergeImportsWith(prefixManifest.encoder);
2221
- childManifest.decoder.mergeImportsWith(prefixManifest.decoder);
2222
- encoderOptions.push(`prefix: ${prefixManifest.encoder.render}`);
2223
- decoderOptions.push(`prefix: ${prefixManifest.decoder.render}`);
2788
+ const prefixManifest = visit8(optionType.prefix, self);
2789
+ encoderOptions.push(fragment`prefix: ${prefixManifest.encoder}`);
2790
+ decoderOptions.push(fragment`prefix: ${prefixManifest.decoder}`);
2224
2791
  }
2225
2792
  if (optionType.fixed) {
2226
- encoderOptions.push(`noneValue: "zeroes"`);
2227
- decoderOptions.push(`noneValue: "zeroes"`);
2793
+ encoderOptions.push(fragment`noneValue: "zeroes"`);
2794
+ decoderOptions.push(fragment`noneValue: "zeroes"`);
2228
2795
  }
2229
- const encoderOptionsAsString = encoderOptions.length > 0 ? `, { ${encoderOptions.join(", ")} }` : "";
2230
- const decoderOptionsAsString = decoderOptions.length > 0 ? `, { ${decoderOptions.join(", ")} }` : "";
2231
- childManifest.encoder.mapRender((r) => `getOptionEncoder(${r + encoderOptionsAsString})`).addImports("solanaOptions", "getOptionEncoder");
2232
- childManifest.decoder.mapRender((r) => `getOptionDecoder(${r + decoderOptionsAsString})`).addImports("solanaOptions", "getOptionDecoder");
2233
- return childManifest;
2796
+ const encoderOptionsFragment = mergeFragments(
2797
+ encoderOptions,
2798
+ (cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
2799
+ );
2800
+ const decoderOptionsFragment = mergeFragments(
2801
+ decoderOptions,
2802
+ (cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
2803
+ );
2804
+ return typeManifest({
2805
+ ...childManifest,
2806
+ decoder: fragment`${use("getOptionDecoder", "solanaOptions")}(${childManifest.decoder}${decoderOptionsFragment})`,
2807
+ encoder: fragment`${use("getOptionEncoder", "solanaOptions")}(${childManifest.encoder}${encoderOptionsFragment})`,
2808
+ looseType: fragment`${use("type OptionOrNullable", "solanaOptions")}<${childManifest.looseType}>`,
2809
+ strictType: fragment`${use("type Option", "solanaOptions")}<${childManifest.strictType}>`
2810
+ });
2234
2811
  },
2235
2812
  visitPostOffsetType(node, { self }) {
2236
- const manifest = visit5(node.type, self);
2813
+ const manifest = visit8(node.type, self);
2237
2814
  if (node.strategy === "padded") {
2238
- manifest.encoder.mapRender((r) => `padRightEncoder(${r}, ${node.offset})`).addImports("solanaCodecsCore", "padRightEncoder");
2239
- manifest.decoder.mapRender((r) => `padRightDecoder(${r}, ${node.offset})`).addImports("solanaCodecsCore", "padRightDecoder");
2240
- return manifest;
2815
+ return typeManifest({
2816
+ ...manifest,
2817
+ decoder: fragment`${use("padRightDecoder", "solanaCodecsCore")}(${manifest.decoder}, ${node.offset})`,
2818
+ encoder: fragment`${use("padRightEncoder", "solanaCodecsCore")}(${manifest.encoder}, ${node.offset})`
2819
+ });
2241
2820
  }
2242
2821
  const fn = (() => {
2243
2822
  switch (node.strategy) {
@@ -2250,16 +2829,20 @@ function getTypeManifestVisitor(input) {
2250
2829
  return node.offset < 0 ? `({ postOffset }) => postOffset ${node.offset}` : `({ postOffset }) => postOffset + ${node.offset}`;
2251
2830
  }
2252
2831
  })();
2253
- manifest.encoder.mapRender((r) => `offsetEncoder(${r}, { postOffset: ${fn} })`).addImports("solanaCodecsCore", "offsetEncoder");
2254
- manifest.decoder.mapRender((r) => `offsetDecoder(${r}, { postOffset: ${fn} })`).addImports("solanaCodecsCore", "offsetDecoder");
2255
- return manifest;
2832
+ return typeManifest({
2833
+ ...manifest,
2834
+ decoder: fragment`${use("offsetDecoder", "solanaCodecsCore")}(${manifest.decoder}, { postOffset: ${fn} })`,
2835
+ encoder: fragment`${use("offsetEncoder", "solanaCodecsCore")}(${manifest.encoder}, { postOffset: ${fn} })`
2836
+ });
2256
2837
  },
2257
2838
  visitPreOffsetType(node, { self }) {
2258
- const manifest = visit5(node.type, self);
2839
+ const manifest = visit8(node.type, self);
2259
2840
  if (node.strategy === "padded") {
2260
- manifest.encoder.mapRender((r) => `padLeftEncoder(${r}, ${node.offset})`).addImports("solanaCodecsCore", "padLeftEncoder");
2261
- manifest.decoder.mapRender((r) => `padLeftDecoder(${r}, ${node.offset})`).addImports("solanaCodecsCore", "padLeftDecoder");
2262
- return manifest;
2841
+ return typeManifest({
2842
+ ...manifest,
2843
+ decoder: fragment`${use("padLeftDecoder", "solanaCodecsCore")}(${manifest.decoder}, ${node.offset})`,
2844
+ encoder: fragment`${use("padLeftEncoder", "solanaCodecsCore")}(${manifest.encoder}, ${node.offset})`
2845
+ });
2263
2846
  }
2264
2847
  const fn = (() => {
2265
2848
  switch (node.strategy) {
@@ -2270,85 +2853,91 @@ function getTypeManifestVisitor(input) {
2270
2853
  return node.offset < 0 ? `({ preOffset }) => preOffset ${node.offset}` : `({ preOffset }) => preOffset + ${node.offset}`;
2271
2854
  }
2272
2855
  })();
2273
- manifest.encoder.mapRender((r) => `offsetEncoder(${r}, { preOffset: ${fn} })`).addImports("solanaCodecsCore", "offsetEncoder");
2274
- manifest.decoder.mapRender((r) => `offsetDecoder(${r}, { preOffset: ${fn} })`).addImports("solanaCodecsCore", "offsetDecoder");
2275
- return manifest;
2856
+ return typeManifest({
2857
+ ...manifest,
2858
+ decoder: fragment`${use("offsetDecoder", "solanaCodecsCore")}(${manifest.decoder}, { preOffset: ${fn} })`,
2859
+ encoder: fragment`${use("offsetEncoder", "solanaCodecsCore")}(${manifest.encoder}, { preOffset: ${fn} })`
2860
+ });
2276
2861
  },
2277
2862
  visitPublicKeyType() {
2278
- const imports = new ImportMap().add("solanaAddresses", "type Address");
2279
- return {
2280
- decoder: fragment("getAddressDecoder()").addImports("solanaAddresses", "getAddressDecoder"),
2281
- encoder: fragment("getAddressEncoder()").addImports("solanaAddresses", "getAddressEncoder"),
2282
- isEnum: false,
2283
- looseType: fragment("Address", imports),
2284
- strictType: fragment("Address", imports),
2285
- value: fragment("")
2286
- };
2863
+ return typeManifest({
2864
+ decoder: fragment`${use("getAddressDecoder", "solanaAddresses")}()`,
2865
+ encoder: fragment`${use("getAddressEncoder", "solanaAddresses")}()`,
2866
+ looseType: use("type Address", "solanaAddresses"),
2867
+ strictType: use("type Address", "solanaAddresses")
2868
+ });
2287
2869
  },
2288
2870
  visitPublicKeyValue(node) {
2289
- const manifest = typeManifest();
2290
- manifest.value.setRender(`address("${node.publicKey}")`).addImports("solanaAddresses", "address");
2291
- return manifest;
2871
+ return typeManifest({
2872
+ value: fragment`${use("address", "solanaAddresses")}("${node.publicKey}")`
2873
+ });
2292
2874
  },
2293
2875
  visitRemainderOptionType(node, { self }) {
2294
- const childManifest = visit5(node.item, self);
2295
- childManifest.strictType.mapRender((r) => `Option<${r}>`).addImports("solanaOptions", "type Option");
2296
- childManifest.looseType.mapRender((r) => `OptionOrNullable<${r}>`).addImports("solanaOptions", "type OptionOrNullable");
2876
+ const childManifest = visit8(node.item, self);
2297
2877
  const encoderOptions = ["prefix: null"];
2298
2878
  const decoderOptions = ["prefix: null"];
2299
2879
  const encoderOptionsAsString = encoderOptions.length > 0 ? `, { ${encoderOptions.join(", ")} }` : "";
2300
2880
  const decoderOptionsAsString = decoderOptions.length > 0 ? `, { ${decoderOptions.join(", ")} }` : "";
2301
- childManifest.encoder.mapRender((r) => `getOptionEncoder(${r + encoderOptionsAsString})`).addImports("solanaOptions", "getOptionEncoder");
2302
- childManifest.decoder.mapRender((r) => `getOptionDecoder(${r + decoderOptionsAsString})`).addImports("solanaOptions", "getOptionDecoder");
2303
- return childManifest;
2881
+ return typeManifest({
2882
+ ...childManifest,
2883
+ decoder: fragment`${use("getOptionDecoder", "solanaOptions")}(${childManifest.decoder}${decoderOptionsAsString})`,
2884
+ encoder: fragment`${use("getOptionEncoder", "solanaOptions")}(${childManifest.encoder}${encoderOptionsAsString})`,
2885
+ looseType: fragment`${use("type OptionOrNullable", "solanaOptions")}<${childManifest.looseType}>`,
2886
+ strictType: fragment`${use("type Option", "solanaOptions")}<${childManifest.strictType}>`
2887
+ });
2304
2888
  },
2305
2889
  visitSentinelType(node, { self }) {
2306
- const manifest = visit5(node.type, self);
2307
- const sentinel = visit5(node.sentinel, self).value;
2308
- manifest.encoder.mapRender((r) => `addEncoderSentinel(${r}, ${sentinel.render})`).mergeImportsWith(sentinel).addImports("solanaCodecsCore", "addEncoderSentinel");
2309
- manifest.decoder.mapRender((r) => `addDecoderSentinel(${r}, ${sentinel.render})`).mergeImportsWith(sentinel).addImports("solanaCodecsCore", "addDecoderSentinel");
2310
- return manifest;
2890
+ const manifest = visit8(node.type, self);
2891
+ const sentinel = visit8(node.sentinel, self).value;
2892
+ return typeManifest({
2893
+ ...manifest,
2894
+ decoder: fragment`${use("addDecoderSentinel", "solanaCodecsCore")}(${manifest.decoder}, ${sentinel})`,
2895
+ encoder: fragment`${use("addEncoderSentinel", "solanaCodecsCore")}(${manifest.encoder}, ${sentinel})`
2896
+ });
2311
2897
  },
2312
2898
  visitSetType(setType, { self }) {
2313
- const childManifest = visit5(setType.item, self);
2314
- childManifest.strictType.mapRender((r) => `Set<${r}>`);
2315
- childManifest.looseType.mapRender((r) => `Set<${r}>`);
2899
+ const childManifest = visit8(setType.item, self);
2316
2900
  const sizeManifest = getArrayLikeSizeOption(setType.count, self);
2317
- const encoderOptions = sizeManifest.encoder.render ? `, { ${sizeManifest.encoder.render} }` : "";
2318
- const decoderOptions = sizeManifest.decoder.render ? `, { ${sizeManifest.decoder.render} }` : "";
2319
- childManifest.encoder.mergeImportsWith(sizeManifest.encoder).mapRender((r) => `getSetEncoder(${r + encoderOptions})`).addImports("solanaCodecsDataStructures", "getSetEncoder");
2320
- childManifest.decoder.mergeImportsWith(sizeManifest.decoder).mapRender((r) => `getSetDecoder(${r + decoderOptions})`).addImports("solanaCodecsDataStructures", "getSetDecoder");
2321
- return childManifest;
2901
+ const encoderOptions = sizeManifest.encoder ? fragment`, { ${sizeManifest.encoder} }` : "";
2902
+ const decoderOptions = sizeManifest.decoder ? fragment`, { ${sizeManifest.decoder} }` : "";
2903
+ return typeManifest({
2904
+ ...childManifest,
2905
+ decoder: fragment`${use("getSetDecoder", "solanaCodecsDataStructures")}(${childManifest.decoder}${decoderOptions})`,
2906
+ encoder: fragment`${use("getSetEncoder", "solanaCodecsDataStructures")}(${childManifest.encoder}${encoderOptions})`,
2907
+ looseType: fragment`Set<${childManifest.looseType}>`,
2908
+ strictType: fragment`Set<${childManifest.strictType}>`
2909
+ });
2322
2910
  },
2323
2911
  visitSetValue(node, { self }) {
2324
- return mergeManifests(
2325
- node.items.map((v) => visit5(v, self)),
2912
+ return mergeTypeManifests(
2913
+ node.items.map((v) => visit8(v, self)),
2326
2914
  { mergeValues: (renders) => `new Set([${renders.join(", ")}])` }
2327
2915
  );
2328
2916
  },
2329
2917
  visitSizePrefixType(node, { self }) {
2330
- const manifest = visit5(node.type, self);
2331
- const prefix = visit5(node.prefix, self);
2332
- manifest.encoder.mapRender((r) => `addEncoderSizePrefix(${r}, ${prefix.encoder.render})`).mergeImportsWith(prefix.encoder).addImports("solanaCodecsCore", "addEncoderSizePrefix");
2333
- manifest.decoder.mapRender((r) => `addDecoderSizePrefix(${r}, ${prefix.decoder.render})`).mergeImportsWith(prefix.decoder).addImports("solanaCodecsCore", "addDecoderSizePrefix");
2334
- return manifest;
2918
+ const manifest = visit8(node.type, self);
2919
+ const prefix = visit8(node.prefix, self);
2920
+ return typeManifest({
2921
+ ...manifest,
2922
+ decoder: fragment`${use("addDecoderSizePrefix", "solanaCodecsCore")}(${manifest.decoder}, ${prefix.decoder})`,
2923
+ encoder: fragment`${use("addEncoderSizePrefix", "solanaCodecsCore")}(${manifest.encoder}, ${prefix.encoder})`
2924
+ });
2335
2925
  },
2336
2926
  visitSolAmountType({ number }, { self }) {
2337
- const numberManifest = visit5(number, self);
2338
- const lamportsType = "Lamports";
2339
- const lamportsImport = new ImportMap().add("solanaRpcTypes", "type Lamports");
2340
- return {
2927
+ const numberManifest = visit8(number, self);
2928
+ return typeManifest({
2341
2929
  ...numberManifest,
2342
- decoder: numberManifest.decoder.mapRender((r) => `getLamportsDecoder(${r})`).addImports("solanaRpcTypes", "getLamportsDecoder"),
2343
- encoder: numberManifest.encoder.mapRender((r) => `getLamportsEncoder(${r})`).addImports("solanaRpcTypes", "getLamportsEncoder"),
2344
- looseType: fragment(lamportsType, lamportsImport),
2345
- strictType: fragment(lamportsType, lamportsImport)
2346
- };
2930
+ decoder: fragment`${use("getLamportsDecoder", "solanaRpcTypes")}(${numberManifest.decoder})`,
2931
+ encoder: fragment`${use("getLamportsEncoder", "solanaRpcTypes")}(${numberManifest.encoder})`,
2932
+ looseType: use("type Lamports", "solanaRpcTypes"),
2933
+ strictType: use("type Lamports", "solanaRpcTypes")
2934
+ });
2347
2935
  },
2348
2936
  visitSomeValue(node, { self }) {
2349
- const manifest = typeManifest();
2350
- manifest.value = visit5(node.value, self).value.mapRender((r) => `some(${r})`).addImports("solanaOptions", "some");
2351
- return manifest;
2937
+ const innerValue = visit8(node.value, self).value;
2938
+ return typeManifest({
2939
+ value: fragment`${use("some", "solanaOptions")}(${innerValue})`
2940
+ });
2352
2941
  },
2353
2942
  visitStringType(stringType) {
2354
2943
  const [encoder, decoder] = (() => {
@@ -2365,57 +2954,63 @@ function getTypeManifestVisitor(input) {
2365
2954
  throw new Error(`Unsupported string encoding: ${stringType.encoding}`);
2366
2955
  }
2367
2956
  })();
2368
- return {
2369
- decoder: fragment(`${decoder}()`).addImports("solanaCodecsStrings", decoder),
2370
- encoder: fragment(`${encoder}()`).addImports("solanaCodecsStrings", encoder),
2371
- isEnum: false,
2372
- looseType: fragment("string"),
2373
- strictType: fragment("string"),
2374
- value: fragment("")
2375
- };
2957
+ return typeManifest({
2958
+ decoder: fragment`${use(decoder, "solanaCodecsStrings")}()`,
2959
+ encoder: fragment`${use(encoder, "solanaCodecsStrings")}()`,
2960
+ looseType: fragment`string`,
2961
+ strictType: fragment`string`
2962
+ });
2376
2963
  },
2377
2964
  visitStringValue(node) {
2378
- const manifest = typeManifest();
2379
- manifest.value.setRender(JSON.stringify(node.string));
2380
- return manifest;
2965
+ return typeManifest({
2966
+ value: fragment`${JSON.stringify(node.string)}`
2967
+ });
2381
2968
  },
2382
2969
  visitStructFieldType(structFieldType, { self }) {
2383
- const name = camelCase10(structFieldType.name);
2384
- const childManifest = visit5(structFieldType.type, self);
2385
- const structFieldDocs = parseDocs2(structFieldType.docs);
2386
- const docblock = structFieldDocs.length > 0 ? `
2387
- ${jsDocblock(structFieldDocs)}` : "";
2388
- const originalLooseType = childManifest.looseType.render;
2389
- childManifest.strictType.mapRender((r) => `${docblock}${name}: ${r}; `);
2390
- childManifest.looseType.mapRender((r) => `${docblock}${name}: ${r}; `);
2391
- childManifest.encoder.mapRender((r) => `['${name}', ${r}]`);
2392
- childManifest.decoder.mapRender((r) => `['${name}', ${r}]`);
2970
+ const name = camelCase13(structFieldType.name);
2971
+ const originalChildManifest = visit8(structFieldType.type, self);
2972
+ let docs = getDocblockFragment(structFieldType.docs ?? [], true);
2973
+ docs = docs ? fragment`\n${docs}` : docs;
2974
+ const childManifest = typeManifest({
2975
+ ...originalChildManifest,
2976
+ decoder: fragment`['${name}', ${originalChildManifest.decoder}]`,
2977
+ encoder: fragment`['${name}', ${originalChildManifest.encoder}]`,
2978
+ looseType: fragment`${docs}${name}: ${originalChildManifest.looseType}; `,
2979
+ strictType: fragment`${docs}${name}: ${originalChildManifest.strictType}; `
2980
+ });
2393
2981
  if (!structFieldType.defaultValue) {
2394
2982
  return childManifest;
2395
2983
  }
2396
2984
  if (structFieldType.defaultValueStrategy !== "omitted") {
2397
- childManifest.looseType.setRender(`${docblock}${name}?: ${originalLooseType}; `);
2398
- return childManifest;
2985
+ return typeManifest({
2986
+ ...childManifest,
2987
+ looseType: fragment`${docs}${name}?: ${originalChildManifest.looseType}; `
2988
+ });
2399
2989
  }
2400
- childManifest.looseType = fragment("");
2401
- return childManifest;
2990
+ return typeManifest({ ...childManifest, looseType: fragment`` });
2402
2991
  },
2403
2992
  visitStructFieldValue(node, { self }) {
2404
- const manifest = typeManifest();
2405
- manifest.value = visit5(node.value, self).value.mapRender((r) => `${node.name}: ${r}`);
2406
- return manifest;
2993
+ const innerValue = visit8(node.value, self).value;
2994
+ return typeManifest({
2995
+ value: fragment`${node.name}: ${innerValue}`
2996
+ });
2407
2997
  },
2408
2998
  visitStructType(structType, { self }) {
2409
2999
  const optionalFields = structType.fields.filter((f) => !!f.defaultValue);
2410
- const mergedManifest = mergeManifests(
2411
- structType.fields.map((field) => visit5(field, self)),
2412
- {
2413
- mergeCodecs: (renders) => `([${renders.join(", ")}])`,
2414
- mergeTypes: (renders) => `{ ${renders.join("")} }`
2415
- }
3000
+ const mergedManifest = pipe15(
3001
+ mergeTypeManifests(
3002
+ structType.fields.map((field) => visit8(field, self)),
3003
+ {
3004
+ mergeCodecs: (renders) => `([${renders.join(", ")}])`,
3005
+ mergeTypes: (renders) => `{ ${renders.join("")} }`
3006
+ }
3007
+ ),
3008
+ (manifest) => typeManifest({
3009
+ ...manifest,
3010
+ decoder: fragment`${use("getStructDecoder", "solanaCodecsDataStructures")}${manifest.decoder}`,
3011
+ encoder: fragment`${use("getStructEncoder", "solanaCodecsDataStructures")}${manifest.encoder}`
3012
+ })
2416
3013
  );
2417
- mergedManifest.encoder.mapRender((r) => `getStructEncoder${r}`).addImports("solanaCodecsDataStructures", "getStructEncoder");
2418
- mergedManifest.decoder.mapRender((r) => `getStructDecoder${r}`).addImports("solanaCodecsDataStructures", "getStructDecoder");
2419
3014
  if (optionalFields.length === 0) {
2420
3015
  return mergedManifest;
2421
3016
  }
@@ -2425,63 +3020,75 @@ ${jsDocblock(structFieldDocs)}` : "";
2425
3020
  const discriminatorPrefix = instructionNode ? instructionNode.name : accountNode?.name;
2426
3021
  const discriminators = (instructionNode ? instructionNode.discriminators : accountNode?.discriminators) ?? [];
2427
3022
  const fieldDiscriminators = discriminators.filter(isNodeFilter6("fieldDiscriminatorNode"));
2428
- const defaultValues = optionalFields.map((f) => {
2429
- const key = camelCase10(f.name);
2430
- if (fieldDiscriminators.some((d) => d.name === f.name)) {
2431
- const constantName = nameApi.constant(camelCase10(`${discriminatorPrefix}_${f.name}`));
2432
- return f.defaultValueStrategy === "omitted" ? `${key}: ${constantName}` : `${key}: value.${key} ?? ${constantName}`;
2433
- }
2434
- const defaultValue = f.defaultValue;
2435
- const { render: renderedValue, imports } = visit5(defaultValue, self).value;
2436
- mergedManifest.encoder.mergeImportsWith(imports);
2437
- return f.defaultValueStrategy === "omitted" ? `${key}: ${renderedValue}` : `${key}: value.${key} ?? ${renderedValue}`;
2438
- }).join(", ");
2439
- mergedManifest.encoder.mapRender((r) => `transformEncoder(${r}, (value) => ({ ...value, ${defaultValues} }))`).addImports("solanaCodecsCore", "transformEncoder");
2440
- return mergedManifest;
3023
+ const defaultValues = mergeFragments(
3024
+ optionalFields.map((f) => {
3025
+ const key = camelCase13(f.name);
3026
+ if (fieldDiscriminators.some((d) => d.name === f.name)) {
3027
+ const constantName = nameApi.constant(camelCase13(`${discriminatorPrefix}_${f.name}`));
3028
+ return f.defaultValueStrategy === "omitted" ? fragment`${key}: ${constantName}` : fragment`${key}: value.${key} ?? ${constantName}`;
3029
+ }
3030
+ const defaultValue = f.defaultValue;
3031
+ const value = visit8(defaultValue, self).value;
3032
+ return f.defaultValueStrategy === "omitted" ? fragment`${key}: ${value}` : fragment`${key}: value.${key} ?? ${value}`;
3033
+ }),
3034
+ (cs) => cs.join(", ")
3035
+ );
3036
+ return typeManifest({
3037
+ ...mergedManifest,
3038
+ encoder: fragment`${use("transformEncoder", "solanaCodecsCore")}(${mergedManifest.encoder}, (value) => ({ ...value, ${defaultValues} }))`
3039
+ });
2441
3040
  },
2442
3041
  visitStructValue(node, { self }) {
2443
- return mergeManifests(
2444
- node.fields.map((field) => visit5(field, self)),
3042
+ return mergeTypeManifests(
3043
+ node.fields.map((field) => visit8(field, self)),
2445
3044
  { mergeValues: (renders) => `{ ${renders.join(", ")} }` }
2446
3045
  );
2447
3046
  },
2448
3047
  visitTupleType(tupleType, { self }) {
2449
- const items = tupleType.items.map((item) => visit5(item, self));
2450
- const mergedManifest = mergeManifests(items, {
3048
+ const items = tupleType.items.map((item) => visit8(item, self));
3049
+ const mergedManifest = mergeTypeManifests(items, {
2451
3050
  mergeCodecs: (codecs) => `[${codecs.join(", ")}]`,
2452
3051
  mergeTypes: (types) => `readonly [${types.join(", ")}]`
2453
3052
  });
2454
- mergedManifest.encoder.mapRender((render2) => `getTupleEncoder(${render2})`).addImports("solanaCodecsDataStructures", "getTupleEncoder");
2455
- mergedManifest.decoder.mapRender((render2) => `getTupleDecoder(${render2})`).addImports("solanaCodecsDataStructures", "getTupleDecoder");
2456
- return mergedManifest;
3053
+ return typeManifest({
3054
+ ...mergedManifest,
3055
+ decoder: fragment`${use("getTupleDecoder", "solanaCodecsDataStructures")}(${mergedManifest.decoder})`,
3056
+ encoder: fragment`${use("getTupleEncoder", "solanaCodecsDataStructures")}(${mergedManifest.encoder})`
3057
+ });
2457
3058
  },
2458
3059
  visitTupleValue(node, { self }) {
2459
- return mergeManifests(
2460
- node.items.map((v) => visit5(v, self)),
3060
+ return mergeTypeManifests(
3061
+ node.items.map((v) => visit8(v, self)),
2461
3062
  { mergeValues: (renders) => `[${renders.join(", ")}]` }
2462
3063
  );
2463
3064
  },
2464
3065
  visitZeroableOptionType(node, { self }) {
2465
- const childManifest = visit5(node.item, self);
2466
- childManifest.strictType.mapRender((r) => `Option<${r}>`).addImports("solanaOptions", "type Option");
2467
- childManifest.looseType.mapRender((r) => `OptionOrNullable<${r}>`).addImports("solanaOptions", "type OptionOrNullable");
2468
- const encoderOptions = ["prefix: null"];
2469
- const decoderOptions = ["prefix: null"];
3066
+ const childManifest = visit8(node.item, self);
3067
+ const encoderOptions = [fragment`prefix: null`];
3068
+ const decoderOptions = [fragment`prefix: null`];
2470
3069
  if (node.zeroValue) {
2471
- const zeroValueManifest = visit5(node.zeroValue, self);
2472
- childManifest.encoder.mergeImportsWith(zeroValueManifest.value);
2473
- childManifest.decoder.mergeImportsWith(zeroValueManifest.value);
2474
- encoderOptions.push(`noneValue: ${zeroValueManifest.value.render}`);
2475
- decoderOptions.push(`noneValue: ${zeroValueManifest.value.render}`);
3070
+ const zeroValueManifest = visit8(node.zeroValue, self);
3071
+ encoderOptions.push(fragment`noneValue: ${zeroValueManifest.value}`);
3072
+ decoderOptions.push(fragment`noneValue: ${zeroValueManifest.value}`);
2476
3073
  } else {
2477
- encoderOptions.push(`noneValue: "zeroes"`);
2478
- decoderOptions.push(`noneValue: "zeroes"`);
3074
+ encoderOptions.push(fragment`noneValue: "zeroes"`);
3075
+ decoderOptions.push(fragment`noneValue: "zeroes"`);
2479
3076
  }
2480
- const encoderOptionsAsString = encoderOptions.length > 0 ? `, { ${encoderOptions.join(", ")} }` : "";
2481
- const decoderOptionsAsString = decoderOptions.length > 0 ? `, { ${decoderOptions.join(", ")} }` : "";
2482
- childManifest.encoder.mapRender((r) => `getOptionEncoder(${r + encoderOptionsAsString})`).addImports("solanaOptions", "getOptionEncoder");
2483
- childManifest.decoder.mapRender((r) => `getOptionDecoder(${r + decoderOptionsAsString})`).addImports("solanaOptions", "getOptionDecoder");
2484
- return childManifest;
3077
+ const encoderOptionsFragment = mergeFragments(
3078
+ encoderOptions,
3079
+ (cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
3080
+ );
3081
+ const decoderOptionsFragment = mergeFragments(
3082
+ decoderOptions,
3083
+ (cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
3084
+ );
3085
+ return typeManifest({
3086
+ ...childManifest,
3087
+ decoder: fragment`${use("getOptionDecoder", "solanaOptions")}(${childManifest.decoder}${decoderOptionsFragment})`,
3088
+ encoder: fragment`${use("getOptionEncoder", "solanaOptions")}(${childManifest.encoder}${encoderOptionsFragment})`,
3089
+ looseType: fragment`${use("type OptionOrNullable", "solanaOptions")}<${childManifest.looseType}>`,
3090
+ strictType: fragment`${use("type Option", "solanaOptions")}<${childManifest.strictType}>`
3091
+ });
2485
3092
  }
2486
3093
  }),
2487
3094
  (visitor) => recordNodeStackVisitor(visitor, stack)
@@ -2490,290 +3097,99 @@ ${jsDocblock(structFieldDocs)}` : "";
2490
3097
  function getArrayLikeSizeOption(count, visitor) {
2491
3098
  if (isNode15(count, "fixedCountNode")) {
2492
3099
  return {
2493
- decoder: fragment(`size: ${count.value}`),
2494
- encoder: fragment(`size: ${count.value}`)
3100
+ decoder: fragment`size: ${count.value}`,
3101
+ encoder: fragment`size: ${count.value}`
2495
3102
  };
2496
3103
  }
2497
3104
  if (isNode15(count, "remainderCountNode")) {
2498
3105
  return {
2499
- decoder: fragment(`size: 'remainder'`),
2500
- encoder: fragment(`size: 'remainder'`)
3106
+ decoder: fragment`size: 'remainder'`,
3107
+ encoder: fragment`size: 'remainder'`
2501
3108
  };
2502
3109
  }
2503
- const prefix = resolveNestedTypeNode3(count.prefix);
3110
+ const prefix = resolveNestedTypeNode4(count.prefix);
2504
3111
  if (prefix.format === "u32" && prefix.endian === "le") {
2505
- return { decoder: fragment(""), encoder: fragment("") };
3112
+ return { decoder: void 0, encoder: void 0 };
2506
3113
  }
2507
- const prefixManifest = visit5(count.prefix, visitor);
2508
- prefixManifest.encoder.mapRender((r) => `size: ${r}`);
2509
- prefixManifest.decoder.mapRender((r) => `size: ${r}`);
2510
- return prefixManifest;
2511
- }
2512
-
2513
- // src/nameTransformers.ts
2514
- import { camelCase as camelCase11, capitalize, kebabCase as kebabCase2, pascalCase as pascalCase7, snakeCase as snakeCase2, titleCase as titleCase2 } from "@codama/nodes";
2515
- function getNameApi(transformers) {
2516
- const helpers = {
2517
- camelCase: camelCase11,
2518
- capitalize,
2519
- kebabCase: kebabCase2,
2520
- pascalCase: pascalCase7,
2521
- snakeCase: snakeCase2,
2522
- titleCase: titleCase2
3114
+ const prefixManifest = visit8(count.prefix, visitor);
3115
+ return {
3116
+ decoder: pipe15(prefixManifest.decoder, (f) => mapFragmentContent11(f, (c) => `size: ${c}`)),
3117
+ encoder: pipe15(prefixManifest.encoder, (f) => mapFragmentContent11(f, (c) => `size: ${c}`))
2523
3118
  };
2524
- return Object.fromEntries(
2525
- Object.entries(transformers).map(([key, transformer]) => [key, (name) => transformer(name, helpers)])
2526
- );
2527
3119
  }
2528
- var DEFAULT_NAME_TRANSFORMERS = {
2529
- accountDecodeFunction: (name) => `decode${pascalCase7(name)}`,
2530
- accountFetchAllFunction: (name) => `fetchAll${pascalCase7(name)}`,
2531
- accountFetchAllMaybeFunction: (name) => `fetchAllMaybe${pascalCase7(name)}`,
2532
- accountFetchFromSeedsFunction: (name) => `fetch${pascalCase7(name)}FromSeeds`,
2533
- accountFetchFunction: (name) => `fetch${pascalCase7(name)}`,
2534
- accountFetchMaybeFromSeedsFunction: (name) => `fetchMaybe${pascalCase7(name)}FromSeeds`,
2535
- accountFetchMaybeFunction: (name) => `fetchMaybe${pascalCase7(name)}`,
2536
- accountGetSizeFunction: (name) => `get${pascalCase7(name)}Size`,
2537
- codecFunction: (name) => `get${pascalCase7(name)}Codec`,
2538
- constant: (name) => snakeCase2(name).toUpperCase(),
2539
- constantFunction: (name) => `get${pascalCase7(name)}Bytes`,
2540
- dataArgsType: (name) => `${pascalCase7(name)}Args`,
2541
- dataType: (name) => `${pascalCase7(name)}`,
2542
- decoderFunction: (name) => `get${pascalCase7(name)}Decoder`,
2543
- discriminatedUnionDiscriminator: () => "__kind",
2544
- discriminatedUnionFunction: (name) => `${camelCase11(name)}`,
2545
- discriminatedUnionVariant: (name) => `${pascalCase7(name)}`,
2546
- encoderFunction: (name) => `get${pascalCase7(name)}Encoder`,
2547
- enumVariant: (name) => `${pascalCase7(name)}`,
2548
- instructionAsyncFunction: (name) => `get${pascalCase7(name)}InstructionAsync`,
2549
- instructionAsyncInputType: (name) => `${pascalCase7(name)}AsyncInput`,
2550
- instructionDataType: (name) => `${pascalCase7(name)}InstructionData`,
2551
- instructionExtraType: (name) => `${pascalCase7(name)}InstructionExtra`,
2552
- instructionParseFunction: (name) => `parse${pascalCase7(name)}Instruction`,
2553
- instructionParsedType: (name) => `Parsed${pascalCase7(name)}Instruction`,
2554
- instructionSyncFunction: (name) => `get${pascalCase7(name)}Instruction`,
2555
- instructionSyncInputType: (name) => `${pascalCase7(name)}Input`,
2556
- instructionType: (name) => `${pascalCase7(name)}Instruction`,
2557
- isDiscriminatedUnionFunction: (name) => `is${pascalCase7(name)}`,
2558
- pdaFindFunction: (name) => `find${pascalCase7(name)}Pda`,
2559
- pdaSeedsType: (name) => `${pascalCase7(name)}Seeds`,
2560
- programAccountsEnum: (name) => `${pascalCase7(name)}Account`,
2561
- programAccountsEnumVariant: (name) => `${pascalCase7(name)}`,
2562
- programAccountsIdentifierFunction: (name) => `identify${pascalCase7(name)}Account`,
2563
- programAddressConstant: (name) => `${snakeCase2(name).toUpperCase()}_PROGRAM_ADDRESS`,
2564
- programErrorConstant: (name) => snakeCase2(name).toUpperCase(),
2565
- programErrorConstantPrefix: (name) => `${snakeCase2(name).toUpperCase()}_ERROR__`,
2566
- programErrorMessagesMap: (name) => `${camelCase11(name)}ErrorMessages`,
2567
- programErrorUnion: (name) => `${pascalCase7(name)}Error`,
2568
- programGetErrorMessageFunction: (name) => `get${pascalCase7(name)}ErrorMessage`,
2569
- programInstructionsEnum: (name) => `${pascalCase7(name)}Instruction`,
2570
- programInstructionsEnumVariant: (name) => `${pascalCase7(name)}`,
2571
- programInstructionsIdentifierFunction: (name) => `identify${pascalCase7(name)}Instruction`,
2572
- programInstructionsParsedUnionType: (name) => `Parsed${pascalCase7(name)}Instruction`,
2573
- programIsErrorFunction: (name) => `is${pascalCase7(name)}Error`,
2574
- resolverFunction: (name) => `${camelCase11(name)}`
2575
- };
2576
3120
 
2577
- // src/getRenderMapVisitor.ts
3121
+ // src/visitors/getRenderMapVisitor.ts
2578
3122
  function getRenderMapVisitor(options = {}) {
2579
3123
  const linkables = new LinkableDictionary3();
2580
3124
  const stack = new NodeStack2();
2581
- const nameTransformers = {
2582
- ...DEFAULT_NAME_TRANSFORMERS,
2583
- ...options.nameTransformers
2584
- };
2585
- const nameApi = getNameApi(nameTransformers);
2586
- const renderParentInstructions = options.renderParentInstructions ?? false;
2587
- const dependencyMap = options.dependencyMap ?? {};
2588
- const useGranularImports = options.useGranularImports ?? false;
2589
- const asyncResolvers = (options.asyncResolvers ?? []).map(camelCase12);
2590
- const nonScalarEnums = (options.nonScalarEnums ?? []).map(camelCase12);
2591
- const internalNodes = (options.internalNodes ?? []).map(camelCase12);
2592
3125
  const customAccountData = parseCustomDataOptions(options.customAccountData ?? [], "AccountData");
2593
3126
  const customInstructionData = parseCustomDataOptions(options.customInstructionData ?? [], "InstructionData");
2594
- const getImportFrom = getImportFromFactory(options.linkOverrides ?? {}, customAccountData, customInstructionData);
2595
- const typeManifestVisitor = getTypeManifestVisitor({
3127
+ const renderScopeWithTypeManifestVisitor = {
3128
+ asyncResolvers: (options.asyncResolvers ?? []).map(camelCase14),
2596
3129
  customAccountData,
2597
3130
  customInstructionData,
2598
- getImportFrom,
3131
+ dependencyMap: options.dependencyMap ?? {},
3132
+ getImportFrom: getImportFromFactory(options.linkOverrides ?? {}, customAccountData, customInstructionData),
2599
3133
  linkables,
2600
- nameApi,
2601
- nonScalarEnums,
2602
- stack
2603
- });
3134
+ nameApi: getNameApi({ ...DEFAULT_NAME_TRANSFORMERS, ...options.nameTransformers }),
3135
+ nonScalarEnums: (options.nonScalarEnums ?? []).map(camelCase14),
3136
+ renderParentInstructions: options.renderParentInstructions ?? false,
3137
+ useGranularImports: options.useGranularImports ?? false
3138
+ };
3139
+ const typeManifestVisitor = getTypeManifestVisitor({ ...renderScopeWithTypeManifestVisitor, stack });
3140
+ const renderScope = { ...renderScopeWithTypeManifestVisitor, typeManifestVisitor };
3141
+ const internalNodes = (options.internalNodes ?? []).map(camelCase14);
2604
3142
  const resolvedInstructionInputVisitor = getResolvedInstructionInputsVisitor();
2605
3143
  const byteSizeVisitor = getByteSizeVisitor(linkables, { stack });
2606
- const globalScope = {
2607
- asyncResolvers,
2608
- customAccountData,
2609
- customInstructionData,
2610
- getImportFrom,
2611
- linkables,
2612
- nameApi,
2613
- nonScalarEnums,
2614
- renderParentInstructions,
2615
- typeManifestVisitor
2616
- };
2617
- const render2 = (template, context, renderOptions) => {
2618
- return render(join3("pages", template), context, renderOptions);
3144
+ const asPage = (fragment2, dependencyMap = {}) => {
3145
+ if (!fragment2) return void 0;
3146
+ return getPageFragment(fragment2, {
3147
+ ...renderScope,
3148
+ dependencyMap: { ...renderScope.dependencyMap, ...dependencyMap }
3149
+ });
2619
3150
  };
2620
- return pipe2(
2621
- staticVisitor2(() => new RenderMap(), {
3151
+ return pipe16(
3152
+ staticVisitor2(() => createRenderMap(), {
2622
3153
  keys: ["rootNode", "programNode", "pdaNode", "accountNode", "definedTypeNode", "instructionNode"]
2623
3154
  }),
2624
3155
  (v) => extendVisitor2(v, {
2625
3156
  visitAccount(node) {
2626
- const accountPath = stack.getPath("accountNode");
2627
- if (!findProgramNodeFromPath7(accountPath)) {
2628
- throw new Error("Account must be visited inside a program.");
2629
- }
2630
- const scope = {
2631
- ...globalScope,
2632
- accountPath,
2633
- size: visit6(node, byteSizeVisitor),
2634
- typeManifest: visit6(node, typeManifestVisitor)
2635
- };
2636
- const fields = resolveNestedTypeNode4(node.data).fields;
2637
- const accountDiscriminatorConstantsFragment = getDiscriminatorConstantsFragment({
2638
- ...scope,
2639
- discriminatorNodes: node.discriminators ?? [],
2640
- fields,
2641
- prefix: node.name
2642
- });
2643
- const accountTypeFragment = getAccountTypeFragment(scope);
2644
- const accountFetchHelpersFragment = getAccountFetchHelpersFragment(scope);
2645
- const accountSizeHelpersFragment = getAccountSizeHelpersFragment(scope);
2646
- const accountPdaHelpersFragment = getAccountPdaHelpersFragment(scope);
2647
- const imports = new ImportMap().mergeWith(
2648
- accountDiscriminatorConstantsFragment,
2649
- accountTypeFragment,
2650
- accountFetchHelpersFragment,
2651
- accountSizeHelpersFragment,
2652
- accountPdaHelpersFragment
2653
- );
2654
- return new RenderMap().add(
2655
- `accounts/${camelCase12(node.name)}.ts`,
2656
- render2("accountsPage.njk", {
2657
- accountDiscriminatorConstantsFragment,
2658
- accountFetchHelpersFragment,
2659
- accountPdaHelpersFragment,
2660
- accountSizeHelpersFragment,
2661
- accountTypeFragment,
2662
- imports: imports.toString(dependencyMap, useGranularImports)
2663
- })
3157
+ return createRenderMap(
3158
+ `accounts/${camelCase14(node.name)}.ts`,
3159
+ asPage(
3160
+ getAccountPageFragment({
3161
+ ...renderScope,
3162
+ accountPath: stack.getPath("accountNode"),
3163
+ size: visit9(node, byteSizeVisitor)
3164
+ })
3165
+ )
2664
3166
  );
2665
3167
  },
2666
3168
  visitDefinedType(node) {
2667
- const scope = {
2668
- ...globalScope,
2669
- codecDocs: [],
2670
- decoderDocs: [],
2671
- encoderDocs: [],
2672
- manifest: visit6(node, typeManifestVisitor),
2673
- name: node.name,
2674
- node: node.type,
2675
- size: visit6(node, byteSizeVisitor),
2676
- typeDocs: node.docs,
2677
- typeNode: node.type
2678
- };
2679
- const typeWithCodecFragment = getTypeWithCodecFragment(scope);
2680
- const typeDiscriminatedUnionHelpersFragment = getTypeDiscriminatedUnionHelpersFragment(scope);
2681
- const imports = new ImportMap().mergeWith(typeWithCodecFragment, typeDiscriminatedUnionHelpersFragment).remove("generatedTypes", [
2682
- nameApi.dataType(node.name),
2683
- nameApi.dataArgsType(node.name),
2684
- nameApi.encoderFunction(node.name),
2685
- nameApi.decoderFunction(node.name),
2686
- nameApi.codecFunction(node.name)
2687
- ]);
2688
- return new RenderMap().add(
2689
- `types/${camelCase12(node.name)}.ts`,
2690
- render2("definedTypesPage.njk", {
2691
- imports: imports.toString({
2692
- ...dependencyMap,
2693
- generatedTypes: "."
2694
- }),
2695
- typeDiscriminatedUnionHelpersFragment,
2696
- typeWithCodecFragment
3169
+ return createRenderMap(
3170
+ `types/${camelCase14(node.name)}.ts`,
3171
+ asPage(getTypePageFragment({ ...renderScope, node, size: visit9(node, byteSizeVisitor) }), {
3172
+ generatedTypes: "."
2697
3173
  })
2698
3174
  );
2699
3175
  },
2700
3176
  visitInstruction(node) {
2701
- const instructionPath = stack.getPath("instructionNode");
2702
- if (!findProgramNodeFromPath7(instructionPath)) {
2703
- throw new Error("Instruction must be visited inside a program.");
2704
- }
2705
- const instructionExtraName = nameApi.instructionExtraType(node.name);
2706
- const scope = {
2707
- ...globalScope,
2708
- dataArgsManifest: visit6(node, typeManifestVisitor),
2709
- extraArgsManifest: visit6(
2710
- definedTypeNode2({
2711
- name: instructionExtraName,
2712
- type: structTypeNodeFromInstructionArgumentNodes5(node.extraArguments ?? [])
2713
- }),
2714
- typeManifestVisitor
2715
- ),
2716
- instructionPath,
2717
- renamedArgs: getRenamedArgsMap(node),
2718
- resolvedInputs: visit6(node, resolvedInstructionInputVisitor),
2719
- size: visit6(node, byteSizeVisitor)
2720
- };
2721
- const instructionDiscriminatorConstantsFragment = getDiscriminatorConstantsFragment({
2722
- ...scope,
2723
- discriminatorNodes: node.discriminators ?? [],
2724
- fields: node.arguments,
2725
- prefix: node.name
2726
- });
2727
- const instructionTypeFragment = getInstructionTypeFragment(scope);
2728
- const instructionDataFragment = getInstructionDataFragment(scope);
2729
- const instructionExtraArgsFragment = getInstructionExtraArgsFragment(scope);
2730
- const instructionFunctionAsyncFragment = getInstructionFunctionFragment({
2731
- ...scope,
2732
- useAsync: true
2733
- });
2734
- const instructionFunctionSyncFragment = getInstructionFunctionFragment({
2735
- ...scope,
2736
- useAsync: false
2737
- });
2738
- const instructionParseFunctionFragment = getInstructionParseFunctionFragment(scope);
2739
- const imports = new ImportMap().mergeWith(
2740
- instructionDiscriminatorConstantsFragment,
2741
- instructionTypeFragment,
2742
- instructionDataFragment,
2743
- instructionExtraArgsFragment,
2744
- instructionFunctionAsyncFragment,
2745
- instructionFunctionSyncFragment,
2746
- instructionParseFunctionFragment
2747
- );
2748
- return new RenderMap().add(
2749
- `instructions/${camelCase12(node.name)}.ts`,
2750
- render2("instructionsPage.njk", {
2751
- imports: imports.toString(dependencyMap, useGranularImports),
2752
- instruction: node,
2753
- instructionDataFragment,
2754
- instructionDiscriminatorConstantsFragment,
2755
- instructionExtraArgsFragment,
2756
- instructionFunctionAsyncFragment,
2757
- instructionFunctionSyncFragment,
2758
- instructionParseFunctionFragment,
2759
- instructionTypeFragment
2760
- })
3177
+ return createRenderMap(
3178
+ `instructions/${camelCase14(node.name)}.ts`,
3179
+ asPage(
3180
+ getInstructionPageFragment({
3181
+ ...renderScope,
3182
+ instructionPath: stack.getPath("instructionNode"),
3183
+ resolvedInputs: visit9(node, resolvedInstructionInputVisitor),
3184
+ size: visit9(node, byteSizeVisitor)
3185
+ })
3186
+ )
2761
3187
  );
2762
3188
  },
2763
3189
  visitPda(node) {
2764
- const pdaPath = stack.getPath("pdaNode");
2765
- if (!findProgramNodeFromPath7(pdaPath)) {
2766
- throw new Error("Account must be visited inside a program.");
2767
- }
2768
- const scope = { ...globalScope, pdaPath };
2769
- const pdaFunctionFragment = getPdaFunctionFragment(scope);
2770
- const imports = new ImportMap().mergeWith(pdaFunctionFragment);
2771
- return new RenderMap().add(
2772
- `pdas/${camelCase12(node.name)}.ts`,
2773
- render2("pdasPage.njk", {
2774
- imports: imports.toString(dependencyMap, useGranularImports),
2775
- pdaFunctionFragment
2776
- })
3190
+ return createRenderMap(
3191
+ `pdas/${camelCase14(node.name)}.ts`,
3192
+ asPage(getPdaPageFragment({ ...renderScope, pdaPath: stack.getPath("pdaNode") }))
2777
3193
  );
2778
3194
  },
2779
3195
  visitProgram(node, { self }) {
@@ -2781,36 +3197,20 @@ function getRenderMapVisitor(options = {}) {
2781
3197
  ...getDefinedTypeNodesToExtract(node.accounts, customAccountData),
2782
3198
  ...getDefinedTypeNodesToExtract(node.instructions, customInstructionData)
2783
3199
  ];
2784
- const scope = { ...globalScope, programNode: node };
2785
- const renderMap = new RenderMap().mergeWith(...node.pdas.map((p) => visit6(p, self))).mergeWith(...node.accounts.map((a) => visit6(a, self))).mergeWith(...node.definedTypes.map((t) => visit6(t, self))).mergeWith(...customDataDefinedType.map((t) => visit6(t, self)));
2786
- if (node.errors.length > 0) {
2787
- const programErrorsFragment = getProgramErrorsFragment(scope);
2788
- renderMap.add(
2789
- `errors/${camelCase12(node.name)}.ts`,
2790
- render2("errorsPage.njk", {
2791
- imports: new ImportMap().mergeWith(programErrorsFragment).toString(dependencyMap, useGranularImports),
2792
- programErrorsFragment
2793
- })
2794
- );
2795
- }
2796
- const programFragment = getProgramFragment(scope);
2797
- const programAccountsFragment = getProgramAccountsFragment(scope);
2798
- const programInstructionsFragment = getProgramInstructionsFragment(scope);
2799
- renderMap.add(
2800
- `programs/${camelCase12(node.name)}.ts`,
2801
- render2("programsPage.njk", {
2802
- imports: new ImportMap().mergeWith(programFragment, programAccountsFragment, programInstructionsFragment).toString(dependencyMap, useGranularImports),
2803
- programAccountsFragment,
2804
- programFragment,
2805
- programInstructionsFragment
2806
- })
2807
- );
2808
- renderMap.mergeWith(
2809
- ...getAllInstructionsWithSubs2(node, {
2810
- leavesOnly: !renderParentInstructions
2811
- }).map((ix) => visit6(ix, self))
2812
- );
2813
- return renderMap;
3200
+ const scope = { ...renderScope, programNode: node };
3201
+ return mergeRenderMaps([
3202
+ createRenderMap({
3203
+ [`programs/${camelCase14(node.name)}.ts`]: asPage(getProgramPageFragment(scope)),
3204
+ [`errors/${camelCase14(node.name)}.ts`]: node.errors.length > 0 ? asPage(getErrorPageFragment(scope)) : void 0
3205
+ }),
3206
+ ...node.pdas.map((p) => visit9(p, self)),
3207
+ ...node.accounts.map((a) => visit9(a, self)),
3208
+ ...node.definedTypes.map((t) => visit9(t, self)),
3209
+ ...customDataDefinedType.map((t) => visit9(t, self)),
3210
+ ...getAllInstructionsWithSubs2(node, { leavesOnly: !renderScope.renderParentInstructions }).map(
3211
+ (i) => visit9(i, self)
3212
+ )
3213
+ ]);
2814
3214
  },
2815
3215
  visitRoot(node, { self }) {
2816
3216
  const isNotInternal = (n) => !internalNodes.includes(n.name);
@@ -2819,88 +3219,41 @@ function getRenderMapVisitor(options = {}) {
2819
3219
  const pdasToExport = getAllPdas(node);
2820
3220
  const accountsToExport = getAllAccounts(node).filter(isNotInternal);
2821
3221
  const instructionsToExport = getAllInstructionsWithSubs2(node, {
2822
- leavesOnly: !renderParentInstructions
3222
+ leavesOnly: !renderScope.renderParentInstructions
2823
3223
  }).filter(isNotInternal);
2824
3224
  const definedTypesToExport = getAllDefinedTypes(node).filter(isNotInternal);
2825
3225
  const hasAnythingToExport = programsToExport.length > 0 || accountsToExport.length > 0 || instructionsToExport.length > 0 || definedTypesToExport.length > 0;
2826
- const ctx = {
3226
+ const scope = {
3227
+ ...renderScope,
2827
3228
  accountsToExport,
2828
3229
  definedTypesToExport,
2829
- hasAnythingToExport,
2830
3230
  instructionsToExport,
2831
3231
  pdasToExport,
2832
- programsToExport,
2833
- programsWithErrorsToExport,
2834
- root: node
3232
+ programsToExport
2835
3233
  };
2836
- const map = new RenderMap();
2837
- if (hasAnythingToExport) {
2838
- map.add(
2839
- "shared/index.ts",
2840
- render2("sharedPage.njk", {
2841
- ...ctx,
2842
- imports: new ImportMap().add("solanaAddresses", [
2843
- "type Address",
2844
- "isProgramDerivedAddress",
2845
- "type ProgramDerivedAddress"
2846
- ]).add("solanaInstructions", [
2847
- "AccountRole",
2848
- "type AccountMeta",
2849
- "upgradeRoleToSigner"
2850
- ]).add("solanaSigners", [
2851
- "type AccountSignerMeta",
2852
- "isTransactionSigner",
2853
- "type TransactionSigner"
2854
- ]).addAlias("solanaSigners", "isTransactionSigner", "kitIsTransactionSigner").toString(dependencyMap, useGranularImports)
2855
- })
2856
- );
2857
- }
2858
- if (programsToExport.length > 0) {
2859
- map.add("programs/index.ts", render2("programsIndex.njk", ctx));
2860
- }
2861
- if (programsWithErrorsToExport.length > 0) {
2862
- map.add("errors/index.ts", render2("errorsIndex.njk", ctx));
2863
- }
2864
- if (accountsToExport.length > 0) {
2865
- map.add("accounts/index.ts", render2("accountsIndex.njk", ctx));
2866
- }
2867
- if (pdasToExport.length > 0) {
2868
- map.add("pdas/index.ts", render2("pdasIndex.njk", ctx));
2869
- }
2870
- if (instructionsToExport.length > 0) {
2871
- map.add("instructions/index.ts", render2("instructionsIndex.njk", ctx));
2872
- }
2873
- if (definedTypesToExport.length > 0) {
2874
- map.add("types/index.ts", render2("definedTypesIndex.njk", ctx));
2875
- }
2876
- return map.add("index.ts", render2("rootIndex.njk", ctx)).mergeWith(...getAllPrograms(node).map((p) => visit6(p, self)));
3234
+ return mergeRenderMaps([
3235
+ createRenderMap({
3236
+ ["accounts/index.ts"]: asPage(getIndexPageFragment(accountsToExport)),
3237
+ ["errors/index.ts"]: asPage(getIndexPageFragment(programsWithErrorsToExport)),
3238
+ ["index.ts"]: asPage(getRootIndexPageFragment(scope)),
3239
+ ["instructions/index.ts"]: asPage(getIndexPageFragment(instructionsToExport)),
3240
+ ["pdas/index.ts"]: asPage(getIndexPageFragment(pdasToExport)),
3241
+ ["programs/index.ts"]: asPage(getIndexPageFragment(programsToExport)),
3242
+ ["shared/index.ts"]: hasAnythingToExport ? asPage(getSharedPageFragment()) : void 0,
3243
+ ["types/index.ts"]: asPage(getIndexPageFragment(definedTypesToExport))
3244
+ }),
3245
+ ...getAllPrograms(node).map((p) => visit9(p, self))
3246
+ ]);
2877
3247
  }
2878
3248
  }),
2879
3249
  (v) => recordNodeStackVisitor2(v, stack),
2880
3250
  (v) => recordLinkablesOnFirstVisitVisitor(v, linkables)
2881
3251
  );
2882
3252
  }
2883
- function getRenamedArgsMap(instruction) {
2884
- const argNames = [
2885
- ...instruction.arguments.map((a) => a.name),
2886
- ...(instruction.extraArguments ?? []).map((a) => a.name)
2887
- ];
2888
- const duplicateArgs = argNames.filter((e, i, a) => a.indexOf(e) !== i);
2889
- if (duplicateArgs.length > 0) {
2890
- throw new Error(`Duplicate args found: [${duplicateArgs.join(", ")}] in instruction [${instruction.name}].`);
2891
- }
2892
- const allNames = [...instruction.accounts.map((account) => account.name), ...argNames];
2893
- const duplicates = allNames.filter((e, i, a) => a.indexOf(e) !== i);
2894
- if (duplicates.length === 0) return /* @__PURE__ */ new Map();
2895
- logWarn(
2896
- `[JavaScript] Accounts and args of instruction [${instruction.name}] have the following conflicting attributes [${duplicates.join(", ")}]. Thus, the arguments have been renamed to avoid conflicts in the input type.`
2897
- );
2898
- return new Map(duplicates.map((name) => [camelCase12(name), camelCase12(`${name}Arg`)]));
2899
- }
2900
3253
 
2901
- // src/renderVisitor.ts
2902
- import { deleteDirectory } from "@codama/renderers-core";
2903
- import { rootNodeVisitor, visit as visit7 } from "@codama/visitors-core";
3254
+ // src/visitors/renderVisitor.ts
3255
+ import { deleteDirectory, mapRenderMapContentAsync, writeRenderMap } from "@codama/renderers-core";
3256
+ import { rootNodeVisitor, visit as visit10 } from "@codama/visitors-core";
2904
3257
  import * as estreePlugin from "prettier/plugins/estree";
2905
3258
  import * as typeScriptPlugin from "prettier/plugins/typescript";
2906
3259
  import { format } from "prettier/standalone";
@@ -2920,22 +3273,27 @@ function renderVisitor(path, options = {}) {
2920
3273
  if (options.deleteFolderBeforeRendering ?? true) {
2921
3274
  deleteDirectory(path);
2922
3275
  }
2923
- const renderMap = visit7(root, getRenderMapVisitor(options));
3276
+ let renderMap = visit10(root, getRenderMapVisitor(options));
2924
3277
  if (options.formatCode ?? true) {
2925
3278
  const prettierOptions = { ...DEFAULT_PRETTIER_OPTIONS, ...options.prettierOptions };
2926
- await renderMap.mapContentAsync((code) => format(code, prettierOptions));
3279
+ renderMap = await mapRenderMapContentAsync(renderMap, (code) => format(code, prettierOptions));
2927
3280
  }
2928
- renderMap.write(path);
3281
+ writeRenderMap(renderMap, path);
2929
3282
  });
2930
3283
  }
2931
3284
  export {
2932
3285
  DEFAULT_NAME_TRANSFORMERS,
2933
- ImportMap,
3286
+ addToImportMap,
3287
+ createImportMap,
2934
3288
  renderVisitor as default,
2935
3289
  getNameApi,
2936
3290
  getRenderMapVisitor,
2937
3291
  getTypeManifestVisitor,
2938
- mergeManifests,
3292
+ importMapToString,
3293
+ mergeImportMaps,
3294
+ mergeTypeManifests,
3295
+ parseImportInput,
3296
+ removeFromImportMap,
2939
3297
  renderVisitor,
2940
3298
  typeManifest
2941
3299
  };