@codama/renderers-js 1.0.1 → 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 (38) hide show
  1. package/dist/index.node.cjs +89 -72
  2. package/dist/index.node.cjs.map +1 -1
  3. package/dist/index.node.mjs +91 -74
  4. package/dist/index.node.mjs.map +1 -1
  5. package/dist/types/fragments/accountFetchHelpers.d.ts +2 -1
  6. package/dist/types/fragments/accountFetchHelpers.d.ts.map +1 -1
  7. package/dist/types/fragments/accountPdaHelpers.d.ts +3 -3
  8. package/dist/types/fragments/accountPdaHelpers.d.ts.map +1 -1
  9. package/dist/types/fragments/accountSizeHelpers.d.ts +2 -1
  10. package/dist/types/fragments/accountSizeHelpers.d.ts.map +1 -1
  11. package/dist/types/fragments/accountType.d.ts +2 -1
  12. package/dist/types/fragments/accountType.d.ts.map +1 -1
  13. package/dist/types/fragments/instructionAccountTypeParam.d.ts +3 -4
  14. package/dist/types/fragments/instructionAccountTypeParam.d.ts.map +1 -1
  15. package/dist/types/fragments/instructionByteDelta.d.ts +2 -1
  16. package/dist/types/fragments/instructionByteDelta.d.ts.map +1 -1
  17. package/dist/types/fragments/instructionData.d.ts +2 -1
  18. package/dist/types/fragments/instructionData.d.ts.map +1 -1
  19. package/dist/types/fragments/instructionExtraArgs.d.ts +2 -1
  20. package/dist/types/fragments/instructionExtraArgs.d.ts.map +1 -1
  21. package/dist/types/fragments/instructionFunction.d.ts +3 -4
  22. package/dist/types/fragments/instructionFunction.d.ts.map +1 -1
  23. package/dist/types/fragments/instructionInputResolved.d.ts +2 -2
  24. package/dist/types/fragments/instructionInputResolved.d.ts.map +1 -1
  25. package/dist/types/fragments/instructionInputType.d.ts +2 -2
  26. package/dist/types/fragments/instructionInputType.d.ts.map +1 -1
  27. package/dist/types/fragments/instructionParseFunction.d.ts +3 -3
  28. package/dist/types/fragments/instructionParseFunction.d.ts.map +1 -1
  29. package/dist/types/fragments/instructionRemainingAccounts.d.ts +2 -1
  30. package/dist/types/fragments/instructionRemainingAccounts.d.ts.map +1 -1
  31. package/dist/types/fragments/instructionType.d.ts +3 -3
  32. package/dist/types/fragments/instructionType.d.ts.map +1 -1
  33. package/dist/types/fragments/pdaFunction.d.ts +3 -3
  34. package/dist/types/fragments/pdaFunction.d.ts.map +1 -1
  35. package/dist/types/getRenderMapVisitor.d.ts.map +1 -1
  36. package/dist/types/getTypeManifestVisitor.d.ts +2 -5
  37. package/dist/types/getTypeManifestVisitor.d.ts.map +1 -1
  38. package/package.json +6 -6
@@ -1,8 +1,8 @@
1
+ import { NodeStack, pipe, staticVisitor, extendVisitor, visit, findLastNodeFromPath, recordNodeStackVisitor, LinkableDictionary, getResolvedInstructionInputsVisitor, findProgramNodeFromPath, recordLinkablesOnFirstVisitVisitor, rootNodeVisitor, getLastNodeFromPath, deduplicateInstructionDependencies, findInstructionNodeFromPath } from '@codama/visitors-core';
1
2
  import { join, dirname } from 'node:path';
