Browse Source

Feat: mark more fields as optional (#512)

Sammy Harris 8 months ago
parent
commit
5071455b05
25 changed files with 60 additions and 31 deletions
  1. 11 0
      .changeset/new-cycles-sip.md
  2. 1 1
      packages/node-types/src/AccountNode.ts
  3. 1 1
      packages/node-types/src/DefinedTypeNode.ts
  4. 1 1
      packages/node-types/src/ErrorNode.ts
  5. 2 2
      packages/node-types/src/InstructionAccountNode.ts
  6. 1 1
      packages/node-types/src/InstructionArgumentNode.ts
  7. 4 2
      packages/node-types/src/InstructionNode.ts
  8. 1 1
      packages/node-types/src/InstructionRemainingAccountsNode.ts
  9. 1 1
      packages/node-types/src/PdaNode.ts
  10. 1 1
      packages/node-types/src/ProgramNode.ts
  11. 1 1
      packages/node-types/src/contextualValueNodes/ResolverValueNode.ts
  12. 1 1
      packages/node-types/src/pdaSeedNodes/VariablePdaSeedNode.ts
  13. 1 1
      packages/node-types/src/typeNodes/OptionTypeNode.ts
  14. 1 1
      packages/node-types/src/typeNodes/StructFieldTypeNode.ts
  15. 8 1
      packages/nodes/src/InstructionNode.ts
  16. 2 1
      packages/renderers-js-umi/src/getRenderMapVisitor.ts
  17. 3 1
      packages/renderers-js-umi/src/getTypeManifestVisitor.ts
  18. 3 3
      packages/renderers-js-umi/src/renderInstructionDefaults.ts
  19. 2 2
      packages/renderers-js/src/fragments/instructionInputDefault.ts
  20. 2 2
      packages/renderers-js/src/fragments/instructionInputResolved.ts
  21. 3 1
      packages/renderers-js/src/fragments/instructionInputType.ts
  22. 3 1
      packages/renderers-js/src/getTypeManifestVisitor.ts
  23. 2 1
      packages/renderers-rust/src/getTypeManifestVisitor.ts
  24. 2 1
      packages/renderers-vixen-parser/src/getTypeManifestVisitor.ts
  25. 2 2
      packages/visitors-core/src/getResolvedInstructionInputsVisitor.ts

+ 11 - 0
.changeset/new-cycles-sip.md

@@ -0,0 +1,11 @@
+---
+'@codama/renderers-vixen-parser': patch
+'@codama/renderers-js-umi': patch
+'@codama/renderers-rust': patch
+'@codama/visitors-core': patch
+'@codama/renderers-js': patch
+'@codama/node-types': patch
+'@codama/nodes': patch
+---
+
+Marked additional node type fields as optional

+ 1 - 1
packages/node-types/src/AccountNode.ts

@@ -13,7 +13,7 @@ export interface AccountNode<
     // Data.
     readonly name: CamelCaseString;
     readonly size?: number | null;
-    readonly docs: Docs;
+    readonly docs?: Docs;
 
     // Children.
     readonly data: TData;

+ 1 - 1
packages/node-types/src/DefinedTypeNode.ts

@@ -6,7 +6,7 @@ export interface DefinedTypeNode<TType extends TypeNode = TypeNode> {
 
     // Data.
     readonly name: CamelCaseString;
-    readonly docs: Docs;
+    readonly docs?: Docs;
 
     // Children.
     readonly type: TType;

+ 1 - 1
packages/node-types/src/ErrorNode.ts

@@ -7,5 +7,5 @@ export interface ErrorNode {
     readonly name: CamelCaseString;
     readonly code: number;
     readonly message: string;
-    readonly docs: Docs;
+    readonly docs?: Docs;
 }

+ 2 - 2
packages/node-types/src/InstructionAccountNode.ts

@@ -10,8 +10,8 @@ export interface InstructionAccountNode<
     readonly name: CamelCaseString;
     readonly isWritable: boolean;
     readonly isSigner: boolean | 'either';
-    readonly isOptional: boolean;
-    readonly docs: Docs;
+    readonly isOptional?: boolean;
+    readonly docs?: Docs;
 
     // Children.
     readonly defaultValue?: TDefaultValue;

+ 1 - 1
packages/node-types/src/InstructionArgumentNode.ts

@@ -10,7 +10,7 @@ export interface InstructionArgumentNode<
     // Data.
     readonly name: CamelCaseString;
     readonly defaultValueStrategy?: 'omitted' | 'optional';
-    readonly docs: Docs;
+    readonly docs?: Docs;
 
     // Children.
     readonly type: TypeNode;

+ 4 - 2
packages/node-types/src/InstructionNode.ts

@@ -7,6 +7,8 @@ import type { CamelCaseString, Docs } from './shared';
 
 type SubInstructionNode = InstructionNode;
 
+export type OptionalAccountStrategy = 'omitted' | 'programId';
+
 export interface InstructionNode<
     TAccounts extends InstructionAccountNode[] = InstructionAccountNode[],
     TArguments extends InstructionArgumentNode[] = InstructionArgumentNode[],
@@ -22,8 +24,8 @@ export interface InstructionNode<
 
     // Data.
     readonly name: CamelCaseString;
-    readonly docs: Docs;
-    readonly optionalAccountStrategy: 'omitted' | 'programId';
+    readonly docs?: Docs;
+    readonly optionalAccountStrategy?: OptionalAccountStrategy;
 
     // Children.
     readonly accounts: TAccounts;

+ 1 - 1
packages/node-types/src/InstructionRemainingAccountsNode.ts

@@ -10,7 +10,7 @@ export interface InstructionRemainingAccountsNode<
     readonly isOptional?: boolean;
     readonly isSigner?: boolean | 'either';
     readonly isWritable?: boolean;
-    readonly docs: Docs;
+    readonly docs?: Docs;
 
     // Children.
     readonly value: TValue;

+ 1 - 1
packages/node-types/src/PdaNode.ts

@@ -6,7 +6,7 @@ export interface PdaNode<TSeeds extends PdaSeedNode[] = PdaSeedNode[]> {
 
     // Data.
     readonly name: CamelCaseString;
-    readonly docs: Docs;
+    readonly docs?: Docs;
     readonly programId?: string;
 
     // Children.

+ 1 - 1
packages/node-types/src/ProgramNode.ts

@@ -19,7 +19,7 @@ export interface ProgramNode<
     readonly publicKey: string;
     readonly version: ProgramVersion;
     readonly origin?: 'anchor' | 'shank';
-    readonly docs: Docs;
+    readonly docs?: Docs;
 
     // Children.
     readonly accounts: TAccounts;

+ 1 - 1
packages/node-types/src/contextualValueNodes/ResolverValueNode.ts

@@ -9,7 +9,7 @@ export interface ResolverValueNode<
 
     // Data.
     readonly name: CamelCaseString;
-    readonly docs: Docs;
+    readonly docs?: Docs;
 
     // Children.
     readonly dependsOn?: TDependsOn;

+ 1 - 1
packages/node-types/src/pdaSeedNodes/VariablePdaSeedNode.ts

@@ -6,7 +6,7 @@ export interface VariablePdaSeedNode<TType extends TypeNode = TypeNode> {
 
     // Data.
     readonly name: CamelCaseString;
-    readonly docs: Docs;
+    readonly docs?: Docs;
 
     // Children.
     readonly type: TType;

+ 1 - 1
packages/node-types/src/typeNodes/OptionTypeNode.ts

@@ -9,7 +9,7 @@ export interface OptionTypeNode<
     readonly kind: 'optionTypeNode';
 
     // Data.
-    readonly fixed: boolean;
+    readonly fixed?: boolean;
 
     // Children.
     readonly item: TItem;

+ 1 - 1
packages/node-types/src/typeNodes/StructFieldTypeNode.ts

@@ -11,7 +11,7 @@ export interface StructFieldTypeNode<
     // Data.
     readonly name: CamelCaseString;
     readonly defaultValueStrategy?: 'omitted' | 'optional';
-    readonly docs: Docs;
+    readonly docs?: Docs;
 
     // Children.
     readonly type: TType;

+ 8 - 1
packages/nodes/src/InstructionNode.ts

@@ -5,6 +5,7 @@ import type {
     InstructionByteDeltaNode,
     InstructionNode,
     InstructionRemainingAccountsNode,
+    OptionalAccountStrategy,
     ProgramNode,
     RootNode,
 } from '@codama/node-types';
@@ -76,7 +77,7 @@ export function instructionNode<
         // Data.
         name: camelCase(input.name),
         docs: parseDocs(input.docs),
-        optionalAccountStrategy: input.optionalAccountStrategy ?? 'programId',
+        optionalAccountStrategy: parseOptionalAccountStrategy(input.optionalAccountStrategy),
 
         // Children.
         accounts: (input.accounts ?? []) as TAccounts,
@@ -89,6 +90,12 @@ export function instructionNode<
     });
 }
 
+export function parseOptionalAccountStrategy(
+    optionalAccountStrategy: OptionalAccountStrategy | undefined,
+): OptionalAccountStrategy {
+    return optionalAccountStrategy ?? 'programId';
+}
+
 export function getAllInstructionArguments(node: InstructionNode): InstructionArgumentNode[] {
     return [...node.arguments, ...(node.extraArguments ?? [])];
 }

+ 2 - 1
packages/renderers-js-umi/src/getRenderMapVisitor.ts

@@ -13,6 +13,7 @@ import {
     isDataEnum,
     isNode,
     isNodeFilter,
+    parseOptionalAccountStrategy,
     pascalCase,
     ProgramNode,
     resolveNestedTypeNode,
@@ -340,7 +341,7 @@ export function getRenderMapVisitor(options: GetRenderMapOptions = {}): Visitor<
                             const renderedInput = renderInstructionDefaults(
                                 input,
                                 typeManifestVisitor,
-                                node.optionalAccountStrategy,
+                                parseOptionalAccountStrategy(node.optionalAccountStrategy),
                                 argObject,
                                 getImportFrom,
                             );

+ 3 - 1
packages/renderers-js-umi/src/getTypeManifestVisitor.ts

@@ -8,6 +8,7 @@ import {
     isScalarEnum,
     isUnsignedInteger,
     NumberTypeNode,
+    parseDocs,
     pascalCase,
     REGISTERED_TYPE_NODE_KINDS,
     REGISTERED_VALUE_NODE_KINDS,
@@ -730,7 +731,8 @@ export function getTypeManifestVisitor(input: {
                 visitStructFieldType(structFieldType, { self }) {
                     const name = camelCase(structFieldType.name);
                     const fieldChild = visit(structFieldType.type, self);
-                    const docblock = structFieldType.docs.length > 0 ? `\n${jsDocblock(structFieldType.docs)}` : '';
+                    const structFieldDocs = parseDocs(structFieldType.docs);
+                    const docblock = structFieldDocs.length > 0 ? `\n${jsDocblock(structFieldDocs)}` : '';
                     const baseField = {
                         ...fieldChild,
                         looseType: `${docblock}${name}: ${fieldChild.looseType}; `,

+ 3 - 3
packages/renderers-js-umi/src/renderInstructionDefaults.ts

@@ -1,5 +1,5 @@
 /* eslint-disable no-case-declarations */
-import { camelCase, InstructionInputValueNode, isNode, pascalCase } from '@codama/nodes';
+import { camelCase, InstructionInputValueNode, isNode, OptionalAccountStrategy, pascalCase } from '@codama/nodes';
 import { ResolvedInstructionInput, visit } from '@codama/visitors-core';
 
 import { ContextMap } from './ContextMap';
@@ -10,7 +10,7 @@ import { GetImportFromFunction } from './utils';
 export function renderInstructionDefaults(
     input: ResolvedInstructionInput,
     typeManifestVisitor: ReturnType<typeof getTypeManifestVisitor>,
-    optionalAccountStrategy: 'omitted' | 'programId',
+    optionalAccountStrategy: OptionalAccountStrategy,
     argObject: string,
     getImportFrom: GetImportFromFunction,
 ): {
@@ -272,7 +272,7 @@ export function renderInstructionDefaults(
 function renderNestedInstructionDefault(
     input: ResolvedInstructionInput,
     typeManifestVisitor: ReturnType<typeof getTypeManifestVisitor>,
-    optionalAccountStrategy: 'omitted' | 'programId',
+    optionalAccountStrategy: OptionalAccountStrategy,
     defaultValue: InstructionInputValueNode | undefined,
     argObject: string,
     getImportFrom: GetImportFromFunction,

+ 2 - 2
packages/renderers-js/src/fragments/instructionInputDefault.ts

@@ -1,5 +1,5 @@
 /* eslint-disable no-case-declarations */
-import { camelCase, InstructionInputValueNode, isNode } from '@codama/nodes';
+import { camelCase, InstructionInputValueNode, isNode, OptionalAccountStrategy } from '@codama/nodes';
 import { ResolvedInstructionInput, visit } from '@codama/visitors-core';
 
 import { GlobalFragmentScope } from '../getRenderMapVisitor';
@@ -9,7 +9,7 @@ import { Fragment, fragment, mergeFragments } from './common';
 export function getInstructionInputDefaultFragment(
     scope: Pick<GlobalFragmentScope, 'asyncResolvers' | 'getImportFrom' | 'nameApi' | 'typeManifestVisitor'> & {
         input: ResolvedInstructionInput;
-        optionalAccountStrategy: 'omitted' | 'programId';
+        optionalAccountStrategy: OptionalAccountStrategy;
         useAsync: boolean;
     },
 ): Fragment {

+ 2 - 2
packages/renderers-js/src/fragments/instructionInputResolved.ts

@@ -1,4 +1,4 @@
-import { camelCase, InstructionNode, isNode } from '@codama/nodes';
+import { camelCase, InstructionNode, isNode, parseOptionalAccountStrategy } from '@codama/nodes';
 import { getLastNodeFromPath, NodePath, ResolvedInstructionInput } from '@codama/visitors-core';
 
 import type { GlobalFragmentScope } from '../getRenderMapVisitor';
@@ -17,7 +17,7 @@ export function getInstructionInputResolvedFragment(
         const inputFragment = getInstructionInputDefaultFragment({
             ...scope,
             input,
-            optionalAccountStrategy: instructionNode.optionalAccountStrategy,
+            optionalAccountStrategy: parseOptionalAccountStrategy(instructionNode.optionalAccountStrategy),
         });
         if (!inputFragment.render) return [];
         const camelName = camelCase(input.name);

+ 3 - 1
packages/renderers-js/src/fragments/instructionInputType.ts

@@ -4,6 +4,7 @@ import {
     InstructionArgumentNode,
     InstructionNode,
     isNode,
+    parseDocs,
     pascalCase,
 } from '@codama/nodes';
 import {
@@ -76,7 +77,8 @@ function getAccountsFragment(
             !!resolvedAccount.defaultValue &&
             !isNode(resolvedAccount.defaultValue, ['identityValueNode', 'payerValueNode']) &&
             (useAsync || !isAsyncDefaultValue(resolvedAccount.defaultValue, asyncResolvers));
-        const docblock = account.docs.length > 0 ? jsDocblock(account.docs) : '';
+        const accountDocs = parseDocs(account.docs);
+        const docblock = accountDocs.length > 0 ? jsDocblock(accountDocs) : '';
         const optionalSign = hasDefaultValue || resolvedAccount.isOptional ? '?' : '';
         return getAccountTypeFragment(resolvedAccount).mapRender(
             r => `${docblock}${camelCase(account.name)}${optionalSign}: ${r};`,

+ 3 - 1
packages/renderers-js/src/getTypeManifestVisitor.ts

@@ -5,6 +5,7 @@ import {
     isNode,
     isNodeFilter,
     isScalarEnum,
+    parseDocs,
     REGISTERED_TYPE_NODE_KINDS,
     REGISTERED_VALUE_NODE_KINDS,
     resolveNestedTypeNode,
@@ -777,7 +778,8 @@ export function getTypeManifestVisitor(input: {
                 visitStructFieldType(structFieldType, { self }) {
                     const name = camelCase(structFieldType.name);
                     const childManifest = visit(structFieldType.type, self);
-                    const docblock = structFieldType.docs.length > 0 ? `\n${jsDocblock(structFieldType.docs)}` : '';
+                    const structFieldDocs = parseDocs(structFieldType.docs);
+                    const docblock = structFieldDocs.length > 0 ? `\n${jsDocblock(structFieldDocs)}` : '';
                     const originalLooseType = childManifest.looseType.render;
                     childManifest.strictType.mapRender(r => `${docblock}${name}: ${r}; `);
                     childManifest.looseType.mapRender(r => `${docblock}${name}: ${r}; `);

+ 2 - 1
packages/renderers-rust/src/getTypeManifestVisitor.ts

@@ -7,6 +7,7 @@ import {
     isNode,
     NumberTypeNode,
     numberTypeNode,
+    parseDocs,
     pascalCase,
     prefixedCountNode,
     REGISTERED_TYPE_NODE_KINDS,
@@ -380,7 +381,7 @@ export function getTypeManifestVisitor(options: {
                     nestedStruct = originalNestedStruct;
 
                     const fieldName = snakeCase(structFieldType.name);
-                    const docblock = rustDocblock(structFieldType.docs);
+                    const docblock = rustDocblock(parseDocs(structFieldType.docs));
                     const resolvedNestedType = resolveNestedTypeNode(structFieldType.type);
 
                     let derive = '';

+ 2 - 1
packages/renderers-vixen-parser/src/getTypeManifestVisitor.ts

@@ -7,6 +7,7 @@ import {
     isNode,
     NumberTypeNode,
     numberTypeNode,
+    parseDocs,
     pascalCase,
     prefixedCountNode,
     REGISTERED_TYPE_NODE_KINDS,
@@ -380,7 +381,7 @@ export function getTypeManifestVisitor(options: {
                     nestedStruct = originalNestedStruct;
 
                     const fieldName = snakeCase(structFieldType.name);
-                    const docblock = rustDocblock(structFieldType.docs);
+                    const docblock = rustDocblock(parseDocs(structFieldType.docs));
                     const resolvedNestedType = resolveNestedTypeNode(structFieldType.type);
 
                     let derive = '';

+ 2 - 2
packages/visitors-core/src/getResolvedInstructionInputsVisitor.ts

@@ -102,7 +102,7 @@ export function getResolvedInstructionInputsVisitor(
                     isNode(argument.defaultValue, 'accountBumpValueNode') &&
                     argument.defaultValue.name === account.name,
             ),
-            resolvedIsOptional: account.isOptional,
+            resolvedIsOptional: !!account.isOptional,
             resolvedIsSigner: account.isSigner,
         };
 
@@ -113,7 +113,7 @@ export function getResolvedInstructionInputsVisitor(
                 const resolvedIsSigner = account.isSigner === true && defaultAccount.isSigner === true;
                 const resolvedIsOptionalSigner = !resolvedIsPublicKey && !resolvedIsSigner;
                 localResolved.resolvedIsSigner = resolvedIsOptionalSigner ? 'either' : resolvedIsSigner;
-                localResolved.resolvedIsOptional = defaultAccount.isOptional;
+                localResolved.resolvedIsOptional = !!defaultAccount.isOptional;
                 break;
             case 'publicKeyValueNode':
             case 'programLinkNode':