@codama/renderers-js 1.0.0 → 1.1.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 (39) hide show
  1. package/dist/index.node.cjs +91 -75
  2. package/dist/index.node.cjs.map +1 -1
  3. package/dist/index.node.mjs +93 -77
  4. package/dist/index.node.mjs.map +1 -1
  5. package/dist/templates/fragments/instructionFunction.njk +1 -1
  6. package/dist/types/fragments/accountFetchHelpers.d.ts +2 -1
  7. package/dist/types/fragments/accountFetchHelpers.d.ts.map +1 -1
  8. package/dist/types/fragments/accountPdaHelpers.d.ts +3 -3
  9. package/dist/types/fragments/accountPdaHelpers.d.ts.map +1 -1
  10. package/dist/types/fragments/accountSizeHelpers.d.ts +2 -1
  11. package/dist/types/fragments/accountSizeHelpers.d.ts.map +1 -1
  12. package/dist/types/fragments/accountType.d.ts +2 -1
  13. package/dist/types/fragments/accountType.d.ts.map +1 -1
  14. package/dist/types/fragments/instructionAccountTypeParam.d.ts +3 -4
  15. package/dist/types/fragments/instructionAccountTypeParam.d.ts.map +1 -1
  16. package/dist/types/fragments/instructionByteDelta.d.ts +2 -1
  17. package/dist/types/fragments/instructionByteDelta.d.ts.map +1 -1
  18. package/dist/types/fragments/instructionData.d.ts +2 -1
  19. package/dist/types/fragments/instructionData.d.ts.map +1 -1
  20. package/dist/types/fragments/instructionExtraArgs.d.ts +2 -1
  21. package/dist/types/fragments/instructionExtraArgs.d.ts.map +1 -1
  22. package/dist/types/fragments/instructionFunction.d.ts +3 -4
  23. package/dist/types/fragments/instructionFunction.d.ts.map +1 -1
  24. package/dist/types/fragments/instructionInputResolved.d.ts +2 -2
  25. package/dist/types/fragments/instructionInputResolved.d.ts.map +1 -1
  26. package/dist/types/fragments/instructionInputType.d.ts +2 -2
  27. package/dist/types/fragments/instructionInputType.d.ts.map +1 -1
  28. package/dist/types/fragments/instructionParseFunction.d.ts +3 -3
  29. package/dist/types/fragments/instructionParseFunction.d.ts.map +1 -1
  30. package/dist/types/fragments/instructionRemainingAccounts.d.ts +2 -1
  31. package/dist/types/fragments/instructionRemainingAccounts.d.ts.map +1 -1
  32. package/dist/types/fragments/instructionType.d.ts +3 -3
  33. package/dist/types/fragments/instructionType.d.ts.map +1 -1
  34. package/dist/types/fragments/pdaFunction.d.ts +3 -3
  35. package/dist/types/fragments/pdaFunction.d.ts.map +1 -1
  36. package/dist/types/getRenderMapVisitor.d.ts.map +1 -1
  37. package/dist/types/getTypeManifestVisitor.d.ts +2 -5
  38. package/dist/types/getTypeManifestVisitor.d.ts.map +1 -1
  39. package/package.json +6 -6
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var visitorsCore = require('@codama/visitors-core');
3
4
  var path = require('path');
4
5
  var nodes = require('@codama/nodes');
5
- var visitorsCore = require('@codama/visitors-core');
6
6
  var codecsStrings = require('@solana/codecs-strings');
7
7
  var errors = require('@codama/errors');
8
8
  require('url');
