codama-renderers-dart 0.5.3 → 0.5.4
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.
- package/README.md +6 -0
- package/dist/index.browser.cjs +176 -107
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +177 -108
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +176 -107
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +177 -108
- package/dist/index.node.js.map +1 -1
- package/dist/index.react-native.js +177 -108
- package/dist/index.react-native.js.map +1 -1
- package/dist/types/fragments/accountPage.d.ts.map +1 -1
- package/dist/types/fragments/errorPage.d.ts.map +1 -1
- package/dist/types/fragments/instructionPage.d.ts.map +1 -1
- package/dist/types/fragments/pdaPage.d.ts.map +1 -1
- package/dist/types/fragments/programPage.d.ts.map +1 -1
- package/dist/types/utils/nameTransformers.d.ts.map +1 -1
- package/dist/types/utils/valueNodes.d.ts +4 -0
- package/dist/types/utils/valueNodes.d.ts.map +1 -1
- package/dist/types/visitors/getRenderMapVisitor.d.ts.map +1 -1
- package/dist/types/visitors/getTypeManifestVisitor.d.ts.map +1 -1
- package/dist/types/visitors/renderVisitor.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/fragments/accountPage.ts +2 -1
- package/src/fragments/errorPage.ts +8 -5
- package/src/fragments/instructionPage.ts +51 -21
- package/src/fragments/pdaPage.ts +7 -14
- package/src/fragments/programPage.ts +3 -2
- package/src/utils/formatCode.ts +2 -2
- package/src/utils/nameTransformers.ts +11 -0
- package/src/utils/valueNodes.ts +24 -1
- package/src/visitors/getRenderMapVisitor.ts +30 -5
- package/src/visitors/getTypeManifestVisitor.ts +100 -75
- package/src/visitors/renderVisitor.ts +11 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accountPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/accountPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,eAAe,CAAC;AAItE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAQrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"accountPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/accountPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,eAAe,CAAC;AAItE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAQrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAWvD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,WAAW,GACjB,QAAQ,CA8OV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/errorPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"errorPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/errorPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AASrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,WAAW,GACjB,QAAQ,CA2DV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructionPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/instructionPage.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,WAAW,GACjB,QAAQ,
|
|
1
|
+
{"version":3,"file":"instructionPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/instructionPage.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,WAAW,GACjB,QAAQ,CA+VV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdaPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/pdaPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"pdaPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/pdaPage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,WAAW,GACjB,QAAQ,CAoJV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"programPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/programPage.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAQrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"programPage.d.ts","sourceRoot":"","sources":["../../../src/fragments/programPage.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAQrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKvD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,WAAW,GACjB,QAAQ,CAiJV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nameTransformers.d.ts","sourceRoot":"","sources":["../../../src/utils/nameTransformers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;GAEG;AAEH,qCAAqC;AACrC,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"nameTransformers.d.ts","sourceRoot":"","sources":["../../../src/utils/nameTransformers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;GAEG;AAEH,qCAAqC;AACrC,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM9C;AAoBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,oCAAoC;AACpC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI7C;AAED,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS7C;AAED,+CAA+C;AAC/C,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,sDAAsD;IACtD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,sDAAsD;IACtD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,kDAAkD;IAClD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,kDAAkD;IAClD,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3C,6DAA6D;IAC7D,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAChD,oDAAoD;IACpD,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5C,+CAA+C;IAC/C,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1C,iDAAiD;IACjD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,iEAAiE;IACjE,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1C,iEAAiE;IACjE,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/C,4DAA4D;IAC5D,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7C,4DAA4D;IAC5D,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9D,4DAA4D;IAC5D,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3C,gCAAgC;IAChC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,mEAAmE;IACnE,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IACpE,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,yDAAyD;IACzD,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5C,oDAAoD;IACpD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CACtC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAwB/C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAEhE"}
|
|
@@ -12,5 +12,9 @@ type RenderableValueNode = InstructionInputValueNode | ValueNode;
|
|
|
12
12
|
export declare function getDartValueFragment(value: RenderableValueNode, dartType?: string): Fragment;
|
|
13
13
|
/** Return whether a rendered standalone value is valid in a const initializer. */
|
|
14
14
|
export declare function isConstDartValueNode(value: RenderableValueNode): boolean;
|
|
15
|
+
/** Escape IDL text so it remains data inside a Dart string literal. */
|
|
16
|
+
export declare function toDartStringLiteral(value: string): string;
|
|
17
|
+
/** Reject executable or lossy sizes from serialized IDLs before generating Dart. */
|
|
18
|
+
export declare function getNonNegativeInteger(value: number): string;
|
|
15
19
|
export {};
|
|
16
20
|
//# sourceMappingURL=valueNodes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valueNodes.d.ts","sourceRoot":"","sources":["../../../src/utils/valueNodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,SAAS,EACV,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAI9C,KAAK,mBAAmB,GAAG,yBAAyB,GAAG,SAAS,CAAC;AAEjE;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,mBAAmB,EAC1B,QAAQ,CAAC,EAAE,MAAM,GAChB,QAAQ,
|
|
1
|
+
{"version":3,"file":"valueNodes.d.ts","sourceRoot":"","sources":["../../../src/utils/valueNodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,SAAS,EACV,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAI9C,KAAK,mBAAmB,GAAG,yBAAyB,GAAG,SAAS,CAAC;AAEjE;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,mBAAmB,EAC1B,QAAQ,CAAC,EAAE,MAAM,GAChB,QAAQ,CAmDV;AAED,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAWxE;AAED,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUzD;AAED,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM3D"}
|
|
@@ -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,
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTypeManifestVisitor.d.ts","sourceRoot":"","sources":["../../../src/visitors/getTypeManifestVisitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,eAAe,
|
|
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 +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,
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
|
-
"@codama/errors": "^1.10.
|
|
4
|
-
"@codama/nodes": "^1.10.
|
|
5
|
-
"@codama/renderers-core": "^1.
|
|
6
|
-
"@codama/visitors-core": "^1.10.
|
|
3
|
+
"@codama/errors": "^1.10.2",
|
|
4
|
+
"@codama/nodes": "^1.10.2",
|
|
5
|
+
"@codama/renderers-core": "^1.4.0",
|
|
6
|
+
"@codama/visitors-core": "^1.10.2"
|
|
7
7
|
},
|
|
8
8
|
"description": "Codama renderer for generating Dart code targeting the solana_kit SDK",
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@codama/nodes-from-anchor": "^1.5.
|
|
11
|
-
"@codama/renderers-js": "^2.
|
|
10
|
+
"@codama/nodes-from-anchor": "^1.5.5",
|
|
11
|
+
"@codama/renderers-js": "^2.4.0",
|
|
12
12
|
"@types/node": "25.3.0",
|
|
13
13
|
"@vitest/coverage-v8": "4.1.0",
|
|
14
14
|
"rimraf": "6.1.3",
|
|
@@ -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.
|
|
58
|
+
"version": "0.5.4",
|
|
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",
|
|
@@ -16,6 +16,7 @@ import { getDiscriminatorValidationFragment } from "../utils/discriminators.js";
|
|
|
16
16
|
import { getTopLevelDecoderFragment } from "../utils/exactDecoder.js";
|
|
17
17
|
import {
|
|
18
18
|
getDartValueFragment,
|
|
19
|
+
getNonNegativeInteger,
|
|
19
20
|
isConstDartValueNode,
|
|
20
21
|
} from "../utils/valueNodes.js";
|
|
21
22
|
import { getDiscriminatorConstantsFragment } from "./discriminatorConstants.js";
|
|
@@ -160,7 +161,7 @@ export function getAccountPageFragment(
|
|
|
160
161
|
const sizeFragment = node.size != null
|
|
161
162
|
? fragment`
|
|
162
163
|
/// The size of the [${fragmentFromString(typeName)}] account data in bytes.
|
|
163
|
-
const int ${fragmentFromString(scope.nameApi.accountSizeConstant(name))} = ${fragmentFromString(
|
|
164
|
+
const int ${fragmentFromString(scope.nameApi.accountSizeConstant(name))} = ${fragmentFromString(getNonNegativeInteger(node.size))};`
|
|
164
165
|
: emptyFragment();
|
|
165
166
|
|
|
166
167
|
// Discriminator
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
mergeFragments,
|
|
9
9
|
use,
|
|
10
10
|
} from "../utils/fragment.js";
|
|
11
|
+
import { getNonNegativeInteger, toDartStringLiteral } from "../utils/valueNodes.js";
|
|
11
12
|
import type { RenderScope } from "../utils/options.js";
|
|
12
13
|
import { camelCase, pascalCase, screamingSnakeCase } from "../utils/nameTransformers.js";
|
|
13
14
|
|
|
@@ -30,11 +31,12 @@ export function getErrorPageFragment(
|
|
|
30
31
|
programName,
|
|
31
32
|
err.name as string,
|
|
32
33
|
);
|
|
34
|
+
getNonNegativeInteger(err.code);
|
|
33
35
|
const hexCode = `0x${err.code.toString(16)}`;
|
|
34
36
|
const docs = err.docs?.length
|
|
35
|
-
? err.docs.map(
|
|
37
|
+
? err.docs.map(toDartDocComment).join("\n") + "\n"
|
|
36
38
|
: "";
|
|
37
|
-
const message = err.message ?
|
|
39
|
+
const message = err.message ? `${toDartDocComment(`Message: "${err.message}"`)}\n` : "";
|
|
38
40
|
return `${docs}${message}const int ${constName} = ${hexCode}; // ${err.code}`;
|
|
39
41
|
})
|
|
40
42
|
.join("\n\n");
|
|
@@ -47,7 +49,7 @@ export function getErrorPageFragment(
|
|
|
47
49
|
err.name as string,
|
|
48
50
|
);
|
|
49
51
|
const message = err.message ?? err.name as string;
|
|
50
|
-
return ` ${constName}:
|
|
52
|
+
return ` ${constName}: ${toDartStringLiteral(message)},`;
|
|
51
53
|
})
|
|
52
54
|
.join("\n");
|
|
53
55
|
|
|
@@ -77,6 +79,7 @@ bool ${fragmentFromString(isErrorFnName)}(int code) {
|
|
|
77
79
|
}`;
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
/** Prefix every physical line so IDL documentation cannot become Dart code. */
|
|
83
|
+
function toDartDocComment(value: string): string {
|
|
84
|
+
return value.split(/\r\n?|\n/).map((line) => `/// ${line}`).join("\n");
|
|
82
85
|
}
|
|
@@ -172,19 +172,36 @@ export function getInstructionPageFragment(
|
|
|
172
172
|
const dataDecoderName = `get${typeName}InstructionDataDecoder`;
|
|
173
173
|
const dataCodecName = `get${typeName}InstructionDataCodec`;
|
|
174
174
|
|
|
175
|
-
//
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
175
|
+
// Generated parameters and locals must not shadow IDL account or argument names.
|
|
176
|
+
const usedNames = new Set([
|
|
177
|
+
...args.map((arg) => camelCase(arg.name as string)),
|
|
178
|
+
...accounts.map((account) => camelCase(account.name as string)),
|
|
179
|
+
]);
|
|
180
|
+
const instrProgramParam = reserveName(
|
|
181
|
+
usedNames.has("programAddress") ? "instructionProgramAddress" : "programAddress",
|
|
182
|
+
usedNames,
|
|
183
|
+
);
|
|
184
|
+
const instructionDataLocal = reserveName("instructionData", usedNames);
|
|
185
|
+
const signerParams = new Map<InstructionAccountNode, string>();
|
|
186
|
+
|
|
187
|
+
for (const account of accounts) {
|
|
188
|
+
if (account.isSigner === "either") {
|
|
189
|
+
signerParams.set(
|
|
190
|
+
account,
|
|
191
|
+
reserveName(`${camelCase(account.name as string)}IsSigner`, usedNames),
|
|
192
|
+
);
|
|
193
|
+
}
|
|
186
194
|
}
|
|
187
195
|
|
|
196
|
+
const signerParamDeclarations = [...signerParams.values()]
|
|
197
|
+
.map((parameter) => ` bool ${parameter} = true,`)
|
|
198
|
+
.join("\n");
|
|
199
|
+
const signerParamDocs = [...signerParams.entries()]
|
|
200
|
+
.map(([account, parameter]) =>
|
|
201
|
+
`/// Set [${parameter}] to false when [${camelCase(account.name as string)}] does not sign (for example, a multisig authority).`
|
|
202
|
+
)
|
|
203
|
+
.join("\n");
|
|
204
|
+
|
|
188
205
|
// Build the instruction builder function
|
|
189
206
|
const accountParams = accounts
|
|
190
207
|
.map((acc) => {
|
|
@@ -221,7 +238,7 @@ export function getInstructionPageFragment(
|
|
|
221
238
|
const accountMetas = accounts
|
|
222
239
|
.map((acc) => {
|
|
223
240
|
const fieldName = camelCase(acc.name as string);
|
|
224
|
-
const role = getAccountRole(acc);
|
|
241
|
+
const role = getAccountRole(acc, signerParams.get(acc));
|
|
225
242
|
const isOptional = acc.isOptional ?? false;
|
|
226
243
|
if (isOptional) {
|
|
227
244
|
if (optionalAccountStrategy === "omitted") {
|
|
@@ -323,11 +340,11 @@ Codec<${fragmentFromString(dataClassName)}, ${fragmentFromString(dataClassName)}
|
|
|
323
340
|
|
|
324
341
|
// Instruction builder
|
|
325
342
|
parts.push(fragment`
|
|
326
|
-
/// Creates a [${fragmentFromString(typeName)}] instruction
|
|
343
|
+
/// Creates a [${fragmentFromString(typeName)}] instruction.${fragmentFromString(signerParamDocs ? `\n${signerParamDocs}` : "")}
|
|
327
344
|
Instruction ${fragmentFromString(instrFnName)}({
|
|
328
345
|
required Address ${fragmentFromString(instrProgramParam)},
|
|
329
346
|
${fragmentFromString(accountParams)}
|
|
330
|
-
${fragmentFromString(argParams)}
|
|
347
|
+
${fragmentFromString(argParams)}${fragmentFromString(signerParamDeclarations ? `\n${signerParamDeclarations}` : "")}
|
|
331
348
|
}) {
|
|
332
349
|
final ${instructionDataLocal} = ${fragmentFromString(dataClassName)}(
|
|
333
350
|
${fragmentFromString(dataConstruction)}
|
|
@@ -364,14 +381,27 @@ ${fragmentFromString(dataClassName)} ${fragmentFromString(parseFnName)}(Instruct
|
|
|
364
381
|
return result;
|
|
365
382
|
}
|
|
366
383
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
384
|
+
/** Reserves an identifier without shadowing existing builder parameters or locals. */
|
|
385
|
+
function reserveName(preferredName: string, usedNames: Set<string>): string {
|
|
386
|
+
let name = preferredName;
|
|
387
|
+
|
|
388
|
+
while (usedNames.has(name)) {
|
|
389
|
+
name = `${name}_`;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
usedNames.add(name);
|
|
393
|
+
return name;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Preserves fixed permissions and lets either-signer accounts choose their role. */
|
|
397
|
+
function getAccountRole(acc: InstructionAccountNode, signerParameter?: string): string {
|
|
398
|
+
const role = acc.isWritable ? "AccountRole.writable" : "AccountRole.readonly";
|
|
399
|
+
|
|
400
|
+
if (signerParameter) {
|
|
401
|
+
return `${signerParameter} ? ${role}Signer : ${role}`;
|
|
402
|
+
}
|
|
370
403
|
|
|
371
|
-
|
|
372
|
-
if (isSigner) return "AccountRole.readonlySigner";
|
|
373
|
-
if (isWritable) return "AccountRole.writable";
|
|
374
|
-
return "AccountRole.readonly";
|
|
404
|
+
return acc.isSigner === true ? `${role}Signer` : role;
|
|
375
405
|
}
|
|
376
406
|
|
|
377
407
|
function isDiscriminatorArg(
|
package/src/fragments/pdaPage.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "../utils/fragment.js";
|
|
11
11
|
import type { RenderScope } from "../utils/options.js";
|
|
12
12
|
import { camelCase, pascalCase } from "../utils/nameTransformers.js";
|
|
13
|
+
import { getDartValueFragment, toDartStringLiteral } from "../utils/valueNodes.js";
|
|
13
14
|
import type { TypeManifest } from "../utils/typeManifest.js";
|
|
14
15
|
import { WELL_KNOWN_ADDRESSES } from "../utils/wellKnownAddresses.js";
|
|
15
16
|
|
|
@@ -66,9 +67,9 @@ export function getPdaPageFragment(
|
|
|
66
67
|
for (const seed of seeds) {
|
|
67
68
|
if (seed.kind === "constantPdaSeedNode") {
|
|
68
69
|
if (seed.value.kind === "bytesValueNode") {
|
|
69
|
-
seedValues.push(`
|
|
70
|
+
seedValues.push(` ${getDartValueFragment(seed.value).content},`);
|
|
70
71
|
} else if (seed.value.kind === "stringValueNode") {
|
|
71
|
-
seedValues.push(`
|
|
72
|
+
seedValues.push(` ${toDartStringLiteral(seed.value.string)},`);
|
|
72
73
|
} else if (seed.value.kind === "publicKeyValueNode") {
|
|
73
74
|
const wellKnownSeedName = WELL_KNOWN_ADDRESSES.get(seed.value.publicKey);
|
|
74
75
|
if (wellKnownSeedName) {
|
|
@@ -78,13 +79,14 @@ export function getPdaPageFragment(
|
|
|
78
79
|
);
|
|
79
80
|
} else {
|
|
80
81
|
seedValues.push(
|
|
81
|
-
` getAddressEncoder().encode(Address(
|
|
82
|
+
` getAddressEncoder().encode(Address(${toDartStringLiteral(seed.value.publicKey)})),`,
|
|
82
83
|
);
|
|
83
84
|
}
|
|
84
85
|
} else if (seed.value.kind === "numberValueNode") {
|
|
85
86
|
const manifest = visit(seed.type, scope.typeManifestVisitor);
|
|
86
87
|
seedManifests.push(manifest);
|
|
87
|
-
|
|
88
|
+
const value = getDartValueFragment(seed.value, manifest.type.content);
|
|
89
|
+
seedValues.push(` ${manifest.encoder.content}.encode(${value.content}),`);
|
|
88
90
|
}
|
|
89
91
|
} else if (seed.kind === "variablePdaSeedNode") {
|
|
90
92
|
const manifest = visit(seed.type, scope.typeManifestVisitor);
|
|
@@ -105,7 +107,7 @@ export function getPdaPageFragment(
|
|
|
105
107
|
const programIdParam = node.programId
|
|
106
108
|
? wellKnownProgramName
|
|
107
109
|
? `Address programAddress = ${wellKnownProgramName}`
|
|
108
|
-
: `Address programAddress = const Address(
|
|
110
|
+
: `Address programAddress = const Address(${toDartStringLiteral(node.programId)})`
|
|
109
111
|
: "required Address programAddress";
|
|
110
112
|
|
|
111
113
|
const typedDataImport = hasByteSeeds
|
|
@@ -167,12 +169,3 @@ ${fragmentFromString(seedValues.join("\n"))}
|
|
|
167
169
|
|
|
168
170
|
return result;
|
|
169
171
|
}
|
|
170
|
-
|
|
171
|
-
function bytesValueToDart(hex: string): string {
|
|
172
|
-
const clean = hex.replace(/^0x/, "");
|
|
173
|
-
const pairs: string[] = [];
|
|
174
|
-
for (let i = 0; i < clean.length; i += 2) {
|
|
175
|
-
pairs.push(`0x${clean.slice(i, i + 2)}`);
|
|
176
|
-
}
|
|
177
|
-
return `[${pairs.join(", ")}]`;
|
|
178
|
-
}
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from "../utils/fragment.js";
|
|
17
17
|
import type { RenderScope } from "../utils/options.js";
|
|
18
18
|
import { camelCase, pascalCase } from "../utils/nameTransformers.js";
|
|
19
|
+
import { toDartStringLiteral } from "../utils/valueNodes.js";
|
|
19
20
|
import { WELL_KNOWN_ADDRESSES } from "../utils/wellKnownAddresses.js";
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -55,7 +56,7 @@ const ${fragmentFromString(addressConstName)} = ${fragmentFromString(wellKnownNa
|
|
|
55
56
|
${use("Address", "solanaAddresses")}
|
|
56
57
|
|
|
57
58
|
/// The address of the ${fragmentFromString(pascalCase(name))} program.
|
|
58
|
-
const ${fragmentFromString(addressConstName)} = Address(
|
|
59
|
+
const ${fragmentFromString(addressConstName)} = Address(${fragmentFromString(toDartStringLiteral(node.publicKey))});`;
|
|
59
60
|
|
|
60
61
|
const parts: Fragment[] = [addressDeclaration];
|
|
61
62
|
|
|
@@ -232,7 +233,7 @@ function getValueFragment(
|
|
|
232
233
|
case "booleanValueNode":
|
|
233
234
|
return fragmentFromString(String(value.boolean));
|
|
234
235
|
case "stringValueNode":
|
|
235
|
-
return fragmentFromString(
|
|
236
|
+
return fragmentFromString(toDartStringLiteral(value.string));
|
|
236
237
|
case "bytesValueNode": {
|
|
237
238
|
const clean = value.data.replace(/^0x/, "");
|
|
238
239
|
const bytes = clean.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) ?? [];
|
package/src/utils/formatCode.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { execSync } from "node:child_process";
|
|
1
|
+
import { execFileSync, execSync } from "node:child_process";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Format Dart code using `dart format`.
|
|
@@ -23,7 +23,7 @@ export function formatDartCode(code: string): string {
|
|
|
23
23
|
* Format all Dart files in a directory using `dart format`.
|
|
24
24
|
*/
|
|
25
25
|
export function formatDartDirectory(dir: string): void {
|
|
26
|
-
|
|
26
|
+
execFileSync("dart", ["format", "--", dir], {
|
|
27
27
|
encoding: "utf-8",
|
|
28
28
|
timeout: 60_000,
|
|
29
29
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -6,6 +6,8 @@ import type { CamelCaseString } from "@codama/nodes";
|
|
|
6
6
|
|
|
7
7
|
/** Convert a string to PascalCase */
|
|
8
8
|
export function pascalCase(str: string): string {
|
|
9
|
+
assertSafeName(str);
|
|
10
|
+
|
|
9
11
|
return str
|
|
10
12
|
.replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
|
|
11
13
|
.replace(/^(.)/, (c) => c.toUpperCase());
|
|
@@ -46,6 +48,8 @@ export function camelCase(str: string): string {
|
|
|
46
48
|
|
|
47
49
|
/** Convert a string to snake_case */
|
|
48
50
|
export function snakeCase(str: string): string {
|
|
51
|
+
assertSafeName(str);
|
|
52
|
+
|
|
49
53
|
return str
|
|
50
54
|
.replace(/([A-Z])/g, "_$1")
|
|
51
55
|
.replace(/[-\s]+/g, "_")
|
|
@@ -138,3 +142,10 @@ export function createDartNameApi(): DartNameApi {
|
|
|
138
142
|
export function fromCamelCaseString(str: CamelCaseString): string {
|
|
139
143
|
return str as string;
|
|
140
144
|
}
|
|
145
|
+
|
|
146
|
+
/** Reject IDL names that could escape generated identifiers, strings, or paths. */
|
|
147
|
+
function assertSafeName(name: string): void {
|
|
148
|
+
if (!/^[a-zA-Z0-9_ -]*$/.test(name)) {
|
|
149
|
+
throw new Error(`Invalid Dart node name: ${JSON.stringify(name)}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
package/src/utils/valueNodes.ts
CHANGED
|
@@ -23,12 +23,25 @@ export function getDartValueFragment(
|
|
|
23
23
|
): Fragment {
|
|
24
24
|
switch (value.kind) {
|
|
25
25
|
case "numberValueNode":
|
|
26
|
+
// Serialized IDLs bypass TypeScript types; never interpolate unvalidated data.
|
|
27
|
+
if (typeof value.number !== "number" || !Number.isFinite(value.number)) {
|
|
28
|
+
throw new Error("Invalid Dart number: expected a finite number");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (dartType === "BigInt" && !Number.isSafeInteger(value.number)) {
|
|
32
|
+
throw new Error("Invalid Dart BigInt: expected a safe integer");
|
|
33
|
+
}
|
|
34
|
+
|
|
26
35
|
return fragmentFromString(
|
|
27
36
|
dartType === "BigInt"
|
|
28
37
|
? `BigInt.from(${value.number})`
|
|
29
38
|
: String(value.number),
|
|
30
39
|
);
|
|
31
40
|
case "booleanValueNode":
|
|
41
|
+
if (typeof value.boolean !== "boolean") {
|
|
42
|
+
throw new Error("Invalid Dart boolean: expected a boolean");
|
|
43
|
+
}
|
|
44
|
+
|
|
32
45
|
return fragmentFromString(String(value.boolean));
|
|
33
46
|
case "stringValueNode":
|
|
34
47
|
return fragmentFromString(toDartStringLiteral(value.string));
|
|
@@ -74,7 +87,8 @@ export function isConstDartValueNode(value: RenderableValueNode): boolean {
|
|
|
74
87
|
}
|
|
75
88
|
}
|
|
76
89
|
|
|
77
|
-
|
|
90
|
+
/** Escape IDL text so it remains data inside a Dart string literal. */
|
|
91
|
+
export function toDartStringLiteral(value: string): string {
|
|
78
92
|
return `'${value
|
|
79
93
|
.replaceAll("\\", "\\\\")
|
|
80
94
|
.replaceAll("\n", "\\n")
|
|
@@ -85,3 +99,12 @@ function toDartStringLiteral(value: string): string {
|
|
|
85
99
|
.replaceAll("$", "\\$")
|
|
86
100
|
.replaceAll("'", "\\'")}'`;
|
|
87
101
|
}
|
|
102
|
+
|
|
103
|
+
/** Reject executable or lossy sizes from serialized IDLs before generating Dart. */
|
|
104
|
+
export function getNonNegativeInteger(value: number): string {
|
|
105
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
106
|
+
throw new Error("Expected a non-negative safe integer value");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return String(value);
|
|
110
|
+
}
|
|
@@ -89,10 +89,13 @@ export function getRenderMapVisitor(
|
|
|
89
89
|
...(node.additionalPrograms ?? []).map((p) => visit(p, self)),
|
|
90
90
|
];
|
|
91
91
|
|
|
92
|
-
const mergedProgramMap =
|
|
92
|
+
const mergedProgramMap = mergeRenderMapsWithoutCollisions(programMaps);
|
|
93
93
|
const categoryMaps = getSharedCategoryIndexMaps(mergedProgramMap);
|
|
94
94
|
|
|
95
|
-
return
|
|
95
|
+
return mergeRenderMapsWithoutCollisions([
|
|
96
|
+
mergedProgramMap,
|
|
97
|
+
...categoryMaps,
|
|
98
|
+
]);
|
|
96
99
|
},
|
|
97
100
|
|
|
98
101
|
visitProgram(node: ProgramNode, { self }) {
|
|
@@ -173,7 +176,7 @@ export function getRenderMapVisitor(
|
|
|
173
176
|
maps.push(rootMap);
|
|
174
177
|
}
|
|
175
178
|
|
|
176
|
-
return
|
|
179
|
+
return mergeRenderMapsWithoutCollisions(maps);
|
|
177
180
|
},
|
|
178
181
|
|
|
179
182
|
visitAccount(node: AccountNode, { self }) {
|
|
@@ -213,6 +216,30 @@ export function getRenderMapVisitor(
|
|
|
213
216
|
);
|
|
214
217
|
}
|
|
215
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Merges generated files while rejecting ambiguous output paths.
|
|
221
|
+
*
|
|
222
|
+
* Silent overwrites could replace signer checks or data layouts when an
|
|
223
|
+
* untrusted IDL contains duplicate names.
|
|
224
|
+
*/
|
|
225
|
+
function mergeRenderMapsWithoutCollisions(
|
|
226
|
+
maps: RenderMap<Fragment>[],
|
|
227
|
+
): RenderMap<Fragment> {
|
|
228
|
+
const paths = new Set<string>();
|
|
229
|
+
|
|
230
|
+
for (const map of maps) {
|
|
231
|
+
for (const path of map.keys()) {
|
|
232
|
+
if (paths.has(path)) {
|
|
233
|
+
throw new Error(`Duplicate generated path "${path}"`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
paths.add(path);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return mergeRenderMaps(maps);
|
|
241
|
+
}
|
|
242
|
+
|
|
216
243
|
function getSharedCategoryIndexMaps(
|
|
217
244
|
renderMap: RenderMap<Fragment>,
|
|
218
245
|
): RenderMap<Fragment>[] {
|
|
@@ -233,8 +260,6 @@ function getSharedCategoryIndexMaps(
|
|
|
233
260
|
if (!match) continue;
|
|
234
261
|
|
|
235
262
|
const [, category, fileName] = match;
|
|
236
|
-
if (fileName === categoryIndexNames[category]) continue;
|
|
237
|
-
|
|
238
263
|
if (!categories.has(category)) {
|
|
239
264
|
categories.set(category, new Set());
|
|
240
265
|
}
|