@codama/renderers-js 1.5.4 → 1.6.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.
@@ -1,10 +1,12 @@
1
1
  import { camelCase, pascalCase, snakeCase, titleCase, kebabCase, capitalize, REGISTERED_TYPE_NODE_KINDS, REGISTERED_VALUE_NODE_KINDS, isNodeFilter, resolveNestedTypeNode, structTypeNodeFromInstructionArgumentNodes, isNode, isScalarEnum, structTypeNode, structFieldTypeNode, getAllPrograms, getAllPdas, getAllAccounts, getAllInstructionsWithSubs, getAllDefinedTypes, definedTypeLinkNode, definedTypeNode, isDataEnum, accountValueNode, argumentValueNode, parseOptionalAccountStrategy, VALUE_NODES, getAllInstructionArguments, constantDiscriminatorNode, constantValueNodeFromBytes, constantValueNode, assertIsNode } from '@codama/nodes';
2
- import { setFragmentContent, mapFragmentContent, createRenderMap, mergeRenderMaps, deleteDirectory, writeRenderMap, createFragmentTemplate, mapRenderMapContentAsync, joinPath, fileExists, readJson, writeFile } from '@codama/renderers-core';
2
+ import { setFragmentContent, mapFragmentContent, createRenderMap, mergeRenderMaps, deleteDirectory, mapRenderMapContentAsync, writeRenderMap, createFragmentTemplate, joinPath, fileExists, readJson, writeFile } from '@codama/renderers-core';
3
3
  import { NodeStack, pipe, staticVisitor, extendVisitor, visit, findLastNodeFromPath, recordNodeStackVisitor, LinkableDictionary, getResolvedInstructionInputsVisitor, getByteSizeVisitor, recordLinkablesOnFirstVisitVisitor, rootNodeVisitor, findProgramNodeFromPath, getLastNodeFromPath, findInstructionNodeFromPath, deduplicateInstructionDependencies } from '@codama/visitors-core';
4
4
  import { getBase64Encoder, getBase58Encoder, getBase16Encoder, getUtf8Encoder, getBase64Decoder } from '@solana/codecs-strings';
5
- import { format } from 'prettier';
5
+ import 'prettier';
6
+ import * as babelPlugin from 'prettier/plugins/babel';
6
7
  import * as estreePlugin from 'prettier/plugins/estree';
7
8
  import * as typeScriptPlugin from 'prettier/plugins/typescript';
9
+ import { format } from 'prettier/standalone';
8
10
  import { CodamaError, CODAMA_ERROR__UNEXPECTED_NODE_KIND, logWarn, CODAMA_ERROR__RENDERERS__MISSING_DEPENDENCY_VERSIONS } from '@codama/errors';
9
11
  import { subset, minVersion, lt } from 'semver';
10
12
 
@@ -188,6 +190,7 @@ var DEFAULT_NAME_TRANSFORMERS = {
188
190
  programInstructionsEnum: (name) => `${pascalCase(name)}Instruction`,
189
191
  programInstructionsEnumVariant: (name) => `${pascalCase(name)}`,
190
192
  programInstructionsIdentifierFunction: (name) => `identify${pascalCase(name)}Instruction`,
193
+ programInstructionsParseFunction: (name) => `parse${pascalCase(name)}Instruction`,
191
194
  programInstructionsParsedUnionType: (name) => `Parsed${pascalCase(name)}Instruction`,
192
195
  programIsErrorFunction: (name) => `is${pascalCase(name)}Error`,
193
196
  resolverFunction: (name) => `${camelCase(name)}`
@@ -384,25 +387,17 @@ var getDefinedTypeNodesToExtract = (nodes, parsedCustomDataOptions) => nodes.fla
384
387
  ];
385
388
  });
386
389
  var DEFAULT_PRETTIER_OPTIONS = {
387
- arrowParens: "always",
388
- parser: "typescript",
389
- plugins: [estreePlugin, typeScriptPlugin],
390
- printWidth: 80,
391
- semi: true,
392
- singleQuote: true,
393
- tabWidth: 2,
394
- trailingComma: "es5",
395
- useTabs: false
390
+ plugins: [estreePlugin, typeScriptPlugin, babelPlugin]
396
391
  };