@@ -424,7 +424,8 @@ var Fragment = class _Fragment {
424
424
 
425
425
  // src/fragments/accountFetchHelpers.ts
426
426
  function getAccountFetchHelpersFragment(scope) {
427
- const { accountNode, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
427
+ const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
428
+ const accountNode = visitorsCore.getLastNodeFromPath(accountPath);
428
429
  const hasCustomData = customAccountData.has(accountNode.name);
429
430
  const accountTypeFragment = hasCustomData ? typeManifest2.strictType.clone() : fragment(nameApi.dataType(accountNode.name));
430
431
  const decoderFunctionFragment = hasCustomData ? typeManifest2.decoder.clone() : fragment(`${nameApi.decoderFunction(accountNode.name)}()`);
@@ -451,8 +452,10 @@ function getAccountFetchHelpersFragment(scope) {
451
452
  ]);
452
453
  }
453
454
  function getAccountPdaHelpersFragment(scope) {
454
- const { accountNode, programNode, nameApi, linkables, customAccountData, typeManifest: typeManifest2 } = scope;
455
- const pdaNode = accountNode.pda ? linkables.get(accountNode.pda) : void 0;
455
+ const { accountPath, nameApi, linkables, customAccountData, typeManifest: typeManifest2 } = scope;
456
+ const accountNode = visitorsCore.getLastNodeFromPath(accountPath);
457
+ const programNode = visitorsCore.findProgramNodeFromPath(accountPath);
458
+ const pdaNode = accountNode.pda ? linkables.get([...accountPath, accountNode.pda]) : void 0;
456
459
  if (!pdaNode) {
457
460
  return fragment("");
458
461
  }
@@ -478,10 +481,9 @@ function getAccountPdaHelpersFragment(scope) {
478
481
  "type MaybeAccount"
479
482
  ]);
480
483
  }
