codama-renderers-dart 0.2.0 → 0.3.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.
- package/dist/index.browser.cjs +2102 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.js +2092 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.node.cjs +2102 -0
- package/dist/index.node.cjs.map +1 -0
- package/dist/index.node.js +2092 -0
- package/dist/index.node.js.map +1 -0
- package/dist/index.react-native.js +2092 -0
- package/dist/index.react-native.js.map +1 -0
- package/dist/types/fragments/accountPage.d.ts +8 -0
- package/dist/types/fragments/accountPage.d.ts.map +1 -0
- package/dist/types/fragments/discriminatorConstants.d.ts +8 -0
- package/dist/types/fragments/discriminatorConstants.d.ts.map +1 -0
- package/dist/types/fragments/errorPage.d.ts +8 -0
- package/dist/types/fragments/errorPage.d.ts.map +1 -0
- package/dist/types/fragments/index.d.ts +9 -0
- package/dist/types/fragments/index.d.ts.map +1 -0
- package/dist/types/fragments/indexPage.d.ts +10 -0
- package/dist/types/fragments/indexPage.d.ts.map +1 -0
- package/dist/types/fragments/instructionPage.d.ts +8 -0
- package/dist/types/fragments/instructionPage.d.ts.map +1 -0
- package/dist/types/fragments/pdaPage.d.ts +8 -0
- package/dist/types/fragments/pdaPage.d.ts.map +1 -0
- package/dist/types/fragments/programPage.d.ts +8 -0
- package/dist/types/fragments/programPage.d.ts.map +1 -0
- package/dist/types/fragments/typePage.d.ts +8 -0
- package/dist/types/fragments/typePage.d.ts.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/utils/codecs.d.ts +10 -0
- package/dist/types/utils/codecs.d.ts.map +1 -0
- package/dist/types/utils/formatCode.d.ts +10 -0
- package/dist/types/utils/formatCode.d.ts.map +1 -0
- package/dist/types/utils/fragment.d.ts +31 -0
- package/dist/types/utils/fragment.d.ts.map +1 -0
- package/dist/types/utils/importMap.d.ts +40 -0
- package/dist/types/utils/importMap.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +8 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/dist/types/utils/nameTransformers.d.ts +64 -0
- package/dist/types/utils/nameTransformers.d.ts.map +1 -0
- package/dist/types/utils/options.d.ts +41 -0
- package/dist/types/utils/options.d.ts.map +1 -0
- package/dist/types/utils/typeManifest.d.ts +21 -0
- package/dist/types/utils/typeManifest.d.ts.map +1 -0
- package/dist/types/visitors/getRenderMapVisitor.d.ts +9 -0
- package/dist/types/visitors/getRenderMapVisitor.d.ts.map +1 -0
- package/dist/types/visitors/getTypeManifestVisitor.d.ts +19 -0
- package/dist/types/visitors/getTypeManifestVisitor.d.ts.map +1 -0
- package/dist/types/visitors/index.d.ts +4 -0
- package/dist/types/visitors/index.d.ts.map +1 -0
- package/dist/types/visitors/renderVisitor.d.ts +9 -0
- package/dist/types/visitors/renderVisitor.d.ts.map +1 -0
- package/package.json +6 -11
- package/src/fragments/pdaPage.ts +18 -13
|
@@ -0,0 +1,2102 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var fs = require('fs');
|
|
6
|
+
var path = require('path');
|
|
7
|
+
var visitorsCore = require('@codama/visitors-core');
|
|
8
|
+
var renderersCore = require('@codama/renderers-core');
|
|
9
|
+
var child_process = require('child_process');
|
|
10
|
+
var nodes = require('@codama/nodes');
|
|
11
|
+
var errors = require('@codama/errors');
|
|
12
|
+
|
|
13
|
+
// src/visitors/renderVisitor.ts
|
|
14
|
+
function formatDartDirectory(dir) {
|
|
15
|
+
try {
|
|
16
|
+
child_process.execSync(`dart format --fix "${dir}"`, {
|
|
17
|
+
encoding: "utf-8",
|
|
18
|
+
timeout: 6e4,
|
|
19
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
20
|
+
});
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/utils/nameTransformers.ts
|
|
26
|
+
function pascalCase(str) {
|
|
27
|
+
return str.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : "").replace(/^(.)/, (c) => c.toUpperCase());
|
|
28
|
+
}
|
|
29
|
+
function camelCase(str) {
|
|
30
|
+
const pascal = pascalCase(str);
|
|
31
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
32
|
+
}
|
|
33
|
+
function snakeCase(str) {
|
|
34
|
+
return str.replace(/([A-Z])/g, "_$1").replace(/[-\s]+/g, "_").replace(/^_/, "").replace(/_+/g, "_").toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
function createDartNameApi() {
|
|
37
|
+
return {
|
|
38
|
+
dataType: (name) => pascalCase(name),
|
|
39
|
+
encoderFunction: (name) => `get${pascalCase(name)}Encoder`,
|
|
40
|
+
decoderFunction: (name) => `get${pascalCase(name)}Decoder`,
|
|
41
|
+
codecFunction: (name) => `get${pascalCase(name)}Codec`,
|
|
42
|
+
accountFetchFunction: (name) => `fetch${pascalCase(name)}`,
|
|
43
|
+
accountFetchMaybeFunction: (name) => `fetchMaybe${pascalCase(name)}`,
|
|
44
|
+
accountDecodeFunction: (name) => `decode${pascalCase(name)}`,
|
|
45
|
+
accountSizeConstant: (name) => `${camelCase(name)}Size`,
|
|
46
|
+
pdaFindFunction: (name) => `find${pascalCase(name)}Pda`,
|
|
47
|
+
instructionFunction: (name) => `get${pascalCase(name)}Instruction`,
|
|
48
|
+
instructionParseFunction: (name) => `parse${pascalCase(name)}Instruction`,
|
|
49
|
+
programAddressConstant: (name) => `${camelCase(name)}ProgramAddress`,
|
|
50
|
+
errorConstant: (programName, errorName) => `${camelCase(programName)}Error${pascalCase(errorName)}`,
|
|
51
|
+
errorMessageFunction: (name) => `get${pascalCase(name)}ErrorMessage`,
|
|
52
|
+
enumVariant: (name) => camelCase(name),
|
|
53
|
+
sealedClassVariant: (_parentName, variantName) => pascalCase(variantName),
|
|
54
|
+
isTypeFunction: (name) => `is${pascalCase(name)}`,
|
|
55
|
+
fileName: (name) => snakeCase(name),
|
|
56
|
+
discriminatorConstant: (name) => `${camelCase(name)}Discriminator`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/utils/codecs.ts
|
|
61
|
+
function bytesToDartHexList(bytes) {
|
|
62
|
+
const pairs = [];
|
|
63
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
64
|
+
pairs.push(`0x${bytes[i].toString(16).padStart(2, "0")}`);
|
|
65
|
+
}
|
|
66
|
+
return `[${pairs.join(", ")}]`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/utils/importMap.ts
|
|
70
|
+
var DART_EXTERNAL_PACKAGE_MAP = {
|
|
71
|
+
// Dart core
|
|
72
|
+
dartTypedData: "dart:typed_data",
|
|
73
|
+
dartConvert: "dart:convert",
|
|
74
|
+
meta: "package:meta/meta.dart",
|
|
75
|
+
// solana_kit packages
|
|
76
|
+
solanaAddresses: "package:solana_kit_addresses/solana_kit_addresses.dart",
|
|
77
|
+
solanaCodecsCore: "package:solana_kit_codecs_core/solana_kit_codecs_core.dart",
|
|
78
|
+
solanaCodecsDataStructures: "package:solana_kit_codecs_data_structures/solana_kit_codecs_data_structures.dart",
|
|
79
|
+
solanaCodecsNumbers: "package:solana_kit_codecs_numbers/solana_kit_codecs_numbers.dart",
|
|
80
|
+
solanaCodecsStrings: "package:solana_kit_codecs_strings/solana_kit_codecs_strings.dart",
|
|
81
|
+
solanaErrors: "package:solana_kit_errors/solana_kit_errors.dart",
|
|
82
|
+
solanaAccounts: "package:solana_kit_accounts/solana_kit_accounts.dart",
|
|
83
|
+
solanaInstructions: "package:solana_kit_instructions/solana_kit_instructions.dart",
|
|
84
|
+
solanaPrograms: "package:solana_kit_programs/solana_kit_programs.dart",
|
|
85
|
+
solanaRpcTypes: "package:solana_kit_rpc_types/solana_kit_rpc_types.dart",
|
|
86
|
+
solanaSigners: "package:solana_kit_signers/solana_kit_signers.dart"
|
|
87
|
+
};
|
|
88
|
+
var DartImportMap = class {
|
|
89
|
+
_imports = /* @__PURE__ */ new Set();
|
|
90
|
+
/**
|
|
91
|
+
* Add a logical module name (resolved via DART_EXTERNAL_PACKAGE_MAP)
|
|
92
|
+
* or a raw Dart import URI.
|
|
93
|
+
*/
|
|
94
|
+
add(module) {
|
|
95
|
+
this._imports.add(module);
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Merge another DartImportMap into this one.
|
|
100
|
+
*/
|
|
101
|
+
mergeWith(other) {
|
|
102
|
+
for (const imp of other._imports) {
|
|
103
|
+
this._imports.add(imp);
|
|
104
|
+
}
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if this import map is empty.
|
|
109
|
+
*/
|
|
110
|
+
get isEmpty() {
|
|
111
|
+
return this._imports.size === 0;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get all raw module keys.
|
|
115
|
+
*/
|
|
116
|
+
get modules() {
|
|
117
|
+
return new Set(this._imports);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Resolve all imports to Dart import URIs and return them sorted.
|
|
121
|
+
* @param internalMap Maps logical names to relative file paths for generated code cross-references.
|
|
122
|
+
*/
|
|
123
|
+
resolve(internalMap = {}) {
|
|
124
|
+
const uris = /* @__PURE__ */ new Set();
|
|
125
|
+
for (const module of this._imports) {
|
|
126
|
+
if (module in internalMap) {
|
|
127
|
+
uris.add(internalMap[module]);
|
|
128
|
+
} else if (module in DART_EXTERNAL_PACKAGE_MAP) {
|
|
129
|
+
uris.add(DART_EXTERNAL_PACKAGE_MAP[module]);
|
|
130
|
+
} else {
|
|
131
|
+
uris.add(module);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return [...uris].sort((a, b) => {
|
|
135
|
+
const aWeight = a.startsWith("dart:") ? 0 : a.startsWith("package:") ? 1 : 2;
|
|
136
|
+
const bWeight = b.startsWith("dart:") ? 0 : b.startsWith("package:") ? 1 : 2;
|
|
137
|
+
if (aWeight !== bWeight) return aWeight - bWeight;
|
|
138
|
+
return a.localeCompare(b);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Render all imports as Dart import statements.
|
|
143
|
+
*/
|
|
144
|
+
toString(internalMap = {}) {
|
|
145
|
+
const resolved = this.resolve(internalMap);
|
|
146
|
+
if (resolved.length === 0) return "";
|
|
147
|
+
const lines = [];
|
|
148
|
+
let lastPrefix = "";
|
|
149
|
+
for (const uri of resolved) {
|
|
150
|
+
const prefix = uri.startsWith("dart:") ? "dart" : uri.startsWith("package:") ? "package" : "relative";
|
|
151
|
+
if (lastPrefix && lastPrefix !== prefix) {
|
|
152
|
+
lines.push("");
|
|
153
|
+
}
|
|
154
|
+
lastPrefix = prefix;
|
|
155
|
+
lines.push(`import '${uri}';`);
|
|
156
|
+
}
|
|
157
|
+
return lines.join("\n");
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// src/utils/fragment.ts
|
|
162
|
+
function fragment(strings, ...values) {
|
|
163
|
+
const imports = new DartImportMap();
|
|
164
|
+
const parts = [];
|
|
165
|
+
for (let i = 0; i < strings.length; i++) {
|
|
166
|
+
parts.push(strings[i]);
|
|
167
|
+
if (i < values.length) {
|
|
168
|
+
const value = values[i];
|
|
169
|
+
if (value != null && typeof value === "object" && "imports" in value) {
|
|
170
|
+
parts.push(value.content);
|
|
171
|
+
imports.mergeWith(value.imports);
|
|
172
|
+
} else {
|
|
173
|
+
parts.push(String(value ?? ""));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
content: parts.join(""),
|
|
179
|
+
imports
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function emptyFragment() {
|
|
183
|
+
return { content: "", imports: new DartImportMap() };
|
|
184
|
+
}
|
|
185
|
+
function fragmentFromString(content) {
|
|
186
|
+
return { content, imports: new DartImportMap() };
|
|
187
|
+
}
|
|
188
|
+
function mergeFragments(fragments, joiner) {
|
|
189
|
+
const imports = new DartImportMap();
|
|
190
|
+
const contents = [];
|
|
191
|
+
for (const frag of fragments) {
|
|
192
|
+
contents.push(frag.content);
|
|
193
|
+
imports.mergeWith(frag.imports);
|
|
194
|
+
}
|
|
195
|
+
return { content: joiner(contents), imports };
|
|
196
|
+
}
|
|
197
|
+
function use(typeName, module) {
|
|
198
|
+
const imports = new DartImportMap();
|
|
199
|
+
imports.add(module);
|
|
200
|
+
return { content: typeName, imports };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/utils/typeManifest.ts
|
|
204
|
+
function emptyTypeManifest() {
|
|
205
|
+
return {
|
|
206
|
+
type: emptyFragment(),
|
|
207
|
+
encoder: emptyFragment(),
|
|
208
|
+
decoder: emptyFragment(),
|
|
209
|
+
value: emptyFragment(),
|
|
210
|
+
isEnum: false
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// src/visitors/getTypeManifestVisitor.ts
|
|
215
|
+
function getTypeManifestVisitor(input) {
|
|
216
|
+
const { nameApi, linkables, nonScalarEnums = [] } = input;
|
|
217
|
+
const baseVisitor = visitorsCore.staticVisitor(
|
|
218
|
+
(node) => {
|
|
219
|
+
throw new errors.CodamaError(errors.CODAMA_ERROR__UNEXPECTED_NODE_KIND, {
|
|
220
|
+
expectedKinds: ["typeNode"],
|
|
221
|
+
kind: node.kind
|
|
222
|
+
});
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
keys: [
|
|
226
|
+
// Type nodes
|
|
227
|
+
"numberTypeNode",
|
|
228
|
+
"booleanTypeNode",
|
|
229
|
+
"stringTypeNode",
|
|
230
|
+
"publicKeyTypeNode",
|
|
231
|
+
"bytesTypeNode",
|
|
232
|
+
"arrayTypeNode",
|
|
233
|
+
"mapTypeNode",
|
|
234
|
+
"setTypeNode",
|
|
235
|
+
"tupleTypeNode",
|
|
236
|
+
"structTypeNode",
|
|
237
|
+
"structFieldTypeNode",
|
|
238
|
+
"enumTypeNode",
|
|
239
|
+
"enumEmptyVariantTypeNode",
|
|
240
|
+
"enumStructVariantTypeNode",
|
|
241
|
+
"enumTupleVariantTypeNode",
|
|
242
|
+
"optionTypeNode",
|
|
243
|
+
"remainderOptionTypeNode",
|
|
244
|
+
"zeroableOptionTypeNode",
|
|
245
|
+
"fixedSizeTypeNode",
|
|
246
|
+
"sizePrefixTypeNode",
|
|
247
|
+
"hiddenPrefixTypeNode",
|
|
248
|
+
"hiddenSuffixTypeNode",
|
|
249
|
+
"sentinelTypeNode",
|
|
250
|
+
"preOffsetTypeNode",
|
|
251
|
+
"postOffsetTypeNode",
|
|
252
|
+
"solAmountTypeNode",
|
|
253
|
+
"amountTypeNode",
|
|
254
|
+
"dateTimeTypeNode",
|
|
255
|
+
"definedTypeLinkNode",
|
|
256
|
+
// Context nodes (for links)
|
|
257
|
+
"definedTypeNode",
|
|
258
|
+
"accountNode",
|
|
259
|
+
"instructionNode"
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
return visitorsCore.extendVisitor(baseVisitor, {
|
|
264
|
+
visitNumberType(node, { self }) {
|
|
265
|
+
const { format, endian } = node;
|
|
266
|
+
const endianSuffix = endian === "be" ? ", NumberCodecConfig(endian: Endian.big)" : "";
|
|
267
|
+
const endianDecoderSuffix = endian === "be" ? ", NumberCodecConfig(endian: Endian.big)" : "";
|
|
268
|
+
const dartType = getNumberDartType(format);
|
|
269
|
+
const codecName = getNumberCodecName(format);
|
|
270
|
+
return {
|
|
271
|
+
type: dartType === "BigInt" ? use("BigInt", "dartTypedData") : fragmentFromString(dartType),
|
|
272
|
+
encoder: fragment`${use(
|
|
273
|
+
`get${codecName}Encoder`,
|
|
274
|
+
"solanaCodecsNumbers"
|
|
275
|
+
)}(${endianSuffix ? fragmentFromString(endianSuffix.slice(2)) : fragmentFromString("")})`,
|
|
276
|
+
decoder: fragment`${use(
|
|
277
|
+
`get${codecName}Decoder`,
|
|
278
|
+
"solanaCodecsNumbers"
|
|
279
|
+
)}(${endianDecoderSuffix ? fragmentFromString(endianDecoderSuffix.slice(2)) : fragmentFromString("")})`,
|
|
280
|
+
value: emptyTypeManifest().value,
|
|
281
|
+
isEnum: false
|
|
282
|
+
};
|
|
283
|
+
},
|
|
284
|
+
visitBooleanType(_node, { self }) {
|
|
285
|
+
return {
|
|
286
|
+
type: fragmentFromString("bool"),
|
|
287
|
+
encoder: fragment`${use(
|
|
288
|
+
"getBooleanEncoder",
|
|
289
|
+
"solanaCodecsDataStructures"
|
|
290
|
+
)}()`,
|
|
291
|
+
decoder: fragment`${use(
|
|
292
|
+
"getBooleanDecoder",
|
|
293
|
+
"solanaCodecsDataStructures"
|
|
294
|
+
)}()`,
|
|
295
|
+
value: emptyTypeManifest().value,
|
|
296
|
+
isEnum: false
|
|
297
|
+
};
|
|
298
|
+
},
|
|
299
|
+
visitStringType(node, { self }) {
|
|
300
|
+
const { encoding } = node;
|
|
301
|
+
const codecMap = {
|
|
302
|
+
utf8: "Utf8",
|
|
303
|
+
base58: "Base58",
|
|
304
|
+
base64: "Base64",
|
|
305
|
+
base16: "Base16"
|
|
306
|
+
};
|
|
307
|
+
const codecName = codecMap[encoding] ?? "Utf8";
|
|
308
|
+
return {
|
|
309
|
+
type: fragmentFromString("String"),
|
|
310
|
+
encoder: fragment`${use(
|
|
311
|
+
`get${codecName}Encoder`,
|
|
312
|
+
"solanaCodecsStrings"
|
|
313
|
+
)}()`,
|
|
314
|
+
decoder: fragment`${use(
|
|
315
|
+
`get${codecName}Decoder`,
|
|
316
|
+
"solanaCodecsStrings"
|
|
317
|
+
)}()`,
|
|
318
|
+
value: emptyTypeManifest().value,
|
|
319
|
+
isEnum: false
|
|
320
|
+
};
|
|
321
|
+
},
|
|
322
|
+
visitPublicKeyType(_node, { self }) {
|
|
323
|
+
return {
|
|
324
|
+
type: fragment`${use("Address", "solanaAddresses")}`,
|
|
325
|
+
encoder: fragment`${use(
|
|
326
|
+
"getAddressEncoder",
|
|
327
|
+
"solanaAddresses"
|
|
328
|
+
)}()`,
|
|
329
|
+
decoder: fragment`${use(
|
|
330
|
+
"getAddressDecoder",
|
|
331
|
+
"solanaAddresses"
|
|
332
|
+
)}()`,
|
|
333
|
+
value: emptyTypeManifest().value,
|
|
334
|
+
isEnum: false
|
|
335
|
+
};
|
|
336
|
+
},
|
|
337
|
+
visitBytesType(_node, { self }) {
|
|
338
|
+
return {
|
|
339
|
+
type: fragment`${use("Uint8List", "dartTypedData")}`,
|
|
340
|
+
encoder: fragment`${use(
|
|
341
|
+
"getBytesEncoder",
|
|
342
|
+
"solanaCodecsDataStructures"
|
|
343
|
+
)}()`,
|
|
344
|
+
decoder: fragment`${use(
|
|
345
|
+
"getBytesDecoder",
|
|
346
|
+
"solanaCodecsDataStructures"
|
|
347
|
+
)}()`,
|
|
348
|
+
value: emptyTypeManifest().value,
|
|
349
|
+
isEnum: false
|
|
350
|
+
};
|
|
351
|
+
},
|
|
352
|
+
visitArrayType(node, { self }) {
|
|
353
|
+
const itemManifest = visitorsCore.visit(node.item, self);
|
|
354
|
+
const sizeExpr = getArraySizeExpression(node);
|
|
355
|
+
return {
|
|
356
|
+
type: fragment`List<${itemManifest.type}>`,
|
|
357
|
+
encoder: fragment`${use(
|
|
358
|
+
"getArrayEncoder",
|
|
359
|
+
"solanaCodecsDataStructures"
|
|
360
|
+
)}(${itemManifest.encoder}${sizeExpr})`,
|
|
361
|
+
decoder: fragment`${use(
|
|
362
|
+
"getArrayDecoder",
|
|
363
|
+
"solanaCodecsDataStructures"
|
|
364
|
+
)}(${itemManifest.decoder}${sizeExpr})`,
|
|
365
|
+
value: emptyTypeManifest().value,
|
|
366
|
+
isEnum: false
|
|
367
|
+
};
|
|
368
|
+
},
|
|
369
|
+
visitMapType(node, { self }) {
|
|
370
|
+
const keyManifest = visitorsCore.visit(node.key, self);
|
|
371
|
+
const valueManifest = visitorsCore.visit(node.value, self);
|
|
372
|
+
const sizeExpr = getMapSizeExpression(node);
|
|
373
|
+
return {
|
|
374
|
+
type: fragment`Map<${keyManifest.type}, ${valueManifest.type}>`,
|
|
375
|
+
encoder: fragment`${use(
|
|
376
|
+
"getMapEncoder",
|
|
377
|
+
"solanaCodecsDataStructures"
|
|
378
|
+
)}(${keyManifest.encoder}, ${valueManifest.encoder}${sizeExpr})`,
|
|
379
|
+
decoder: fragment`${use(
|
|
380
|
+
"getMapDecoder",
|
|
381
|
+
"solanaCodecsDataStructures"
|
|
382
|
+
)}(${keyManifest.decoder}, ${valueManifest.decoder}${sizeExpr})`,
|
|
383
|
+
value: emptyTypeManifest().value,
|
|
384
|
+
isEnum: false
|
|
385
|
+
};
|
|
386
|
+
},
|
|
387
|
+
visitSetType(node, { self }) {
|
|
388
|
+
const itemManifest = visitorsCore.visit(node.item, self);
|
|
389
|
+
const sizeExpr = getSetSizeExpression(node);
|
|
390
|
+
return {
|
|
391
|
+
type: fragment`Set<${itemManifest.type}>`,
|
|
392
|
+
encoder: fragment`${use(
|
|
393
|
+
"getSetEncoder",
|
|
394
|
+
"solanaCodecsDataStructures"
|
|
395
|
+
)}(${itemManifest.encoder}${sizeExpr})`,
|
|
396
|
+
decoder: fragment`${use(
|
|
397
|
+
"getSetDecoder",
|
|
398
|
+
"solanaCodecsDataStructures"
|
|
399
|
+
)}(${itemManifest.decoder}${sizeExpr})`,
|
|
400
|
+
value: emptyTypeManifest().value,
|
|
401
|
+
isEnum: false
|
|
402
|
+
};
|
|
403
|
+
},
|
|
404
|
+
visitTupleType(node, { self }) {
|
|
405
|
+
const itemManifests = node.items.map((item) => visitorsCore.visit(item, self));
|
|
406
|
+
const typeList = itemManifests.map((m) => m.type.content).join(", ");
|
|
407
|
+
const encoderList = itemManifests.map((m) => m.encoder);
|
|
408
|
+
const decoderList = itemManifests.map((m) => m.decoder);
|
|
409
|
+
const typeFragment = fragment`(${fragmentFromString(typeList)})`;
|
|
410
|
+
for (const m of itemManifests) {
|
|
411
|
+
typeFragment.imports.mergeWith(m.type.imports);
|
|
412
|
+
}
|
|
413
|
+
const encoderListStr = encoderList.map((e) => e.content).join(", ");
|
|
414
|
+
const encoderFrag = fragment`${use(
|
|
415
|
+
"getTupleEncoder",
|
|
416
|
+
"solanaCodecsDataStructures"
|
|
417
|
+
)}([${fragmentFromString(encoderListStr)}])`;
|
|
418
|
+
for (const e of encoderList) {
|
|
419
|
+
encoderFrag.imports.mergeWith(e.imports);
|
|
420
|
+
}
|
|
421
|
+
const decoderListStr = decoderList.map((d) => d.content).join(", ");
|
|
422
|
+
const decoderFrag = fragment`${use(
|
|
423
|
+
"getTupleDecoder",
|
|
424
|
+
"solanaCodecsDataStructures"
|
|
425
|
+
)}([${fragmentFromString(decoderListStr)}])`;
|
|
426
|
+
for (const d of decoderList) {
|
|
427
|
+
decoderFrag.imports.mergeWith(d.imports);
|
|
428
|
+
}
|
|
429
|
+
return {
|
|
430
|
+
type: typeFragment,
|
|
431
|
+
encoder: encoderFrag,
|
|
432
|
+
decoder: decoderFrag,
|
|
433
|
+
value: emptyTypeManifest().value,
|
|
434
|
+
isEnum: false
|
|
435
|
+
};
|
|
436
|
+
},
|
|
437
|
+
visitStructType(node, { self }) {
|
|
438
|
+
const fields = node.fields.map((f) => visitorsCore.visit(f, self));
|
|
439
|
+
const fieldNames = node.fields.map((f) => f.name);
|
|
440
|
+
const typeStr = "Map<String, Object?>";
|
|
441
|
+
const encoderFields = fields.map((f, i) => `('${fieldNames[i]}', ${f.encoder.content})`).join(", ");
|
|
442
|
+
const encoderFrag = fragment`${use(
|
|
443
|
+
"getStructEncoder",
|
|
444
|
+
"solanaCodecsDataStructures"
|
|
445
|
+
)}([${fragmentFromString(encoderFields)}])`;
|
|
446
|
+
for (const f of fields) {
|
|
447
|
+
encoderFrag.imports.mergeWith(f.encoder.imports);
|
|
448
|
+
}
|
|
449
|
+
const decoderFields = fields.map((f, i) => `('${fieldNames[i]}', ${f.decoder.content})`).join(", ");
|
|
450
|
+
const decoderFrag = fragment`${use(
|
|
451
|
+
"getStructDecoder",
|
|
452
|
+
"solanaCodecsDataStructures"
|
|
453
|
+
)}([${fragmentFromString(decoderFields)}])`;
|
|
454
|
+
for (const f of fields) {
|
|
455
|
+
decoderFrag.imports.mergeWith(f.decoder.imports);
|
|
456
|
+
}
|
|
457
|
+
return {
|
|
458
|
+
type: fragmentFromString(typeStr),
|
|
459
|
+
encoder: encoderFrag,
|
|
460
|
+
decoder: decoderFrag,
|
|
461
|
+
value: emptyTypeManifest().value,
|
|
462
|
+
isEnum: false
|
|
463
|
+
};
|
|
464
|
+
},
|
|
465
|
+
visitStructFieldType(node, { self }) {
|
|
466
|
+
return visitorsCore.visit(node.type, self);
|
|
467
|
+
},
|
|
468
|
+
visitEnumType(node, { self }) {
|
|
469
|
+
const isScalar = node.variants.every(
|
|
470
|
+
(v) => v.kind === "enumEmptyVariantTypeNode"
|
|
471
|
+
);
|
|
472
|
+
if (isScalar) {
|
|
473
|
+
return {
|
|
474
|
+
type: emptyTypeManifest().type,
|
|
475
|
+
// Will be replaced by the named type
|
|
476
|
+
encoder: emptyTypeManifest().encoder,
|
|
477
|
+
decoder: emptyTypeManifest().decoder,
|
|
478
|
+
value: emptyTypeManifest().value,
|
|
479
|
+
isEnum: true
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
return {
|
|
483
|
+
type: emptyTypeManifest().type,
|
|
484
|
+
encoder: emptyTypeManifest().encoder,
|
|
485
|
+
decoder: emptyTypeManifest().decoder,
|
|
486
|
+
value: emptyTypeManifest().value,
|
|
487
|
+
isEnum: false
|
|
488
|
+
};
|
|
489
|
+
},
|
|
490
|
+
visitEnumEmptyVariantType(_node, { self }) {
|
|
491
|
+
return emptyTypeManifest();
|
|
492
|
+
},
|
|
493
|
+
visitEnumStructVariantType(node, { self }) {
|
|
494
|
+
return visitorsCore.visit(node.struct, self);
|
|
495
|
+
},
|
|
496
|
+
visitEnumTupleVariantType(node, { self }) {
|
|
497
|
+
return visitorsCore.visit(node.tuple, self);
|
|
498
|
+
},
|
|
499
|
+
visitOptionType(node, { self }) {
|
|
500
|
+
const itemManifest = visitorsCore.visit(node.item, self);
|
|
501
|
+
const resolvedPrefix = nodes.resolveNestedTypeNode(node.prefix);
|
|
502
|
+
const prefixExpr = resolvedPrefix.format !== "u8" ? `, prefix: ${getNumberCodecExpression(resolvedPrefix.format, "Encoder")}` : "";
|
|
503
|
+
const prefixDecoderExpr = resolvedPrefix.format !== "u8" ? `, prefix: ${getNumberCodecExpression(resolvedPrefix.format, "Decoder")}` : "";
|
|
504
|
+
return {
|
|
505
|
+
type: fragment`${itemManifest.type}?`,
|
|
506
|
+
encoder: fragment`${use(
|
|
507
|
+
"getNullableEncoder",
|
|
508
|
+
"solanaCodecsDataStructures"
|
|
509
|
+
)}(${itemManifest.encoder}${fragmentFromString(prefixExpr)})`,
|
|
510
|
+
decoder: fragment`${use(
|
|
511
|
+
"getNullableDecoder",
|
|
512
|
+
"solanaCodecsDataStructures"
|
|
513
|
+
)}(${itemManifest.decoder}${fragmentFromString(prefixDecoderExpr)})`,
|
|
514
|
+
value: emptyTypeManifest().value,
|
|
515
|
+
isEnum: false
|
|
516
|
+
};
|
|
517
|
+
},
|
|
518
|
+
visitRemainderOptionType(node, { self }) {
|
|
519
|
+
const itemManifest = visitorsCore.visit(node.item, self);
|
|
520
|
+
return {
|
|
521
|
+
type: fragment`${itemManifest.type}?`,
|
|
522
|
+
encoder: fragment`${use(
|
|
523
|
+
"getNullableEncoder",
|
|
524
|
+
"solanaCodecsDataStructures"
|
|
525
|
+
)}(${itemManifest.encoder}, hasPrefix: false)`,
|
|
526
|
+
decoder: fragment`${use(
|
|
527
|
+
"getNullableDecoder",
|
|
528
|
+
"solanaCodecsDataStructures"
|
|
529
|
+
)}(${itemManifest.decoder}, hasPrefix: false)`,
|
|
530
|
+
value: emptyTypeManifest().value,
|
|
531
|
+
isEnum: false
|
|
532
|
+
};
|
|
533
|
+
},
|
|
534
|
+
visitZeroableOptionType(node, { self }) {
|
|
535
|
+
const itemManifest = visitorsCore.visit(node.item, self);
|
|
536
|
+
return {
|
|
537
|
+
type: fragment`${itemManifest.type}?`,
|
|
538
|
+
encoder: fragment`${use(
|
|
539
|
+
"getNullableEncoder",
|
|
540
|
+
"solanaCodecsDataStructures"
|
|
541
|
+
)}(${itemManifest.encoder}, hasPrefix: false, noneValue: const ZeroesNoneValue())`,
|
|
542
|
+
decoder: fragment`${use(
|
|
543
|
+
"getNullableDecoder",
|
|
544
|
+
"solanaCodecsDataStructures"
|
|
545
|
+
)}(${itemManifest.decoder}, hasPrefix: false, noneValue: const ZeroesNoneValue())`,
|
|
546
|
+
value: emptyTypeManifest().value,
|
|
547
|
+
isEnum: false
|
|
548
|
+
};
|
|
549
|
+
},
|
|
550
|
+
visitFixedSizeType(node, { self }) {
|
|
551
|
+
const innerManifest = visitorsCore.visit(node.type, self);
|
|
552
|
+
return {
|
|
553
|
+
type: innerManifest.type,
|
|
554
|
+
encoder: fragment`${use(
|
|
555
|
+
"fixEncoderSize",
|
|
556
|
+
"solanaCodecsCore"
|
|
557
|
+
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))})`,
|
|
558
|
+
decoder: fragment`${use(
|
|
559
|
+
"fixDecoderSize",
|
|
560
|
+
"solanaCodecsCore"
|
|
561
|
+
)}(${innerManifest.decoder}, ${fragmentFromString(String(node.size))})`,
|
|
562
|
+
value: innerManifest.value,
|
|
563
|
+
isEnum: innerManifest.isEnum
|
|
564
|
+
};
|
|
565
|
+
},
|
|
566
|
+
visitSizePrefixType(node, { self }) {
|
|
567
|
+
const innerManifest = visitorsCore.visit(node.type, self);
|
|
568
|
+
const prefixManifest = visitorsCore.visit(node.prefix, self);
|
|
569
|
+
return {
|
|
570
|
+
type: innerManifest.type,
|
|
571
|
+
encoder: fragment`${use(
|
|
572
|
+
"addEncoderSizePrefix",
|
|
573
|
+
"solanaCodecsCore"
|
|
574
|
+
)}(${innerManifest.encoder}, ${prefixManifest.encoder})`,
|
|
575
|
+
decoder: fragment`${use(
|
|
576
|
+
"addDecoderSizePrefix",
|
|
577
|
+
"solanaCodecsCore"
|
|
578
|
+
)}(${innerManifest.decoder}, ${prefixManifest.decoder})`,
|
|
579
|
+
value: innerManifest.value,
|
|
580
|
+
isEnum: innerManifest.isEnum
|
|
581
|
+
};
|
|
582
|
+
},
|
|
583
|
+
visitHiddenPrefixType(node, { self }) {
|
|
584
|
+
const innerManifest = visitorsCore.visit(node.type, self);
|
|
585
|
+
const prefixes = node.prefix.map((p) => visitorsCore.visit(p, self));
|
|
586
|
+
const prefixEncoders = prefixes.map((p) => p.encoder.content).join(", ");
|
|
587
|
+
const prefixDecoders = prefixes.map((p) => p.decoder.content).join(", ");
|
|
588
|
+
const encoderFrag = fragment`${use(
|
|
589
|
+
"getHiddenPrefixEncoder",
|
|
590
|
+
"solanaCodecsDataStructures"
|
|
591
|
+
)}(${innerManifest.encoder}, [${fragmentFromString(prefixEncoders)}])`;
|
|
592
|
+
for (const p of prefixes) {
|
|
593
|
+
encoderFrag.imports.mergeWith(p.encoder.imports);
|
|
594
|
+
}
|
|
595
|
+
const decoderFrag = fragment`${use(
|
|
596
|
+
"getHiddenPrefixDecoder",
|
|
597
|
+
"solanaCodecsDataStructures"
|
|
598
|
+
)}(${innerManifest.decoder}, [${fragmentFromString(prefixDecoders)}])`;
|
|
599
|
+
for (const p of prefixes) {
|
|
600
|
+
decoderFrag.imports.mergeWith(p.decoder.imports);
|
|
601
|
+
}
|
|
602
|
+
return {
|
|
603
|
+
type: innerManifest.type,
|
|
604
|
+
encoder: encoderFrag,
|
|
605
|
+
decoder: decoderFrag,
|
|
606
|
+
value: innerManifest.value,
|
|
607
|
+
isEnum: innerManifest.isEnum
|
|
608
|
+
};
|
|
609
|
+
},
|
|
610
|
+
visitHiddenSuffixType(node, { self }) {
|
|
611
|
+
const innerManifest = visitorsCore.visit(node.type, self);
|
|
612
|
+
const suffixes = node.suffix.map((s) => visitorsCore.visit(s, self));
|
|
613
|
+
const suffixEncoders = suffixes.map((s) => s.encoder.content).join(", ");
|
|
614
|
+
const suffixDecoders = suffixes.map((s) => s.decoder.content).join(", ");
|
|
615
|
+
const encoderFrag = fragment`${use(
|
|
616
|
+
"getHiddenSuffixEncoder",
|
|
617
|
+
"solanaCodecsDataStructures"
|
|
618
|
+
)}(${innerManifest.encoder}, [${fragmentFromString(suffixEncoders)}])`;
|
|
619
|
+
for (const s of suffixes) {
|
|
620
|
+
encoderFrag.imports.mergeWith(s.encoder.imports);
|
|
621
|
+
}
|
|
622
|
+
const decoderFrag = fragment`${use(
|
|
623
|
+
"getHiddenSuffixDecoder",
|
|
624
|
+
"solanaCodecsDataStructures"
|
|
625
|
+
)}(${innerManifest.decoder}, [${fragmentFromString(suffixDecoders)}])`;
|
|
626
|
+
for (const s of suffixes) {
|
|
627
|
+
decoderFrag.imports.mergeWith(s.decoder.imports);
|
|
628
|
+
}
|
|
629
|
+
return {
|
|
630
|
+
type: innerManifest.type,
|
|
631
|
+
encoder: encoderFrag,
|
|
632
|
+
decoder: decoderFrag,
|
|
633
|
+
value: innerManifest.value,
|
|
634
|
+
isEnum: innerManifest.isEnum
|
|
635
|
+
};
|
|
636
|
+
},
|
|
637
|
+
visitSentinelType(node, { self }) {
|
|
638
|
+
const innerManifest = visitorsCore.visit(node.type, self);
|
|
639
|
+
const sentinelManifest = visitorsCore.visit(node.sentinel, self);
|
|
640
|
+
return {
|
|
641
|
+
type: innerManifest.type,
|
|
642
|
+
encoder: fragment`${use(
|
|
643
|
+
"addEncoderSentinel",
|
|
644
|
+
"solanaCodecsCore"
|
|
645
|
+
)}(${innerManifest.encoder}, ${sentinelManifest.encoder})`,
|
|
646
|
+
decoder: fragment`${use(
|
|
647
|
+
"addDecoderSentinel",
|
|
648
|
+
"solanaCodecsCore"
|
|
649
|
+
)}(${innerManifest.decoder}, ${sentinelManifest.decoder})`,
|
|
650
|
+
value: innerManifest.value,
|
|
651
|
+
isEnum: innerManifest.isEnum
|
|
652
|
+
};
|
|
653
|
+
},
|
|
654
|
+
visitPreOffsetType(node, { self }) {
|
|
655
|
+
return visitorsCore.visit(node.type, self);
|
|
656
|
+
},
|
|
657
|
+
visitPostOffsetType(node, { self }) {
|
|
658
|
+
return visitorsCore.visit(node.type, self);
|
|
659
|
+
},
|
|
660
|
+
visitSolAmountType(node, { self }) {
|
|
661
|
+
return visitorsCore.visit(node.number, self);
|
|
662
|
+
},
|
|
663
|
+
visitAmountType(node, { self }) {
|
|
664
|
+
return visitorsCore.visit(node.number, self);
|
|
665
|
+
},
|
|
666
|
+
visitDateTimeType(node, { self }) {
|
|
667
|
+
return visitorsCore.visit(node.number, self);
|
|
668
|
+
},
|
|
669
|
+
visitDefinedTypeLink(node, { self }) {
|
|
670
|
+
const name = node.name;
|
|
671
|
+
const typeName = nameApi.dataType(name);
|
|
672
|
+
const isNonScalar = nonScalarEnums.includes(node.name);
|
|
673
|
+
const moduleKey = `definedType:${snakeCase(name)}`;
|
|
674
|
+
return {
|
|
675
|
+
type: fragment`${use(typeName, moduleKey)}`,
|
|
676
|
+
encoder: fragment`${use(nameApi.encoderFunction(name), moduleKey)}()`,
|
|
677
|
+
decoder: fragment`${use(nameApi.decoderFunction(name), moduleKey)}()`,
|
|
678
|
+
value: emptyTypeManifest().value,
|
|
679
|
+
isEnum: !isNonScalar
|
|
680
|
+
};
|
|
681
|
+
},
|
|
682
|
+
visitDefinedType(node, { self }) {
|
|
683
|
+
return visitorsCore.visit(node.type, self);
|
|
684
|
+
},
|
|
685
|
+
visitAccount(node, { self }) {
|
|
686
|
+
return visitorsCore.visit(node.data, self);
|
|
687
|
+
},
|
|
688
|
+
visitInstruction(node, { self }) {
|
|
689
|
+
return emptyTypeManifest();
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
function getNumberDartType(format) {
|
|
694
|
+
switch (format) {
|
|
695
|
+
case "u8":
|
|
696
|
+
case "u16":
|
|
697
|
+
case "u32":
|
|
698
|
+
case "i8":
|
|
699
|
+
case "i16":
|
|
700
|
+
case "i32":
|
|
701
|
+
case "shortU16":
|
|
702
|
+
return "int";
|
|
703
|
+
case "u64":
|
|
704
|
+
case "u128":
|
|
705
|
+
case "i64":
|
|
706
|
+
case "i128":
|
|
707
|
+
return "BigInt";
|
|
708
|
+
case "f32":
|
|
709
|
+
case "f64":
|
|
710
|
+
return "double";
|
|
711
|
+
default:
|
|
712
|
+
return "int";
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
function getNumberCodecName(format) {
|
|
716
|
+
switch (format) {
|
|
717
|
+
case "u8":
|
|
718
|
+
return "U8";
|
|
719
|
+
case "u16":
|
|
720
|
+
return "U16";
|
|
721
|
+
case "u32":
|
|
722
|
+
return "U32";
|
|
723
|
+
case "u64":
|
|
724
|
+
return "U64";
|
|
725
|
+
case "u128":
|
|
726
|
+
return "U128";
|
|
727
|
+
case "i8":
|
|
728
|
+
return "I8";
|
|
729
|
+
case "i16":
|
|
730
|
+
return "I16";
|
|
731
|
+
case "i32":
|
|
732
|
+
return "I32";
|
|
733
|
+
case "i64":
|
|
734
|
+
return "I64";
|
|
735
|
+
case "i128":
|
|
736
|
+
return "I128";
|
|
737
|
+
case "f32":
|
|
738
|
+
return "F32";
|
|
739
|
+
case "f64":
|
|
740
|
+
return "F64";
|
|
741
|
+
case "shortU16":
|
|
742
|
+
return "ShortU16";
|
|
743
|
+
default:
|
|
744
|
+
return "U8";
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
function getNumberCodecExpression(format, codecType) {
|
|
748
|
+
const name = getNumberCodecName(format);
|
|
749
|
+
return `get${name}${codecType}()`;
|
|
750
|
+
}
|
|
751
|
+
function getArraySizeExpression(node) {
|
|
752
|
+
if (!("count" in node) || !node.count) return "";
|
|
753
|
+
const count = node.count;
|
|
754
|
+
switch (count.kind) {
|
|
755
|
+
case "fixedCountNode":
|
|
756
|
+
return `, size: FixedArraySize(${count.value})`;
|
|
757
|
+
case "remainderCountNode":
|
|
758
|
+
return ", size: RemainderArraySize()";
|
|
759
|
+
case "prefixedCountNode": {
|
|
760
|
+
const resolvedPrefix = nodes.resolveNestedTypeNode(count.prefix);
|
|
761
|
+
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
762
|
+
return "";
|
|
763
|
+
}
|
|
764
|
+
return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
|
|
765
|
+
}
|
|
766
|
+
default:
|
|
767
|
+
return "";
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
function getMapSizeExpression(node) {
|
|
771
|
+
if (!("count" in node) || !node.count) return "";
|
|
772
|
+
const count = node.count;
|
|
773
|
+
switch (count.kind) {
|
|
774
|
+
case "fixedCountNode":
|
|
775
|
+
return `, size: FixedArraySize(${count.value})`;
|
|
776
|
+
case "remainderCountNode":
|
|
777
|
+
return ", size: RemainderArraySize()";
|
|
778
|
+
case "prefixedCountNode": {
|
|
779
|
+
const resolvedPrefix = nodes.resolveNestedTypeNode(count.prefix);
|
|
780
|
+
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
781
|
+
return "";
|
|
782
|
+
}
|
|
783
|
+
return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
|
|
784
|
+
}
|
|
785
|
+
default:
|
|
786
|
+
return "";
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function getSetSizeExpression(node) {
|
|
790
|
+
if (!("count" in node) || !node.count) return "";
|
|
791
|
+
const count = node.count;
|
|
792
|
+
switch (count.kind) {
|
|
793
|
+
case "fixedCountNode":
|
|
794
|
+
return `, size: FixedArraySize(${count.value})`;
|
|
795
|
+
case "remainderCountNode":
|
|
796
|
+
return ", size: RemainderArraySize()";
|
|
797
|
+
case "prefixedCountNode": {
|
|
798
|
+
const resolvedPrefix = nodes.resolveNestedTypeNode(count.prefix);
|
|
799
|
+
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
800
|
+
return "";
|
|
801
|
+
}
|
|
802
|
+
return `, size: PrefixedArraySize(get${getNumberCodecName(resolvedPrefix.format)}Encoder())`;
|
|
803
|
+
}
|
|
804
|
+
default:
|
|
805
|
+
return "";
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// src/fragments/discriminatorConstants.ts
|
|
810
|
+
function getDiscriminatorConstantsFragment(node, scope) {
|
|
811
|
+
const discriminators = node.discriminators ?? [];
|
|
812
|
+
if (discriminators.length === 0) return emptyFragment();
|
|
813
|
+
const name = node.name;
|
|
814
|
+
const constName = scope.nameApi.discriminatorConstant(name);
|
|
815
|
+
const fragments = [];
|
|
816
|
+
for (const disc of discriminators) {
|
|
817
|
+
switch (disc.kind) {
|
|
818
|
+
case "constantDiscriminatorNode": {
|
|
819
|
+
const constDisc = disc;
|
|
820
|
+
if (constDisc.constant.value.kind === "bytesValueNode") {
|
|
821
|
+
const bytes = hexToBytes(constDisc.constant.value.data);
|
|
822
|
+
const hexList = bytesToDartHexList(bytes);
|
|
823
|
+
fragments.push(
|
|
824
|
+
fragment`/// The discriminator bytes for this ${node.kind === "accountNode" ? "account" : "instruction"}.
|
|
825
|
+
final ${constName} = ${use("Uint8List", "dartTypedData")}.fromList(${fragmentFromString(hexList)});`
|
|
826
|
+
);
|
|
827
|
+
}
|
|
828
|
+
break;
|
|
829
|
+
}
|
|
830
|
+
case "fieldDiscriminatorNode": {
|
|
831
|
+
const fieldDisc = disc;
|
|
832
|
+
fragments.push(
|
|
833
|
+
fragment`/// The discriminator field name: '${fragmentFromString(fieldDisc.name)}'.
|
|
834
|
+
/// Offset: ${fragmentFromString(String(fieldDisc.offset))}.`
|
|
835
|
+
);
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
case "sizeDiscriminatorNode": {
|
|
839
|
+
const sizeDisc = disc;
|
|
840
|
+
fragments.push(
|
|
841
|
+
fragment`/// This ${node.kind === "accountNode" ? "account" : "instruction"} has a size discriminator of ${fragmentFromString(String(sizeDisc.size))} bytes.`
|
|
842
|
+
);
|
|
843
|
+
break;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
if (fragments.length === 0) return emptyFragment();
|
|
848
|
+
return mergeFragments(fragments, (cs) => cs.join("\n\n"));
|
|
849
|
+
}
|
|
850
|
+
function hexToBytes(hex) {
|
|
851
|
+
const clean = hex.replace(/^0x/, "");
|
|
852
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
853
|
+
for (let i = 0; i < clean.length; i += 2) {
|
|
854
|
+
bytes[i / 2] = parseInt(clean.slice(i, i + 2), 16);
|
|
855
|
+
}
|
|
856
|
+
return bytes;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// src/fragments/accountPage.ts
|
|
860
|
+
function getAccountPageFragment(node, scope) {
|
|
861
|
+
const name = node.name;
|
|
862
|
+
const typeName = scope.nameApi.dataType(name);
|
|
863
|
+
const dataNode = nodes.resolveNestedTypeNode(node.data);
|
|
864
|
+
const fields = dataNode.fields;
|
|
865
|
+
const fieldManifests = fields.map((f) => ({
|
|
866
|
+
field: f,
|
|
867
|
+
manifest: visitorsCore.visit(f.type, scope.typeManifestVisitor)
|
|
868
|
+
}));
|
|
869
|
+
const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
|
|
870
|
+
return ` final ${manifest.type.content} ${camelCase(f.name)};`;
|
|
871
|
+
}).join("\n");
|
|
872
|
+
const ctorParams = fields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
|
|
873
|
+
const eqChecks = fields.length === 0 ? "true" : fields.map(
|
|
874
|
+
(f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`
|
|
875
|
+
).join(" &&\n ");
|
|
876
|
+
const hashFields = fields.map((f) => camelCase(f.name)).join(", ");
|
|
877
|
+
const toStringFields = fields.map(
|
|
878
|
+
(f) => `${camelCase(f.name)}: $${camelCase(f.name)}`
|
|
879
|
+
).join(", ");
|
|
880
|
+
const encFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
881
|
+
return ` ('${f.name}', ${manifest.encoder.content}),`;
|
|
882
|
+
}).join("\n");
|
|
883
|
+
const decFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
884
|
+
return ` ('${f.name}', ${manifest.decoder.content}),`;
|
|
885
|
+
}).join("\n");
|
|
886
|
+
const toMapFields = fields.map(
|
|
887
|
+
(f) => ` '${f.name}': value.${camelCase(f.name)},`
|
|
888
|
+
).join("\n");
|
|
889
|
+
const fromMapFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
890
|
+
const typeStr = manifest.type.content;
|
|
891
|
+
const isNullable = typeStr.endsWith("?");
|
|
892
|
+
const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
|
|
893
|
+
return ` ${camelCase(f.name)}: ${accessor} as ${typeStr},`;
|
|
894
|
+
}).join("\n");
|
|
895
|
+
const encoderName = scope.nameApi.encoderFunction(name);
|
|
896
|
+
const decoderName = scope.nameApi.decoderFunction(name);
|
|
897
|
+
const codecName = scope.nameApi.codecFunction(name);
|
|
898
|
+
const decodeFnName = scope.nameApi.accountDecodeFunction(name);
|
|
899
|
+
const sizeFragment = node.size != null ? fragment`
|
|
900
|
+
/// The size of the [${fragmentFromString(typeName)}] account data in bytes.
|
|
901
|
+
const int ${fragmentFromString(scope.nameApi.accountSizeConstant(name))} = ${fragmentFromString(String(node.size))};` : emptyFragment();
|
|
902
|
+
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
903
|
+
const parts = [
|
|
904
|
+
fragment`// Auto-generated. Do not edit.
|
|
905
|
+
// ignore_for_file: type=lint
|
|
906
|
+
|
|
907
|
+
${use("Uint8List", "dartTypedData")}
|
|
908
|
+
${use("immutable", "meta")}
|
|
909
|
+
${use("Encoder", "solanaCodecsCore")}
|
|
910
|
+
${use("Decoder", "solanaCodecsCore")}
|
|
911
|
+
${use("Codec", "solanaCodecsCore")}
|
|
912
|
+
${use("combineCodec", "solanaCodecsCore")}
|
|
913
|
+
${use("transformEncoder", "solanaCodecsCore")}
|
|
914
|
+
${use("transformDecoder", "solanaCodecsCore")}
|
|
915
|
+
${use("getStructEncoder", "solanaCodecsDataStructures")}
|
|
916
|
+
${use("getStructDecoder", "solanaCodecsDataStructures")}
|
|
917
|
+
${use("Account", "solanaAccounts")}
|
|
918
|
+
${use("EncodedAccount", "solanaAccounts")}
|
|
919
|
+
${use("decodeAccount", "solanaAccounts")}
|
|
920
|
+
|
|
921
|
+
@immutable
|
|
922
|
+
class ${fragmentFromString(typeName)} {
|
|
923
|
+
const ${fragmentFromString(typeName)}({
|
|
924
|
+
${fragmentFromString(ctorParams)}
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
${fragmentFromString(fieldDecls)}
|
|
928
|
+
|
|
929
|
+
@override
|
|
930
|
+
bool operator ==(Object other) =>
|
|
931
|
+
identical(this, other) ||
|
|
932
|
+
other is ${fragmentFromString(typeName)} &&
|
|
933
|
+
runtimeType == other.runtimeType &&
|
|
934
|
+
${fragmentFromString(eqChecks)};
|
|
935
|
+
|
|
936
|
+
@override
|
|
937
|
+
int get hashCode => Object.hash(${fragmentFromString(hashFields)});
|
|
938
|
+
|
|
939
|
+
@override
|
|
940
|
+
String toString() => '${fragmentFromString(typeName)}(${fragmentFromString(toStringFields)})';
|
|
941
|
+
}`
|
|
942
|
+
];
|
|
943
|
+
if (sizeFragment.content) parts.push(sizeFragment);
|
|
944
|
+
if (discFragment.content) parts.push(discFragment);
|
|
945
|
+
parts.push(fragment`
|
|
946
|
+
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
947
|
+
final structEncoder = getStructEncoder(<(String, Encoder<Object?>)>[
|
|
948
|
+
${fragmentFromString(encFields)}
|
|
949
|
+
]);
|
|
950
|
+
|
|
951
|
+
return transformEncoder(
|
|
952
|
+
structEncoder,
|
|
953
|
+
(${fragmentFromString(typeName)} value) => <String, Object?>{
|
|
954
|
+
${fragmentFromString(toMapFields)}
|
|
955
|
+
},
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
960
|
+
final structDecoder = getStructDecoder(<(String, Decoder<Object?>)>[
|
|
961
|
+
${fragmentFromString(decFields)}
|
|
962
|
+
]);
|
|
963
|
+
|
|
964
|
+
return transformDecoder(
|
|
965
|
+
structDecoder,
|
|
966
|
+
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}(
|
|
967
|
+
${fragmentFromString(fromMapFields)}
|
|
968
|
+
),
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
|
|
973
|
+
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
Account<${fragmentFromString(typeName)}> ${fragmentFromString(decodeFnName)}(EncodedAccount encodedAccount) {
|
|
977
|
+
return decodeAccount(encodedAccount, ${fragmentFromString(decoderName)}());
|
|
978
|
+
}`);
|
|
979
|
+
const result = mergeFragments(parts, (cs) => cs.join("\n\n"));
|
|
980
|
+
for (const { manifest } of fieldManifests) {
|
|
981
|
+
result.imports.mergeWith(manifest.encoder.imports);
|
|
982
|
+
result.imports.mergeWith(manifest.decoder.imports);
|
|
983
|
+
result.imports.mergeWith(manifest.type.imports);
|
|
984
|
+
}
|
|
985
|
+
return result;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
// src/fragments/errorPage.ts
|
|
989
|
+
function getErrorPageFragment(programNode, scope) {
|
|
990
|
+
const errors = programNode.errors ?? [];
|
|
991
|
+
if (errors.length === 0) return emptyFragment();
|
|
992
|
+
const programName = programNode.name;
|
|
993
|
+
const errorConstants = errors.map((err) => {
|
|
994
|
+
const constName = scope.nameApi.errorConstant(
|
|
995
|
+
programName,
|
|
996
|
+
err.name
|
|
997
|
+
);
|
|
998
|
+
const hexCode = `0x${err.code.toString(16)}`;
|
|
999
|
+
const docs = err.docs?.length ? err.docs.map((d) => `/// ${d}`).join("\n") + "\n" : "";
|
|
1000
|
+
const message = err.message ? `/// Message: "${err.message}"
|
|
1001
|
+
` : "";
|
|
1002
|
+
return `${docs}${message}const int ${constName} = ${hexCode}; // ${err.code}`;
|
|
1003
|
+
}).join("\n\n");
|
|
1004
|
+
const messageEntries = errors.map((err) => {
|
|
1005
|
+
const constName = scope.nameApi.errorConstant(
|
|
1006
|
+
programName,
|
|
1007
|
+
err.name
|
|
1008
|
+
);
|
|
1009
|
+
const message = err.message ?? err.name;
|
|
1010
|
+
return ` ${constName}: '${escapeString(message)}',`;
|
|
1011
|
+
}).join("\n");
|
|
1012
|
+
const errorMessageFnName = scope.nameApi.errorMessageFunction(programName);
|
|
1013
|
+
const isErrorFnName = `is${pascalCase(programName)}Error`;
|
|
1014
|
+
return fragment`// Auto-generated. Do not edit.
|
|
1015
|
+
// ignore_for_file: type=lint, constant_identifier_names
|
|
1016
|
+
|
|
1017
|
+
/// Error codes for the ${fragmentFromString(pascalCase(programName))} program.
|
|
1018
|
+
|
|
1019
|
+
${fragmentFromString(errorConstants)}
|
|
1020
|
+
|
|
1021
|
+
/// Map of error codes to human-readable messages.
|
|
1022
|
+
const Map<int, String> _${fragmentFromString(camelCase(programName))}ErrorMessages = {
|
|
1023
|
+
${fragmentFromString(messageEntries)}
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
/// Get the error message for a ${fragmentFromString(pascalCase(programName))} program error code.
|
|
1027
|
+
String? ${fragmentFromString(errorMessageFnName)}(int code) {
|
|
1028
|
+
return _${fragmentFromString(camelCase(programName))}ErrorMessages[code];
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/// Check if an error code belongs to the ${fragmentFromString(pascalCase(programName))} program.
|
|
1032
|
+
bool ${fragmentFromString(isErrorFnName)}(int code) {
|
|
1033
|
+
return _${fragmentFromString(camelCase(programName))}ErrorMessages.containsKey(code);
|
|
1034
|
+
}`;
|
|
1035
|
+
}
|
|
1036
|
+
function escapeString(str) {
|
|
1037
|
+
return str.replace(/'/g, "\\'").replace(/\n/g, "\\n");
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
// src/fragments/indexPage.ts
|
|
1041
|
+
function getIndexPageFragment(fileNames, relativePath = "") {
|
|
1042
|
+
if (fileNames.length === 0) {
|
|
1043
|
+
return fragmentFromString(
|
|
1044
|
+
"// Auto-generated. Do not edit.\n// ignore_for_file: type=lint\n"
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
const exports$1 = fileNames.sort().map((f) => {
|
|
1048
|
+
const path = relativePath ? `${relativePath}/${f}` : f;
|
|
1049
|
+
return `export '${path}';`;
|
|
1050
|
+
}).join("\n");
|
|
1051
|
+
return fragmentFromString(
|
|
1052
|
+
`// Auto-generated. Do not edit.
|
|
1053
|
+
// ignore_for_file: type=lint
|
|
1054
|
+
|
|
1055
|
+
${exports$1}
|
|
1056
|
+
`
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
function getRootIndexPageFragment(categories) {
|
|
1060
|
+
const exports$1 = categories.sort().map((cat) => `export '${cat}/${cat}.dart';`).join("\n");
|
|
1061
|
+
return fragmentFromString(
|
|
1062
|
+
`// Auto-generated. Do not edit.
|
|
1063
|
+
// ignore_for_file: type=lint
|
|
1064
|
+
|
|
1065
|
+
${exports$1}
|
|
1066
|
+
`
|
|
1067
|
+
);
|
|
1068
|
+
}
|
|
1069
|
+
function getInstructionPageFragment(node, scope) {
|
|
1070
|
+
const name = node.name;
|
|
1071
|
+
const typeName = scope.nameApi.dataType(name);
|
|
1072
|
+
const instrFnName = scope.nameApi.instructionFunction(name);
|
|
1073
|
+
const parseFnName = scope.nameApi.instructionParseFunction(name);
|
|
1074
|
+
const accounts = node.accounts ?? [];
|
|
1075
|
+
const args = (node.arguments ?? []).filter(
|
|
1076
|
+
(arg) => !isDiscriminatorArg(arg, node)
|
|
1077
|
+
);
|
|
1078
|
+
const allArgs = node.arguments ?? [];
|
|
1079
|
+
const dataClassName = `${typeName}InstructionData`;
|
|
1080
|
+
const allArgManifests = allArgs.map((arg) => ({
|
|
1081
|
+
arg,
|
|
1082
|
+
manifest: visitorsCore.visit(arg.type, scope.typeManifestVisitor)
|
|
1083
|
+
}));
|
|
1084
|
+
const dataFieldDecls = allArgManifests.map(({ arg, manifest }) => {
|
|
1085
|
+
const fieldName = camelCase(arg.name);
|
|
1086
|
+
return ` final ${manifest.type.content} ${fieldName};`;
|
|
1087
|
+
}).join("\n");
|
|
1088
|
+
const dataCtorParams = allArgManifests.map(({ arg }) => {
|
|
1089
|
+
const fieldName = camelCase(arg.name);
|
|
1090
|
+
if (isDiscriminatorArg(arg, node)) {
|
|
1091
|
+
return ` this.${fieldName} = ${getDiscriminatorDefault(arg)},`;
|
|
1092
|
+
}
|
|
1093
|
+
return ` required this.${fieldName},`;
|
|
1094
|
+
}).join("\n");
|
|
1095
|
+
const encFields = allArgManifests.map(({ arg, manifest }) => {
|
|
1096
|
+
return ` ('${arg.name}', ${manifest.encoder.content}),`;
|
|
1097
|
+
}).join("\n");
|
|
1098
|
+
const decFields = allArgManifests.map(({ arg, manifest }) => {
|
|
1099
|
+
return ` ('${arg.name}', ${manifest.decoder.content}),`;
|
|
1100
|
+
}).join("\n");
|
|
1101
|
+
const toMapFields = allArgs.map(
|
|
1102
|
+
(arg) => ` '${arg.name}': value.${camelCase(arg.name)},`
|
|
1103
|
+
).join("\n");
|
|
1104
|
+
const fromMapFields = allArgManifests.map(({ arg, manifest }) => {
|
|
1105
|
+
const typeStr = manifest.type.content;
|
|
1106
|
+
const isNullable = typeStr.endsWith("?");
|
|
1107
|
+
const accessor = isNullable ? `map['${arg.name}']` : `map['${arg.name}']!`;
|
|
1108
|
+
return ` ${camelCase(arg.name)}: ${accessor} as ${typeStr},`;
|
|
1109
|
+
}).join("\n");
|
|
1110
|
+
const dataEncoderName = `get${typeName}InstructionDataEncoder`;
|
|
1111
|
+
const dataDecoderName = `get${typeName}InstructionDataDecoder`;
|
|
1112
|
+
const dataCodecName = `get${typeName}InstructionDataCodec`;
|
|
1113
|
+
const accountParams = accounts.map((acc) => {
|
|
1114
|
+
const fieldName = camelCase(acc.name);
|
|
1115
|
+
const isRequired = !(acc.isOptional ?? false);
|
|
1116
|
+
return isRequired ? ` required Address ${fieldName},` : ` Address? ${fieldName},`;
|
|
1117
|
+
}).join("\n");
|
|
1118
|
+
const argManifestMap = new Map(allArgManifests.map(({ arg, manifest }) => [arg, manifest]));
|
|
1119
|
+
const argParams = args.map((arg) => {
|
|
1120
|
+
const manifest = argManifestMap.get(arg);
|
|
1121
|
+
const fieldName = camelCase(arg.name);
|
|
1122
|
+
const hasDefault = arg.defaultValue != null;
|
|
1123
|
+
if (hasDefault) {
|
|
1124
|
+
return ` ${manifest.type.content}? ${fieldName},`;
|
|
1125
|
+
}
|
|
1126
|
+
return ` required ${manifest.type.content} ${fieldName},`;
|
|
1127
|
+
}).join("\n");
|
|
1128
|
+
const accountMetas = accounts.map((acc) => {
|
|
1129
|
+
const fieldName = camelCase(acc.name);
|
|
1130
|
+
const role = getAccountRole(acc);
|
|
1131
|
+
const isOptional = acc.isOptional ?? false;
|
|
1132
|
+
if (isOptional) {
|
|
1133
|
+
return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}),`;
|
|
1134
|
+
}
|
|
1135
|
+
return ` AccountMeta(address: ${fieldName}, role: ${role}),`;
|
|
1136
|
+
}).join("\n");
|
|
1137
|
+
const dataConstruction = allArgs.map((arg) => {
|
|
1138
|
+
const fieldName = camelCase(arg.name);
|
|
1139
|
+
if (isDiscriminatorArg(arg, node)) {
|
|
1140
|
+
return "";
|
|
1141
|
+
}
|
|
1142
|
+
return ` ${fieldName}: ${fieldName}${arg.defaultValue != null ? ` ?? ${getDefaultValue(arg)}` : ""},`;
|
|
1143
|
+
}).filter(Boolean).join("\n");
|
|
1144
|
+
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
1145
|
+
const parts = [
|
|
1146
|
+
fragment`// Auto-generated. Do not edit.
|
|
1147
|
+
// ignore_for_file: type=lint
|
|
1148
|
+
|
|
1149
|
+
${use("Uint8List", "dartTypedData")}
|
|
1150
|
+
${use("immutable", "meta")}
|
|
1151
|
+
${use("Encoder", "solanaCodecsCore")}
|
|
1152
|
+
${use("Decoder", "solanaCodecsCore")}
|
|
1153
|
+
${use("Codec", "solanaCodecsCore")}
|
|
1154
|
+
${use("combineCodec", "solanaCodecsCore")}
|
|
1155
|
+
${use("transformEncoder", "solanaCodecsCore")}
|
|
1156
|
+
${use("transformDecoder", "solanaCodecsCore")}
|
|
1157
|
+
${use("getStructEncoder", "solanaCodecsDataStructures")}
|
|
1158
|
+
${use("getStructDecoder", "solanaCodecsDataStructures")}
|
|
1159
|
+
${use("Address", "solanaAddresses")}
|
|
1160
|
+
${use("Instruction", "solanaInstructions")}
|
|
1161
|
+
${use("AccountMeta", "solanaInstructions")}
|
|
1162
|
+
${use("AccountRole", "solanaInstructions")}`
|
|
1163
|
+
];
|
|
1164
|
+
if (discFragment.content) parts.push(discFragment);
|
|
1165
|
+
parts.push(fragment`
|
|
1166
|
+
@immutable
|
|
1167
|
+
class ${fragmentFromString(dataClassName)} {
|
|
1168
|
+
const ${fragmentFromString(dataClassName)}({
|
|
1169
|
+
${fragmentFromString(dataCtorParams)}
|
|
1170
|
+
});
|
|
1171
|
+
|
|
1172
|
+
${fragmentFromString(dataFieldDecls)}
|
|
1173
|
+
}`);
|
|
1174
|
+
parts.push(fragment`
|
|
1175
|
+
Encoder<${fragmentFromString(dataClassName)}> ${fragmentFromString(dataEncoderName)}() {
|
|
1176
|
+
final structEncoder = getStructEncoder(<(String, Encoder<Object?>)>[
|
|
1177
|
+
${fragmentFromString(encFields)}
|
|
1178
|
+
]);
|
|
1179
|
+
|
|
1180
|
+
return transformEncoder(
|
|
1181
|
+
structEncoder,
|
|
1182
|
+
(${fragmentFromString(dataClassName)} value) => <String, Object?>{
|
|
1183
|
+
${fragmentFromString(toMapFields)}
|
|
1184
|
+
},
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
Decoder<${fragmentFromString(dataClassName)}> ${fragmentFromString(dataDecoderName)}() {
|
|
1189
|
+
final structDecoder = getStructDecoder(<(String, Decoder<Object?>)>[
|
|
1190
|
+
${fragmentFromString(decFields)}
|
|
1191
|
+
]);
|
|
1192
|
+
|
|
1193
|
+
return transformDecoder(
|
|
1194
|
+
structDecoder,
|
|
1195
|
+
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(dataClassName)}(
|
|
1196
|
+
${fragmentFromString(fromMapFields)}
|
|
1197
|
+
),
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
Codec<${fragmentFromString(dataClassName)}, ${fragmentFromString(dataClassName)}> ${fragmentFromString(dataCodecName)}() {
|
|
1202
|
+
return combineCodec(${fragmentFromString(dataEncoderName)}(), ${fragmentFromString(dataDecoderName)}());
|
|
1203
|
+
}`);
|
|
1204
|
+
parts.push(fragment`
|
|
1205
|
+
/// Creates a [${fragmentFromString(typeName)}] instruction.
|
|
1206
|
+
Instruction ${fragmentFromString(instrFnName)}({
|
|
1207
|
+
required Address programAddress,
|
|
1208
|
+
${fragmentFromString(accountParams)}
|
|
1209
|
+
${fragmentFromString(argParams)}
|
|
1210
|
+
}) {
|
|
1211
|
+
final data = ${fragmentFromString(dataClassName)}(
|
|
1212
|
+
${fragmentFromString(dataConstruction)}
|
|
1213
|
+
);
|
|
1214
|
+
|
|
1215
|
+
return Instruction(
|
|
1216
|
+
programAddress: programAddress,
|
|
1217
|
+
accounts: [
|
|
1218
|
+
${fragmentFromString(accountMetas)}
|
|
1219
|
+
],
|
|
1220
|
+
data: ${fragmentFromString(dataEncoderName)}().encode(data),
|
|
1221
|
+
);
|
|
1222
|
+
}`);
|
|
1223
|
+
parts.push(fragment`
|
|
1224
|
+
/// Parses a [${fragmentFromString(typeName)}] instruction from raw instruction data.
|
|
1225
|
+
${fragmentFromString(dataClassName)} ${fragmentFromString(parseFnName)}(Instruction instruction) {
|
|
1226
|
+
return ${fragmentFromString(dataDecoderName)}().decode(instruction.data!);
|
|
1227
|
+
}`);
|
|
1228
|
+
const result = mergeFragments(parts, (cs) => cs.join("\n"));
|
|
1229
|
+
for (const { manifest } of allArgManifests) {
|
|
1230
|
+
result.imports.mergeWith(manifest.encoder.imports);
|
|
1231
|
+
result.imports.mergeWith(manifest.decoder.imports);
|
|
1232
|
+
result.imports.mergeWith(manifest.type.imports);
|
|
1233
|
+
}
|
|
1234
|
+
return result;
|
|
1235
|
+
}
|
|
1236
|
+
function getAccountRole(acc) {
|
|
1237
|
+
const isSigner = acc.isSigner === true || acc.isSigner === "either";
|
|
1238
|
+
const isWritable = acc.isWritable ?? false;
|
|
1239
|
+
if (isSigner && isWritable) return "AccountRole.writableSigner";
|
|
1240
|
+
if (isSigner) return "AccountRole.readonlySigner";
|
|
1241
|
+
if (isWritable) return "AccountRole.writable";
|
|
1242
|
+
return "AccountRole.readonly";
|
|
1243
|
+
}
|
|
1244
|
+
function isDiscriminatorArg(arg, node) {
|
|
1245
|
+
const discriminators = node.discriminators ?? [];
|
|
1246
|
+
return discriminators.some(
|
|
1247
|
+
(d) => d.kind === "fieldDiscriminatorNode" && d.name === arg.name
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
function getDiscriminatorDefault(arg, _node) {
|
|
1251
|
+
if (arg.defaultValue) {
|
|
1252
|
+
if (arg.defaultValue.kind === "numberValueNode") {
|
|
1253
|
+
return String(arg.defaultValue.number);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
return "0";
|
|
1257
|
+
}
|
|
1258
|
+
function getDefaultValue(arg) {
|
|
1259
|
+
if (!arg.defaultValue) return "null";
|
|
1260
|
+
const dv = arg.defaultValue;
|
|
1261
|
+
switch (dv.kind) {
|
|
1262
|
+
case "numberValueNode":
|
|
1263
|
+
return String(dv.number);
|
|
1264
|
+
case "booleanValueNode":
|
|
1265
|
+
return String(dv.boolean);
|
|
1266
|
+
case "stringValueNode":
|
|
1267
|
+
return `'${dv.string}'`;
|
|
1268
|
+
case "publicKeyValueNode":
|
|
1269
|
+
return `Address('${dv.publicKey}')`;
|
|
1270
|
+
case "noneValueNode":
|
|
1271
|
+
return "null";
|
|
1272
|
+
default:
|
|
1273
|
+
return "null";
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
function getPdaPageFragment(node, scope) {
|
|
1277
|
+
const name = node.name;
|
|
1278
|
+
const findFnName = scope.nameApi.pdaFindFunction(name);
|
|
1279
|
+
const seedsClassName = `${pascalCase(name)}Seeds`;
|
|
1280
|
+
const seeds = node.seeds ?? [];
|
|
1281
|
+
const variableSeeds = seeds.filter(
|
|
1282
|
+
(s) => s.kind === "variablePdaSeedNode"
|
|
1283
|
+
);
|
|
1284
|
+
seeds.filter(
|
|
1285
|
+
(s) => s.kind === "constantPdaSeedNode"
|
|
1286
|
+
);
|
|
1287
|
+
const hasSeedsClass = variableSeeds.length > 0;
|
|
1288
|
+
const seedFieldDecls = variableSeeds.map((s) => {
|
|
1289
|
+
if (s.kind !== "variablePdaSeedNode") return "";
|
|
1290
|
+
const manifest = visitorsCore.visit(s.type, scope.typeManifestVisitor);
|
|
1291
|
+
return ` final ${manifest.type.content} ${camelCase(s.name)};`;
|
|
1292
|
+
}).join("\n");
|
|
1293
|
+
const seedCtorParams = variableSeeds.map((s) => {
|
|
1294
|
+
if (s.kind !== "variablePdaSeedNode") return "";
|
|
1295
|
+
return ` required this.${camelCase(s.name)},`;
|
|
1296
|
+
}).join("\n");
|
|
1297
|
+
const seedBytesList = [];
|
|
1298
|
+
for (const seed of seeds) {
|
|
1299
|
+
if (seed.kind === "constantPdaSeedNode") {
|
|
1300
|
+
if (seed.value.kind === "bytesValueNode") {
|
|
1301
|
+
seedBytesList.push(` ...${bytesValueToDart(seed.value.data)},`);
|
|
1302
|
+
} else if (seed.value.kind === "stringValueNode") {
|
|
1303
|
+
seedBytesList.push(` ...utf8.encode('${seed.value.string}'),`);
|
|
1304
|
+
} else if (seed.value.kind === "publicKeyValueNode") {
|
|
1305
|
+
seedBytesList.push(` ...getAddressEncoder().encode(Address('${seed.value.publicKey}')),`);
|
|
1306
|
+
} else if (seed.value.kind === "numberValueNode") {
|
|
1307
|
+
const manifest = visitorsCore.visit(seed.type, scope.typeManifestVisitor);
|
|
1308
|
+
seedBytesList.push(` ...${manifest.encoder.content}.encode(${seed.value.number}),`);
|
|
1309
|
+
}
|
|
1310
|
+
} else if (seed.kind === "variablePdaSeedNode") {
|
|
1311
|
+
const manifest = visitorsCore.visit(seed.type, scope.typeManifestVisitor);
|
|
1312
|
+
seedBytesList.push(
|
|
1313
|
+
` ...${manifest.encoder.content}.encode(seeds.${camelCase(seed.name)}),`
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
const programIdParam = node.programId ? `Address programAddress = const Address('${node.programId}')` : "required Address programAddress";
|
|
1318
|
+
const parts = [
|
|
1319
|
+
fragment`// Auto-generated. Do not edit.
|
|
1320
|
+
// ignore_for_file: type=lint
|
|
1321
|
+
|
|
1322
|
+
${use("Uint8List", "dartTypedData")}
|
|
1323
|
+
${use("immutable", "meta")}
|
|
1324
|
+
${use("Address", "solanaAddresses")}
|
|
1325
|
+
${use("getAddressEncoder", "solanaAddresses")}`
|
|
1326
|
+
];
|
|
1327
|
+
if (hasSeedsClass) {
|
|
1328
|
+
parts.push(fragment`
|
|
1329
|
+
@immutable
|
|
1330
|
+
class ${fragmentFromString(seedsClassName)} {
|
|
1331
|
+
const ${fragmentFromString(seedsClassName)}({
|
|
1332
|
+
${fragmentFromString(seedCtorParams)}
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
${fragmentFromString(seedFieldDecls)}
|
|
1336
|
+
}`);
|
|
1337
|
+
}
|
|
1338
|
+
const seedsParam = hasSeedsClass ? ` required ${seedsClassName} seeds,` : "";
|
|
1339
|
+
parts.push(fragment`
|
|
1340
|
+
/// Finds the program derived address for [${fragmentFromString(pascalCase(name))}].
|
|
1341
|
+
Future<(Address, int)> ${fragmentFromString(findFnName)}({
|
|
1342
|
+
${fragmentFromString(seedsParam)}
|
|
1343
|
+
${fragmentFromString(programIdParam)},
|
|
1344
|
+
}) async {
|
|
1345
|
+
final seedBytes = <int>[
|
|
1346
|
+
${fragmentFromString(seedBytesList.join("\n"))}
|
|
1347
|
+
];
|
|
1348
|
+
|
|
1349
|
+
// TODO: Call getProgramDerivedAddress with seedBytes and programAddress
|
|
1350
|
+
throw UnimplementedError('PDA derivation not yet implemented');
|
|
1351
|
+
}`);
|
|
1352
|
+
return mergeFragments(parts, (cs) => cs.join("\n"));
|
|
1353
|
+
}
|
|
1354
|
+
function bytesValueToDart(hex) {
|
|
1355
|
+
const clean = hex.replace(/^0x/, "");
|
|
1356
|
+
const pairs = [];
|
|
1357
|
+
for (let i = 0; i < clean.length; i += 2) {
|
|
1358
|
+
pairs.push(`0x${clean.slice(i, i + 2)}`);
|
|
1359
|
+
}
|
|
1360
|
+
return `[${pairs.join(", ")}]`;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
// src/fragments/programPage.ts
|
|
1364
|
+
function getProgramPageFragment(node, scope) {
|
|
1365
|
+
const name = node.name;
|
|
1366
|
+
const addressConstName = scope.nameApi.programAddressConstant(name);
|
|
1367
|
+
const parts = [
|
|
1368
|
+
fragment`// Auto-generated. Do not edit.
|
|
1369
|
+
// ignore_for_file: type=lint
|
|
1370
|
+
|
|
1371
|
+
${use("Address", "solanaAddresses")}
|
|
1372
|
+
|
|
1373
|
+
/// The address of the ${fragmentFromString(pascalCase(name))} program.
|
|
1374
|
+
const ${fragmentFromString(addressConstName)} = Address('${fragmentFromString(node.publicKey)}');`
|
|
1375
|
+
];
|
|
1376
|
+
const accounts = node.accounts ?? [];
|
|
1377
|
+
if (accounts.length > 0) {
|
|
1378
|
+
const accountVariants = accounts.map((acc) => ` ${camelCase(acc.name)},`).join("\n");
|
|
1379
|
+
parts.push(fragment`
|
|
1380
|
+
/// Known accounts for the ${fragmentFromString(pascalCase(name))} program.
|
|
1381
|
+
enum ${fragmentFromString(pascalCase(name))}Account {
|
|
1382
|
+
${fragmentFromString(accountVariants)}
|
|
1383
|
+
}`);
|
|
1384
|
+
}
|
|
1385
|
+
const instructions = node.instructions ?? [];
|
|
1386
|
+
if (instructions.length > 0) {
|
|
1387
|
+
const instrVariants = instructions.map((instr) => ` ${camelCase(instr.name)},`).join("\n");
|
|
1388
|
+
parts.push(fragment`
|
|
1389
|
+
/// Known instructions for the ${fragmentFromString(pascalCase(name))} program.
|
|
1390
|
+
enum ${fragmentFromString(pascalCase(name))}Instruction {
|
|
1391
|
+
${fragmentFromString(instrVariants)}
|
|
1392
|
+
}`);
|
|
1393
|
+
}
|
|
1394
|
+
return mergeFragments(parts, (cs) => cs.join("\n"));
|
|
1395
|
+
}
|
|
1396
|
+
function getTypePageFragment(node, scope) {
|
|
1397
|
+
const name = node.name;
|
|
1398
|
+
scope.nameApi.dataType(name);
|
|
1399
|
+
const typeNode = node.type;
|
|
1400
|
+
if (typeNode.kind === "enumTypeNode") {
|
|
1401
|
+
const isScalar = typeNode.variants.every(
|
|
1402
|
+
(v) => v.kind === "enumEmptyVariantTypeNode"
|
|
1403
|
+
);
|
|
1404
|
+
if (isScalar) {
|
|
1405
|
+
return getScalarEnumPageFragment(node, scope);
|
|
1406
|
+
}
|
|
1407
|
+
return getDataEnumPageFragment(node, scope);
|
|
1408
|
+
}
|
|
1409
|
+
if (typeNode.kind === "structTypeNode") {
|
|
1410
|
+
return getStructPageFragment(node, scope);
|
|
1411
|
+
}
|
|
1412
|
+
return getTypeAliasPageFragment(node, scope);
|
|
1413
|
+
}
|
|
1414
|
+
function getScalarEnumPageFragment(node, scope) {
|
|
1415
|
+
const name = node.name;
|
|
1416
|
+
const typeName = scope.nameApi.dataType(name);
|
|
1417
|
+
const enumNode = node.type;
|
|
1418
|
+
if (enumNode.kind !== "enumTypeNode") return emptyFragment();
|
|
1419
|
+
const variants = enumNode.variants.map((v) => {
|
|
1420
|
+
const variantName = scope.nameApi.enumVariant(v.name);
|
|
1421
|
+
return variantName;
|
|
1422
|
+
});
|
|
1423
|
+
const variantLines = variants.map((v) => ` ${v},`).join("\n");
|
|
1424
|
+
const encoderName = scope.nameApi.encoderFunction(name);
|
|
1425
|
+
const decoderName = scope.nameApi.decoderFunction(name);
|
|
1426
|
+
const codecName = scope.nameApi.codecFunction(name);
|
|
1427
|
+
const resolvedSize = nodes.resolveNestedTypeNode(enumNode.size);
|
|
1428
|
+
const sizeType = resolvedSize.format ?? "u8";
|
|
1429
|
+
const sizeCodecName = getNumberCodecName2(sizeType);
|
|
1430
|
+
return fragment`// Auto-generated. Do not edit.
|
|
1431
|
+
// ignore_for_file: type=lint
|
|
1432
|
+
|
|
1433
|
+
${use("Uint8List", "dartTypedData")}
|
|
1434
|
+
${use("Encoder", "solanaCodecsCore")}
|
|
1435
|
+
${use("Decoder", "solanaCodecsCore")}
|
|
1436
|
+
${use("Codec", "solanaCodecsCore")}
|
|
1437
|
+
${use("combineCodec", "solanaCodecsCore")}
|
|
1438
|
+
${use("transformEncoder", "solanaCodecsCore")}
|
|
1439
|
+
${use("transformDecoder", "solanaCodecsCore")}
|
|
1440
|
+
${use(`get${sizeCodecName}Encoder`, "solanaCodecsNumbers")}
|
|
1441
|
+
${use(`get${sizeCodecName}Decoder`, "solanaCodecsNumbers")}
|
|
1442
|
+
|
|
1443
|
+
enum ${fragmentFromString(typeName)} {
|
|
1444
|
+
${fragmentFromString(variantLines)}
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
1448
|
+
return transformEncoder(
|
|
1449
|
+
get${fragmentFromString(sizeCodecName)}Encoder(),
|
|
1450
|
+
(${fragmentFromString(typeName)} value) => value.index,
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
1455
|
+
return transformDecoder(
|
|
1456
|
+
get${fragmentFromString(sizeCodecName)}Decoder(),
|
|
1457
|
+
(int value, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}.values[value],
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
|
|
1462
|
+
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
1463
|
+
}`;
|
|
1464
|
+
}
|
|
1465
|
+
function getDataEnumPageFragment(node, scope) {
|
|
1466
|
+
const name = node.name;
|
|
1467
|
+
const typeName = scope.nameApi.dataType(name);
|
|
1468
|
+
const enumNode = node.type;
|
|
1469
|
+
if (enumNode.kind !== "enumTypeNode") return emptyFragment();
|
|
1470
|
+
const variantClasses = [];
|
|
1471
|
+
const encoderVariants = [];
|
|
1472
|
+
const decoderVariants = [];
|
|
1473
|
+
const allVariantManifests = [];
|
|
1474
|
+
for (let i = 0; i < enumNode.variants.length; i++) {
|
|
1475
|
+
const variant = enumNode.variants[i];
|
|
1476
|
+
const variantClassName = scope.nameApi.sealedClassVariant(
|
|
1477
|
+
name,
|
|
1478
|
+
variant.name
|
|
1479
|
+
);
|
|
1480
|
+
if (variant.kind === "enumEmptyVariantTypeNode") {
|
|
1481
|
+
variantClasses.push(`final class ${variantClassName} extends ${typeName} {
|
|
1482
|
+
const ${variantClassName}();
|
|
1483
|
+
|
|
1484
|
+
@override
|
|
1485
|
+
bool operator ==(Object other) =>
|
|
1486
|
+
identical(this, other) || other is ${variantClassName};
|
|
1487
|
+
|
|
1488
|
+
@override
|
|
1489
|
+
int get hashCode => runtimeType.hashCode;
|
|
1490
|
+
|
|
1491
|
+
@override
|
|
1492
|
+
String toString() => '${typeName}.${variantClassName}()';
|
|
1493
|
+
}`);
|
|
1494
|
+
encoderVariants.push(
|
|
1495
|
+
`(${i}, getStructEncoder(<(String, Encoder<Object?>)>[]))`
|
|
1496
|
+
);
|
|
1497
|
+
decoderVariants.push(
|
|
1498
|
+
`(${i}, getStructDecoder(<(String, Decoder<Object?>)>[]).map((_) => const ${variantClassName}()))`
|
|
1499
|
+
);
|
|
1500
|
+
} else if (variant.kind === "enumStructVariantTypeNode") {
|
|
1501
|
+
const resolvedStruct = nodes.resolveNestedTypeNode(variant.struct);
|
|
1502
|
+
const fields = resolvedStruct.fields;
|
|
1503
|
+
const fieldManifests = fields.map((f) => ({
|
|
1504
|
+
field: f,
|
|
1505
|
+
manifest: visitorsCore.visit(f.type, scope.typeManifestVisitor)
|
|
1506
|
+
}));
|
|
1507
|
+
for (const { manifest } of fieldManifests) {
|
|
1508
|
+
allVariantManifests.push(manifest);
|
|
1509
|
+
}
|
|
1510
|
+
const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
|
|
1511
|
+
return ` final ${manifest.type.content} ${camelCase(f.name)};`;
|
|
1512
|
+
}).join("\n");
|
|
1513
|
+
const ctorParams = fields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
|
|
1514
|
+
const eqChecks = fields.map((f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`).join(" &&\n ");
|
|
1515
|
+
const hashFields = fields.map((f) => camelCase(f.name)).join(", ");
|
|
1516
|
+
const toStringFields = fields.map((f) => `${camelCase(f.name)}: $${camelCase(f.name)}`).join(", ");
|
|
1517
|
+
variantClasses.push(`final class ${variantClassName} extends ${typeName} {
|
|
1518
|
+
const ${variantClassName}({
|
|
1519
|
+
${ctorParams}
|
|
1520
|
+
});
|
|
1521
|
+
|
|
1522
|
+
${fieldDecls}
|
|
1523
|
+
|
|
1524
|
+
@override
|
|
1525
|
+
bool operator ==(Object other) =>
|
|
1526
|
+
identical(this, other) ||
|
|
1527
|
+
other is ${variantClassName} &&
|
|
1528
|
+
${eqChecks};
|
|
1529
|
+
|
|
1530
|
+
@override
|
|
1531
|
+
int get hashCode => Object.hash(${hashFields});
|
|
1532
|
+
|
|
1533
|
+
@override
|
|
1534
|
+
String toString() => '${typeName}.${variantClassName}(${toStringFields})';
|
|
1535
|
+
}`);
|
|
1536
|
+
const encFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1537
|
+
return `('${f.name}', ${manifest.encoder.content})`;
|
|
1538
|
+
}).join(", ");
|
|
1539
|
+
const decFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1540
|
+
return `('${f.name}', ${manifest.decoder.content})`;
|
|
1541
|
+
}).join(", ");
|
|
1542
|
+
const fromMapFields = fieldManifests.map(
|
|
1543
|
+
({ field: f, manifest }) => {
|
|
1544
|
+
const typeStr = manifest.type.content;
|
|
1545
|
+
const isNullable = typeStr.endsWith("?");
|
|
1546
|
+
const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
|
|
1547
|
+
return `${camelCase(f.name)}: ${accessor} as ${typeStr}`;
|
|
1548
|
+
}
|
|
1549
|
+
).join(", ");
|
|
1550
|
+
const toMapFields = fields.map(
|
|
1551
|
+
(f) => `'${f.name}': value.${camelCase(f.name)}`
|
|
1552
|
+
).join(", ");
|
|
1553
|
+
encoderVariants.push(
|
|
1554
|
+
`(${i}, transformEncoder(getStructEncoder([${encFields}]), (${variantClassName} value) => <String, Object?>{${toMapFields}}))`
|
|
1555
|
+
);
|
|
1556
|
+
decoderVariants.push(
|
|
1557
|
+
`(${i}, transformDecoder(getStructDecoder([${decFields}]), (Map<String, Object?> map, Uint8List bytes, int offset) => ${variantClassName}(${fromMapFields})))`
|
|
1558
|
+
);
|
|
1559
|
+
} else if (variant.kind === "enumTupleVariantTypeNode") {
|
|
1560
|
+
const resolvedTuple = nodes.resolveNestedTypeNode(variant.tuple);
|
|
1561
|
+
const items = resolvedTuple.items;
|
|
1562
|
+
if (items.length === 1) {
|
|
1563
|
+
const manifest = visitorsCore.visit(items[0], scope.typeManifestVisitor);
|
|
1564
|
+
allVariantManifests.push(manifest);
|
|
1565
|
+
variantClasses.push(`final class ${variantClassName} extends ${typeName} {
|
|
1566
|
+
const ${variantClassName}(this.value);
|
|
1567
|
+
|
|
1568
|
+
final ${manifest.type.content} value;
|
|
1569
|
+
|
|
1570
|
+
@override
|
|
1571
|
+
bool operator ==(Object other) =>
|
|
1572
|
+
identical(this, other) ||
|
|
1573
|
+
other is ${variantClassName} && value == other.value;
|
|
1574
|
+
|
|
1575
|
+
@override
|
|
1576
|
+
int get hashCode => value.hashCode;
|
|
1577
|
+
|
|
1578
|
+
@override
|
|
1579
|
+
String toString() => '${typeName}.${variantClassName}($value)';
|
|
1580
|
+
}`);
|
|
1581
|
+
encoderVariants.push(
|
|
1582
|
+
`(${i}, transformEncoder(${manifest.encoder.content}, (${variantClassName} value) => value.value))`
|
|
1583
|
+
);
|
|
1584
|
+
decoderVariants.push(
|
|
1585
|
+
`(${i}, transformDecoder(${manifest.decoder.content}, (${manifest.type.content} value, Uint8List bytes, int offset) => ${variantClassName}(value)))`
|
|
1586
|
+
);
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
const encoderName = scope.nameApi.encoderFunction(name);
|
|
1591
|
+
const decoderName = scope.nameApi.decoderFunction(name);
|
|
1592
|
+
const codecName = scope.nameApi.codecFunction(name);
|
|
1593
|
+
const resolvedSize = nodes.resolveNestedTypeNode(enumNode.size);
|
|
1594
|
+
const sizeType = resolvedSize.format ?? "u8";
|
|
1595
|
+
const sizeCodecName = getNumberCodecName2(sizeType);
|
|
1596
|
+
const result = fragment`// Auto-generated. Do not edit.
|
|
1597
|
+
// ignore_for_file: type=lint
|
|
1598
|
+
|
|
1599
|
+
${use("Uint8List", "dartTypedData")}
|
|
1600
|
+
${use("immutable", "meta")}
|
|
1601
|
+
${use("Encoder", "solanaCodecsCore")}
|
|
1602
|
+
${use("Decoder", "solanaCodecsCore")}
|
|
1603
|
+
${use("Codec", "solanaCodecsCore")}
|
|
1604
|
+
${use("combineCodec", "solanaCodecsCore")}
|
|
1605
|
+
${use("transformEncoder", "solanaCodecsCore")}
|
|
1606
|
+
${use("transformDecoder", "solanaCodecsCore")}
|
|
1607
|
+
${use("getStructEncoder", "solanaCodecsDataStructures")}
|
|
1608
|
+
${use("getStructDecoder", "solanaCodecsDataStructures")}
|
|
1609
|
+
${use("getDiscriminatedUnionEncoder", "solanaCodecsDataStructures")}
|
|
1610
|
+
${use("getDiscriminatedUnionDecoder", "solanaCodecsDataStructures")}
|
|
1611
|
+
${use(`get${sizeCodecName}Encoder`, "solanaCodecsNumbers")}
|
|
1612
|
+
${use(`get${sizeCodecName}Decoder`, "solanaCodecsNumbers")}
|
|
1613
|
+
|
|
1614
|
+
sealed class ${fragmentFromString(typeName)} {
|
|
1615
|
+
const ${fragmentFromString(typeName)}();
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
${fragmentFromString(variantClasses.join("\n\n"))}
|
|
1619
|
+
|
|
1620
|
+
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
1621
|
+
return getDiscriminatedUnionEncoder([
|
|
1622
|
+
${fragmentFromString(encoderVariants.join(",\n "))},
|
|
1623
|
+
], size: get${fragmentFromString(sizeCodecName)}Encoder());
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
1627
|
+
return getDiscriminatedUnionDecoder([
|
|
1628
|
+
${fragmentFromString(decoderVariants.join(",\n "))},
|
|
1629
|
+
], size: get${fragmentFromString(sizeCodecName)}Decoder());
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
|
|
1633
|
+
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
1634
|
+
}`;
|
|
1635
|
+
for (const manifest of allVariantManifests) {
|
|
1636
|
+
result.imports.mergeWith(manifest.encoder.imports);
|
|
1637
|
+
result.imports.mergeWith(manifest.decoder.imports);
|
|
1638
|
+
result.imports.mergeWith(manifest.type.imports);
|
|
1639
|
+
}
|
|
1640
|
+
return result;
|
|
1641
|
+
}
|
|
1642
|
+
function getStructPageFragment(node, scope) {
|
|
1643
|
+
const name = node.name;
|
|
1644
|
+
const typeName = scope.nameApi.dataType(name);
|
|
1645
|
+
const structNode = node.type;
|
|
1646
|
+
if (structNode.kind !== "structTypeNode") return emptyFragment();
|
|
1647
|
+
const fields = structNode.fields;
|
|
1648
|
+
const fieldManifests = fields.map((f) => ({
|
|
1649
|
+
field: f,
|
|
1650
|
+
manifest: visitorsCore.visit(f.type, scope.typeManifestVisitor)
|
|
1651
|
+
}));
|
|
1652
|
+
const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
|
|
1653
|
+
return ` final ${manifest.type.content} ${camelCase(f.name)};`;
|
|
1654
|
+
}).join("\n");
|
|
1655
|
+
const ctorParams = fields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
|
|
1656
|
+
const eqChecks = fields.length === 0 ? "true" : fields.map(
|
|
1657
|
+
(f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`
|
|
1658
|
+
).join(" &&\n ");
|
|
1659
|
+
const hashFields = fields.map((f) => camelCase(f.name)).join(", ");
|
|
1660
|
+
const toStringFields = fields.map(
|
|
1661
|
+
(f) => `${camelCase(f.name)}: $${camelCase(f.name)}`
|
|
1662
|
+
).join(", ");
|
|
1663
|
+
const encoderName = scope.nameApi.encoderFunction(name);
|
|
1664
|
+
const decoderName = scope.nameApi.decoderFunction(name);
|
|
1665
|
+
const codecName = scope.nameApi.codecFunction(name);
|
|
1666
|
+
const encFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1667
|
+
return ` ('${f.name}', ${manifest.encoder.content}),`;
|
|
1668
|
+
}).join("\n");
|
|
1669
|
+
const decFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1670
|
+
return ` ('${f.name}', ${manifest.decoder.content}),`;
|
|
1671
|
+
}).join("\n");
|
|
1672
|
+
const toMapFields = fields.map(
|
|
1673
|
+
(f) => ` '${f.name}': value.${camelCase(f.name)},`
|
|
1674
|
+
).join("\n");
|
|
1675
|
+
const fromMapFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1676
|
+
const typeStr = manifest.type.content;
|
|
1677
|
+
const isNullable = typeStr.endsWith("?");
|
|
1678
|
+
const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
|
|
1679
|
+
return ` ${camelCase(f.name)}: ${accessor} as ${typeStr},`;
|
|
1680
|
+
}).join("\n");
|
|
1681
|
+
const result = fragment`// Auto-generated. Do not edit.
|
|
1682
|
+
// ignore_for_file: type=lint
|
|
1683
|
+
|
|
1684
|
+
${use("Uint8List", "dartTypedData")}
|
|
1685
|
+
${use("immutable", "meta")}
|
|
1686
|
+
${use("Encoder", "solanaCodecsCore")}
|
|
1687
|
+
${use("Decoder", "solanaCodecsCore")}
|
|
1688
|
+
${use("Codec", "solanaCodecsCore")}
|
|
1689
|
+
${use("combineCodec", "solanaCodecsCore")}
|
|
1690
|
+
${use("transformEncoder", "solanaCodecsCore")}
|
|
1691
|
+
${use("transformDecoder", "solanaCodecsCore")}
|
|
1692
|
+
${use("getStructEncoder", "solanaCodecsDataStructures")}
|
|
1693
|
+
${use("getStructDecoder", "solanaCodecsDataStructures")}
|
|
1694
|
+
|
|
1695
|
+
@immutable
|
|
1696
|
+
class ${fragmentFromString(typeName)} {
|
|
1697
|
+
const ${fragmentFromString(typeName)}({
|
|
1698
|
+
${fragmentFromString(ctorParams)}
|
|
1699
|
+
});
|
|
1700
|
+
|
|
1701
|
+
${fragmentFromString(fieldDecls)}
|
|
1702
|
+
|
|
1703
|
+
@override
|
|
1704
|
+
bool operator ==(Object other) =>
|
|
1705
|
+
identical(this, other) ||
|
|
1706
|
+
other is ${fragmentFromString(typeName)} &&
|
|
1707
|
+
runtimeType == other.runtimeType &&
|
|
1708
|
+
${fragmentFromString(eqChecks)};
|
|
1709
|
+
|
|
1710
|
+
@override
|
|
1711
|
+
int get hashCode => Object.hash(${fragmentFromString(hashFields)});
|
|
1712
|
+
|
|
1713
|
+
@override
|
|
1714
|
+
String toString() => '${fragmentFromString(typeName)}(${fragmentFromString(toStringFields)})';
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
1718
|
+
final structEncoder = getStructEncoder(<(String, Encoder<Object?>)>[
|
|
1719
|
+
${fragmentFromString(encFields)}
|
|
1720
|
+
]);
|
|
1721
|
+
|
|
1722
|
+
return transformEncoder(
|
|
1723
|
+
structEncoder,
|
|
1724
|
+
(${fragmentFromString(typeName)} value) => <String, Object?>{
|
|
1725
|
+
${fragmentFromString(toMapFields)}
|
|
1726
|
+
},
|
|
1727
|
+
);
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
1731
|
+
final structDecoder = getStructDecoder(<(String, Decoder<Object?>)>[
|
|
1732
|
+
${fragmentFromString(decFields)}
|
|
1733
|
+
]);
|
|
1734
|
+
|
|
1735
|
+
return transformDecoder(
|
|
1736
|
+
structDecoder,
|
|
1737
|
+
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}(
|
|
1738
|
+
${fragmentFromString(fromMapFields)}
|
|
1739
|
+
),
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
|
|
1744
|
+
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
1745
|
+
}`;
|
|
1746
|
+
for (const { manifest } of fieldManifests) {
|
|
1747
|
+
result.imports.mergeWith(manifest.encoder.imports);
|
|
1748
|
+
result.imports.mergeWith(manifest.decoder.imports);
|
|
1749
|
+
result.imports.mergeWith(manifest.type.imports);
|
|
1750
|
+
}
|
|
1751
|
+
return result;
|
|
1752
|
+
}
|
|
1753
|
+
function getTypeAliasPageFragment(node, scope) {
|
|
1754
|
+
const name = node.name;
|
|
1755
|
+
const typeName = scope.nameApi.dataType(name);
|
|
1756
|
+
const manifest = visitorsCore.visit(node.type, scope.typeManifestVisitor);
|
|
1757
|
+
const encoderName = scope.nameApi.encoderFunction(name);
|
|
1758
|
+
const decoderName = scope.nameApi.decoderFunction(name);
|
|
1759
|
+
const codecName = scope.nameApi.codecFunction(name);
|
|
1760
|
+
return fragment`// Auto-generated. Do not edit.
|
|
1761
|
+
// ignore_for_file: type=lint
|
|
1762
|
+
|
|
1763
|
+
${use("Encoder", "solanaCodecsCore")}
|
|
1764
|
+
${use("Decoder", "solanaCodecsCore")}
|
|
1765
|
+
${use("Codec", "solanaCodecsCore")}
|
|
1766
|
+
${use("combineCodec", "solanaCodecsCore")}
|
|
1767
|
+
|
|
1768
|
+
typedef ${fragmentFromString(typeName)} = ${manifest.type};
|
|
1769
|
+
|
|
1770
|
+
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
1771
|
+
return ${manifest.encoder};
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
1775
|
+
return ${manifest.decoder};
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
|
|
1779
|
+
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
1780
|
+
}`;
|
|
1781
|
+
}
|
|
1782
|
+
function getNumberCodecName2(format) {
|
|
1783
|
+
switch (format) {
|
|
1784
|
+
case "u8":
|
|
1785
|
+
return "U8";
|
|
1786
|
+
case "u16":
|
|
1787
|
+
return "U16";
|
|
1788
|
+
case "u32":
|
|
1789
|
+
return "U32";
|
|
1790
|
+
case "u64":
|
|
1791
|
+
return "U64";
|
|
1792
|
+
case "u128":
|
|
1793
|
+
return "U128";
|
|
1794
|
+
case "i8":
|
|
1795
|
+
return "I8";
|
|
1796
|
+
case "i16":
|
|
1797
|
+
return "I16";
|
|
1798
|
+
case "i32":
|
|
1799
|
+
return "I32";
|
|
1800
|
+
case "i64":
|
|
1801
|
+
return "I64";
|
|
1802
|
+
case "i128":
|
|
1803
|
+
return "I128";
|
|
1804
|
+
case "f32":
|
|
1805
|
+
return "F32";
|
|
1806
|
+
case "f64":
|
|
1807
|
+
return "F64";
|
|
1808
|
+
case "shortU16":
|
|
1809
|
+
return "ShortU16";
|
|
1810
|
+
default:
|
|
1811
|
+
return "U8";
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
// src/visitors/getRenderMapVisitor.ts
|
|
1816
|
+
function getRenderMapVisitor(options = {}) {
|
|
1817
|
+
const nameApi = {
|
|
1818
|
+
...createDartNameApi(),
|
|
1819
|
+
...options.nameApi
|
|
1820
|
+
};
|
|
1821
|
+
options.dependencyMap ?? {};
|
|
1822
|
+
const stack = new visitorsCore.NodeStack();
|
|
1823
|
+
const linkables = new visitorsCore.LinkableDictionary();
|
|
1824
|
+
const typeManifestVisitor = getTypeManifestVisitor({
|
|
1825
|
+
nameApi,
|
|
1826
|
+
linkables});
|
|
1827
|
+
const scope = {
|
|
1828
|
+
nameApi,
|
|
1829
|
+
typeManifestVisitor};
|
|
1830
|
+
return visitorsCore.pipe(
|
|
1831
|
+
visitorsCore.staticVisitor(
|
|
1832
|
+
() => renderersCore.createRenderMap(),
|
|
1833
|
+
{
|
|
1834
|
+
keys: [
|
|
1835
|
+
"rootNode",
|
|
1836
|
+
"programNode",
|
|
1837
|
+
"accountNode",
|
|
1838
|
+
"definedTypeNode",
|
|
1839
|
+
"instructionNode",
|
|
1840
|
+
"pdaNode"
|
|
1841
|
+
]
|
|
1842
|
+
}
|
|
1843
|
+
),
|
|
1844
|
+
(v) => visitorsCore.extendVisitor(v, {
|
|
1845
|
+
visitRoot(node, { self }) {
|
|
1846
|
+
const programMaps = [
|
|
1847
|
+
visitorsCore.visit(node.program, self),
|
|
1848
|
+
...node.additionalPrograms.map((p) => visitorsCore.visit(p, self))
|
|
1849
|
+
];
|
|
1850
|
+
return renderersCore.mergeRenderMaps(programMaps);
|
|
1851
|
+
},
|
|
1852
|
+
visitProgram(node, { self }) {
|
|
1853
|
+
const programName = node.name;
|
|
1854
|
+
const maps = [];
|
|
1855
|
+
const accountFiles = [];
|
|
1856
|
+
const instructionFiles = [];
|
|
1857
|
+
const typeFiles = [];
|
|
1858
|
+
const pdaFiles = [];
|
|
1859
|
+
const errorFiles = [];
|
|
1860
|
+
const programFiles = [];
|
|
1861
|
+
for (const account of node.accounts ?? []) {
|
|
1862
|
+
maps.push(visitorsCore.visit(account, self));
|
|
1863
|
+
accountFiles.push(`${snakeCase(account.name)}.dart`);
|
|
1864
|
+
}
|
|
1865
|
+
for (const instruction of node.instructions ?? []) {
|
|
1866
|
+
maps.push(visitorsCore.visit(instruction, self));
|
|
1867
|
+
instructionFiles.push(
|
|
1868
|
+
`${snakeCase(instruction.name)}.dart`
|
|
1869
|
+
);
|
|
1870
|
+
}
|
|
1871
|
+
for (const definedType of node.definedTypes ?? []) {
|
|
1872
|
+
maps.push(visitorsCore.visit(definedType, self));
|
|
1873
|
+
typeFiles.push(
|
|
1874
|
+
`${snakeCase(definedType.name)}.dart`
|
|
1875
|
+
);
|
|
1876
|
+
}
|
|
1877
|
+
for (const pda of node.pdas ?? []) {
|
|
1878
|
+
maps.push(visitorsCore.visit(pda, self));
|
|
1879
|
+
pdaFiles.push(`${snakeCase(pda.name)}.dart`);
|
|
1880
|
+
}
|
|
1881
|
+
const programFragment = getProgramPageFragment(node, scope);
|
|
1882
|
+
const programFileName = `${snakeCase(programName)}.dart`;
|
|
1883
|
+
programFiles.push(programFileName);
|
|
1884
|
+
let programMap = renderersCore.createRenderMap();
|
|
1885
|
+
programMap = renderersCore.addToRenderMap(programMap, `programs/${programFileName}`, programFragment);
|
|
1886
|
+
maps.push(programMap);
|
|
1887
|
+
const errors = node.errors ?? [];
|
|
1888
|
+
if (errors.length > 0) {
|
|
1889
|
+
const errorFragment = getErrorPageFragment(node, scope);
|
|
1890
|
+
const errorFileName = `${snakeCase(programName)}.dart`;
|
|
1891
|
+
errorFiles.push(errorFileName);
|
|
1892
|
+
let errorMap = renderersCore.createRenderMap();
|
|
1893
|
+
errorMap = renderersCore.addToRenderMap(errorMap, `errors/${errorFileName}`, errorFragment);
|
|
1894
|
+
maps.push(errorMap);
|
|
1895
|
+
}
|
|
1896
|
+
const categories = [];
|
|
1897
|
+
if (accountFiles.length > 0) {
|
|
1898
|
+
categories.push("accounts");
|
|
1899
|
+
let indexMap = renderersCore.createRenderMap();
|
|
1900
|
+
indexMap = renderersCore.addToRenderMap(
|
|
1901
|
+
indexMap,
|
|
1902
|
+
"accounts/accounts.dart",
|
|
1903
|
+
getIndexPageFragment(accountFiles)
|
|
1904
|
+
);
|
|
1905
|
+
maps.push(indexMap);
|
|
1906
|
+
}
|
|
1907
|
+
if (instructionFiles.length > 0) {
|
|
1908
|
+
categories.push("instructions");
|
|
1909
|
+
let indexMap = renderersCore.createRenderMap();
|
|
1910
|
+
indexMap = renderersCore.addToRenderMap(
|
|
1911
|
+
indexMap,
|
|
1912
|
+
"instructions/instructions.dart",
|
|
1913
|
+
getIndexPageFragment(instructionFiles)
|
|
1914
|
+
);
|
|
1915
|
+
maps.push(indexMap);
|
|
1916
|
+
}
|
|
1917
|
+
if (typeFiles.length > 0) {
|
|
1918
|
+
categories.push("types");
|
|
1919
|
+
let indexMap = renderersCore.createRenderMap();
|
|
1920
|
+
indexMap = renderersCore.addToRenderMap(
|
|
1921
|
+
indexMap,
|
|
1922
|
+
"types/types.dart",
|
|
1923
|
+
getIndexPageFragment(typeFiles)
|
|
1924
|
+
);
|
|
1925
|
+
maps.push(indexMap);
|
|
1926
|
+
}
|
|
1927
|
+
if (pdaFiles.length > 0) {
|
|
1928
|
+
categories.push("pdas");
|
|
1929
|
+
let indexMap = renderersCore.createRenderMap();
|
|
1930
|
+
indexMap = renderersCore.addToRenderMap(
|
|
1931
|
+
indexMap,
|
|
1932
|
+
"pdas/pdas.dart",
|
|
1933
|
+
getIndexPageFragment(pdaFiles)
|
|
1934
|
+
);
|
|
1935
|
+
maps.push(indexMap);
|
|
1936
|
+
}
|
|
1937
|
+
if (errorFiles.length > 0) {
|
|
1938
|
+
categories.push("errors");
|
|
1939
|
+
let indexMap = renderersCore.createRenderMap();
|
|
1940
|
+
indexMap = renderersCore.addToRenderMap(
|
|
1941
|
+
indexMap,
|
|
1942
|
+
"errors/errors.dart",
|
|
1943
|
+
getIndexPageFragment(errorFiles)
|
|
1944
|
+
);
|
|
1945
|
+
maps.push(indexMap);
|
|
1946
|
+
}
|
|
1947
|
+
if (programFiles.length > 0) {
|
|
1948
|
+
categories.push("programs");
|
|
1949
|
+
let indexMap = renderersCore.createRenderMap();
|
|
1950
|
+
indexMap = renderersCore.addToRenderMap(
|
|
1951
|
+
indexMap,
|
|
1952
|
+
"programs/programs.dart",
|
|
1953
|
+
getIndexPageFragment(programFiles)
|
|
1954
|
+
);
|
|
1955
|
+
maps.push(indexMap);
|
|
1956
|
+
}
|
|
1957
|
+
if (categories.length > 0) {
|
|
1958
|
+
let rootMap = renderersCore.createRenderMap();
|
|
1959
|
+
rootMap = renderersCore.addToRenderMap(
|
|
1960
|
+
rootMap,
|
|
1961
|
+
`${snakeCase(programName)}.dart`,
|
|
1962
|
+
getRootIndexPageFragment(categories)
|
|
1963
|
+
);
|
|
1964
|
+
maps.push(rootMap);
|
|
1965
|
+
}
|
|
1966
|
+
return renderersCore.mergeRenderMaps(maps);
|
|
1967
|
+
},
|
|
1968
|
+
visitAccount(node, { self }) {
|
|
1969
|
+
const fileName = `${snakeCase(node.name)}.dart`;
|
|
1970
|
+
const frag = getAccountPageFragment(node, scope);
|
|
1971
|
+
let map = renderersCore.createRenderMap();
|
|
1972
|
+
map = renderersCore.addToRenderMap(map, `accounts/${fileName}`, frag);
|
|
1973
|
+
return map;
|
|
1974
|
+
},
|
|
1975
|
+
visitDefinedType(node, { self }) {
|
|
1976
|
+
const fileName = `${snakeCase(node.name)}.dart`;
|
|
1977
|
+
const frag = getTypePageFragment(node, scope);
|
|
1978
|
+
let map = renderersCore.createRenderMap();
|
|
1979
|
+
map = renderersCore.addToRenderMap(map, `types/${fileName}`, frag);
|
|
1980
|
+
return map;
|
|
1981
|
+
},
|
|
1982
|
+
visitInstruction(node, { self }) {
|
|
1983
|
+
const fileName = `${snakeCase(node.name)}.dart`;
|
|
1984
|
+
const frag = getInstructionPageFragment(node, scope);
|
|
1985
|
+
let map = renderersCore.createRenderMap();
|
|
1986
|
+
map = renderersCore.addToRenderMap(map, `instructions/${fileName}`, frag);
|
|
1987
|
+
return map;
|
|
1988
|
+
},
|
|
1989
|
+
visitPda(node, { self }) {
|
|
1990
|
+
const fileName = `${snakeCase(node.name)}.dart`;
|
|
1991
|
+
const frag = getPdaPageFragment(node, scope);
|
|
1992
|
+
let map = renderersCore.createRenderMap();
|
|
1993
|
+
map = renderersCore.addToRenderMap(map, `pdas/${fileName}`, frag);
|
|
1994
|
+
return map;
|
|
1995
|
+
}
|
|
1996
|
+
}),
|
|
1997
|
+
(v) => visitorsCore.recordNodeStackVisitor(v, stack),
|
|
1998
|
+
(v) => visitorsCore.recordLinkablesOnFirstVisitVisitor(v, linkables)
|
|
1999
|
+
);
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
// src/visitors/renderVisitor.ts
|
|
2003
|
+
function renderVisitor(outputDir, options = {}) {
|
|
2004
|
+
const {
|
|
2005
|
+
deleteFolderBeforeRendering = true,
|
|
2006
|
+
formatCode = false,
|
|
2007
|
+
nameApi,
|
|
2008
|
+
dependencyMap
|
|
2009
|
+
} = options;
|
|
2010
|
+
return visitorsCore.rootNodeVisitor((root) => {
|
|
2011
|
+
if (deleteFolderBeforeRendering && fs.existsSync(outputDir)) {
|
|
2012
|
+
renderersCore.deleteDirectory(outputDir);
|
|
2013
|
+
}
|
|
2014
|
+
const renderMap = visitorsCore.visit(
|
|
2015
|
+
root,
|
|
2016
|
+
getRenderMapVisitor({ nameApi, dependencyMap })
|
|
2017
|
+
);
|
|
2018
|
+
const typePathMap = {};
|
|
2019
|
+
for (const renderPath of renderMap.keys()) {
|
|
2020
|
+
const match = renderPath.match(/^(?:.*\/)?types\/([a-z_]+)\.dart$/);
|
|
2021
|
+
if (match) {
|
|
2022
|
+
typePathMap[`definedType:${match[1]}`] = renderPath;
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
for (const [filePath, frag] of renderMap.entries()) {
|
|
2026
|
+
const fullPath = path.join(outputDir, filePath);
|
|
2027
|
+
const dir = path.dirname(fullPath);
|
|
2028
|
+
if (!fs.existsSync(dir)) {
|
|
2029
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
2030
|
+
}
|
|
2031
|
+
const fileDir = path.dirname(filePath);
|
|
2032
|
+
const internalMap = {};
|
|
2033
|
+
for (const [key, typePath] of Object.entries(typePathMap)) {
|
|
2034
|
+
if (typePath === filePath) continue;
|
|
2035
|
+
let rel = path.posix.relative(fileDir, typePath);
|
|
2036
|
+
if (!rel.startsWith(".")) {
|
|
2037
|
+
rel = `./${rel}`;
|
|
2038
|
+
}
|
|
2039
|
+
internalMap[key] = rel;
|
|
2040
|
+
}
|
|
2041
|
+
const content = resolveFragmentContent(frag, dependencyMap ?? {}, internalMap);
|
|
2042
|
+
fs.writeFileSync(fullPath, content, "utf-8");
|
|
2043
|
+
}
|
|
2044
|
+
if (formatCode) {
|
|
2045
|
+
formatDartDirectory(outputDir);
|
|
2046
|
+
}
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
function resolveFragmentContent(frag, dependencyMap, internalMap = {}) {
|
|
2050
|
+
const { content, imports } = frag;
|
|
2051
|
+
const importStr = imports.toString({
|
|
2052
|
+
...internalMap,
|
|
2053
|
+
...dependencyMap
|
|
2054
|
+
});
|
|
2055
|
+
if (!importStr) {
|
|
2056
|
+
return content + "\n";
|
|
2057
|
+
}
|
|
2058
|
+
const lines = content.split("\n");
|
|
2059
|
+
const headerLines = [];
|
|
2060
|
+
let restIndex = 0;
|
|
2061
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2062
|
+
if (lines[i].startsWith("//") || lines[i].trim() === "") {
|
|
2063
|
+
headerLines.push(lines[i]);
|
|
2064
|
+
restIndex = i + 1;
|
|
2065
|
+
} else {
|
|
2066
|
+
break;
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
const header = headerLines.join("\n");
|
|
2070
|
+
const rest = lines.slice(restIndex).join("\n");
|
|
2071
|
+
const cleanContent = cleanFragmentContent(rest);
|
|
2072
|
+
return `${header}
|
|
2073
|
+
|
|
2074
|
+
${importStr}
|
|
2075
|
+
|
|
2076
|
+
${cleanContent}
|
|
2077
|
+
`;
|
|
2078
|
+
}
|
|
2079
|
+
function cleanFragmentContent(content) {
|
|
2080
|
+
const lines = content.split("\n");
|
|
2081
|
+
const cleanLines = lines.filter((line) => {
|
|
2082
|
+
const trimmed = line.trim();
|
|
2083
|
+
if (/^[a-zA-Z][a-zA-Z0-9]*$/.test(trimmed)) {
|
|
2084
|
+
return false;
|
|
2085
|
+
}
|
|
2086
|
+
return true;
|
|
2087
|
+
});
|
|
2088
|
+
return cleanLines.join("\n");
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
// src/index.ts
|
|
2092
|
+
var src_default = renderVisitor;
|
|
2093
|
+
|
|
2094
|
+
exports.DART_EXTERNAL_PACKAGE_MAP = DART_EXTERNAL_PACKAGE_MAP;
|
|
2095
|
+
exports.DartImportMap = DartImportMap;
|
|
2096
|
+
exports.createDartNameApi = createDartNameApi;
|
|
2097
|
+
exports.default = src_default;
|
|
2098
|
+
exports.getRenderMapVisitor = getRenderMapVisitor;
|
|
2099
|
+
exports.getTypeManifestVisitor = getTypeManifestVisitor;
|
|
2100
|
+
exports.renderVisitor = renderVisitor;
|
|
2101
|
+
//# sourceMappingURL=index.browser.cjs.map
|
|
2102
|
+
//# sourceMappingURL=index.browser.cjs.map
|