codama-renderers-dart 0.5.4 → 0.5.6

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 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC1F,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC1F,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;eAC7C,aAAa"}
@@ -1 +1 @@
1
- {"version":3,"file":"discriminators.d.ts","sourceRoot":"","sources":["../../../src/utils/discriminators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,eAAe,EAEhB,MAAM,eAAe,CAAC;AAIvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQ9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,KAAK,iBAAiB,GAAG,WAAW,GAAG,eAAe,CAAC;AAEvD;;GAEG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,WAAW,GACjB,QAAQ,CAwDV"}
1
+ {"version":3,"file":"discriminators.d.ts","sourceRoot":"","sources":["../../../src/utils/discriminators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,eAAe,EAEhB,MAAM,eAAe,CAAC;AAIvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQ9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,KAAK,iBAAiB,GAAG,WAAW,GAAG,eAAe,CAAC;AAEvD;;GAEG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,WAAW,GACjB,QAAQ,CA+DV"}
@@ -1 +1 @@
1
- {"version":3,"file":"importMap.d.ts","sourceRoot":"","sources":["../../../src/utils/importMap.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsB5D,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAqB;IAErC;;;OAGG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKzB;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAOrC;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,CAEzB;IAED;;;OAGG;IACH,OAAO,CAAC,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,EAAE;IAgC3D;;OAEG;IACH,QAAQ,CAAC,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM;CAyB3D"}
1
+ {"version":3,"file":"importMap.d.ts","sourceRoot":"","sources":["../../../src/utils/importMap.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsB5D,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAqB;IAErC;;;OAGG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGxB;IAED;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAKpC;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,CAEzB;IAED;;;OAGG;IACH,OAAO,CAAC,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,EAAE,CA8B1D;IAED;;OAEG;IACH,QAAQ,CAAC,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,CAwBzD;CACF"}
@@ -1,6 +1,28 @@
1
1
  import type { LinkableDictionary } from "@codama/visitors-core";
2
2
  import type { DartNameApi } from "./nameTransformers.js";
3
3
  import type { TypeManifestVisitor } from "../visitors/getTypeManifestVisitor.js";
4
+ /**
5
+ * A hand-written codec that backs a defined-type link in the rendered IDL.
6
+ *
7
+ * Some IDL fields cannot be expressed with Codama type nodes and need a
8
+ * hand-written codec instead — for example, the Token-2022 TLV extension
9
+ * region, which stops at the first `Uninitialized` header rather than
10
+ * consuming every trailing byte. Codama has no "stop at a discriminator" type
11
+ * node, so the IDL is prepared to link the inner type to a name and the
12
+ * renderer is told which hand-written codec backs that link. Wrappers around
13
+ * the link (`Option`, `HiddenPrefix`, …) still come from the IDL, so the wire
14
+ * format is unchanged.
15
+ */
16
+ export interface LinkOverride {
17
+ /** The Dart file the codec lives in, relative to the package's `lib/`. */
18
+ path: string;
19
+ /** The Dart type the link resolves to, e.g. `List<Extension>`. */
20
+ type: string;
21
+ /** The encoder expression, e.g. `getExtensionsEncoder()`. */
22
+ encoder: string;
23
+ /** The decoder expression, e.g. `getExtensionsDecoder()`. */
24
+ decoder: string;
25
+ }
4
26
  /**
5
27
  * Options for the top-level renderVisitor.
6
28
  */
@@ -22,6 +44,13 @@ export interface GetRenderMapOptions {
22
44
  nameApi?: Partial<DartNameApi>;
23
45
  /** Dependency map overrides (logical module -> Dart package URI). */
24
46
  dependencyMap?: Record<string, string>;
47
+ /**
48
+ * Hand-written codec overrides for defined-type links, keyed by the link
49
+ * name as it appears in Codama nodes. A link with a matching key emits the
50
+ * override's type and codec expressions instead of resolving to a generated
51
+ * type file, and imports the override's Dart file.
52
+ */
53
+ linkOverrides?: Record<string, LinkOverride>;
25
54
  }
26
55
  /**
27
56
  * Shared rendering context passed to fragment generators.
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/utils/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,mBAAmB;IACxD,2EAA2E;IAC3E,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,OAAO,EAAE,WAAW,CAAC;IACrB,0DAA0D;IAC1D,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,sDAAsD;IACtD,SAAS,EAAE,kBAAkB,CAAC;IAC9B,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gEAAgE;IAChE,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/utils/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjF;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,mBAAmB;IACxD,2EAA2E;IAC3E,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,OAAO,EAAE,WAAW,CAAC;IACrB,0DAA0D;IAC1D,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,sDAAsD;IACtD,SAAS,EAAE,kBAAkB,CAAC;IAC9B,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gEAAgE;IAChE,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"wellKnownAddresses.d.ts","sourceRoot":"","sources":["../../../src/utils/wellKnownAddresses.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAsD3D,CAAC"}
1
+ {"version":3,"file":"wellKnownAddresses.d.ts","sourceRoot":"","sources":["../../../src/utils/wellKnownAddresses.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAuD3D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"getRenderMapVisitor.d.ts","sourceRoot":"","sources":["../../../src/visitors/getRenderMapVisitor.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,OAAO,EASb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,qBAAqB,CAAC;AAa5E;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,aAAa,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,SAAS,CAAC,CA2K9H"}
1
+ {"version":3,"file":"getRenderMapVisitor.d.ts","sourceRoot":"","sources":["../../../src/visitors/getRenderMapVisitor.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,OAAO,EASb,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,qBAAqB,CAAC;AAa5E;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,aAAa,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,SAAS,CAAC,CA4K9H"}
@@ -2,6 +2,7 @@ import { type CamelCaseString } from "@codama/nodes";
2
2
  import { type LinkableDictionary, type NodeStack, type Visitor } from "@codama/visitors-core";
3
3
  import { type TypeManifest } from "../utils/index.js";
4
4
  import { type DartNameApi } from "../utils/nameTransformers.js";
5
+ import type { LinkOverride } from "../utils/options.js";
5
6
  /**
6
7
  * Type alias for the type manifest visitor.
7
8
  */
@@ -15,5 +16,6 @@ export declare function getTypeManifestVisitor(input: {
15
16
  linkables: LinkableDictionary;
16
17
  stack: NodeStack;
17
18
  nonScalarEnums?: CamelCaseString[];
18
- }): Visitor<TypeManifest, "accountBumpValueNode" | "accountFieldValueNode" | "accountValueNode" | "argumentValueNode" | "conditionalValueNode" | "identityValueNode" | "payerValueNode" | "pdaValueNode" | "programIdValueNode" | "resolverValueNode" | "programLinkNode" | "arrayValueNode" | "booleanValueNode" | "bytesValueNode" | "constantValueNode" | "enumValueNode" | "injectedValueNode" | "mapValueNode" | "noneValueNode" | "numberValueNode" | "publicKeyValueNode" | "setValueNode" | "someValueNode" | "stringValueNode" | "structValueNode" | "tupleValueNode" | "amountTypeNode" | "arrayTypeNode" | "booleanTypeNode" | "bytesTypeNode" | "dateTimeTypeNode" | "enumTypeNode" | "fixedSizeTypeNode" | "hiddenPrefixTypeNode" | "hiddenSuffixTypeNode" | "mapTypeNode" | "numberTypeNode" | "optionTypeNode" | "postOffsetTypeNode" | "preOffsetTypeNode" | "publicKeyTypeNode" | "remainderOptionTypeNode" | "sentinelTypeNode" | "setTypeNode" | "sizePrefixTypeNode" | "solAmountTypeNode" | "stringTypeNode" | "structTypeNode" | "tupleTypeNode" | "zeroableOptionTypeNode" | "structFieldDisplayNode" | "constantDiscriminatorNode" | "fieldDiscriminatorNode" | "sizeDiscriminatorNode" | "instructionAccountDisplayNode" | "instructionStatusNode" | "accountNode" | "constantNode" | "definedTypeNode" | "errorNode" | "eventNode" | "instructionAccountNode" | "instructionArgumentNode" | "instructionByteDeltaNode" | "instructionNode" | "instructionRemainingAccountsNode" | "pdaNode" | "pluginNode" | "programNode" | "providedNode" | "pdaSeedValueNode" | "fixedCountNode" | "prefixedCountNode" | "remainderCountNode" | "amountNumberDisplayNode" | "dateTimeNumberDisplayNode" | "durationNumberDisplayNode" | "enumVariantDisplayNode" | "instructionDisplayNode" | "stringDisplayNode" | "accountLinkNode" | "definedTypeLinkNode" | "instructionAccountLinkNode" | "instructionArgumentLinkNode" | "instructionLinkNode" | "pdaLinkNode" | "constantPdaSeedNode" | "variablePdaSeedNode" | "enumEmptyVariantTypeNode" | "enumStructVariantTypeNode" | "enumTupleVariantTypeNode" | "structFieldTypeNode" | "mapEntryValueNode" | "structFieldValueNode" | "rootNode">;
19
+ linkOverrides?: Record<string, LinkOverride>;
20
+ }): Visitor<TypeManifest, "accountBumpValueNode" | "accountFieldValueNode" | "accountLinkNode" | "accountNode" | "accountValueNode" | "amountNumberDisplayNode" | "amountTypeNode" | "argumentValueNode" | "arrayTypeNode" | "arrayValueNode" | "booleanTypeNode" | "booleanValueNode" | "bytesTypeNode" | "bytesValueNode" | "conditionalValueNode" | "constantDiscriminatorNode" | "constantNode" | "constantPdaSeedNode" | "constantValueNode" | "dateTimeNumberDisplayNode" | "dateTimeTypeNode" | "definedTypeLinkNode" | "definedTypeNode" | "durationNumberDisplayNode" | "enumEmptyVariantTypeNode" | "enumStructVariantTypeNode" | "enumTupleVariantTypeNode" | "enumTypeNode" | "enumValueNode" | "enumVariantDisplayNode" | "errorNode" | "eventNode" | "fieldDiscriminatorNode" | "fixedCountNode" | "fixedSizeTypeNode" | "hiddenPrefixTypeNode" | "hiddenSuffixTypeNode" | "identityValueNode" | "injectedValueNode" | "instructionAccountDisplayNode" | "instructionAccountLinkNode" | "instructionAccountNode" | "instructionArgumentLinkNode" | "instructionArgumentNode" | "instructionByteDeltaNode" | "instructionDisplayNode" | "instructionLinkNode" | "instructionNode" | "instructionRemainingAccountsNode" | "instructionStatusNode" | "mapEntryValueNode" | "mapTypeNode" | "mapValueNode" | "noneValueNode" | "numberTypeNode" | "numberValueNode" | "optionTypeNode" | "payerValueNode" | "pdaLinkNode" | "pdaNode" | "pdaSeedValueNode" | "pdaValueNode" | "pluginNode" | "postOffsetTypeNode" | "preOffsetTypeNode" | "prefixedCountNode" | "programIdValueNode" | "programLinkNode" | "programNode" | "providedNode" | "publicKeyTypeNode" | "publicKeyValueNode" | "remainderCountNode" | "remainderOptionTypeNode" | "resolverValueNode" | "rootNode" | "sentinelTypeNode" | "setTypeNode" | "setValueNode" | "sizeDiscriminatorNode" | "sizePrefixTypeNode" | "solAmountTypeNode" | "someValueNode" | "stringDisplayNode" | "stringTypeNode" | "stringValueNode" | "structFieldDisplayNode" | "structFieldTypeNode" | "structFieldValueNode" | "structTypeNode" | "structValueNode" | "tupleTypeNode" | "tupleValueNode" | "variablePdaSeedNode" | "zeroableOptionTypeNode">;
19
21
  //# sourceMappingURL=getTypeManifestVisitor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getTypeManifestVisitor.d.ts","sourceRoot":"","sources":["../../../src/visitors/getTypeManifestVisitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,eAAe,EAgCrB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,OAAO,EAIb,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAEL,KAAK,YAAY,EAKlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,8BAA8B,CAAC;AAG3E;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;CACpC,8kEA8mBA"}
1
+ {"version":3,"file":"getTypeManifestVisitor.d.ts","sourceRoot":"","sources":["../../../src/visitors/getTypeManifestVisitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,eAAe,EAgCrB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,OAAO,EAIb,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAEL,KAAK,YAAY,EAKlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC9C,8kEAooBA"}
@@ -1 +1 @@
1
- {"version":3,"file":"renderVisitor.d.ts","sourceRoot":"","sources":["../../../src/visitors/renderVisitor.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMzD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,aAAkB,6DAmE5B"}
1
+ {"version":3,"file":"renderVisitor.d.ts","sourceRoot":"","sources":["../../../src/visitors/renderVisitor.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,qBAAqB,CAAC;AAMvE;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,aAAkB,6DA2E5B"}
package/package.json CHANGED
@@ -9,12 +9,12 @@
9
9
  "devDependencies": {
10
10
  "@codama/nodes-from-anchor": "^1.5.5",
11
11
  "@codama/renderers-js": "^2.4.0",
12
- "@types/node": "25.3.0",
13
- "@vitest/coverage-v8": "4.1.0",
12
+ "@types/node": "26.5.1",
13
+ "@vitest/coverage-v8": "5.0.0",
14
14
  "rimraf": "6.1.3",
15
15
  "tsup": "8.5.1",
16
- "typescript": "5.9.3",
17
- "vitest": "4.1.0"
16
+ "typescript": "7.0.2",
17
+ "vitest": "5.0.0"
18
18
  },
19
19
  "engines": {
20
20
  "node": ">=18"
@@ -55,7 +55,7 @@
55
55
  "repository": "https://github.com/openbudgetfun/solana_kit/tree/main/packages/codama-renderers-dart",
56
56
  "type": "module",
57
57
  "types": "./dist/types/index.d.ts",
58
- "version": "0.5.4",
58
+ "version": "0.5.6",
59
59
  "scripts": {
60
60
  "build": "pnpm exec rimraf dist && pnpm exec tsup && pnpm exec tsc -p tsconfig.declarations.json",
61
61
  "lint": "eslint --ext .ts src",
@@ -67,7 +67,14 @@ export function getDiscriminatorValidationFragment(
67
67
  `Discriminator size must be a non-negative safe integer, got ${discriminator.size}.`,
68
68
  );
69
69
  }
70
- return fragment`if (bytes.length - offset != ${fragmentFromString(String(discriminator.size))}) {
70
+ // For an instruction, the discriminated size is the whole payload and
71
+ // identification depends on an exact match. For an account, the size
72
+ // describes the fixed prefix: accounts whose trailing fields are
73
+ // variable — a Token-2022 account with a TLV extension region, for
74
+ // example — are legitimately longer, so the check is a minimum.
75
+ const comparison =
76
+ node.kind === "accountNode" ? "<" : "!=";
77
+ return fragment`if (bytes.length - offset ${fragmentFromString(comparison)} ${fragmentFromString(String(discriminator.size))}) {
71
78
  throw ${use("SolanaError", "solanaErrors")}(
72
79
  ${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
73
80
  {
@@ -5,6 +5,29 @@ import type {
5
5
  import type { DartNameApi } from "./nameTransformers.js";
6
6
  import type { TypeManifestVisitor } from "../visitors/getTypeManifestVisitor.js";
7
7
 
8
+ /**
9
+ * A hand-written codec that backs a defined-type link in the rendered IDL.
10
+ *
11
+ * Some IDL fields cannot be expressed with Codama type nodes and need a
12
+ * hand-written codec instead — for example, the Token-2022 TLV extension
13
+ * region, which stops at the first `Uninitialized` header rather than
14
+ * consuming every trailing byte. Codama has no "stop at a discriminator" type
15
+ * node, so the IDL is prepared to link the inner type to a name and the
16
+ * renderer is told which hand-written codec backs that link. Wrappers around
17
+ * the link (`Option`, `HiddenPrefix`, …) still come from the IDL, so the wire
18
+ * format is unchanged.
19
+ */
20
+ export interface LinkOverride {
21
+ /** The Dart file the codec lives in, relative to the package's `lib/`. */
22
+ path: string;
23
+ /** The Dart type the link resolves to, e.g. `List<Extension>`. */
24
+ type: string;
25
+ /** The encoder expression, e.g. `getExtensionsEncoder()`. */
26
+ encoder: string;
27
+ /** The decoder expression, e.g. `getExtensionsDecoder()`. */
28
+ decoder: string;
29
+ }
30
+
8
31
  /**
9
32
  * Options for the top-level renderVisitor.
10
33
  */
@@ -27,6 +50,13 @@ export interface GetRenderMapOptions {
27
50
  nameApi?: Partial<DartNameApi>;
28
51
  /** Dependency map overrides (logical module -> Dart package URI). */
29
52
  dependencyMap?: Record<string, string>;
53
+ /**
54
+ * Hand-written codec overrides for defined-type links, keyed by the link
55
+ * name as it appears in Codama nodes. A link with a matching key emits the
56
+ * override's type and codec expressions instead of resolving to a generated
57
+ * type file, and imports the override's Dart file.
58
+ */
59
+ linkOverrides?: Record<string, LinkOverride>;
30
60
  }
31
61
 
32
62
  /**
@@ -46,7 +46,8 @@ export const WELL_KNOWN_ADDRESSES: ReadonlyMap<string, string> = new Map([
46
46
  ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', 'tokenProgramAddress'],
47
47
  ['TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb', 'token2022ProgramAddress'],
48
48
  ['ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', 'associatedTokenProgramAddress'],
49
- ['MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr', 'memoProgramAddress'],
49
+ ['Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH', 'memoProgramAddress'],
50
+ ['MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr', 'memoLegacyProgramAddressV3'],
50
51
  ['Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo', 'memoLegacyProgramAddress'],
51
52
 
52
53
  // Metaplex programs
@@ -57,6 +57,7 @@ export function getRenderMapVisitor(
57
57
  nameApi,
58
58
  linkables,
59
59
  stack,
60
+ linkOverrides: options.linkOverrides,
60
61
  });
61
62
 
62
63
  const scope: RenderScope = {
@@ -57,6 +57,7 @@ import {
57
57
  use,
58
58
  } from "../utils/index.js";
59
59
  import { type DartNameApi, snakeCase } from "../utils/nameTransformers.js";
60
+ import type { LinkOverride } from "../utils/options.js";
60
61
  import { getDartValueFragment, getNonNegativeInteger, toDartStringLiteral } from "../utils/valueNodes.js";
61
62
 
62
63
  /**
@@ -73,8 +74,14 @@ export function getTypeManifestVisitor(input: {
73
74
  linkables: LinkableDictionary;
74
75
  stack: NodeStack;
75
76
  nonScalarEnums?: CamelCaseString[];
77
+ linkOverrides?: Record<string, LinkOverride>;
76
78
  }) {
77
- const { nameApi, linkables, nonScalarEnums = [] } = input;
79
+ const {
80
+ nameApi,
81
+ linkables,
82
+ nonScalarEnums = [],
83
+ linkOverrides = {},
84
+ } = input;
78
85
 
79
86
  const baseVisitor = staticVisitor<TypeManifest>(
80
87
  (node): TypeManifest => {
@@ -209,8 +216,8 @@ export function getTypeManifestVisitor(input: {
209
216
 
210
217
  visitArrayType(node: ArrayTypeNode, { self }) {
211
218
  const itemManifest = visit(node.item, self);
212
- const encoderSizeExpr = getArraySizeExpression(node, "Encoder");
213
- const decoderSizeExpr = getArraySizeExpression(node, "Decoder");
219
+ const encoderSizeExpr = getArraySizeExpression(node, "Encoder", self);
220
+ const decoderSizeExpr = getArraySizeExpression(node, "Decoder", self);
214
221
  const itemType = fragmentFromString(itemManifest.type.content);
215
222
  const itemEncoder = fragment`${use(
216
223
  "transformEncoder",
@@ -235,8 +242,8 @@ export function getTypeManifestVisitor(input: {
235
242
  visitMapType(node: MapTypeNode, { self }) {
236
243
  const keyManifest = visit(node.key, self);
237
244
  const valueManifest = visit(node.value, self);
238
- const encoderSizeExpr = getMapSizeExpression(node, "Encoder");
239
- const decoderSizeExpr = getMapSizeExpression(node, "Decoder");
245
+ const encoderSizeExpr = getMapSizeExpression(node, "Encoder", self);
246
+ const decoderSizeExpr = getMapSizeExpression(node, "Decoder", self);
240
247
 
241
248
  return {
242
249
  type: fragment`Map<${keyManifest.type}, ${valueManifest.type}>`,
@@ -255,8 +262,8 @@ export function getTypeManifestVisitor(input: {
255
262
 
256
263
  visitSetType(node: SetTypeNode, { self }) {
257
264
  const itemManifest = visit(node.item, self);
258
- const encoderSizeExpr = getSetSizeExpression(node, "Encoder");
259
- const decoderSizeExpr = getSetSizeExpression(node, "Decoder");
265
+ const encoderSizeExpr = getSetSizeExpression(node, "Encoder", self);
266
+ const decoderSizeExpr = getSetSizeExpression(node, "Decoder", self);
260
267
 
261
268
  return {
262
269
  type: fragment`Set<${itemManifest.type}>`,
@@ -670,6 +677,23 @@ export function getTypeManifestVisitor(input: {
670
677
  { self }: { self: Visitor<TypeManifest> },
671
678
  ) {
672
679
  const name = node.name as string;
680
+
681
+ // A link may be backed by a hand-written codec. This keeps whatever
682
+ // wrappers the IDL puts around the link (`Option`, `HiddenPrefix`, …)
683
+ // while replacing the inner type and codecs, which is what a type that
684
+ // Codama cannot express needs.
685
+ const override = linkOverrides[name];
686
+ if (override != null) {
687
+ const moduleKey = `linkOverride:${override.path}`;
688
+ return {
689
+ type: use(override.type, moduleKey),
690
+ encoder: use(override.encoder, moduleKey),
691
+ decoder: use(override.decoder, moduleKey),
692
+ value: emptyTypeManifest().value,
693
+ isEnum: false,
694
+ };
695
+ }
696
+
673
697
  const typeName = nameApi.dataType(name);
674
698
  const isNonScalar = nonScalarEnums.includes(node.name);
675
699
  const moduleKey = `definedType:${snakeCase(name)}`;
@@ -772,6 +796,7 @@ function getNumberCodecExpression(
772
796
  function getArraySizeExpression(
773
797
  node: ArrayTypeNode,
774
798
  codecType: "Encoder" | "Decoder",
799
+ self: Visitor<TypeManifest>,
775
800
  ): string | Fragment {
776
801
  if (!("count" in node) || !node.count) return "";
777
802
  const count = node.count;
@@ -781,11 +806,15 @@ function getArraySizeExpression(
781
806
  case "remainderCountNode":
782
807
  return ", size: RemainderArraySize()";
783
808
  case "prefixedCountNode": {
784
- const resolvedPrefix = resolveNestedTypeNode(count.prefix);
785
- if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
809
+ if (
810
+ count.prefix.kind === "numberTypeNode" &&
811
+ count.prefix.format === "u32" &&
812
+ (!count.prefix.endian || count.prefix.endian === "le")
813
+ ) {
786
814
  return ""; // Default
787
815
  }
788
- return fragment`, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix, codecType)})`;
816
+ const prefix = visit(count.prefix, self);
817
+ return fragment`, size: PrefixedArraySize(${codecType === "Encoder" ? prefix.encoder : prefix.decoder})`;
789
818
  }
790
819
  default:
791
820
  return "";
@@ -795,6 +824,7 @@ function getArraySizeExpression(
795
824
  function getMapSizeExpression(
796
825
  node: MapTypeNode,
797
826
  codecType: "Encoder" | "Decoder",
827
+ self: Visitor<TypeManifest>,
798
828
  ): string | Fragment {
799
829
  if (!("count" in node) || !node.count) return "";
800
830
  const count = node.count;
@@ -804,11 +834,15 @@ function getMapSizeExpression(
804
834
  case "remainderCountNode":
805
835
  return ", size: RemainderArraySize()";
806
836
  case "prefixedCountNode": {
807
- const resolvedPrefix = resolveNestedTypeNode(count.prefix);
808
- if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
837
+ if (
838
+ count.prefix.kind === "numberTypeNode" &&
839
+ count.prefix.format === "u32" &&
840
+ (!count.prefix.endian || count.prefix.endian === "le")
841
+ ) {
809
842
  return "";
810
843
  }
811
- return fragment`, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix, codecType)})`;
844
+ const prefix = visit(count.prefix, self);
845
+ return fragment`, size: PrefixedArraySize(${codecType === "Encoder" ? prefix.encoder : prefix.decoder})`;
812
846
  }
813
847
  default:
814
848
  return "";
@@ -818,6 +852,7 @@ function getMapSizeExpression(
818
852
  function getSetSizeExpression(
819
853
  node: SetTypeNode,
820
854
  codecType: "Encoder" | "Decoder",
855
+ self: Visitor<TypeManifest>,
821
856
  ): string | Fragment {
822
857
  if (!("count" in node) || !node.count) return "";
823
858
  const count = node.count;
@@ -827,11 +862,15 @@ function getSetSizeExpression(
827
862
  case "remainderCountNode":
828
863
  return ", size: RemainderArraySize()";
829
864
  case "prefixedCountNode": {
830
- const resolvedPrefix = resolveNestedTypeNode(count.prefix);
831
- if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
865
+ if (
866
+ count.prefix.kind === "numberTypeNode" &&
867
+ count.prefix.format === "u32" &&
868
+ (!count.prefix.endian || count.prefix.endian === "le")
869
+ ) {
832
870
  return "";
833
871
  }
834
- return fragment`, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix, codecType)})`;
872
+ const prefix = visit(count.prefix, self);
873
+ return fragment`, size: PrefixedArraySize(${codecType === "Encoder" ? prefix.encoder : prefix.decoder})`;
835
874
  }
836
875
  default:
837
876
  return "";
@@ -6,7 +6,7 @@ import { rootNodeVisitor, visit } from "@codama/visitors-core";
6
6
  import { deleteDirectory, writeRenderMap } from "@codama/renderers-core";
7
7
 
8
8
  import type { Fragment } from "../utils/fragment.js";
9
- import type { RenderOptions } from "../utils/options.js";
9
+ import type { RenderOptions, LinkOverride } from "../utils/options.js";
10
10
  import { DartImportMap, DART_EXTERNAL_PACKAGE_MAP } from "../utils/importMap.js";
11
11
  import { formatDartDirectory } from "../utils/formatCode.js";
12
12
  import { normalizeRootNode } from "../utils/normalizeRootNode.js";
@@ -27,6 +27,7 @@ export function renderVisitor(
27
27
  formatCode = false,
28
28
  nameApi,
29
29
  dependencyMap,
30
+ linkOverrides,
30
31
  } = options;
31
32
 
32
33
  return rootNodeVisitor((root: RootNode) => {
@@ -35,7 +36,7 @@ export function renderVisitor(
35
36
  // 2. Build the render map
36
37
  const renderMap = visit(
37
38
  normalizedRoot,
38
- getRenderMapVisitor({ nameApi, dependencyMap }),
39
+ getRenderMapVisitor({ nameApi, dependencyMap, linkOverrides }),
39
40
  );
40
41
 
41
42
  // 3. Build a map of definedType module keys to their render map paths
@@ -69,7 +70,14 @@ export function renderVisitor(
69
70
  }
70
71
 
71
72
  // Resolve fragment content with imports
72
- const content = resolveFragmentContent(frag, dependencyMap ?? {}, internalMap);
73
+ const content = resolveFragmentContent(
74
+ frag,
75
+ {
76
+ ...(dependencyMap ?? {}),
77
+ ...linkOverrideImports(outputDir, filePath, options.linkOverrides ?? {}),
78
+ },
79
+ internalMap,
80
+ );
73
81
  files.push([fullPath, content]);
74
82
  }
75
83
 
@@ -89,6 +97,62 @@ export function renderVisitor(
89
97
  });
90
98
  }
91
99
 
100
+ /**
101
+ * Resolve `linkOverride:` logical import keys into relative Dart imports.
102
+ *
103
+ * Override paths are relative to the package's `lib/` directory, while
104
+ * generated files live under `lib/src/generated/...`, so each consuming file
105
+ * needs its own relative path. Both sides are resolved against the package's
106
+ * `lib/` root, which is located by walking up from the output directory.
107
+ */
108
+ function linkOverrideImports(
109
+ outputDir: string,
110
+ generatedFilePath: string,
111
+ overrides: Record<string, LinkOverride>,
112
+ ): Record<string, string> {
113
+ const resolved: Record<string, string> = {};
114
+ if (Object.keys(overrides).length === 0) return resolved;
115
+
116
+ // Override paths are resolved against the package's `lib/` directory, so
117
+ // without one there is nothing to anchor them to. Failing loudly beats
118
+ // emitting an import that cannot resolve.
119
+ const libRoot = findLibRoot(outputDir);
120
+ if (libRoot == null) {
121
+ throw new Error(
122
+ `Cannot resolve linkOverrides because the render output directory ` +
123
+ `"${outputDir}" has no "lib" ancestor.`,
124
+ );
125
+ }
126
+
127
+ const generatedAbsolute = posix.join(
128
+ posix.resolve(outputDir),
129
+ generatedFilePath,
130
+ );
131
+
132
+ for (const override of Object.values(overrides)) {
133
+ const overrideAbsolute = posix.join(libRoot, override.path);
134
+ let rel = posix.relative(posix.dirname(generatedAbsolute), overrideAbsolute);
135
+ if (!rel.startsWith(".")) {
136
+ rel = `./${rel}`;
137
+ }
138
+ resolved[`linkOverride:${override.path}`] = rel;
139
+ }
140
+
141
+ return resolved;
142
+ }
143
+
144
+ /**
145
+ * Find the package `lib/` directory containing the render output, so relative
146
+ * imports can point outside the generated tree. Returns null when the output
147
+ * directory has no `lib` ancestor, in which case overrides cannot be linked.
148
+ */
149
+ function findLibRoot(outputDir: string): string | null {
150
+ const segments = posix.resolve(outputDir).split("/");
151
+ const libIndex = segments.lastIndexOf("lib");
152
+ if (libIndex < 0) return null;
153
+ return segments.slice(0, libIndex + 1).join("/");
154
+ }
155
+
92
156
  /**
93
157
  * Resolve a fragment into its final Dart file content,
94
158
  * prepending the resolved import statements.