397
- async function formatCode(renderMap, options) {
392
+ async function getCodeFormatter(options) {
398
393
  const shouldFormatCode = options.formatCode ?? true;
399
- if (!shouldFormatCode) return renderMap;
394
+ if (!shouldFormatCode) return (code) => Promise.resolve(code);
400
395
  const prettierOptions = {
401
396
  ...DEFAULT_PRETTIER_OPTIONS,
402
397
  ...await resolvePrettierOptions(options.packageFolder),
403
398
  ...options.prettierOptions
404
399
  };
405
- return await mapRenderMapContentAsync(renderMap, (code) => format(code, prettierOptions));
400
+ return (code, filepath) => format(code, { ...prettierOptions, filepath });
406
401
  }
407
402
  async function resolvePrettierOptions(packageFolder) {
408
403
  {
@@ -466,7 +461,7 @@ var DEFAULT_DEPENDENCY_VERSIONS = {
466
461
  "@solana/rpc-types": "^5.0.0",
467
462
  "@solana/signers": "^5.0.0"
468
463
  };
469
- function syncPackageJson(renderMap, options) {
464
+ async function syncPackageJson(renderMap, formatCode, options) {
470
465
  const shouldSyncPackageJson = options.syncPackageJson ?? false;
471
466
  const packageFolder = options.packageFolder;
472
467
  if (!packageFolder) {
@@ -490,10 +485,10 @@ function syncPackageJson(renderMap, options) {
490
485
  }
491
486
  if (fileExists(packageJsonPath)) {
492
487
  const packageJson = updateExistingPackageJson(readJson(packageJsonPath), usedDependencies);
493
- writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n");
488
+ await writePackageJson(packageJson, packageJsonPath, formatCode);
494
489
  } else {
495
490
  const packageJson = createNewPackageJson(usedDependencies);
496
- writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n");
491
+ await writePackageJson(packageJson, packageJsonPath, formatCode);
497
492
  }
498
493
  }
499
494
  function createNewPackageJson(dependencyVersions) {
@@ -621,6 +616,11 @@ function updateDependency(dependencyGroup, dependency, requiredRange) {
621
616
  if (!shouldUpdateRange(dependency, currentRange, requiredRange)) return;
622
617
  dependencyGroup[dependency] = requiredRange;
623
618
  }
619
+ async function writePackageJson(packageJson, packageJsonPath, formatCode) {
620
+ const packageJsonContent = JSON.stringify(packageJson, null, 2) + "\n";
621
+ const formattedContent = await formatCode(packageJsonContent, packageJsonPath);
622
+ writeFile(packageJsonPath, formattedContent);
623
+ }
624
624
 
625
625
  // src/fragments/accountFetchHelpers.ts
626
626
  function getAccountFetchHelpersFragment(scope) {
@@ -2088,7 +2088,8 @@ function getProgramInstructionsFragment(scope) {
2088
2088
  [
2089
2089
  getProgramInstructionsEnumFragment(scopeWithInstructions),
2090
2090
  getProgramInstructionsIdentifierFunctionFragment(scopeWithInstructions),
2091
- getProgramInstructionsParsedUnionTypeFragment(scopeWithInstructions)
2091
+ getProgramInstructionsParsedUnionTypeFragment(scopeWithInstructions),
2092
+ getProgramInstructionsParseFunctionFragment(scopeWithInstructions)
2092
2093
  ],
2093
2094
  (c) => c.join("\n\n")
2094
2095
  );
@@ -2157,6 +2158,39 @@ function getProgramInstructionsParsedUnionTypeFragment(scope) {
2157
2158
  (c) => c.join("\n")
2158
2159
  );
2159
2160
  }
2161
+ function getProgramInstructionsParseFunctionFragment(scope) {
2162
+ const { programNode, nameApi, allInstructions } = scope;
2163
+ const instructionsWithDiscriminators = allInstructions.filter(
2164
+ (instruction) => (instruction.discriminators ?? []).length > 0
2165
+ );
2166
+ if (instructionsWithDiscriminators.length === 0) return;
2167
+ const programInstructionsEnum = nameApi.programInstructionsEnum(programNode.name);
2168
+ const programInstructionsIdentifierFunction = nameApi.programInstructionsIdentifierFunction(programNode.name);
2169
+ const programInstructionsParsedUnionType = nameApi.programInstructionsParsedUnionType(programNode.name);
2170
+ const parseFunction = nameApi.programInstructionsParseFunction(programNode.name);
2171
+ const switchCases = mergeFragments(
2172
+ allInstructions.map((instruction) => {
2173
+ const enumVariant = nameApi.programInstructionsEnumVariant(instruction.name);
2174
+ const parseFunction2 = use(nameApi.instructionParseFunction(instruction.name), "generatedInstructions");
2175
+ const assertIsInstructionWithAccounts = use("assertIsInstructionWithAccounts", "solanaInstructions");
2176
+ const hasAccounts = instruction.accounts.length > 0;
2177
+ const assertionsCode = hasAccounts ? fragment`${assertIsInstructionWithAccounts}(instruction);\n` : fragment``;
2178
+ return fragment`case ${programInstructionsEnum}.${enumVariant}: { ${assertionsCode}return { instructionType: ${programInstructionsEnum}.${enumVariant}, ...${parseFunction2}(instruction) }; }`;
2179
+ }),
2180
+ (c) => c.join("\n")
2181
+ );
2182
+ return fragment`
2183
+ export function ${parseFunction}<TProgram extends string>(
2184
+ instruction: ${use("type Instruction", "solanaInstructions")}<TProgram>
2185
+ & ${use("type InstructionWithData", "solanaInstructions")}<${use("type ReadonlyUint8Array", "solanaCodecsCore")}>
2186
+ ): ${programInstructionsParsedUnionType}<TProgram> {
2187
+ const instructionType = ${programInstructionsIdentifierFunction}(instruction);
2188
+ switch (instructionType) {
2189
+ ${switchCases}
2190
+ default: throw new Error("Unrecognized instruction type: " + instructionType);
2191
+ }
2192
+ }`;
2193
+ }
2160
2194
 
2161
2195
  // src/fragments/programPage.ts
2162
2196
  function getProgramPageFragment(scope) {
@@ -3202,8 +3236,9 @@ function renderVisitor(path, options = {}) {
3202
3236
  deleteDirectory(path);
3203
3237
  }
3204
3238
  let renderMap = visit(root, getRenderMapVisitor(options));
3205
- renderMap = await formatCode(renderMap, options);
3206
- syncPackageJson(renderMap, options);
3239
+ const formatCode = await getCodeFormatter(options);
3240
+ renderMap = await mapRenderMapContentAsync(renderMap, formatCode);
3241
+ await syncPackageJson(renderMap, formatCode, options);
3207
3242
  writeRenderMap(renderMap, path);
3208
3243
  });
3209
3244
  }