@dedot/codegen 0.0.1-alpha.11
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/LICENSE +201 -0
- package/README.md +3 -0
- package/cjs/genSupportedChainTypes.js +79 -0
- package/cjs/generator/ApiGen.js +16 -0
- package/cjs/generator/ConstsGen.js +32 -0
- package/cjs/generator/ErrorsGen.js +41 -0
- package/cjs/generator/EventsGen.js +68 -0
- package/cjs/generator/IndexGen.js +18 -0
- package/cjs/generator/QueryGen.js +59 -0
- package/cjs/generator/RpcGen.js +175 -0
- package/cjs/generator/RuntimeApisGen.js +120 -0
- package/cjs/generator/TxGen.js +90 -0
- package/cjs/generator/TypeImports.js +56 -0
- package/cjs/generator/TypesGen.js +436 -0
- package/cjs/generator/dirname.js +5 -0
- package/cjs/generator/index.js +26 -0
- package/cjs/generator/utils.js +68 -0
- package/cjs/index.js +76 -0
- package/cjs/package.json +1 -0
- package/cjs/packageInfo.js +5 -0
- package/cjs/templates/consts.hbs +7 -0
- package/cjs/templates/errors.hbs +7 -0
- package/cjs/templates/events.hbs +7 -0
- package/cjs/templates/index.hbs +22 -0
- package/cjs/templates/query.hbs +7 -0
- package/cjs/templates/rpc.hbs +7 -0
- package/cjs/templates/runtime.hbs +8 -0
- package/cjs/templates/tx.hbs +9 -0
- package/cjs/templates/types.hbs +5 -0
- package/cjs/types.js +2 -0
- package/genSupportedChainTypes.d.ts +1 -0
- package/genSupportedChainTypes.js +74 -0
- package/generator/ApiGen.d.ts +138 -0
- package/generator/ApiGen.js +12 -0
- package/generator/ConstsGen.d.ts +4 -0
- package/generator/ConstsGen.js +28 -0
- package/generator/ErrorsGen.d.ts +5 -0
- package/generator/ErrorsGen.js +37 -0
- package/generator/EventsGen.d.ts +5 -0
- package/generator/EventsGen.js +64 -0
- package/generator/IndexGen.d.ts +6 -0
- package/generator/IndexGen.js +14 -0
- package/generator/QueryGen.d.ts +5 -0
- package/generator/QueryGen.js +55 -0
- package/generator/RpcGen.d.ts +10 -0
- package/generator/RpcGen.js +171 -0
- package/generator/RuntimeApisGen.d.ts +9 -0
- package/generator/RuntimeApisGen.js +116 -0
- package/generator/TxGen.d.ts +5 -0
- package/generator/TxGen.js +86 -0
- package/generator/TypeImports.d.ts +14 -0
- package/generator/TypeImports.js +52 -0
- package/generator/TypesGen.d.ts +30 -0
- package/generator/TypesGen.js +432 -0
- package/generator/dirname.d.ts +1 -0
- package/generator/dirname.js +6 -0
- package/generator/index.d.ts +10 -0
- package/generator/index.js +10 -0
- package/generator/utils.d.ts +10 -0
- package/generator/utils.js +35 -0
- package/index.d.ts +4 -0
- package/index.js +48 -0
- package/package.json +49 -0
- package/packageInfo.d.ts +4 -0
- package/packageInfo.js +2 -0
- package/templates/consts.hbs +7 -0
- package/templates/errors.hbs +7 -0
- package/templates/events.hbs +7 -0
- package/templates/index.hbs +22 -0
- package/templates/query.hbs +7 -0
- package/templates/rpc.hbs +7 -0
- package/templates/runtime.hbs +8 -0
- package/templates/tx.hbs +9 -0
- package/templates/types.hbs +5 -0
- package/types.d.ts +6 -0
- package/types.js +1 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TypesGen = exports.BASIC_KNOWN_TYPES = void 0;
|
|
4
|
+
const util_1 = require("@polkadot/util");
|
|
5
|
+
const codecs_1 = require("@dedot/codecs");
|
|
6
|
+
const utils_1 = require("@dedot/utils");
|
|
7
|
+
const utils_2 = require("./utils");
|
|
8
|
+
const types_1 = require("@dedot/types");
|
|
9
|
+
const TypeImports_1 = require("./TypeImports");
|
|
10
|
+
// Skip generate types for these
|
|
11
|
+
// as we do have native types for them
|
|
12
|
+
const SKIP_TYPES = [
|
|
13
|
+
'BoundedBTreeMap',
|
|
14
|
+
'BoundedBTreeSet',
|
|
15
|
+
'BoundedVec',
|
|
16
|
+
'Box',
|
|
17
|
+
'BTreeMap',
|
|
18
|
+
'BTreeSet',
|
|
19
|
+
'Cow',
|
|
20
|
+
'Option',
|
|
21
|
+
'Range',
|
|
22
|
+
'RangeInclusive',
|
|
23
|
+
'Result',
|
|
24
|
+
'WeakBoundedVec',
|
|
25
|
+
'WrapperKeepOpaque',
|
|
26
|
+
'WrapperOpaque',
|
|
27
|
+
];
|
|
28
|
+
// These are common & generic types, so we'll remove these from all paths at index 1
|
|
29
|
+
// This helps make the type name shorter
|
|
30
|
+
const PATH_RM_INDEX_1 = ['generic', 'misc', 'pallet', 'traits', 'types'];
|
|
31
|
+
exports.BASIC_KNOWN_TYPES = ['BitSequence', 'Bytes', 'BytesLike', 'FixedBytes', 'FixedArray', 'Result'];
|
|
32
|
+
const WRAPPER_TYPE_REGEX = /^(\w+)(<.*>)$/g;
|
|
33
|
+
class TypesGen {
|
|
34
|
+
metadata;
|
|
35
|
+
/**
|
|
36
|
+
* Types will be generated its definition out.
|
|
37
|
+
*/
|
|
38
|
+
includedTypes;
|
|
39
|
+
registry;
|
|
40
|
+
typeImports;
|
|
41
|
+
constructor(metadata) {
|
|
42
|
+
this.metadata = metadata;
|
|
43
|
+
this.registry = new codecs_1.CodecRegistry(this.metadata);
|
|
44
|
+
this.includedTypes = this.#includedTypes();
|
|
45
|
+
this.typeImports = new TypeImports_1.TypeImports();
|
|
46
|
+
}
|
|
47
|
+
generate() {
|
|
48
|
+
this.clearCache();
|
|
49
|
+
let defTypeOut = '';
|
|
50
|
+
Object.values(this.includedTypes)
|
|
51
|
+
.filter(({ skip, knownType }) => !(skip || knownType))
|
|
52
|
+
.forEach(({ name, nameOut, id, docs }) => {
|
|
53
|
+
defTypeOut += `${(0, utils_2.commentBlock)(docs)}export type ${nameOut} = ${this.generateType(id, 0, true)};\n\n`;
|
|
54
|
+
if (this.#shouldGenerateTypeIn(id)) {
|
|
55
|
+
defTypeOut += `export type ${name} = ${this.generateType(id)};\n\n`;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const importTypes = this.typeImports.toImports('./types');
|
|
59
|
+
const template = (0, utils_2.compileTemplate)('types.hbs');
|
|
60
|
+
return (0, utils_2.beautifySourceCode)(template({ importTypes, defTypeOut }));
|
|
61
|
+
}
|
|
62
|
+
typeCache = {};
|
|
63
|
+
clearCache() {
|
|
64
|
+
this.typeCache = {};
|
|
65
|
+
this.typeImports.clear();
|
|
66
|
+
}
|
|
67
|
+
generateType(typeId, nestedLevel = 0, typeOut = false) {
|
|
68
|
+
if (nestedLevel > 0) {
|
|
69
|
+
const includedDef = this.includedTypes[typeId];
|
|
70
|
+
// If current typeId has its definition generated,
|
|
71
|
+
// we can just use its name, no need to generate its type again
|
|
72
|
+
if (includedDef) {
|
|
73
|
+
const { name, nameOut } = includedDef;
|
|
74
|
+
if (typeOut) {
|
|
75
|
+
this.addTypeImport(nameOut);
|
|
76
|
+
return nameOut;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.addTypeImport(name);
|
|
80
|
+
return name;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const typeCacheKey = `${typeId}/${typeOut ? 'typeOut' : 'typeIn'}`;
|
|
85
|
+
if (this.typeCache[typeCacheKey]) {
|
|
86
|
+
return this.typeCache[typeCacheKey];
|
|
87
|
+
}
|
|
88
|
+
const type = this.#generateType(typeId, nestedLevel, typeOut);
|
|
89
|
+
this.typeCache[typeCacheKey] = type;
|
|
90
|
+
const baseType = this.#removeGenericPart(type);
|
|
91
|
+
if (exports.BASIC_KNOWN_TYPES.includes(baseType)) {
|
|
92
|
+
this.addTypeImport(baseType);
|
|
93
|
+
}
|
|
94
|
+
return type;
|
|
95
|
+
}
|
|
96
|
+
#generateType(typeId, nestedLevel = 0, typeOut = false) {
|
|
97
|
+
const def = this.metadata.types[typeId];
|
|
98
|
+
if (!def) {
|
|
99
|
+
throw new Error(`Type def not found ${JSON.stringify(def)}`);
|
|
100
|
+
}
|
|
101
|
+
const { type, path, docs } = def;
|
|
102
|
+
const { tag, value } = type;
|
|
103
|
+
switch (tag) {
|
|
104
|
+
case 'Primitive':
|
|
105
|
+
const $codec = this.registry.findCodec(value.kind);
|
|
106
|
+
if ($codec.nativeType) {
|
|
107
|
+
return $codec.nativeType;
|
|
108
|
+
}
|
|
109
|
+
else if (value.kind === 'char') {
|
|
110
|
+
return 'string';
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
throw new Error(`Invalid primitive type: ${value.kind}`);
|
|
114
|
+
}
|
|
115
|
+
case 'Struct': {
|
|
116
|
+
const { fields } = value;
|
|
117
|
+
if (fields.length === 0) {
|
|
118
|
+
return '{}';
|
|
119
|
+
}
|
|
120
|
+
else if (!fields[0].name) {
|
|
121
|
+
if (fields.length === 1) {
|
|
122
|
+
return this.generateType(fields[0].typeId, nestedLevel + 1, typeOut);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
return `[${fields.map((f) => this.generateType(f.typeId, nestedLevel + 1, typeOut)).join(', ')}]`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
return this.generateObjectType(fields, nestedLevel + 1, typeOut);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
case 'Enum': {
|
|
133
|
+
const { members } = value;
|
|
134
|
+
if (path.join('::') === 'Option') {
|
|
135
|
+
const some = members.find((one) => one.name === 'Some');
|
|
136
|
+
if (some) {
|
|
137
|
+
return `${this.generateType(some.fields[0].typeId, nestedLevel + 1, typeOut)} | undefined`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else if (path.join('::') === 'Result') {
|
|
141
|
+
const ok = members.find((one) => one.name === 'Ok');
|
|
142
|
+
const err = members.find((one) => one.name === 'Err');
|
|
143
|
+
if (ok && err) {
|
|
144
|
+
const OkType = this.generateType(ok.fields[0].typeId, nestedLevel + 1, typeOut);
|
|
145
|
+
const ErrType = this.generateType(err.fields[0].typeId, nestedLevel + 1, typeOut);
|
|
146
|
+
return `Result<${OkType}, ${ErrType}>`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (members.length === 0) {
|
|
150
|
+
return 'null';
|
|
151
|
+
}
|
|
152
|
+
else if (members.every((x) => x.fields.length === 0)) {
|
|
153
|
+
return members.map(({ name, docs }) => `${(0, utils_2.commentBlock)(docs)}'${(0, util_1.stringPascalCase)(name)}'`).join(' | ');
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const membersType = [];
|
|
157
|
+
for (const { fields, name, docs } of members) {
|
|
158
|
+
const keyName = (0, util_1.stringPascalCase)(name);
|
|
159
|
+
if (fields.length === 0) {
|
|
160
|
+
membersType.push([keyName, null, docs]);
|
|
161
|
+
}
|
|
162
|
+
else if (fields[0].name === undefined) {
|
|
163
|
+
const valueType = fields.length === 1
|
|
164
|
+
? this.generateType(fields[0].typeId, nestedLevel + 1, typeOut)
|
|
165
|
+
: `[${fields
|
|
166
|
+
.map(({ typeId, docs }) => `${(0, utils_2.commentBlock)(docs)}${this.generateType(typeId, nestedLevel + 1, typeOut)}`)
|
|
167
|
+
.join(', ')}]`;
|
|
168
|
+
membersType.push([keyName, valueType, docs]);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
membersType.push([keyName, this.generateObjectType(fields, nestedLevel + 1, typeOut), docs]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const { tagKey, valueKey } = this.registry.portableRegistry.getEnumOptions(typeId);
|
|
175
|
+
return membersType
|
|
176
|
+
.map(([keyName, valueType, docs]) => ({
|
|
177
|
+
tag: `${tagKey}: '${keyName}'`,
|
|
178
|
+
value: valueType ? `, ${valueKey}${this.#isOptionalType(valueType) ? '?' : ''}: ${valueType} ` : '',
|
|
179
|
+
docs,
|
|
180
|
+
}))
|
|
181
|
+
.map(({ tag, value, docs }) => `${(0, utils_2.commentBlock)(docs)}{ ${tag}${value} }`)
|
|
182
|
+
.join(' | ');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
case 'Tuple': {
|
|
186
|
+
const { fields } = value;
|
|
187
|
+
if (fields.length === 0) {
|
|
188
|
+
return '[]';
|
|
189
|
+
}
|
|
190
|
+
else if (fields.length === 1) {
|
|
191
|
+
return this.generateType(fields[0], nestedLevel + 1, typeOut);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
return `[${fields.map((x) => this.generateType(x, nestedLevel + 1, typeOut)).join(', ')}]`;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
case 'BitSequence':
|
|
198
|
+
return 'BitSequence';
|
|
199
|
+
case 'Compact':
|
|
200
|
+
return this.generateType(value.typeParam, nestedLevel + 1, typeOut);
|
|
201
|
+
case 'Sequence':
|
|
202
|
+
case 'SizedVec': {
|
|
203
|
+
const fixedSize = tag === 'SizedVec' ? `${value.len}` : null;
|
|
204
|
+
const $innerType = this.metadata.types[value.typeParam].type;
|
|
205
|
+
if ($innerType.tag === 'Primitive' && $innerType.value.kind === 'u8') {
|
|
206
|
+
return fixedSize ? `FixedBytes<${fixedSize}>` : typeOut ? 'Bytes' : 'BytesLike';
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const innerType = this.generateType(value.typeParam, nestedLevel + 1, typeOut);
|
|
210
|
+
return fixedSize ? `FixedArray<${innerType}, ${fixedSize}>` : `Array<${innerType}>`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
default:
|
|
214
|
+
throw new Error(`Invalid type! ${tag}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
generateObjectType(fields, nestedLevel = 0, typeOut = false) {
|
|
218
|
+
const props = fields.map(({ typeId, name, docs }) => {
|
|
219
|
+
const type = this.generateType(typeId, nestedLevel + 1, typeOut);
|
|
220
|
+
return {
|
|
221
|
+
name: (0, utils_1.normalizeName)(name),
|
|
222
|
+
type,
|
|
223
|
+
optional: this.#isOptionalType(type),
|
|
224
|
+
docs,
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
return `{${props
|
|
228
|
+
.map(({ name, type, optional, docs }) => `${(0, utils_2.commentBlock)(docs)}${name}${optional ? '?' : ''}: ${type}`)
|
|
229
|
+
.join(',\n')}}`;
|
|
230
|
+
}
|
|
231
|
+
#isOptionalType(type) {
|
|
232
|
+
return type.endsWith('| undefined');
|
|
233
|
+
}
|
|
234
|
+
#includedTypes() {
|
|
235
|
+
const { types } = this.metadata;
|
|
236
|
+
const pathsCount = new Map();
|
|
237
|
+
const typesWithPath = types.filter((one) => one.path.length > 0);
|
|
238
|
+
const skipIds = [];
|
|
239
|
+
const typeSuffixes = new Map();
|
|
240
|
+
typesWithPath.forEach(({ path, id }) => {
|
|
241
|
+
const joinedPath = path.join('::');
|
|
242
|
+
if (pathsCount.has(joinedPath)) {
|
|
243
|
+
// We compare 2 types with the same path here,
|
|
244
|
+
// if they are the same type -> skip the current one, keep the first occurrence
|
|
245
|
+
// if they are not the same type but has the same path -> we'll try to calculate & add a suffix for the current type name
|
|
246
|
+
const firstOccurrenceTypeId = pathsCount.get(joinedPath)[0];
|
|
247
|
+
const sameType = this.typeEql(firstOccurrenceTypeId, id);
|
|
248
|
+
if (sameType) {
|
|
249
|
+
skipIds.push(id);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
pathsCount.get(joinedPath).push(id);
|
|
253
|
+
typeSuffixes.set(id, this.#extractDupTypeSuffix(id, firstOccurrenceTypeId, pathsCount.get(joinedPath).length));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
pathsCount.set(joinedPath, [id]);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
return typesWithPath.reduce((o, type) => {
|
|
261
|
+
const { path, id } = type;
|
|
262
|
+
const joinedPath = path.join('::');
|
|
263
|
+
if (SKIP_TYPES.includes(joinedPath) || SKIP_TYPES.includes(path.at(-1))) {
|
|
264
|
+
return o;
|
|
265
|
+
}
|
|
266
|
+
const suffix = typeSuffixes.get(id) || '';
|
|
267
|
+
let knownType = false;
|
|
268
|
+
let name, nameOut;
|
|
269
|
+
if (this.registry.isKnownType(joinedPath)) {
|
|
270
|
+
const codecType = this.registry.findCodecType(path.at(-1));
|
|
271
|
+
name = codecType.typeIn;
|
|
272
|
+
nameOut = codecType.typeOut;
|
|
273
|
+
knownType = true;
|
|
274
|
+
}
|
|
275
|
+
else if (PATH_RM_INDEX_1.includes(path[1])) {
|
|
276
|
+
const newPath = path.slice();
|
|
277
|
+
newPath.splice(1, 1);
|
|
278
|
+
name = this.#cleanPath(newPath);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
name = this.#cleanPath(path);
|
|
282
|
+
}
|
|
283
|
+
if (this.#shouldGenerateTypeIn(id)) {
|
|
284
|
+
nameOut = name;
|
|
285
|
+
name = name.endsWith('Like') ? name : `${name}Like`;
|
|
286
|
+
}
|
|
287
|
+
o[id] = {
|
|
288
|
+
name: `${name}${suffix}`,
|
|
289
|
+
nameOut: nameOut ? `${nameOut}${suffix}` : `${name}${suffix}`,
|
|
290
|
+
knownType,
|
|
291
|
+
skip: skipIds.includes(id),
|
|
292
|
+
...type,
|
|
293
|
+
};
|
|
294
|
+
return o;
|
|
295
|
+
}, {});
|
|
296
|
+
}
|
|
297
|
+
#removeGenericPart(typeName) {
|
|
298
|
+
if (typeName.match(WRAPPER_TYPE_REGEX)) {
|
|
299
|
+
return typeName.replace(WRAPPER_TYPE_REGEX, (_, $1) => $1);
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
return typeName;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* @description Remove duplicated part of the path
|
|
307
|
+
*
|
|
308
|
+
* Example:
|
|
309
|
+
* ["pallet_staking", "pallet", "pallet", "Event"]
|
|
310
|
+
* => ["pallet_staking", "pallet", "Event"]
|
|
311
|
+
*
|
|
312
|
+
* @param path
|
|
313
|
+
* @private
|
|
314
|
+
*/
|
|
315
|
+
#cleanPath(path) {
|
|
316
|
+
return path
|
|
317
|
+
.map((one) => (0, util_1.stringPascalCase)(one))
|
|
318
|
+
.filter((one, idx, currentPath) => idx === 0 || one !== currentPath[idx - 1])
|
|
319
|
+
.join('');
|
|
320
|
+
}
|
|
321
|
+
#shouldGenerateTypeIn(id) {
|
|
322
|
+
const { callTypeId } = this.metadata.extrinsic;
|
|
323
|
+
const palletCallTypeIds = this.registry.portableRegistry.getPalletCallTypeIds();
|
|
324
|
+
return callTypeId === id || palletCallTypeIds.includes(id);
|
|
325
|
+
}
|
|
326
|
+
eqlCache = new Map();
|
|
327
|
+
typeEql(idA, idB, level = 0) {
|
|
328
|
+
const cacheKey = `${idA}==${idB}`;
|
|
329
|
+
if (!this.eqlCache.has(cacheKey)) {
|
|
330
|
+
this.eqlCache.set(cacheKey, true);
|
|
331
|
+
this.eqlCache.set(cacheKey, this.#typeEql(idA, idB, level));
|
|
332
|
+
}
|
|
333
|
+
return this.eqlCache.get(cacheKey);
|
|
334
|
+
}
|
|
335
|
+
#typeEql(idA, idB, lvl = 0) {
|
|
336
|
+
if (idA === idB)
|
|
337
|
+
return true;
|
|
338
|
+
const { types } = this.metadata;
|
|
339
|
+
const typeA = types[idA];
|
|
340
|
+
const typeB = types[idB];
|
|
341
|
+
if (typeA.path.join('::') !== typeB.path.join('::'))
|
|
342
|
+
return false;
|
|
343
|
+
const { type: defA, params: paramsA } = typeA;
|
|
344
|
+
const { type: defB, params: paramsB } = typeB;
|
|
345
|
+
if (!this.#eqlArray(paramsA, paramsB, (valA, valB) => this.#eqlTypeParam(valA, valB))) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
if (defA.tag !== defB.tag)
|
|
349
|
+
return false;
|
|
350
|
+
if (defA.tag === 'BitSequence')
|
|
351
|
+
return true;
|
|
352
|
+
if (defA.tag === 'Primitive' && defB.tag === 'Primitive') {
|
|
353
|
+
return defA.value.kind === defB.value.kind;
|
|
354
|
+
}
|
|
355
|
+
if ((defA.tag === 'Compact' && defB.tag === 'Compact') || (defA.tag === 'Sequence' && defB.tag === 'Sequence')) {
|
|
356
|
+
return this.typeEql(defA.value.typeParam, defB.value.typeParam, lvl + 1);
|
|
357
|
+
}
|
|
358
|
+
if (defA.tag === 'SizedVec' && defB.tag === 'SizedVec') {
|
|
359
|
+
return defA.value.len === defB.value.len && this.typeEql(defA.value.typeParam, defB.value.typeParam, lvl + 1);
|
|
360
|
+
}
|
|
361
|
+
if (defA.tag === 'Tuple' && defB.tag === 'Tuple') {
|
|
362
|
+
return this.#eqlArray(defA.value.fields, defB.value.fields, (val1, val2) => this.typeEql(val1, val2, lvl + 1));
|
|
363
|
+
}
|
|
364
|
+
if (defA.tag === 'Struct' && defB.tag === 'Struct') {
|
|
365
|
+
return this.#eqlFields(defA.value.fields, defB.value.fields, lvl);
|
|
366
|
+
}
|
|
367
|
+
if (defA.tag === 'Enum' && defB.tag === 'Enum') {
|
|
368
|
+
return this.#eqlArray(defA.value.members, defB.value.members, (val1, val2) => val1.name === val2.name && val1.index === val2.index && this.#eqlFields(val1.fields, val2.fields, lvl));
|
|
369
|
+
}
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
#eqlArray(arr1, arr2, eqlVal) {
|
|
373
|
+
return arr1.length === arr2.length && arr1.every((e1, idx) => eqlVal(e1, arr2[idx]));
|
|
374
|
+
}
|
|
375
|
+
#eqlFields(arr1, arr2, lvl) {
|
|
376
|
+
return this.#eqlArray(arr1, arr2, (val1, val2) => val1.name === val2.name && val1.typeName === val2.typeName && this.#typeEql(val1.typeId, val2.typeId));
|
|
377
|
+
}
|
|
378
|
+
#eqlTypeParam(param1, param2) {
|
|
379
|
+
return (param1.name === param2.name &&
|
|
380
|
+
(param1.typeId === undefined) === (param2.typeId === undefined) &&
|
|
381
|
+
(param1.typeId === undefined || this.#typeEql(param1.typeId, param2.typeId)));
|
|
382
|
+
}
|
|
383
|
+
#extractDupTypeSuffix(dupTypeId, originalTypeId, dupCount) {
|
|
384
|
+
const { types } = this.metadata;
|
|
385
|
+
const originalTypeParams = types[originalTypeId].params;
|
|
386
|
+
const dupTypeParams = types[dupTypeId].params;
|
|
387
|
+
const diffParam = dupTypeParams.find((one, idx) => !this.#eqlTypeParam(one, originalTypeParams[idx]));
|
|
388
|
+
// TODO make sure these suffix is unique if a type is duplicated more than 2 times
|
|
389
|
+
if (diffParam?.typeId) {
|
|
390
|
+
const diffType = types[diffParam.typeId];
|
|
391
|
+
if (diffType.path.length > 0) {
|
|
392
|
+
return (0, util_1.stringPascalCase)(diffType.path.at(-1));
|
|
393
|
+
}
|
|
394
|
+
else if (diffType.type.tag === 'Primitive') {
|
|
395
|
+
return (0, util_1.stringPascalCase)(diffType.type.value.kind);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// Last resort!
|
|
399
|
+
return dupCount.toString().padStart(3, '0');
|
|
400
|
+
}
|
|
401
|
+
addTypeImport(typeName) {
|
|
402
|
+
if (Array.isArray(typeName)) {
|
|
403
|
+
typeName.forEach((one) => this.addTypeImport(one));
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if ((0, utils_1.isNativeType)(typeName)) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
for (let type of Object.values(this.includedTypes)) {
|
|
410
|
+
if (type.skip) {
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
const { name, nameOut, knownType } = type;
|
|
414
|
+
if (name === typeName || nameOut === typeName) {
|
|
415
|
+
if (knownType) {
|
|
416
|
+
this.typeImports.addCodecType(typeName);
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
this.typeImports.addPortableType(typeName);
|
|
420
|
+
}
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (exports.BASIC_KNOWN_TYPES.includes(typeName)) {
|
|
425
|
+
this.typeImports.addCodecType(typeName);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
if (types_1.registry.has(typeName)) {
|
|
429
|
+
this.typeImports.addKnownType(typeName);
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
this.typeImports.addOutType(typeName);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
exports.TypesGen = TypesGen;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./TypesGen"), exports);
|
|
18
|
+
__exportStar(require("./ApiGen"), exports);
|
|
19
|
+
__exportStar(require("./ConstsGen"), exports);
|
|
20
|
+
__exportStar(require("./QueryGen"), exports);
|
|
21
|
+
__exportStar(require("./RpcGen"), exports);
|
|
22
|
+
__exportStar(require("./IndexGen"), exports);
|
|
23
|
+
__exportStar(require("./ErrorsGen"), exports);
|
|
24
|
+
__exportStar(require("./EventsGen"), exports);
|
|
25
|
+
__exportStar(require("./TxGen"), exports);
|
|
26
|
+
__exportStar(require("./RuntimeApisGen"), exports);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.isReservedWord = exports.compileTemplate = exports.beautifySourceCode = exports.commentBlock = exports.TUPLE_TYPE_REGEX = exports.WRAPPER_TYPE_REGEX = void 0;
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
const handlebars_1 = __importDefault(require("handlebars"));
|
|
32
|
+
const path = __importStar(require("path"));
|
|
33
|
+
const prettier = __importStar(require("prettier"));
|
|
34
|
+
const dirname_1 = require("./dirname");
|
|
35
|
+
exports.WRAPPER_TYPE_REGEX = /^(\w+)<(.*)>$/;
|
|
36
|
+
exports.TUPLE_TYPE_REGEX = /^\[(.*)]$/;
|
|
37
|
+
const commentBlock = (...docs) => {
|
|
38
|
+
const flatLines = docs.flat();
|
|
39
|
+
if (flatLines.length === 0) {
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return `
|
|
44
|
+
/**
|
|
45
|
+
${flatLines.map((line) => `* ${line.replaceAll(/\s+/g, ' ').trim()}`).join('\n')}
|
|
46
|
+
**/
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
exports.commentBlock = commentBlock;
|
|
51
|
+
const beautifySourceCode = async (source) => {
|
|
52
|
+
const prettierOptions = await prettier.resolveConfig(path.resolve((0, dirname_1.currentDirname)(), '../../../../.prettierrc.js'));
|
|
53
|
+
return prettier.format(source, { parser: 'babel-ts', ...prettierOptions });
|
|
54
|
+
};
|
|
55
|
+
exports.beautifySourceCode = beautifySourceCode;
|
|
56
|
+
const compileTemplate = (templateFileName) => {
|
|
57
|
+
const templateFilePath = path.resolve((0, dirname_1.currentDirname)(), `../templates/${templateFileName}`);
|
|
58
|
+
return handlebars_1.default.compile(fs.readFileSync(templateFilePath, 'utf8'));
|
|
59
|
+
};
|
|
60
|
+
exports.compileTemplate = compileTemplate;
|
|
61
|
+
// TODO add more reserved words
|
|
62
|
+
const TS_RESERVED_WORDS = ['new', 'class'];
|
|
63
|
+
/**
|
|
64
|
+
* Check if a word is TypeScript/JavaScript reserved
|
|
65
|
+
* @param word
|
|
66
|
+
*/
|
|
67
|
+
const isReservedWord = (word) => TS_RESERVED_WORDS.includes(word);
|
|
68
|
+
exports.isReservedWord = isReservedWord;
|
package/cjs/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.generateTypes = exports.generateTypesFromChain = void 0;
|
|
27
|
+
const dedot_1 = require("dedot");
|
|
28
|
+
const fs = __importStar(require("fs"));
|
|
29
|
+
const path = __importStar(require("path"));
|
|
30
|
+
const generator_1 = require("./generator");
|
|
31
|
+
const util_1 = require("@polkadot/util");
|
|
32
|
+
async function generateTypesFromChain(network, endpoint, outDir) {
|
|
33
|
+
const api = await dedot_1.Dedot.create(endpoint);
|
|
34
|
+
const { methods } = await api.rpc.rpc.methods();
|
|
35
|
+
const apis = api.runtimeVersion?.apis || [];
|
|
36
|
+
if (!network.chain) {
|
|
37
|
+
network.chain = (0, util_1.stringCamelCase)(api.runtimeVersion?.specName || api.runtimeChain || 'local');
|
|
38
|
+
}
|
|
39
|
+
await generateTypes(network, api.metadataLatest, methods, apis, outDir);
|
|
40
|
+
await api.disconnect();
|
|
41
|
+
}
|
|
42
|
+
exports.generateTypesFromChain = generateTypesFromChain;
|
|
43
|
+
async function generateTypes(network, metadata, rpcMethods, runtimeApis, outDir = '.') {
|
|
44
|
+
const dirPath = path.resolve(outDir, network.chain);
|
|
45
|
+
const defTypesFileName = path.join(dirPath, `types.ts`);
|
|
46
|
+
const constsTypesFileName = path.join(dirPath, `consts.ts`);
|
|
47
|
+
const queryTypesFileName = path.join(dirPath, `query.ts`);
|
|
48
|
+
const rpcCallsFileName = path.join(dirPath, `rpc.ts`);
|
|
49
|
+
const indexFileName = path.join(dirPath, `index.ts`);
|
|
50
|
+
const errorsFileName = path.join(dirPath, `errors.ts`);
|
|
51
|
+
const eventsFileName = path.join(dirPath, `events.ts`);
|
|
52
|
+
const runtimeApisFileName = path.join(dirPath, `runtime.ts`);
|
|
53
|
+
const txFileName = path.join(dirPath, `tx.ts`);
|
|
54
|
+
if (!fs.existsSync(dirPath)) {
|
|
55
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
const typesGen = new generator_1.TypesGen(metadata);
|
|
58
|
+
const constsGen = new generator_1.ConstsGen(typesGen);
|
|
59
|
+
const queryGen = new generator_1.QueryGen(typesGen);
|
|
60
|
+
const rpcGen = new generator_1.RpcGen(typesGen, rpcMethods);
|
|
61
|
+
const indexGen = new generator_1.IndexGen(network);
|
|
62
|
+
const errorsGen = new generator_1.ErrorsGen(typesGen);
|
|
63
|
+
const eventsGen = new generator_1.EventsGen(typesGen);
|
|
64
|
+
const runtimeApisGen = new generator_1.RuntimeApisGen(typesGen, runtimeApis);
|
|
65
|
+
const txGen = new generator_1.TxGen(typesGen);
|
|
66
|
+
fs.writeFileSync(defTypesFileName, await typesGen.generate());
|
|
67
|
+
fs.writeFileSync(errorsFileName, await errorsGen.generate());
|
|
68
|
+
fs.writeFileSync(eventsFileName, await eventsGen.generate());
|
|
69
|
+
fs.writeFileSync(rpcCallsFileName, await rpcGen.generate());
|
|
70
|
+
fs.writeFileSync(queryTypesFileName, await queryGen.generate());
|
|
71
|
+
fs.writeFileSync(constsTypesFileName, await constsGen.generate());
|
|
72
|
+
fs.writeFileSync(txFileName, await txGen.generate());
|
|
73
|
+
fs.writeFileSync(indexFileName, await indexGen.generate());
|
|
74
|
+
fs.writeFileSync(runtimeApisFileName, await runtimeApisGen.generate());
|
|
75
|
+
}
|
|
76
|
+
exports.generateTypes = generateTypes;
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "commonjs"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Generated by @dedot/codegen
|
|
2
|
+
|
|
3
|
+
import { GenericSubstrateApi } from '@dedot/types';
|
|
4
|
+
import { ChainConsts } from './consts';
|
|
5
|
+
import { ChainStorage } from './query';
|
|
6
|
+
import { RpcCalls } from './rpc';
|
|
7
|
+
import { ChainErrors } from './errors';
|
|
8
|
+
import { ChainEvents } from './events';
|
|
9
|
+
import { RuntimeApis } from './runtime';
|
|
10
|
+
import { ChainTx } from './tx';
|
|
11
|
+
|
|
12
|
+
export * from './types';
|
|
13
|
+
|
|
14
|
+
export interface {{{interfaceName}}}Api extends GenericSubstrateApi {
|
|
15
|
+
rpc: RpcCalls;
|
|
16
|
+
consts: ChainConsts;
|
|
17
|
+
query: ChainStorage;
|
|
18
|
+
errors: ChainErrors;
|
|
19
|
+
events: ChainEvents;
|
|
20
|
+
call: RuntimeApis;
|
|
21
|
+
tx: ChainTx;
|
|
22
|
+
}
|