2
- import { REGISTERED_TYPE_NODE_KINDS, REGISTERED_VALUE_NODE_KINDS, resolveNestedTypeNode, isNode, camelCase, structTypeNode, structFieldTypeNode, isScalarEnum, structTypeNodeFromInstructionArgumentNodes, isNodeFilter, pascalCase, snakeCase, getAllInstructionsWithSubs, getAllPrograms, getAllPdas, getAllAccounts, getAllDefinedTypes, definedTypeLinkNode, definedTypeNode, isDataEnum, capitalize, kebabCase, titleCase, constantDiscriminatorNode, constantValueNodeFromBytes, constantValueNode, VALUE_NODES, accountValueNode, argumentValueNode, assertIsNode, getAllInstructionArguments } from '@codama/nodes';
3
- import { NodeStack, pipe, staticVisitor, extendVisitor, visit, recordNodeStackVisitor, LinkableDictionary, getResolvedInstructionInputsVisitor, recordLinkablesVisitor, rootNodeVisitor, deduplicateInstructionDependencies } from '@codama/visitors-core';
3
+ import { REGISTERED_TYPE_NODE_KINDS, REGISTERED_VALUE_NODE_KINDS, resolveNestedTypeNode, isNode, camelCase, structTypeNode, structFieldTypeNode, isScalarEnum, structTypeNodeFromInstructionArgumentNodes, isNodeFilter, pascalCase, snakeCase, definedTypeNode, getAllInstructionsWithSubs, getAllPrograms, getAllPdas, getAllAccounts, getAllDefinedTypes, definedTypeLinkNode, VALUE_NODES, isDataEnum, capitalize, kebabCase, titleCase, accountValueNode, argumentValueNode, constantDiscriminatorNode, constantValueNodeFromBytes, constantValueNode, assertIsNode, getAllInstructionArguments } from '@codama/nodes';
4
4
  import { getBase64Encoder, getBase58Encoder, getBase16Encoder, getUtf8Encoder, getBase64Decoder } from '@solana/codecs-strings';
5
- import { CodamaError, CODAMA_ERROR__UNEXPECTED_NODE_KIND, logWarn } from '@codama/errors';
5
+ import { logWarn, CodamaError, CODAMA_ERROR__UNEXPECTED_NODE_KIND } from '@codama/errors';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import nunjucks from 'nunjucks';
8
8
  import { RenderMap, deleteDirectory } from '@codama/renderers-core';
@@ -398,7 +398,8 @@ var Fragment = class _Fragment {
398
398
 
399
399
  // src/fragments/accountFetchHelpers.ts
400
400
  function getAccountFetchHelpersFragment(scope) {
401
- const { accountNode, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
401
+ const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
402
+ const accountNode = getLastNodeFromPath(accountPath);
402
403
  const hasCustomData = customAccountData.has(accountNode.name);
403
404
  const accountTypeFragment = hasCustomData ? typeManifest2.strictType.clone() : fragment(nameApi.dataType(accountNode.name));
404
405
  const decoderFunctionFragment = hasCustomData ? typeManifest2.decoder.clone() : fragment(`${nameApi.decoderFunction(accountNode.name)}()`);
@@ -425,8 +426,10 @@ function getAccountFetchHelpersFragment(scope) {
425
426
  ]);
426
427
  }
427
428
  function getAccountPdaHelpersFragment(scope) {
428
- const { accountNode, programNode, nameApi, linkables, customAccountData, typeManifest: typeManifest2 } = scope;
429
- const pdaNode = accountNode.pda ? linkables.get(accountNode.pda) : void 0;
429
+ const { accountPath, nameApi, linkables, customAccountData, typeManifest: typeManifest2 } = scope;
430
+ const accountNode = getLastNodeFromPath(accountPath);
431
+ const programNode = findProgramNodeFromPath(accountPath);
432
+ const pdaNode = accountNode.pda ? linkables.get([...accountPath, accountNode.pda]) : void 0;
430
433
  if (!pdaNode) {
431
434
  return fragment("");
432
435
  }
@@ -452,10 +455,9 @@ function getAccountPdaHelpersFragment(scope) {
452
455
  "type MaybeAccount"
453
456
  ]);
454
457
  }