481
-
482
- // src/fragments/accountSizeHelpers.ts
483
484
  function getAccountSizeHelpersFragment(scope) {
484
- const { accountNode, nameApi } = scope;
485
+ const { accountPath, nameApi } = scope;
486
+ const accountNode = visitorsCore.getLastNodeFromPath(accountPath);
485
487
  if (accountNode.size == null) {
486
488
  return fragment("");
487
489
  }
@@ -561,7 +563,8 @@ function getTypeWithCodecFragment(scope) {
561
563
 
562
564
  // src/fragments/accountType.ts
563
565
  function getAccountTypeFragment(scope) {
564
- const { accountNode, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
566
+ const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
567
+ const accountNode = visitorsCore.getLastNodeFromPath(accountPath);
565
568
  if (customAccountData.has(accountNode.name)) {
566
569
  return fragment("");
567
570
  }
@@ -632,7 +635,10 @@ function getInstructionAccountMetaFragment(instructionAccountNode) {
632
635
  return fragment(`ReadonlyAccount<${typeParam}>`).addImports("solanaInstructions", "type ReadonlyAccount");
633
636
  }
634
637
  function getInstructionAccountTypeParamFragment(scope) {
635
- const { instructionNode, instructionAccountNode, programNode, allowAccountMeta, linkables } = scope;
638
+ const { instructionAccountPath, allowAccountMeta, linkables } = scope;
639
+ const instructionAccountNode = visitorsCore.getLastNodeFromPath(instructionAccountPath);
640
+ const instructionNode = visitorsCore.findInstructionNodeFromPath(instructionAccountPath);
641
+ const programNode = visitorsCore.findProgramNodeFromPath(instructionAccountPath);
636
642
  const typeParam = `TAccount${nodes.pascalCase(instructionAccountNode.name)}`;
637
643
  const accountMeta = allowAccountMeta ? " | IAccountMeta<string>" : "";
638
644
  const imports = new ImportMap();
@@ -650,7 +656,7 @@ function getDefaultAddress(defaultValue, programId, linkables) {
650
656
  case "publicKeyValueNode":
651
657
  return `"${defaultValue.publicKey}"`;
652
658
  case "programLinkNode":
653
- const programNode = linkables.get(defaultValue);
659
+ const programNode = linkables.get([defaultValue]);
654
660
  return programNode ? `"${programNode.publicKey}"` : "string";
655
661
  case "programIdValueNode":
656
662
  return `"${programId}"`;
@@ -659,7 +665,7 @@ function getDefaultAddress(defaultValue, programId, linkables) {
659
665
  }
660
666
  }
661
667
  function getInstructionByteDeltaFragment(scope) {
662
- const { byteDeltas } = scope.instructionNode;
668
+ const { byteDeltas } = visitorsCore.getLastNodeFromPath(scope.instructionPath);
663
669
  const fragments = (byteDeltas ?? []).flatMap((r) => getByteDeltaFragment(r, scope));
664
670
  if (fragments.length === 0) return fragment("");
665
671
  return mergeFragments(
@@ -715,10 +721,9 @@ function getResolverValueNodeFragment(byteDelta, scope) {
715
721
  const functionName = scope.nameApi.resolverFunction(byteDelta.value.name);
716
722
  return fragment(`${awaitKeyword}${functionName}(resolverScope)`).addImports(scope.getImportFrom(byteDelta.value), functionName).addFeatures(["instruction:resolverScopeVariable"]);
717
723
  }
718
-
719
- // src/fragments/instructionData.ts
720
724
  function getInstructionDataFragment(scope) {
721
- const { instructionNode, dataArgsManifest, nameApi, customInstructionData } = scope;
725
+ const { instructionPath, dataArgsManifest, nameApi, customInstructionData } = scope;
726
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
722
727
  if (instructionNode.arguments.length === 0 || customInstructionData.has(instructionNode.name)) {
723
728
  return fragment("");
724
729
  }
@@ -775,10 +780,9 @@ function getConstantFragment(scope) {
775
780
  (r) => r.join("\n\n")
776
781
  );
777
782
  }
778
-
779
- // src/fragments/instructionExtraArgs.ts
780
783
  function getInstructionExtraArgsFragment(scope) {
781
- const { instructionNode, extraArgsManifest, nameApi } = scope;
784
+ const { instructionPath, extraArgsManifest, nameApi } = scope;
785
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
782
786
  if ((instructionNode.extraArguments ?? []).length === 0) {
783
787
  return fragment("");
784
788
  }
@@ -1000,11 +1004,12 @@ function renderNestedInstructionDefault(scope) {
1000
1004
 
1001
1005
  // src/fragments/instructionInputResolved.ts
1002
1006
  function getInstructionInputResolvedFragment(scope) {
1007
+ const instructionNode = visitorsCore.getLastNodeFromPath(scope.instructionPath);
1003
1008
  const resolvedInputFragments = scope.resolvedInputs.flatMap((input) => {
1004
1009
  const inputFragment = getInstructionInputDefaultFragment({
1005
1010
  ...scope,
1006
1011
  input,
1007
- optionalAccountStrategy: scope.instructionNode.optionalAccountStrategy
1012
+ optionalAccountStrategy: instructionNode.optionalAccountStrategy
1008
1013
  });
1009
1014
  if (!inputFragment.render) return [];
1010
1015
  const camelName = nodes.camelCase(input.name);
@@ -1027,7 +1032,8 @@ ${r}
1027
1032
  );
1028
1033
  }
1029
1034
  function getInstructionInputTypeFragment(scope) {
1030
- const { instructionNode, useAsync, nameApi } = scope;
1035
+ const { instructionPath, useAsync, nameApi } = scope;
1036
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1031
1037
  const instructionInputType = useAsync ? nameApi.instructionAsyncInputType(instructionNode.name) : nameApi.instructionSyncInputType(instructionNode.name);
1032
1038
  const accountsFragment = getAccountsFragment(scope);
1033
1039
  const [dataArgumentsFragment, customDataArgumentsFragment] = getDataArgumentsFragments(scope);
@@ -1050,7 +1056,8 @@ function getInstructionInputTypeFragment(scope) {
1050
1056
  ).addImports("solanaAddresses", ["type Address"]);
1051
1057
  }
1052
1058
  function getAccountsFragment(scope) {
1053
- const { instructionNode, resolvedInputs, useAsync, asyncResolvers } = scope;
1059
+ const { instructionPath, resolvedInputs, useAsync, asyncResolvers } = scope;
1060
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1054
1061
  const fragments = instructionNode.accounts.map((account) => {
1055
1062
  const resolvedAccount = resolvedInputs.find(
1056
1063
  (input) => input.kind === "instructionAccountNode" && input.name === account.name
@@ -1083,7 +1090,8 @@ function getAccountTypeFragment2(account) {
1083
1090
  return fragment(`Address<${typeParam}>`).addImports("solanaAddresses", ["type Address"]);
1084
1091
  }
1085
1092
  function getDataArgumentsFragments(scope) {
1086
- const { instructionNode, nameApi } = scope;
1093
+ const { instructionPath, nameApi } = scope;
1094
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1087
1095
  const customData = scope.customInstructionData.get(instructionNode.name);
1088
1096
  if (customData) {
1089
1097
  return [
@@ -1100,7 +1108,8 @@ function getDataArgumentsFragments(scope) {
1100
1108
  return [mergeFragments(fragments, (r) => r.join("\n")), fragment("")];
1101
1109
  }
1102
1110
  function getExtraArgumentsFragment(scope) {
1103
- const { instructionNode, nameApi } = scope;
1111
+ const { instructionPath, nameApi } = scope;
1112
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1104
1113
  const instructionExtraName = nameApi.instructionExtraType(instructionNode.name);
1105
1114
  const extraArgsType = nameApi.dataArgsType(instructionExtraName);
1106
1115
  const fragments = (instructionNode.extraArguments ?? []).flatMap((arg) => {
@@ -1139,7 +1148,7 @@ function getRemainingAccountsFragment(instructionNode) {
1139
1148
  return mergeFragments(fragments, (r) => r.join("\n"));
1140
1149
  }
1141
1150
  function getInstructionRemainingAccountsFragment(scope) {
1142
- const { remainingAccounts } = scope.instructionNode;
1151
+ const { remainingAccounts } = visitorsCore.getLastNodeFromPath(scope.instructionPath);
1143
1152
  const fragments = (remainingAccounts ?? []).flatMap((r) => getRemainingAccountsFragment2(r, scope));
1144
1153
  if (fragments.length === 0) return fragment("");
1145
1154
  return mergeFragments(
@@ -1162,7 +1171,7 @@ function getRemainingAccountsFragment2(remainingAccounts, scope) {
1162
1171
  return [remainingAccountsFragment];
1163
1172
  }
1164
1173
  function getArgumentValueNodeFragment2(remainingAccounts, scope) {
1165
- const { instructionNode } = scope;
1174
+ const instructionNode = visitorsCore.getLastNodeFromPath(scope.instructionPath);
1166
1175
  nodes.assertIsNode(remainingAccounts.value, "argumentValueNode");
1167
1176
  const argumentName = nodes.camelCase(remainingAccounts.value.name);
1168
1177
  const isOptional = remainingAccounts.isOptional ?? false;
@@ -1205,8 +1214,7 @@ function getResolverValueNodeFragment2(remainingAccounts, scope) {
1205
1214
  function getInstructionFunctionFragment(scope) {
1206
1215
  const {
1207
1216
  useAsync,
1208
- instructionNode,
1209
- programNode,
1217
+ instructionPath,
1210
1218
  resolvedInputs,
1211
1219
  renamedArgs,
1212
1220
  dataArgsManifest,
@@ -1214,6 +1222,8 @@ function getInstructionFunctionFragment(scope) {
1214
1222
  nameApi,
1215
1223
  customInstructionData
1216
1224
  } = scope;
1225
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1226
+ const programNode = visitorsCore.findProgramNodeFromPath(instructionPath);
1217
1227
  if (useAsync && !hasAsyncFunction(instructionNode, resolvedInputs, asyncResolvers)) {
1218
1228
  return fragment("");
1219
1229
  }
@@ -1236,6 +1246,7 @@ function getInstructionFunctionFragment(scope) {
1236
1246
  ).length > 0;
1237
1247
  const hasRemainingAccountArgs = (instructionNode.remainingAccounts ?? []).filter(({ value }) => nodes.isNode(value, "argumentValueNode")).length > 0;
1238
1248
  const hasAnyArgs = hasDataArgs || hasExtraArgs || hasRemainingAccountArgs;
1249
+ const hasInput = hasAccounts || hasAnyArgs;
1239
1250
  const instructionDataName = nameApi.instructionDataType(instructionNode.name);
1240
1251
  const programAddressConstant = nameApi.programAddressConstant(programNode.name);
1241
1252
  const encoderFunction = customData ? dataArgsManifest.encoder.render : `${nameApi.encoderFunction(instructionDataName)}()`;
@@ -1279,6 +1290,7 @@ function getInstructionFunctionFragment(scope) {
1279
1290
  hasData,
1280
1291
  hasDataArgs,
1281
1292
  hasExtraArgs,
1293
+ hasInput,
1282
1294
  hasLegacyOptionalAccounts,
1283
1295
  hasRemainingAccounts,
1284
1296
  hasResolver,
@@ -1313,7 +1325,8 @@ function getTypeParams(instructionNode, programAddressConstant) {
1313
1325
  return fragment(typeParams.filter((x) => !!x).join(", ")).mapRender((r) => `<${r}>`).addImports("generatedPrograms", [programAddressConstant]);
1314
1326
  }
1315
1327
  function getInstructionType(scope) {
1316
- const { instructionNode, nameApi } = scope;
1328
+ const { instructionPath, nameApi } = scope;
1329
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1317
1330
  const instructionTypeName = nameApi.instructionType(instructionNode.name);
1318
1331
  const programAddressFragment = fragment("TProgramAddress");
1319
1332
  const accountTypeParamsFragments = instructionNode.accounts.map((account) => {
@@ -1333,24 +1346,22 @@ function getInstructionType(scope) {
1333
1346
  ).mapRender((r) => `${instructionTypeName}<${r}>`);
1334
1347
  }
1335
1348
  function getInputTypeCall(scope) {
1336
- const { instructionNode, useAsync, nameApi } = scope;
1349
+ const { instructionPath, useAsync, nameApi } = scope;
1350
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1337
1351
  const inputTypeName = useAsync ? nameApi.instructionAsyncInputType(instructionNode.name) : nameApi.instructionSyncInputType(instructionNode.name);
1338
1352
  if (instructionNode.accounts.length === 0) return fragment(inputTypeName);
1339
1353
  const accountTypeParams = instructionNode.accounts.map((account) => `TAccount${nodes.pascalCase(account.name)}`).join(", ");
1340
1354
  return fragment(`${inputTypeName}<${accountTypeParams}>`);
1341
1355
  }
1342
-
1343
- // src/fragments/instructionParseFunction.ts
1344
1356
  function getInstructionParseFunctionFragment(scope) {
1345
- const { instructionNode, programNode, dataArgsManifest, nameApi, customInstructionData } = scope;
1357
+ const { instructionPath, dataArgsManifest, nameApi, customInstructionData } = scope;
1358
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1359
+ const programNode = visitorsCore.findProgramNodeFromPath(instructionPath);
1346
1360
  const customData = customInstructionData.get(instructionNode.name);
1347
1361
  const hasAccounts = instructionNode.accounts.length > 0;
1348
1362
  const hasOptionalAccounts = instructionNode.accounts.some((account) => account.isOptional);
1349
1363
  const minimumNumberOfAccounts = instructionNode.optionalAccountStrategy === "omitted" ? instructionNode.accounts.filter((account) => !account.isOptional).length : instructionNode.accounts.length;
1350
1364
  const hasData = !!customData || instructionNode.arguments.length > 0;
1351
- if (!hasAccounts && !hasData) {
1352
- return fragment("");
1353
- }
1354
1365
  const instructionDataName = nameApi.instructionDataType(instructionNode.name);
1355
1366
  const programAddressConstant = nameApi.programAddressConstant(programNode.name);
1356
1367
  const dataTypeFragment = fragment(
@@ -1374,7 +1385,9 @@ function getInstructionParseFunctionFragment(scope) {
1374
1385
  }).mergeImportsWith(dataTypeFragment).addImports("generatedPrograms", [programAddressConstant]).addImports("solanaInstructions", ["type IInstruction"]).addImports("solanaInstructions", hasAccounts ? ["type IInstructionWithAccounts", "type IAccountMeta"] : []).addImports("solanaInstructions", hasData ? ["type IInstructionWithData"] : []);
1375
1386
  }
1376
1387
  function getInstructionTypeFragment(scope) {
1377
- const { instructionNode, programNode, nameApi, customInstructionData } = scope;
1388
+ const { instructionPath, nameApi, customInstructionData } = scope;
1389
+ const instructionNode = visitorsCore.getLastNodeFromPath(instructionPath);
1390
+ const programNode = visitorsCore.findProgramNodeFromPath(instructionPath);
1378
1391
  const hasAccounts = instructionNode.accounts.length > 0;
1379
1392
  const customData = customInstructionData.get(instructionNode.name);
1380
1393
  const hasData = !!customData || instructionNode.arguments.length > 0;
@@ -1386,7 +1399,7 @@ function getInstructionTypeFragment(scope) {
1386
1399
  (account) => getInstructionAccountTypeParamFragment({
1387
1400
  ...scope,
1388
1401
  allowAccountMeta: true,
1389
- instructionAccountNode: account
1402
+ instructionAccountPath: [...instructionPath, account]
1390
1403
  })
1391
1404
  ),
1392
1405
  (renders) => renders.join(", ")
@@ -1422,7 +1435,9 @@ function getInstructionTypeFragment(scope) {
1422
1435
  return fragment2;
1423
1436
  }
1424
1437
  function getPdaFunctionFragment(scope) {
1425
- const { pdaNode, programNode, typeManifestVisitor, nameApi } = scope;
1438
+ const { pdaPath, typeManifestVisitor, nameApi } = scope;
1439
+ const pdaNode = visitorsCore.getLastNodeFromPath(pdaPath);
1440
+ const programNode = visitorsCore.findProgramNodeFromPath(pdaPath);
1426
1441
  const imports = new ImportMap();
1427
1442
  const seeds = pdaNode.seeds.map((seed) => {
1428
1443
  if (nodes.isNode(seed, "variablePdaSeedNode")) {
@@ -1641,8 +1656,8 @@ function mergeManifests(manifests, options = {}) {
1641
1656
  }
1642
1657
  function getTypeManifestVisitor(input) {
1643
1658
  const { nameApi, linkables, nonScalarEnums, customAccountData, customInstructionData, getImportFrom } = input;
1644
- const stack = new visitorsCore.NodeStack();
1645
- let parentName = input.parentName ?? null;
1659
+ const stack = input.stack ?? new visitorsCore.NodeStack();
1660
+ let parentName = null;
1646
1661
  return visitorsCore.pipe(
1647
1662
  visitorsCore.staticVisitor(
1648
1663
  () => ({
@@ -1653,14 +1668,16 @@ function getTypeManifestVisitor(input) {
1653
1668
  strictType: fragment(""),
1654
1669
  value: fragment("")
1655
1670
  }),
1656
- [
1657
- ...nodes.REGISTERED_TYPE_NODE_KINDS,
1658
- ...nodes.REGISTERED_VALUE_NODE_KINDS,
1659
- "definedTypeLinkNode",
1660
- "definedTypeNode",
1661
- "accountNode",
1662
- "instructionNode"
1663
- ]
1671
+ {
1672
+ keys: [
1673
+ ...nodes.REGISTERED_TYPE_NODE_KINDS,
1674
+ ...nodes.REGISTERED_VALUE_NODE_KINDS,
1675
+ "definedTypeLinkNode",
1676
+ "definedTypeNode",
1677
+ "accountNode",
1678
+ "instructionNode"
1679
+ ]
1680
+ }
1664
1681
  ),
1665
1682
  (visitor) => visitorsCore.extendVisitor(visitor, {
1666
1683
  visitAccount(account, { self }) {
@@ -1905,7 +1922,7 @@ function getTypeManifestVisitor(input) {
1905
1922
  const enumName = nameApi.dataType(node.enum.name);
1906
1923
  const enumFunction = nameApi.discriminatedUnionFunction(node.enum.name);
1907
1924
  const importFrom = getImportFrom(node.enum);
1908
- const enumNode = linkables.get(node.enum)?.type;
1925
+ const enumNode = linkables.get([...stack.getPath(), node.enum])?.type;
1909
1926
  const isScalar = enumNode && nodes.isNode(enumNode, "enumTypeNode") ? nodes.isScalarEnum(enumNode) : !nonScalarEnums.includes(node.enum.name);
1910
1927
  if (!node.value && isScalar) {
1911
1928
  const variantName2 = nameApi.enumVariant(node.variant);
@@ -2225,8 +2242,9 @@ ${jsDocblock(structFieldType.docs)}` : "";
2225
2242
  if (optionalFields.length === 0) {
2226
2243
  return mergedManifest;
2227
2244
  }
2228
- const instructionNode = stack.find("instructionNode");
2229
- const accountNode = stack.find("accountNode");
2245
+ const parentPath = stack.getPath();
2246
+ const instructionNode = visitorsCore.findLastNodeFromPath(parentPath, "instructionNode");
2247
+ const accountNode = visitorsCore.findLastNodeFromPath(parentPath, "accountNode");
2230
2248
  const discriminatorPrefix = instructionNode ? instructionNode.name : accountNode?.name;
2231
2249
  const discriminators = (instructionNode ? instructionNode.discriminators : accountNode?.discriminators) ?? [];
2232
2250
  const fieldDiscriminators = discriminators.filter(nodes.isNodeFilter("fieldDiscriminatorNode"));
@@ -2379,7 +2397,7 @@ var DEFAULT_NAME_TRANSFORMERS = {
2379
2397
  // src/getRenderMapVisitor.ts
2380
2398
  function getRenderMapVisitor(options = {}) {
2381
2399
  const linkables = new visitorsCore.LinkableDictionary();
2382
- let program = null;
2400
+ const stack = new visitorsCore.NodeStack();
2383
2401
  const nameTransformers = {
2384
2402
  ...DEFAULT_NAME_TRANSFORMERS,
2385
2403
  ...options.nameTransformers
@@ -2394,16 +2412,15 @@ function getRenderMapVisitor(options = {}) {
2394
2412
  const customAccountData = parseCustomDataOptions(options.customAccountData ?? [], "AccountData");
2395
2413
  const customInstructionData = parseCustomDataOptions(options.customInstructionData ?? [], "InstructionData");
2396
2414
  const getImportFrom = getImportFromFactory(options.linkOverrides ?? {}, customAccountData, customInstructionData);
2397
- const getTypeManifestVisitor2 = (parentName) => getTypeManifestVisitor({
2415
+ const typeManifestVisitor = getTypeManifestVisitor({
2398
2416
  customAccountData,
2399
2417
  customInstructionData,
2400
2418
  getImportFrom,
2401
2419
  linkables,
2402
2420
  nameApi,
2403
2421
  nonScalarEnums,
2404
- parentName
2422
+ stack
2405
2423
  });
2406
- const typeManifestVisitor = getTypeManifestVisitor2();
2407
2424
  const resolvedInstructionInputVisitor = visitorsCore.getResolvedInstructionInputsVisitor();
2408
2425
  const globalScope = {
2409
2426
  asyncResolvers,
@@ -2420,19 +2437,18 @@ function getRenderMapVisitor(options = {}) {
2420
2437
  return render(path.join("pages", template), context, renderOptions);
2421
2438
  };
2422
2439
  return visitorsCore.pipe(
2423
- visitorsCore.staticVisitor(
2424
- () => new renderersCore.RenderMap(),
2425
- ["rootNode", "programNode", "pdaNode", "accountNode", "definedTypeNode", "instructionNode"]
2426
- ),
2440
+ visitorsCore.staticVisitor(() => new renderersCore.RenderMap(), {
2441
+ keys: ["rootNode", "programNode", "pdaNode", "accountNode", "definedTypeNode", "instructionNode"]
2442
+ }),
2427
2443
  (v) => visitorsCore.extendVisitor(v, {
2428
2444
  visitAccount(node) {
2429
- if (!program) {
2445
+ const accountPath = stack.getPath("accountNode");
2446
+ if (!visitorsCore.findProgramNodeFromPath(accountPath)) {
2430
2447
  throw new Error("Account must be visited inside a program.");
2431
2448
  }
2432
2449
  const scope = {
2433
2450
  ...globalScope,
2434
- accountNode: node,
2435
- programNode: program,
2451
+ accountPath,
2436
2452
  typeManifest: visitorsCore.visit(node, typeManifestVisitor)
2437
2453
  };
2438
2454
  const fields = nodes.resolveNestedTypeNode(node.data).fields;
@@ -2498,7 +2514,8 @@ function getRenderMapVisitor(options = {}) {
2498
2514
  );
2499
2515
  },
2500
2516
  visitInstruction(node) {
2501
- if (!program) {
2517
+ const instructionPath = stack.getPath("instructionNode");
2518
+ if (!visitorsCore.findProgramNodeFromPath(instructionPath)) {
2502
2519
  throw new Error("Instruction must be visited inside a program.");
2503
2520
  }
2504
2521
  const instructionExtraName = nameApi.instructionExtraType(node.name);
@@ -2506,14 +2523,13 @@ function getRenderMapVisitor(options = {}) {
2506
2523
  ...globalScope,
2507
2524
  dataArgsManifest: visitorsCore.visit(node, typeManifestVisitor),
2508
2525
  extraArgsManifest: visitorsCore.visit(
2509
- nodes.structTypeNodeFromInstructionArgumentNodes(node.extraArguments ?? []),
2510
- getTypeManifestVisitor2({
2511
- loose: nameApi.dataArgsType(instructionExtraName),
2512
- strict: nameApi.dataType(instructionExtraName)
2513
- })
2526
+ nodes.definedTypeNode({
2527
+ name: instructionExtraName,
2528
+ type: nodes.structTypeNodeFromInstructionArgumentNodes(node.extraArguments ?? [])
2529
+ }),
2530
+ typeManifestVisitor
2514
2531
  ),
2515
- instructionNode: node,
2516
- programNode: program,
2532
+ instructionPath,
2517
2533
  renamedArgs: getRenamedArgsMap(node),
2518
2534
  resolvedInputs: visitorsCore.visit(node, resolvedInstructionInputVisitor)
2519
2535
  };
@@ -2560,10 +2576,11 @@ function getRenderMapVisitor(options = {}) {
2560
2576
  );
2561
2577
  },
2562
2578
  visitPda(node) {
2563
- if (!program) {
2579
+ const pdaPath = stack.getPath("pdaNode");
2580
+ if (!visitorsCore.findProgramNodeFromPath(pdaPath)) {
2564
2581
  throw new Error("Account must be visited inside a program.");
2565
2582
  }
2566
- const scope = { ...globalScope, pdaNode: node, programNode: program };
2583
+ const scope = { ...globalScope, pdaPath };
2567
2584
  const pdaFunctionFragment = getPdaFunctionFragment(scope);
2568
2585
  const imports = new ImportMap().mergeWith(pdaFunctionFragment);
2569
2586
  return new renderersCore.RenderMap().add(
@@ -2575,7 +2592,6 @@ function getRenderMapVisitor(options = {}) {
2575
2592
  );
2576
2593
  },
2577
2594
  visitProgram(node, { self }) {
2578
- program = node;
2579
2595
  const customDataDefinedType = [
2580
2596
  ...getDefinedTypeNodesToExtract(node.accounts, customAccountData),
2581
2597
  ...getDefinedTypeNodesToExtract(node.instructions, customInstructionData)
@@ -2605,11 +2621,10 @@ function getRenderMapVisitor(options = {}) {
2605
2621
  })
2606
2622
  );
2607
2623
  renderMap.mergeWith(
2608
- ...nodes.getAllInstructionsWithSubs(program, {
2624
+ ...nodes.getAllInstructionsWithSubs(node, {
2609
2625
  leavesOnly: !renderParentInstructions
2610
2626
  }).map((ix) => visitorsCore.visit(ix, self))
2611
2627
  );
2612
- program = null;
2613
2628
  return renderMap;
2614
2629
  },
2615
2630
  visitRoot(node, { self }) {
@@ -2676,7 +2691,8 @@ function getRenderMapVisitor(options = {}) {
2676
2691
  return map.add("index.ts", render2("rootIndex.njk", ctx)).mergeWith(...nodes.getAllPrograms(node).map((p) => visitorsCore.visit(p, self)));
2677
2692
  }
2678
2693
  }),
2679
- (v) => visitorsCore.recordLinkablesVisitor(v, linkables)
2694
+ (v) => visitorsCore.recordNodeStackVisitor(v, stack),
2695
+ (v) => visitorsCore.recordLinkablesOnFirstVisitVisitor(v, linkables)
2680
2696
  );
2681
2697
  }
2682
2698
  function getRenamedArgsMap(instruction) {