@pezkuwi/typegen 16.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/build/augment.d.ts +2 -0
- package/build/bundle.d.ts +2 -0
- package/build/extractChain.d.ts +1 -0
- package/build/fromChain.d.ts +1 -0
- package/build/fromDefs.d.ts +1 -0
- package/build/generate/consts.d.ts +5 -0
- package/build/generate/errors.d.ts +4 -0
- package/build/generate/events.d.ts +5 -0
- package/build/generate/index.d.ts +10 -0
- package/build/generate/interfaceRegistry.d.ts +4 -0
- package/build/generate/lookup.d.ts +4 -0
- package/build/generate/query.d.ts +5 -0
- package/build/generate/rpc.d.ts +6 -0
- package/build/generate/runtime.d.ts +7 -0
- package/build/generate/tsDef.d.ts +16 -0
- package/build/generate/tx.d.ts +5 -0
- package/build/generate/types.d.ts +12 -0
- package/build/index.d.ts +2 -0
- package/build/interfacesTs.d.ts +1 -0
- package/build/metadataMd.d.ts +1 -0
- package/build/packageDetect.d.ts +1 -0
- package/build/packageInfo.d.ts +6 -0
- package/build/scripts/polkadot-types-chain-info.mjs +7 -0
- package/build/scripts/polkadot-types-from-chain.mjs +7 -0
- package/build/scripts/polkadot-types-from-defs.mjs +7 -0
- package/build/scripts/polkadot-types-internal-interfaces.mjs +7 -0
- package/build/scripts/polkadot-types-internal-metadata.mjs +7 -0
- package/build/util/assert.d.ts +2 -0
- package/build/util/derived.d.ts +4 -0
- package/build/util/docs.d.ts +1 -0
- package/build/util/file.d.ts +2 -0
- package/build/util/formatting.d.ts +11 -0
- package/build/util/imports.d.ts +23 -0
- package/build/util/index.d.ts +15 -0
- package/build/util/initMeta.d.ts +12 -0
- package/build/util/register.d.ts +4 -0
- package/build/util/wsMeta.d.ts +4 -0
- package/package.json +52 -0
- package/scripts/polkadot-types-chain-info.mjs +7 -0
- package/scripts/polkadot-types-from-chain.mjs +7 -0
- package/scripts/polkadot-types-from-defs.mjs +7 -0
- package/scripts/polkadot-types-internal-interfaces.mjs +7 -0
- package/scripts/polkadot-types-internal-metadata.mjs +7 -0
- package/src/augment.ts +5 -0
- package/src/bundle.ts +5 -0
- package/src/extractChain.ts +54 -0
- package/src/fromChain.ts +123 -0
- package/src/fromDefs.ts +106 -0
- package/src/generate/consts.ts +112 -0
- package/src/generate/errors.ts +75 -0
- package/src/generate/events.ts +165 -0
- package/src/generate/index.ts +13 -0
- package/src/generate/interfaceRegistry.ts +85 -0
- package/src/generate/lookup.ts +294 -0
- package/src/generate/query.ts +169 -0
- package/src/generate/rpc.ts +158 -0
- package/src/generate/runtime.ts +284 -0
- package/src/generate/tsDef.ts +321 -0
- package/src/generate/tx.ts +152 -0
- package/src/generate/types.ts +26 -0
- package/src/index.ts +6 -0
- package/src/interfacesTs.ts +35 -0
- package/src/metadataMd.ts +844 -0
- package/src/packageDetect.ts +14 -0
- package/src/packageInfo.ts +6 -0
- package/src/templates/calls.hbs +30 -0
- package/src/templates/consts.hbs +28 -0
- package/src/templates/docs.hbs +7 -0
- package/src/templates/errors.hbs +28 -0
- package/src/templates/events.hbs +28 -0
- package/src/templates/header.hbs +2 -0
- package/src/templates/interfaceRegistry.hbs +15 -0
- package/src/templates/lookup/defs-named.hbs +12 -0
- package/src/templates/lookup/defs.hbs +15 -0
- package/src/templates/lookup/index.hbs +3 -0
- package/src/templates/lookup/types.hbs +14 -0
- package/src/templates/query.hbs +29 -0
- package/src/templates/rpc.hbs +22 -0
- package/src/templates/tsDef/index.hbs +3 -0
- package/src/templates/tsDef/moduleTypes.hbs +10 -0
- package/src/templates/tsDef/types.hbs +7 -0
- package/src/templates/tx.hbs +30 -0
- package/src/util/assert.ts +18 -0
- package/src/util/derived.spec.ts +58 -0
- package/src/util/derived.ts +133 -0
- package/src/util/docs.ts +13 -0
- package/src/util/file.ts +42 -0
- package/src/util/formatting.spec.ts +30 -0
- package/src/util/formatting.ts +295 -0
- package/src/util/imports.ts +164 -0
- package/src/util/index.ts +18 -0
- package/src/util/initMeta.ts +37 -0
- package/src/util/register.ts +12 -0
- package/src/util/wsMeta.ts +70 -0
- package/tsconfig.build.json +28 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.scripts.json +19 -0
- package/tsconfig.spec.json +17 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/typegen authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { RuntimeApiMethodMetadataV16, SiLookupTypeId } from '@pezkuwi/types/interfaces';
|
|
5
|
+
import type { Metadata } from '@pezkuwi/types/metadata/Metadata';
|
|
6
|
+
import type { DefinitionCall, DefinitionCallNamed, Definitions, DefinitionsCall, Registry } from '@pezkuwi/types/types';
|
|
7
|
+
import type { Vec } from '@pezkuwi/types-codec';
|
|
8
|
+
import type { HexString } from '@pezkuwi/util/types';
|
|
9
|
+
|
|
10
|
+
import Handlebars from 'handlebars';
|
|
11
|
+
|
|
12
|
+
import * as defaultDefs from '@pezkuwi/types/interfaces/definitions';
|
|
13
|
+
import lookupDefinitions from '@pezkuwi/types-augment/lookup/definitions';
|
|
14
|
+
import { objectSpread, stringCamelCase } from '@pezkuwi/util';
|
|
15
|
+
import { blake2AsHex } from '@pezkuwi/util-crypto';
|
|
16
|
+
|
|
17
|
+
import { createImports, formatType, getSimilarTypes, initMeta, readTemplate, setImports, writeFile } from '../util/index.js';
|
|
18
|
+
import { type ExtraTypes, getDeprecationNotice } from './types.js';
|
|
19
|
+
|
|
20
|
+
type Apis = [HexString, number][];
|
|
21
|
+
|
|
22
|
+
const generateCallsTypesTemplate = Handlebars.compile(readTemplate('calls'));
|
|
23
|
+
|
|
24
|
+
// This works similar to the PATHS_ALIAS set from the PortableRegistry
|
|
25
|
+
const aliases: Record<string, string> = {
|
|
26
|
+
AssetHubKusamaRuntimeRuntimeCall: 'RuntimeCall',
|
|
27
|
+
AssetHubPolkadotRuntimeRuntimeCall: 'RuntimeCall',
|
|
28
|
+
KitchensinkRuntimeRuntimeCall: 'RuntimeCall',
|
|
29
|
+
OpaqueValue: 'Bytes',
|
|
30
|
+
PolkadotParachainPrimitivesPrimitivesId: 'ParaId',
|
|
31
|
+
PolkadotParachainPrimitivesPrimitivesValidationCodeHash: 'ValidationCodeHash',
|
|
32
|
+
PolkadotPrimitivesV7SlashingOpaqueKeyOwnershipProof: 'OpaqueKeyOwnershipProof',
|
|
33
|
+
PolkadotPrimitivesV8SlashingOpaqueKeyOwnershipProof: 'OpaqueKeyOwnershipProof',
|
|
34
|
+
PolkadotRuntimeRuntimeCall: 'RuntimeCall',
|
|
35
|
+
PrimitiveTypesH160: 'H160',
|
|
36
|
+
PrimitiveTypesH256: 'H256',
|
|
37
|
+
PrimitiveTypesU256: 'U256',
|
|
38
|
+
SpConsensusBabeOpaqueKeyOwnershipProof: 'OpaqueKeyOwnershipProof',
|
|
39
|
+
SpConsensusSlotsSlot: 'Slot',
|
|
40
|
+
SpConsensusSlotsSlotDuration: 'SlotDuration',
|
|
41
|
+
SpCoreCryptoAccountId32: 'AccountId32',
|
|
42
|
+
SpCoreOpaqueMetadata: 'OpaqueMetadata',
|
|
43
|
+
SpRuntimeOpaqueValue: 'Bytes',
|
|
44
|
+
SpRuntimeUncheckedExtrinsic: 'Extrinsic',
|
|
45
|
+
StagingKusamaRuntimeRuntimeCall: 'RuntimeCall'
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const getTypesViaAlias = (registry: Registry, id: SiLookupTypeId) => {
|
|
49
|
+
const typeName = registry.lookup.getName(id) || registry.lookup.getTypeDef(id).type;
|
|
50
|
+
|
|
51
|
+
if (aliases[typeName]) {
|
|
52
|
+
return aliases[typeName];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return typeName;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** @internal */
|
|
59
|
+
function getMethods (registry: Registry, methods: Vec<RuntimeApiMethodMetadataV16>) {
|
|
60
|
+
const result: Record<string, DefinitionCall> = {};
|
|
61
|
+
|
|
62
|
+
methods.forEach((m) => {
|
|
63
|
+
const { deprecationInfo, docs, inputs, name, output } = m;
|
|
64
|
+
let description = docs.map((d) => d.toString()).join();
|
|
65
|
+
|
|
66
|
+
if (!deprecationInfo.isNotDeprecated) {
|
|
67
|
+
const deprecationNotice = getDeprecationNotice(deprecationInfo, stringCamelCase(name));
|
|
68
|
+
const notice = description.length ? `\n * ${deprecationNotice}` : ` * ${deprecationNotice}`;
|
|
69
|
+
|
|
70
|
+
description += notice;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
result[name.toString()] = {
|
|
74
|
+
description,
|
|
75
|
+
params: inputs.map(({ name, type }) => {
|
|
76
|
+
return { name: name.toString(), type: getTypesViaAlias(registry, type) };
|
|
77
|
+
}),
|
|
78
|
+
type: getTypesViaAlias(registry, output)
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** @internal */
|
|
86
|
+
function getRuntimeDefViaMetadata (registry: Registry) {
|
|
87
|
+
const result: DefinitionsCall = {};
|
|
88
|
+
const { apis } = registry.metadata;
|
|
89
|
+
|
|
90
|
+
for (let i = 0, count = apis.length; i < count; i++) {
|
|
91
|
+
const { methods, name } = apis[i];
|
|
92
|
+
|
|
93
|
+
result[name.toString()] = [{
|
|
94
|
+
methods: getMethods(registry, methods),
|
|
95
|
+
// We set the version to 0 here since it will not be relevant when we are grabbing the runtime apis
|
|
96
|
+
// from the Metadata.
|
|
97
|
+
version: 0
|
|
98
|
+
}];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return Object.entries(result);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** @internal */
|
|
105
|
+
function getDefs (apis: Apis | null, defs: Record<string, Definitions>, registry: Registry): Record<string, Record<string, DefinitionCallNamed>> {
|
|
106
|
+
const named: Record<string, Record<string, DefinitionCallNamed>> = {};
|
|
107
|
+
const all = Object.values(defs);
|
|
108
|
+
const isApiInMetadata = registry.metadata.apis.length > 0;
|
|
109
|
+
|
|
110
|
+
if (isApiInMetadata) {
|
|
111
|
+
const sections = getRuntimeDefViaMetadata(registry);
|
|
112
|
+
|
|
113
|
+
for (let j = 0, jcount = sections.length; j < jcount; j++) {
|
|
114
|
+
const [_section, secs] = sections[j];
|
|
115
|
+
const sec = secs[0];
|
|
116
|
+
const sectionHash = blake2AsHex(_section, 64);
|
|
117
|
+
|
|
118
|
+
const section = stringCamelCase(_section);
|
|
119
|
+
const methods = Object.entries(sec.methods);
|
|
120
|
+
|
|
121
|
+
if (!named[section]) {
|
|
122
|
+
named[section] = {};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
for (let m = 0, mcount = methods.length; m < mcount; m++) {
|
|
126
|
+
const [_method, def] = methods[m];
|
|
127
|
+
const method = stringCamelCase(_method);
|
|
128
|
+
|
|
129
|
+
named[section][method] = objectSpread({ method, name: `${_section}_${_method}`, section, sectionHash }, def);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
for (let j = 0, jcount = all.length; j < jcount; j++) {
|
|
134
|
+
const set = all[j].runtime;
|
|
135
|
+
|
|
136
|
+
if (set) {
|
|
137
|
+
const sections = Object.entries(set);
|
|
138
|
+
|
|
139
|
+
for (let i = 0, scount = sections.length; i < scount; i++) {
|
|
140
|
+
const [_section, sec] = sections[i];
|
|
141
|
+
const sectionHash = blake2AsHex(_section, 64);
|
|
142
|
+
const api = apis?.find(([h]) => h === sectionHash);
|
|
143
|
+
|
|
144
|
+
if (api) {
|
|
145
|
+
const ver = sec.find(({ version }) => version === api[1]);
|
|
146
|
+
|
|
147
|
+
if (ver) {
|
|
148
|
+
const methods = Object.entries(ver.methods);
|
|
149
|
+
const mcount = methods.length;
|
|
150
|
+
|
|
151
|
+
if (mcount) {
|
|
152
|
+
const section = stringCamelCase(_section);
|
|
153
|
+
|
|
154
|
+
if (!named[section]) {
|
|
155
|
+
named[section] = {};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (let m = 0; m < mcount; m++) {
|
|
159
|
+
const [_method, def] = methods[m];
|
|
160
|
+
const method = stringCamelCase(_method);
|
|
161
|
+
|
|
162
|
+
named[section][method] = objectSpread({ method, name: `${_section}_${method}`, section, sectionHash, version: ver.version }, def);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
console.warn(`Unable to find matching version for runtime ${_section}, expected ${api[1]}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return named;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** @internal */
|
|
178
|
+
export function generateCallTypes (registry: Registry, meta: Metadata, dest: string, extraTypes: ExtraTypes, isStrict: boolean, customLookupDefinitions?: Definitions): void {
|
|
179
|
+
writeFile(dest, (): string => {
|
|
180
|
+
const allTypes: ExtraTypes = {
|
|
181
|
+
'@pezkuwi/types-augment': {
|
|
182
|
+
lookup: {
|
|
183
|
+
...lookupDefinitions,
|
|
184
|
+
...customLookupDefinitions
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
'@pezkuwi/types/interfaces': defaultDefs,
|
|
188
|
+
...extraTypes
|
|
189
|
+
};
|
|
190
|
+
const imports = createImports(allTypes);
|
|
191
|
+
|
|
192
|
+
// find the system.Version in metadata
|
|
193
|
+
let apis: Apis | null = null;
|
|
194
|
+
const sysp = meta.asLatest.pallets.find(({ name }) => name.eq('System'));
|
|
195
|
+
|
|
196
|
+
if (sysp) {
|
|
197
|
+
const verc = sysp.constants.find(({ name }) => name.eq('Version'));
|
|
198
|
+
|
|
199
|
+
if (verc) {
|
|
200
|
+
apis = registry.createType('RuntimeVersion', verc.value).apis.map(([k, v]): [HexString, number] => [k.toHex(), v.toNumber()]);
|
|
201
|
+
} else {
|
|
202
|
+
console.error('Unable to find System.Version pallet, skipping API extraction');
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
console.error('Unable to find System pallet, skipping API extraction');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const allDefs = Object.entries(allTypes).reduce((defs, [path, obj]) => {
|
|
209
|
+
return Object.entries(obj).reduce((defs, [key, value]) => ({ ...defs, [`${path}/${key}`]: value }), defs);
|
|
210
|
+
}, {});
|
|
211
|
+
const definitions = getDefs(apis, imports.definitions as Record<string, Definitions>, registry);
|
|
212
|
+
const callKeys = Object.keys(definitions);
|
|
213
|
+
|
|
214
|
+
const modules = callKeys.map((section) => {
|
|
215
|
+
const calls = definitions[section];
|
|
216
|
+
|
|
217
|
+
const allMethods = Object.keys(calls).sort().map((methodName) => {
|
|
218
|
+
const def = calls[methodName];
|
|
219
|
+
|
|
220
|
+
setImports(allDefs, imports, [def.type]);
|
|
221
|
+
|
|
222
|
+
const args = def.params.map((param) => {
|
|
223
|
+
const similarTypes = getSimilarTypes(registry, imports.definitions, param.type, imports);
|
|
224
|
+
|
|
225
|
+
setImports(allDefs, imports, [param.type, ...similarTypes]);
|
|
226
|
+
|
|
227
|
+
return `${param.name}: ${similarTypes.join(' | ')}`;
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
args: args.join(', '),
|
|
232
|
+
docs: [def.description],
|
|
233
|
+
name: methodName,
|
|
234
|
+
sectionHash: def.sectionHash,
|
|
235
|
+
sectionName: def.section,
|
|
236
|
+
sectionVersion: def.version,
|
|
237
|
+
type: formatType(registry, allDefs, def.type, imports)
|
|
238
|
+
};
|
|
239
|
+
}).sort((a, b) => a.name.localeCompare(b.name));
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
items: allMethods,
|
|
243
|
+
name: section || 'unknown',
|
|
244
|
+
sectionHash: allMethods.length && allMethods[0].sectionHash,
|
|
245
|
+
sectionName: allMethods.length && allMethods[0].sectionName,
|
|
246
|
+
sectionVersion: allMethods.length && allMethods[0].sectionVersion
|
|
247
|
+
};
|
|
248
|
+
}).filter(({ items }) => items.length).sort((a, b) => a.name.localeCompare(b.name));
|
|
249
|
+
|
|
250
|
+
if (modules.length) {
|
|
251
|
+
imports.typesTypes['Observable'] = true;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return generateCallsTypesTemplate({
|
|
255
|
+
headerType: 'chain',
|
|
256
|
+
imports,
|
|
257
|
+
isStrict,
|
|
258
|
+
modules,
|
|
259
|
+
types: [
|
|
260
|
+
...Object.keys(imports.localTypes).sort().map((packagePath): { file: string; types: string[] } => ({
|
|
261
|
+
file: packagePath.replace('@pezkuwi/types-augment', '@pezkuwi/types'),
|
|
262
|
+
types: Object.keys(imports.localTypes[packagePath])
|
|
263
|
+
})),
|
|
264
|
+
{
|
|
265
|
+
file: '@pezkuwi/api-base/types',
|
|
266
|
+
types: ['ApiTypes', 'AugmentedCall', 'DecoratedCallBase']
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function generateDefaultRuntime (dest: string, data: HexString, extraTypes: ExtraTypes = {}, isStrict = false, customLookupDefinitions?: Definitions): void {
|
|
274
|
+
const { metadata, registry } = initMeta(data, extraTypes);
|
|
275
|
+
|
|
276
|
+
generateCallTypes(
|
|
277
|
+
registry,
|
|
278
|
+
metadata,
|
|
279
|
+
dest,
|
|
280
|
+
extraTypes,
|
|
281
|
+
isStrict,
|
|
282
|
+
customLookupDefinitions
|
|
283
|
+
);
|
|
284
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
// Copyright 2017-2025 @polkadot/typegen authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { Registry } from '@pezkuwi/types/types';
|
|
5
|
+
import type { TypeDef } from '@pezkuwi/types-create/types';
|
|
6
|
+
import type { ModuleTypes } from '../util/imports.js';
|
|
7
|
+
import type { TypeImports } from '../util/index.js';
|
|
8
|
+
|
|
9
|
+
import Handlebars from 'handlebars';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
|
|
12
|
+
import { TypeRegistry } from '@pezkuwi/types/create';
|
|
13
|
+
import * as defaultDefinitions from '@pezkuwi/types/interfaces/definitions';
|
|
14
|
+
import { getTypeDef, TypeDefInfo } from '@pezkuwi/types-create';
|
|
15
|
+
import { assert, isString, stringify, stringPascalCase } from '@pezkuwi/util';
|
|
16
|
+
|
|
17
|
+
import { createImports, exportInterface, formatType, readTemplate, setImports, writeFile } from '../util/index.js';
|
|
18
|
+
|
|
19
|
+
interface Imports extends TypeImports {
|
|
20
|
+
interfaces: [string, string][];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const generateTsDefIndexTemplate = Handlebars.compile(readTemplate('tsDef/index'));
|
|
24
|
+
const generateTsDefModuleTypesTemplate = Handlebars.compile(readTemplate('tsDef/moduleTypes'));
|
|
25
|
+
const generateTsDefTypesTemplate = Handlebars.compile(readTemplate('tsDef/types'));
|
|
26
|
+
|
|
27
|
+
// helper to generate a `readonly <Name>: <Type>;` getter
|
|
28
|
+
/** @internal */
|
|
29
|
+
export function createGetter (definitions: Record<string, ModuleTypes>, name = '', type: string, imports: TypeImports): string {
|
|
30
|
+
setImports(definitions, imports, [type]);
|
|
31
|
+
|
|
32
|
+
return ` readonly ${name}: ${type};\n`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @internal */
|
|
36
|
+
function errorUnhandled (_: Registry, _definitions: Record<string, ModuleTypes>, def: TypeDef, _imports: TypeImports): string {
|
|
37
|
+
throw new Error(`Generate: ${def.name || ''}: Unhandled type ${TypeDefInfo[def.info]}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** @internal */
|
|
41
|
+
function tsExport (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
|
|
42
|
+
return exportInterface(def.lookupIndex, def.name, formatType(registry, definitions, def, imports, false));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @internal */
|
|
46
|
+
function tsEnum (registry: Registry, definitions: Record<string, ModuleTypes>, { lookupIndex, name: enumName, sub }: TypeDef, imports: TypeImports, withShortcut = false): string {
|
|
47
|
+
setImports(definitions, imports, ['Enum']);
|
|
48
|
+
|
|
49
|
+
const indent = withShortcut ? ' ' : '';
|
|
50
|
+
const named = (sub as TypeDef[]).filter(({ name }) => !!name && !name.startsWith('__Unused'));
|
|
51
|
+
const keys = named.map((def): string => {
|
|
52
|
+
const { info, lookupName, name = '', sub, type } = def;
|
|
53
|
+
const getter = stringPascalCase(name.replace(' ', '_'));
|
|
54
|
+
const isComplex = [TypeDefInfo.Option, TypeDefInfo.Range, TypeDefInfo.RangeInclusive, TypeDefInfo.Result, TypeDefInfo.Struct, TypeDefInfo.Tuple, TypeDefInfo.Vec, TypeDefInfo.VecFixed].includes(info);
|
|
55
|
+
|
|
56
|
+
let extractedLookupName;
|
|
57
|
+
|
|
58
|
+
// When the parent type does not have a lookupName, and the sub type is the same
|
|
59
|
+
// type as the parent we can take the lookupName from the sub.
|
|
60
|
+
// This is specific to `StagingXcmV4Junction`.
|
|
61
|
+
// see: https://github.com/polkadot-js/api/pull/5812
|
|
62
|
+
if (sub && !Array.isArray(sub) && type.includes(`${sub.type};`)) {
|
|
63
|
+
if (sub.lookupName === 'StagingXcmV4Junction') {
|
|
64
|
+
extractedLookupName = sub.lookupName;
|
|
65
|
+
} else if (sub.lookupName === 'StagingXcmV5Junction') {
|
|
66
|
+
extractedLookupName = `Vec<${sub.lookupName}>`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const asGetter = type === 'Null' || info === TypeDefInfo.DoNotConstruct
|
|
71
|
+
? ''
|
|
72
|
+
: createGetter(definitions, `as${getter}`, lookupName || extractedLookupName || (isComplex ? formatType(registry, definitions, info === TypeDefInfo.Struct ? def : type, imports, withShortcut) : type), imports);
|
|
73
|
+
const isGetter = info === TypeDefInfo.DoNotConstruct
|
|
74
|
+
? ''
|
|
75
|
+
: createGetter(definitions, `is${getter}`, 'boolean', imports);
|
|
76
|
+
|
|
77
|
+
switch (info) {
|
|
78
|
+
case TypeDefInfo.Compact:
|
|
79
|
+
case TypeDefInfo.Plain:
|
|
80
|
+
case TypeDefInfo.Range:
|
|
81
|
+
case TypeDefInfo.RangeInclusive:
|
|
82
|
+
case TypeDefInfo.Result:
|
|
83
|
+
case TypeDefInfo.Si:
|
|
84
|
+
case TypeDefInfo.Struct:
|
|
85
|
+
case TypeDefInfo.Tuple:
|
|
86
|
+
case TypeDefInfo.Vec:
|
|
87
|
+
case TypeDefInfo.BTreeMap:
|
|
88
|
+
case TypeDefInfo.BTreeSet:
|
|
89
|
+
case TypeDefInfo.Option:
|
|
90
|
+
case TypeDefInfo.VecFixed:
|
|
91
|
+
case TypeDefInfo.WrapperKeepOpaque:
|
|
92
|
+
case TypeDefInfo.WrapperOpaque:
|
|
93
|
+
return `${indent}${isGetter}${indent}${asGetter}`;
|
|
94
|
+
|
|
95
|
+
case TypeDefInfo.DoNotConstruct:
|
|
96
|
+
case TypeDefInfo.Null:
|
|
97
|
+
return `${indent}${isGetter}`;
|
|
98
|
+
|
|
99
|
+
default:
|
|
100
|
+
throw new Error(`Enum: ${enumName || 'undefined'}: Unhandled type ${TypeDefInfo[info]}, ${stringify(def)}`);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return exportInterface(lookupIndex, enumName, 'Enum', `${keys.join('')} ${indent}readonly type: ${named.map(({ name = '' }) => `'${stringPascalCase(name.replace(' ', '_'))}'`).join(' | ')};\n`, withShortcut);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function tsInt (_: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports, type: 'Int' | 'UInt' = 'Int'): string {
|
|
108
|
+
setImports(definitions, imports, [type]);
|
|
109
|
+
|
|
110
|
+
return exportInterface(def.lookupIndex, def.name, type);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** @internal */
|
|
114
|
+
function tsNull (_registry: Registry, definitions: Record<string, ModuleTypes>, { lookupIndex = -1, name }: TypeDef, imports: TypeImports): string {
|
|
115
|
+
setImports(definitions, imports, ['Null']);
|
|
116
|
+
|
|
117
|
+
// * @description extends [[${base}]]
|
|
118
|
+
const doc = `/** @name ${name || ''}${lookupIndex !== -1 ? ` (${lookupIndex})` : ''} */\n`;
|
|
119
|
+
|
|
120
|
+
return `${doc}export type ${name || ''} = Null;`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** @internal */
|
|
124
|
+
function tsResultGetter (registry: Registry, definitions: Record<string, ModuleTypes>, resultName = '', getter: 'Ok' | 'Err', def: TypeDef, imports: TypeImports): string {
|
|
125
|
+
const { info, lookupName, type } = def;
|
|
126
|
+
const asGetter = type === 'Null'
|
|
127
|
+
? ''
|
|
128
|
+
: createGetter(definitions, `as${getter}`, lookupName || (info === TypeDefInfo.Tuple ? formatType(registry, definitions, def, imports, false) : type), imports);
|
|
129
|
+
const isGetter = createGetter(definitions, `is${getter}`, 'boolean', imports);
|
|
130
|
+
|
|
131
|
+
switch (info) {
|
|
132
|
+
case TypeDefInfo.Option:
|
|
133
|
+
case TypeDefInfo.Plain:
|
|
134
|
+
case TypeDefInfo.Si:
|
|
135
|
+
case TypeDefInfo.Tuple:
|
|
136
|
+
case TypeDefInfo.Vec:
|
|
137
|
+
case TypeDefInfo.BTreeMap:
|
|
138
|
+
case TypeDefInfo.BTreeSet:
|
|
139
|
+
case TypeDefInfo.WrapperKeepOpaque:
|
|
140
|
+
case TypeDefInfo.WrapperOpaque:
|
|
141
|
+
return `${isGetter}${asGetter}`;
|
|
142
|
+
|
|
143
|
+
case TypeDefInfo.Null:
|
|
144
|
+
return `${isGetter}`;
|
|
145
|
+
|
|
146
|
+
default:
|
|
147
|
+
throw new Error(`Result: ${resultName}: Unhandled type ${TypeDefInfo[info]}, ${stringify(def)}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** @internal */
|
|
152
|
+
function tsResult (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
|
|
153
|
+
const [okDef, errorDef] = (def.sub as TypeDef[]);
|
|
154
|
+
const inner = [
|
|
155
|
+
tsResultGetter(registry, definitions, def.name, 'Err', errorDef, imports),
|
|
156
|
+
tsResultGetter(registry, definitions, def.name, 'Ok', okDef, imports)
|
|
157
|
+
].join('');
|
|
158
|
+
|
|
159
|
+
setImports(definitions, imports, [def.type]);
|
|
160
|
+
|
|
161
|
+
const fmtType = def.lookupName && def.name !== def.lookupName
|
|
162
|
+
? def.lookupName
|
|
163
|
+
: formatType(registry, definitions, def, imports, false);
|
|
164
|
+
|
|
165
|
+
return exportInterface(def.lookupIndex, def.name, fmtType, inner);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** @internal */
|
|
169
|
+
function tsSi (_registry: Registry, _definitions: Record<string, ModuleTypes>, typeDef: TypeDef, _imports: TypeImports): string {
|
|
170
|
+
// FIXME
|
|
171
|
+
return `// SI: ${stringify(typeDef)}`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** @internal */
|
|
175
|
+
function tsSet (_: Registry, definitions: Record<string, ModuleTypes>, { lookupIndex, name: setName, sub }: TypeDef, imports: TypeImports): string {
|
|
176
|
+
setImports(definitions, imports, ['Set']);
|
|
177
|
+
|
|
178
|
+
const types = (sub as TypeDef[]).map(({ name }): string => {
|
|
179
|
+
assert(name, 'Invalid TypeDef found, no name specified');
|
|
180
|
+
|
|
181
|
+
return createGetter(definitions, `is${name}`, 'boolean', imports);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
return exportInterface(lookupIndex, setName, 'Set', types.join(''));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** @internal */
|
|
188
|
+
function tsStruct (registry: Registry, definitions: Record<string, ModuleTypes>, { lookupIndex, name: structName, sub }: TypeDef, imports: TypeImports): string {
|
|
189
|
+
setImports(definitions, imports, ['Struct']);
|
|
190
|
+
|
|
191
|
+
const keys = (sub as TypeDef[]).map((def): string => {
|
|
192
|
+
const fmtType = def.lookupName && def.name !== def.lookupName
|
|
193
|
+
? def.lookupName
|
|
194
|
+
: def.info === TypeDefInfo.Enum
|
|
195
|
+
? `${tsEnum(registry, definitions, def, imports, true)} & Enum`
|
|
196
|
+
: formatType(registry, definitions, def, imports, false);
|
|
197
|
+
|
|
198
|
+
return createGetter(definitions, def.name, fmtType, imports);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
return exportInterface(lookupIndex, structName, 'Struct', keys.join(''));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** @internal */
|
|
205
|
+
function tsUInt (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
|
|
206
|
+
return tsInt(registry, definitions, def, imports, 'UInt');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** @internal */
|
|
210
|
+
function tsVec (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
|
|
211
|
+
const type = (def.sub as TypeDef).type;
|
|
212
|
+
|
|
213
|
+
if (type === 'u8') {
|
|
214
|
+
if (def.info === TypeDefInfo.VecFixed) {
|
|
215
|
+
setImports(definitions, imports, ['U8aFixed']);
|
|
216
|
+
|
|
217
|
+
return exportInterface(def.lookupIndex, def.name, 'U8aFixed');
|
|
218
|
+
} else {
|
|
219
|
+
setImports(definitions, imports, ['Bytes']);
|
|
220
|
+
|
|
221
|
+
return exportInterface(def.lookupIndex, def.name, 'Bytes');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const fmtType = def.lookupName && def.name !== def.lookupName
|
|
226
|
+
? def.lookupName
|
|
227
|
+
: formatType(registry, definitions, def, imports, false);
|
|
228
|
+
|
|
229
|
+
return exportInterface(def.lookupIndex, def.name, fmtType);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// handlers are defined externally to use - this means that when we do a
|
|
233
|
+
// `generators[typedef.info](...)` TS will show any unhandled types. Rather
|
|
234
|
+
// we are being explicit in having no handlers where we do not support (yet)
|
|
235
|
+
export const typeEncoders: Record<TypeDefInfo, (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports) => string> = {
|
|
236
|
+
[TypeDefInfo.BTreeMap]: tsExport,
|
|
237
|
+
[TypeDefInfo.BTreeSet]: tsExport,
|
|
238
|
+
[TypeDefInfo.Compact]: tsExport,
|
|
239
|
+
[TypeDefInfo.DoNotConstruct]: tsExport,
|
|
240
|
+
[TypeDefInfo.Enum]: tsEnum,
|
|
241
|
+
[TypeDefInfo.HashMap]: tsExport,
|
|
242
|
+
[TypeDefInfo.Int]: tsInt,
|
|
243
|
+
[TypeDefInfo.Linkage]: errorUnhandled,
|
|
244
|
+
[TypeDefInfo.Null]: tsNull,
|
|
245
|
+
[TypeDefInfo.Option]: tsExport,
|
|
246
|
+
[TypeDefInfo.Plain]: tsExport,
|
|
247
|
+
[TypeDefInfo.Range]: tsExport,
|
|
248
|
+
[TypeDefInfo.RangeInclusive]: tsExport,
|
|
249
|
+
[TypeDefInfo.Result]: tsResult,
|
|
250
|
+
[TypeDefInfo.Set]: tsSet,
|
|
251
|
+
[TypeDefInfo.Si]: tsSi,
|
|
252
|
+
[TypeDefInfo.Struct]: tsStruct,
|
|
253
|
+
[TypeDefInfo.Tuple]: tsExport,
|
|
254
|
+
[TypeDefInfo.UInt]: tsUInt,
|
|
255
|
+
[TypeDefInfo.Vec]: tsVec,
|
|
256
|
+
[TypeDefInfo.VecFixed]: tsVec,
|
|
257
|
+
[TypeDefInfo.WrapperKeepOpaque]: tsExport,
|
|
258
|
+
[TypeDefInfo.WrapperOpaque]: tsExport
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/** @internal */
|
|
262
|
+
function generateInterfaces (registry: Registry, definitions: Record<string, ModuleTypes>, { types }: { types: Record<string, any> }, imports: Imports): [string, string][] {
|
|
263
|
+
return Object.entries(types).map(([name, type]): [string, string] => {
|
|
264
|
+
const def = getTypeDef(isString(type) ? type : stringify(type), { name });
|
|
265
|
+
|
|
266
|
+
return [name, typeEncoders[def.info](registry, definitions, def, imports)];
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** @internal */
|
|
271
|
+
export function generateTsDefFor (registry: Registry, importDefinitions: Record<string, Record<string, ModuleTypes>>, defName: string, { types }: { types: Record<string, any> }, outputDir: string): void {
|
|
272
|
+
const imports = { ...createImports(importDefinitions, { types }), interfaces: [] } as Imports;
|
|
273
|
+
const definitions = imports.definitions;
|
|
274
|
+
const interfaces = generateInterfaces(registry, definitions, { types }, imports);
|
|
275
|
+
const items = interfaces.sort((a, b) => a[0].localeCompare(b[0])).map(([, definition]) => definition);
|
|
276
|
+
|
|
277
|
+
writeFile(path.join(outputDir, defName, 'types.ts'), () => generateTsDefModuleTypesTemplate({
|
|
278
|
+
headerType: 'defs',
|
|
279
|
+
imports,
|
|
280
|
+
items,
|
|
281
|
+
name: defName,
|
|
282
|
+
types: [
|
|
283
|
+
...Object.keys(imports.localTypes).sort().map((packagePath): { file: string; types: string[] } => ({
|
|
284
|
+
file: packagePath.replace('@pezkuwi/types/augment', '@pezkuwi/types'),
|
|
285
|
+
types: Object.keys(imports.localTypes[packagePath])
|
|
286
|
+
}))
|
|
287
|
+
]
|
|
288
|
+
}), true);
|
|
289
|
+
writeFile(path.join(outputDir, defName, 'index.ts'), () => generateTsDefIndexTemplate({ headerType: 'defs' }), true);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** @internal */
|
|
293
|
+
export function generateTsDef (importDefinitions: Record<string, Record<string, ModuleTypes>>, outputDir: string, generatingPackage: string): void {
|
|
294
|
+
const registry = new TypeRegistry();
|
|
295
|
+
|
|
296
|
+
writeFile(path.join(outputDir, 'types.ts'), (): string => {
|
|
297
|
+
const definitions = importDefinitions[generatingPackage];
|
|
298
|
+
|
|
299
|
+
Object.entries(definitions).forEach(([defName, obj]): void => {
|
|
300
|
+
console.log(`\tExtracting interfaces for ${defName}`);
|
|
301
|
+
|
|
302
|
+
generateTsDefFor(registry, importDefinitions, defName, obj, outputDir);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
return generateTsDefTypesTemplate({
|
|
306
|
+
headerType: 'defs',
|
|
307
|
+
items: Object.keys(definitions)
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
writeFile(path.join(outputDir, 'index.ts'), () => generateTsDefIndexTemplate({ headerType: 'defs' }), true);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** @internal */
|
|
315
|
+
export function generateDefaultTsDef (): void {
|
|
316
|
+
generateTsDef(
|
|
317
|
+
{ '@pezkuwi/types/interfaces': defaultDefinitions },
|
|
318
|
+
'packages/types/src/interfaces',
|
|
319
|
+
'@pezkuwi/types/interfaces'
|
|
320
|
+
);
|
|
321
|
+
}
|