455
-
456
- // src/fragments/accountSizeHelpers.ts
457
458
  function getAccountSizeHelpersFragment(scope) {
458
- const { accountNode, nameApi } = scope;
459
+ const { accountPath, nameApi } = scope;
460
+ const accountNode = getLastNodeFromPath(accountPath);
459
461
  if (accountNode.size == null) {
460
462
  return fragment("");
461
463
  }
@@ -535,7 +537,8 @@ function getTypeWithCodecFragment(scope) {
535
537
 
536
538
  // src/fragments/accountType.ts
537
539
  function getAccountTypeFragment(scope) {
538
- const { accountNode, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
540
+ const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
541
+ const accountNode = getLastNodeFromPath(accountPath);
539
542
  if (customAccountData.has(accountNode.name)) {
540
543
  return fragment("");
541
544
  }
@@ -606,7 +609,10 @@ function getInstructionAccountMetaFragment(instructionAccountNode) {
606
609
  return fragment(`ReadonlyAccount<${typeParam}>`).addImports("solanaInstructions", "type ReadonlyAccount");
607
610
  }
608
611
  function getInstructionAccountTypeParamFragment(scope) {
609
- const { instructionNode, instructionAccountNode, programNode, allowAccountMeta, linkables } = scope;
612
+ const { instructionAccountPath, allowAccountMeta, linkables } = scope;
613
+ const instructionAccountNode = getLastNodeFromPath(instructionAccountPath);
614
+ const instructionNode = findInstructionNodeFromPath(instructionAccountPath);
615
+ const programNode = findProgramNodeFromPath(instructionAccountPath);
610
616
  const typeParam = `TAccount${pascalCase(instructionAccountNode.name)}`;
611
617
  const accountMeta = allowAccountMeta ? " | IAccountMeta<string>" : "";
612
618
  const imports = new ImportMap();
@@ -624,7 +630,7 @@ function getDefaultAddress(defaultValue, programId, linkables) {
624
630
  case "publicKeyValueNode":
625
631
  return `"${defaultValue.publicKey}"`;
626
632
  case "programLinkNode":
627
- const programNode = linkables.get(defaultValue);
633
+ const programNode = linkables.get([defaultValue]);
628
634
  return programNode ? `"${programNode.publicKey}"` : "string";
629
635
  case "programIdValueNode":
630
636
  return `"${programId}"`;
@@ -633,7 +639,7 @@ function getDefaultAddress(defaultValue, programId, linkables) {
633
639
  }
634
640
  }
635
641
  function getInstructionByteDeltaFragment(scope) {
636
- const { byteDeltas } = scope.instructionNode;
642
+ const { byteDeltas } = getLastNodeFromPath(scope.instructionPath);
637
643
  const fragments = (byteDeltas ?? []).flatMap((r) => getByteDeltaFragment(r, scope));
638
644
  if (fragments.length === 0) return fragment("");
639
645
  return mergeFragments(
@@ -689,10 +695,9 @@ function getResolverValueNodeFragment(byteDelta, scope) {
689
695
  const functionName = scope.nameApi.resolverFunction(byteDelta.value.name);
690
696
  return fragment(`${awaitKeyword}${functionName}(resolverScope)`).addImports(scope.getImportFrom(byteDelta.value), functionName).addFeatures(["instruction:resolverScopeVariable"]);
691
697
  }
692
-
693
- // src/fragments/instructionData.ts
694
698
  function getInstructionDataFragment(scope) {
695
- const { instructionNode, dataArgsManifest, nameApi, customInstructionData } = scope;
699
+ const { instructionPath, dataArgsManifest, nameApi, customInstructionData } = scope;
700
+ const instructionNode = getLastNodeFromPath(instructionPath);
696
701
  if (instructionNode.arguments.length === 0 || customInstructionData.has(instructionNode.name)) {
697
702
  return fragment("");
698
703
  }
@@ -749,10 +754,9 @@ function getConstantFragment(scope) {
749
754
  (r) => r.join("\n\n")
750
755
  );
751
756
  }
752
-
753
- // src/fragments/instructionExtraArgs.ts
754
757
  function getInstructionExtraArgsFragment(scope) {
755
- const { instructionNode, extraArgsManifest, nameApi } = scope;
758
+ const { instructionPath, extraArgsManifest, nameApi } = scope;
759
+ const instructionNode = getLastNodeFromPath(instructionPath);
756
760
  if ((instructionNode.extraArguments ?? []).length === 0) {
757
761
  return fragment("");
758
762
  }
@@ -974,11 +978,12 @@ function renderNestedInstructionDefault(scope) {
974
978
 
975
979
  // src/fragments/instructionInputResolved.ts
976
980
  function getInstructionInputResolvedFragment(scope) {
981
+ const instructionNode = getLastNodeFromPath(scope.instructionPath);
977
982
  const resolvedInputFragments = scope.resolvedInputs.flatMap((input) => {
978
983
  const inputFragment = getInstructionInputDefaultFragment({
979
984
  ...scope,
980
985
  input,
981
- optionalAccountStrategy: scope.instructionNode.optionalAccountStrategy
986
+ optionalAccountStrategy: instructionNode.optionalAccountStrategy
982
987
  });
983
988
  if (!inputFragment.render) return [];
984
989
  const camelName = camelCase(input.name);
@@ -1001,7 +1006,8 @@ ${r}
1001
1006
  );
1002
1007
  }
1003
1008
  function getInstructionInputTypeFragment(scope) {
1004
- const { instructionNode, useAsync, nameApi } = scope;
1009
+ const { instructionPath, useAsync, nameApi } = scope;
1010
+ const instructionNode = getLastNodeFromPath(instructionPath);
1005
1011
  const instructionInputType = useAsync ? nameApi.instructionAsyncInputType(instructionNode.name) : nameApi.instructionSyncInputType(instructionNode.name);
1006
1012
  const accountsFragment = getAccountsFragment(scope);
1007
1013
  const [dataArgumentsFragment, customDataArgumentsFragment] = getDataArgumentsFragments(scope);
@@ -1024,7 +1030,8 @@ function getInstructionInputTypeFragment(scope) {
1024
1030
  ).addImports("solanaAddresses", ["type Address"]);
1025
1031
  }
1026
1032
  function getAccountsFragment(scope) {
1027
- const { instructionNode, resolvedInputs, useAsync, asyncResolvers } = scope;
1033
+ const { instructionPath, resolvedInputs, useAsync, asyncResolvers } = scope;
1034
+ const instructionNode = getLastNodeFromPath(instructionPath);
1028
1035
  const fragments = instructionNode.accounts.map((account) => {
1029
1036
  const resolvedAccount = resolvedInputs.find(
1030
1037
  (input) => input.kind === "instructionAccountNode" && input.name === account.name
@@ -1057,7 +1064,8 @@ function getAccountTypeFragment2(account) {
1057
1064
  return fragment(`Address<${typeParam}>`).addImports("solanaAddresses", ["type Address"]);
1058
1065
  }
1059
1066
  function getDataArgumentsFragments(scope) {
1060
- const { instructionNode, nameApi } = scope;
1067
+ const { instructionPath, nameApi } = scope;
1068
+ const instructionNode = getLastNodeFromPath(instructionPath);
1061
1069
  const customData = scope.customInstructionData.get(instructionNode.name);
1062
1070
  if (customData) {
1063
1071
  return [
@@ -1074,7 +1082,8 @@ function getDataArgumentsFragments(scope) {
1074
1082
  return [mergeFragments(fragments, (r) => r.join("\n")), fragment("")];
1075
1083
  }
1076
1084
  function getExtraArgumentsFragment(scope) {
1077
- const { instructionNode, nameApi } = scope;
1085
+ const { instructionPath, nameApi } = scope;
1086
+ const instructionNode = getLastNodeFromPath(instructionPath);
1078
1087
  const instructionExtraName = nameApi.instructionExtraType(instructionNode.name);
1079
1088
  const extraArgsType = nameApi.dataArgsType(instructionExtraName);
1080
1089
  const fragments = (instructionNode.extraArguments ?? []).flatMap((arg) => {
@@ -1113,7 +1122,7 @@ function getRemainingAccountsFragment(instructionNode) {
1113
1122
  return mergeFragments(fragments, (r) => r.join("\n"));
1114
1123
  }
1115
1124
  function getInstructionRemainingAccountsFragment(scope) {
1116
- const { remainingAccounts } = scope.instructionNode;
1125
+ const { remainingAccounts } = getLastNodeFromPath(scope.instructionPath);
1117
1126
  const fragments = (remainingAccounts ?? []).flatMap((r) => getRemainingAccountsFragment2(r, scope));
1118
1127
  if (fragments.length === 0) return fragment("");
1119
1128
  return mergeFragments(
@@ -1136,7 +1145,7 @@ function getRemainingAccountsFragment2(remainingAccounts, scope) {
1136
1145
  return [remainingAccountsFragment];
1137
1146
  }
1138
1147
  function getArgumentValueNodeFragment2(remainingAccounts, scope) {
1139
- const { instructionNode } = scope;
1148
+ const instructionNode = getLastNodeFromPath(scope.instructionPath);
1140
1149
  assertIsNode(remainingAccounts.value, "argumentValueNode");
1141
1150
  const argumentName = camelCase(remainingAccounts.value.name);
1142
1151
  const isOptional = remainingAccounts.isOptional ?? false;
@@ -1179,8 +1188,7 @@ function getResolverValueNodeFragment2(remainingAccounts, scope) {
1179
1188
  function getInstructionFunctionFragment(scope) {
1180
1189
  const {
1181
1190
  useAsync,
1182
- instructionNode,
1183
- programNode,
1191
+ instructionPath,
1184
1192
  resolvedInputs,
1185
1193
  renamedArgs,
1186
1194
  dataArgsManifest,
@@ -1188,6 +1196,8 @@ function getInstructionFunctionFragment(scope) {
1188
1196
  nameApi,
1189
1197
  customInstructionData
1190
1198
  } = scope;
1199
+ const instructionNode = getLastNodeFromPath(instructionPath);
1200
+ const programNode = findProgramNodeFromPath(instructionPath);
1191
1201
  if (useAsync && !hasAsyncFunction(instructionNode, resolvedInputs, asyncResolvers)) {
1192
1202
  return fragment("");
1193
1203
  }
@@ -1289,7 +1299,8 @@ function getTypeParams(instructionNode, programAddressConstant) {
1289
1299
  return fragment(typeParams.filter((x) => !!x).join(", ")).mapRender((r) => `<${r}>`).addImports("generatedPrograms", [programAddressConstant]);
1290
1300
  }
1291
1301
  function getInstructionType(scope) {
1292
- const { instructionNode, nameApi } = scope;
1302
+ const { instructionPath, nameApi } = scope;
1303
+ const instructionNode = getLastNodeFromPath(instructionPath);
1293
1304
  const instructionTypeName = nameApi.instructionType(instructionNode.name);
1294
1305
  const programAddressFragment = fragment("TProgramAddress");
1295
1306
  const accountTypeParamsFragments = instructionNode.accounts.map((account) => {
@@ -1309,16 +1320,17 @@ function getInstructionType(scope) {
1309
1320
  ).mapRender((r) => `${instructionTypeName}<${r}>`);
1310
1321
  }
1311
1322
  function getInputTypeCall(scope) {
1312
- const { instructionNode, useAsync, nameApi } = scope;
1323
+ const { instructionPath, useAsync, nameApi } = scope;
1324
+ const instructionNode = getLastNodeFromPath(instructionPath);
1313
1325
  const inputTypeName = useAsync ? nameApi.instructionAsyncInputType(instructionNode.name) : nameApi.instructionSyncInputType(instructionNode.name);
1314
1326
  if (instructionNode.accounts.length === 0) return fragment(inputTypeName);
1315
1327
  const accountTypeParams = instructionNode.accounts.map((account) => `TAccount${pascalCase(account.name)}`).join(", ");
1316
1328
  return fragment(`${inputTypeName}<${accountTypeParams}>`);
1317
1329
  }
1318
-
1319
- // src/fragments/instructionParseFunction.ts
1320
1330
  function getInstructionParseFunctionFragment(scope) {
1321
- const { instructionNode, programNode, dataArgsManifest, nameApi, customInstructionData } = scope;
1331
+ const { instructionPath, dataArgsManifest, nameApi, customInstructionData } = scope;
1332
+ const instructionNode = getLastNodeFromPath(instructionPath);
1333
+ const programNode = findProgramNodeFromPath(instructionPath);
1322
1334
  const customData = customInstructionData.get(instructionNode.name);
1323
1335
  const hasAccounts = instructionNode.accounts.length > 0;
1324
1336
  const hasOptionalAccounts = instructionNode.accounts.some((account) => account.isOptional);
@@ -1347,7 +1359,9 @@ function getInstructionParseFunctionFragment(scope) {
1347
1359
  }).mergeImportsWith(dataTypeFragment).addImports("generatedPrograms", [programAddressConstant]).addImports("solanaInstructions", ["type IInstruction"]).addImports("solanaInstructions", hasAccounts ? ["type IInstructionWithAccounts", "type IAccountMeta"] : []).addImports("solanaInstructions", hasData ? ["type IInstructionWithData"] : []);
1348
1360
  }
1349
1361
  function getInstructionTypeFragment(scope) {
1350
- const { instructionNode, programNode, nameApi, customInstructionData } = scope;
1362
+ const { instructionPath, nameApi, customInstructionData } = scope;
1363
+ const instructionNode = getLastNodeFromPath(instructionPath);
1364
+ const programNode = findProgramNodeFromPath(instructionPath);
1351
1365
  const hasAccounts = instructionNode.accounts.length > 0;
1352
1366
  const customData = customInstructionData.get(instructionNode.name);
1353
1367
  const hasData = !!customData || instructionNode.arguments.length > 0;
@@ -1359,7 +1373,7 @@ function getInstructionTypeFragment(scope) {
1359
1373
  (account) => getInstructionAccountTypeParamFragment({
1360
1374
  ...scope,
1361
1375
  allowAccountMeta: true,
1362
- instructionAccountNode: account
1376
+ instructionAccountPath: [...instructionPath, account]
1363
1377
  })
1364
1378
  ),
1365
1379
  (renders) => renders.join(", ")
@@ -1395,7 +1409,9 @@ function getInstructionTypeFragment(scope) {
1395
1409
  return fragment2;
1396
1410
  }
1397
1411
  function getPdaFunctionFragment(scope) {
1398
- const { pdaNode, programNode, typeManifestVisitor, nameApi } = scope;
1412
+ const { pdaPath, typeManifestVisitor, nameApi } = scope;
1413
+ const pdaNode = getLastNodeFromPath(pdaPath);
1414
+ const programNode = findProgramNodeFromPath(pdaPath);
1399
1415
  const imports = new ImportMap();
1400
1416
  const seeds = pdaNode.seeds.map((seed) => {
1401
1417
  if (isNode(seed, "variablePdaSeedNode")) {
@@ -1614,8 +1630,8 @@ function mergeManifests(manifests, options = {}) {
1614
1630
  }
1615
1631
  function getTypeManifestVisitor(input) {
1616
1632
  const { nameApi, linkables, nonScalarEnums, customAccountData, customInstructionData, getImportFrom } = input;
1617
- const stack = new NodeStack();
1618
- let parentName = input.parentName ?? null;
1633
+ const stack = input.stack ?? new NodeStack();
1634
+ let parentName = null;
1619
1635
  return pipe(
1620
1636
  staticVisitor(
1621
1637
  () => ({
@@ -1626,14 +1642,16 @@ function getTypeManifestVisitor(input) {
1626
1642
  strictType: fragment(""),
1627
1643
  value: fragment("")
1628
1644
  }),
1629
- [
1630
- ...REGISTERED_TYPE_NODE_KINDS,
1631
- ...REGISTERED_VALUE_NODE_KINDS,
1632
- "definedTypeLinkNode",
1633
- "definedTypeNode",
1634
- "accountNode",
1635
- "instructionNode"
1636
- ]
1645
+ {
1646
+ keys: [
1647
+ ...REGISTERED_TYPE_NODE_KINDS,
1648
+ ...REGISTERED_VALUE_NODE_KINDS,
1649
+ "definedTypeLinkNode",
1650
+ "definedTypeNode",
1651
+ "accountNode",
1652
+ "instructionNode"
1653
+ ]
1654
+ }
1637
1655
  ),
1638
1656
  (visitor) => extendVisitor(visitor, {
1639
1657
  visitAccount(account, { self }) {
@@ -1878,7 +1896,7 @@ function getTypeManifestVisitor(input) {
1878
1896
  const enumName = nameApi.dataType(node.enum.name);
1879
1897
  const enumFunction = nameApi.discriminatedUnionFunction(node.enum.name);
1880
1898
  const importFrom = getImportFrom(node.enum);
1881
- const enumNode = linkables.get(node.enum)?.type;
1899
+ const enumNode = linkables.get([...stack.getPath(), node.enum])?.type;
1882
1900
  const isScalar = enumNode && isNode(enumNode, "enumTypeNode") ? isScalarEnum(enumNode) : !nonScalarEnums.includes(node.enum.name);
1883
1901
  if (!node.value && isScalar) {
1884
1902
  const variantName2 = nameApi.enumVariant(node.variant);
@@ -2198,8 +2216,9 @@ ${jsDocblock(structFieldType.docs)}` : "";
2198
2216
  if (optionalFields.length === 0) {
2199
2217
  return mergedManifest;
2200
2218
  }
2201
- const instructionNode = stack.find("instructionNode");
2202
- const accountNode = stack.find("accountNode");
2219
+ const parentPath = stack.getPath();
2220
+ const instructionNode = findLastNodeFromPath(parentPath, "instructionNode");
2221
+ const accountNode = findLastNodeFromPath(parentPath, "accountNode");
2203
2222
  const discriminatorPrefix = instructionNode ? instructionNode.name : accountNode?.name;
2204
2223
  const discriminators = (instructionNode ? instructionNode.discriminators : accountNode?.discriminators) ?? [];
2205
2224
  const fieldDiscriminators = discriminators.filter(isNodeFilter("fieldDiscriminatorNode"));
@@ -2352,7 +2371,7 @@ var DEFAULT_NAME_TRANSFORMERS = {
2352
2371
  // src/getRenderMapVisitor.ts
2353
2372
  function getRenderMapVisitor(options = {}) {
2354
2373
  const linkables = new LinkableDictionary();
2355
- let program = null;
2374
+ const stack = new NodeStack();
2356
2375
  const nameTransformers = {
2357
2376
  ...DEFAULT_NAME_TRANSFORMERS,
2358
2377
  ...options.nameTransformers
@@ -2367,16 +2386,15 @@ function getRenderMapVisitor(options = {}) {
2367
2386
  const customAccountData = parseCustomDataOptions(options.customAccountData ?? [], "AccountData");
2368
2387
  const customInstructionData = parseCustomDataOptions(options.customInstructionData ?? [], "InstructionData");
2369
2388
  const getImportFrom = getImportFromFactory(options.linkOverrides ?? {}, customAccountData, customInstructionData);
2370
- const getTypeManifestVisitor2 = (parentName) => getTypeManifestVisitor({
2389
+ const typeManifestVisitor = getTypeManifestVisitor({
2371
2390
  customAccountData,
2372
2391
  customInstructionData,
2373
2392
  getImportFrom,
2374
2393
  linkables,
2375
2394
  nameApi,
2376
2395
  nonScalarEnums,
2377
- parentName
2396
+ stack
2378
2397
  });
2379
- const typeManifestVisitor = getTypeManifestVisitor2();
2380
2398
  const resolvedInstructionInputVisitor = getResolvedInstructionInputsVisitor();
2381
2399
  const globalScope = {
2382
2400
  asyncResolvers,
@@ -2393,19 +2411,18 @@ function getRenderMapVisitor(options = {}) {
2393
2411
  return render(join("pages", template), context, renderOptions);
2394
2412
  };
2395
2413
  return pipe(
2396
- staticVisitor(
2397
- () => new RenderMap(),
2398
- ["rootNode", "programNode", "pdaNode", "accountNode", "definedTypeNode", "instructionNode"]
2399
- ),
2414
+ staticVisitor(() => new RenderMap(), {
2415
+ keys: ["rootNode", "programNode", "pdaNode", "accountNode", "definedTypeNode", "instructionNode"]
2416
+ }),
2400
2417
  (v) => extendVisitor(v, {
2401
2418
  visitAccount(node) {
2402
- if (!program) {
2419
+ const accountPath = stack.getPath("accountNode");
2420
+ if (!findProgramNodeFromPath(accountPath)) {
2403
2421
  throw new Error("Account must be visited inside a program.");
2404
2422
  }
2405
2423
  const scope = {
2406
2424
  ...globalScope,
2407
- accountNode: node,
2408
- programNode: program,
2425
+ accountPath,
2409
2426
  typeManifest: visit(node, typeManifestVisitor)
2410
2427
  };
2411
2428
  const fields = resolveNestedTypeNode(node.data).fields;
@@ -2471,7 +2488,8 @@ function getRenderMapVisitor(options = {}) {
2471
2488
  );
2472
2489
  },
2473
2490
  visitInstruction(node) {
2474
- if (!program) {
2491
+ const instructionPath = stack.getPath("instructionNode");
2492
+ if (!findProgramNodeFromPath(instructionPath)) {
2475
2493
  throw new Error("Instruction must be visited inside a program.");
2476
2494
  }
2477
2495
  const instructionExtraName = nameApi.instructionExtraType(node.name);
@@ -2479,14 +2497,13 @@ function getRenderMapVisitor(options = {}) {
2479
2497
  ...globalScope,
2480
2498
  dataArgsManifest: visit(node, typeManifestVisitor),
2481
2499
  extraArgsManifest: visit(
2482
- structTypeNodeFromInstructionArgumentNodes(node.extraArguments ?? []),
2483
- getTypeManifestVisitor2({
2484
- loose: nameApi.dataArgsType(instructionExtraName),
2485
- strict: nameApi.dataType(instructionExtraName)
2486
- })
2500
+ definedTypeNode({
2501
+ name: instructionExtraName,
2502
+ type: structTypeNodeFromInstructionArgumentNodes(node.extraArguments ?? [])
2503
+ }),
2504
+ typeManifestVisitor
2487
2505
  ),
2488
- instructionNode: node,
2489
- programNode: program,
2506
+ instructionPath,
2490
2507
  renamedArgs: getRenamedArgsMap(node),
2491
2508
  resolvedInputs: visit(node, resolvedInstructionInputVisitor)
2492
2509
  };
@@ -2533,10 +2550,11 @@ function getRenderMapVisitor(options = {}) {
2533
2550
  );
2534
2551
  },
2535
2552
  visitPda(node) {
2536
- if (!program) {
2553
+ const pdaPath = stack.getPath("pdaNode");
2554
+ if (!findProgramNodeFromPath(pdaPath)) {
2537
2555
  throw new Error("Account must be visited inside a program.");
2538
2556
  }
2539
- const scope = { ...globalScope, pdaNode: node, programNode: program };
2557
+ const scope = { ...globalScope, pdaPath };
2540
2558
  const pdaFunctionFragment = getPdaFunctionFragment(scope);
2541
2559
  const imports = new ImportMap().mergeWith(pdaFunctionFragment);
2542
2560
  return new RenderMap().add(
@@ -2548,7 +2566,6 @@ function getRenderMapVisitor(options = {}) {
2548
2566
  );
2549
2567
  },
2550
2568
  visitProgram(node, { self }) {
2551
- program = node;
2552
2569
  const customDataDefinedType = [
2553
2570
  ...getDefinedTypeNodesToExtract(node.accounts, customAccountData),
2554
2571
  ...getDefinedTypeNodesToExtract(node.instructions, customInstructionData)
@@ -2578,11 +2595,10 @@ function getRenderMapVisitor(options = {}) {
2578
2595
  })
2579
2596
  );
2580
2597
  renderMap.mergeWith(
2581
- ...getAllInstructionsWithSubs(program, {
2598
+ ...getAllInstructionsWithSubs(node, {
2582
2599
  leavesOnly: !renderParentInstructions
2583
2600
  }).map((ix) => visit(ix, self))
2584
2601
  );
2585
- program = null;
2586
2602
  return renderMap;
2587
2603
  },
2588
2604
  visitRoot(node, { self }) {
@@ -2649,7 +2665,8 @@ function getRenderMapVisitor(options = {}) {
2649
2665
  return map.add("index.ts", render2("rootIndex.njk", ctx)).mergeWith(...getAllPrograms(node).map((p) => visit(p, self)));
2650
2666
  }
2651
2667
  }),
2652
- (v) => recordLinkablesVisitor(v, linkables)
2668
+ (v) => recordNodeStackVisitor(v, stack),
2669
+ (v) => recordLinkablesOnFirstVisitVisitor(v, linkables)
2653
2670
  );
2654
2671
  }
2655
2672
  function getRenamedArgsMap(instruction) {