Pass registry to formatters (#3799)

This commit is contained in:
Jaco
2021-07-22 19:39:40 +02:00
committed by GitHub
parent 592407d691
commit 196d3c5995
17 changed files with 133 additions and 97 deletions
+2 -2
View File
@@ -119,7 +119,7 @@ export class MetaRegistry extends TypeRegistry {
const displayName = path.pop()?.toString();
return withTypeString({
return withTypeString(this, {
...(displayName
? { displayName }
: {}
@@ -243,7 +243,7 @@ export class MetaRegistry extends TypeRegistry {
name: name.toString(),
type: 'Null'
}))
: variants.map(({ fields, name }) => withTypeString({
: variants.map(({ fields, name }) => withTypeString(this, {
...this.#extractFields(fields),
name: name.toString()
}));
+6 -6
View File
@@ -405,7 +405,7 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
private _decorateStorageEntry<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): QueryableStorageEntry<ApiType> {
// get the storage arguments, with DoubleMap as an array entry, otherwise spread
const getArgs = (args: unknown[]): unknown[] => extractStorageArgs(creator, args);
const getArgs = (args: unknown[]): unknown[] => extractStorageArgs(this.#registry, creator, args);
// Disable this where it occurs for each field we are decorating
/* eslint-disable @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment */
@@ -488,7 +488,7 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
private _decorateStorageEntryAt<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>, blockHash: Uint8Array): QueryableStorageEntryAt<ApiType> {
// get the storage arguments, with DoubleMap as an array entry, otherwise spread
const getArgs = (args: unknown[]): unknown[] => extractStorageArgs(creator, args);
const getArgs = (args: unknown[]): unknown[] => extractStorageArgs(this.#registry, creator, args);
// Disable this where it occurs for each field we are decorating
/* eslint-disable @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment */
@@ -545,18 +545,18 @@ export abstract class Decorate<ApiType extends ApiTypes> extends Events {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return decorateMethod((...args: unknown[]): Observable<Codec> => {
return this.hasSubscriptions
? this._rpcCore.state.subscribeStorage<[Codec]>([extractStorageArgs(creator, args)]).pipe(
? this._rpcCore.state.subscribeStorage<[Codec]>([extractStorageArgs(this.#registry, creator, args)]).pipe(
map(([data]) => data) // extract first/only result from list
)
: this._rpcCore.state.getStorage(extractStorageArgs(creator, args));
: this._rpcCore.state.getStorage(extractStorageArgs(this.#registry, creator, args));
}, {
methodName: creator.method,
overrideNoSub: (...args: unknown[]) => this._rpcCore.state.getStorage(extractStorageArgs(creator, args))
overrideNoSub: (...args: unknown[]) => this._rpcCore.state.getStorage(extractStorageArgs(this.#registry, creator, args))
});
}
private _decorateStorageRange<ApiType extends ApiTypes> (decorated: QueryableStorageEntry<ApiType>, args: Arg[], range: [Hash, Hash?]): Observable<[Hash, Codec][]> {
const outputType = unwrapStorageType(decorated.creator.meta.type, decorated.creator.meta.modifier.isOptional);
const outputType = unwrapStorageType(this.#registry, decorated.creator.meta.type, decorated.creator.meta.modifier.isOptional);
return this._rpcCore.state
.queryStorage<[Option<Raw>]>([decorated.key(...args)], ...range)
+12 -12
View File
@@ -20,79 +20,79 @@ describe('extractStorageArgs', (): void => {
it('validates no-arg plain', (): void => {
expect(
extractStorageArgs(storage.timestamp.now, [])
extractStorageArgs(registry, storage.timestamp.now, [])
).toEqual([storage.timestamp.now]);
});
it('validates no-arg plain (with undefined, undefined)', (): void => {
expect(
extractStorageArgs(storage.timestamp.now, [undefined, undefined])
extractStorageArgs(registry, storage.timestamp.now, [undefined, undefined])
).toEqual([storage.timestamp.now]);
});
it('validates no-arg plain (failing when there are args)', (): void => {
expect(
(): unknown => extractStorageArgs(storage.timestamp.now, [123, 456])
(): unknown => extractStorageArgs(registry, storage.timestamp.now, [123, 456])
).toThrow('timestamp.now() does not take any arguments, 2 found');
});
it('validates map, 1 arg', (): void => {
expect(
extractStorageArgs(storage.staking.payee, ['abc'])
extractStorageArgs(registry, storage.staking.payee, ['abc'])
).toEqual([storage.staking.payee, 'abc']);
});
it('validates map, 1 arg (failing with no args)', (): void => {
expect(
(): any =>
extractStorageArgs(storage.staking.payee, [])
extractStorageArgs(registry, storage.staking.payee, [])
).toThrow('staking.payee(AccountId) is a map, requiring 1 argument, 0 found');
});
it('validates map, 1 arg (failing with no args)', (): void => {
expect(
(): any =>
extractStorageArgs(storage.staking.payee, ['abc', 'def'])
extractStorageArgs(registry, storage.staking.payee, ['abc', 'def'])
).toThrow('staking.payee(AccountId) is a map, requiring 1 argument, 2 found');
});
it('validates doublemap, 2 args', (): void => {
expect(
extractStorageArgs(storage.staking.erasStakers, [1, '0x1234'])
extractStorageArgs(registry, storage.staking.erasStakers, [1, '0x1234'])
).toEqual([storage.staking.erasStakers, [1, '0x1234']]);
});
it('validates doublemap, 2 args (failing with no args)', (): void => {
expect(
(): any =>
extractStorageArgs(storage.staking.erasStakers, [])
extractStorageArgs(registry, storage.staking.erasStakers, [])
).toThrow('staking.erasStakers(EraIndex, AccountId) is a double map, requiring 2 arguments, 0 found');
});
it('validates doublemap, 2 args (failing with 1 arg)', (): void => {
expect(
(): any =>
extractStorageArgs(storage.staking.erasStakers, [123])
extractStorageArgs(registry, storage.staking.erasStakers, [123])
).toThrow('staking.erasStakers(EraIndex, AccountId) is a double map, requiring 2 arguments, 1 found');
});
// Linked maps have been removed
it.skip('validates linked map, no args', (): void => {
expect(
extractStorageArgs(storage.staking.validators, [])
extractStorageArgs(registry, storage.staking.validators, [])
).toEqual([storage.staking.validators]);
});
it.skip('validates linked map, single arg', (): void => {
expect(
extractStorageArgs(storage.staking.validators, [123])
extractStorageArgs(registry, storage.staking.validators, [123])
).toEqual([storage.staking.validators, 123]);
});
it.skip('validates linked map (failing with extra args)', (): void => {
expect(
(): any[] =>
extractStorageArgs(storage.staking.validators, [123, 456])
extractStorageArgs(registry, storage.staking.validators, [123, 456])
).toThrow('staking.validators(AccountId) is a linked map, requiring either 0 arguments (retrieving all) or 1 argument, 2 found');
});
});
+13 -12
View File
@@ -3,26 +3,27 @@
import type { Type } from '@polkadot/types';
import type { StorageEntry } from '@polkadot/types/primitive/types';
import type { Registry } from '@polkadot/types/types';
import { assert, isUndefined } from '@polkadot/util';
function sig ({ method, section }: StorageEntry, args: Type[]): string {
function sig (_: Registry, { method, section }: StorageEntry, args: Type[]): string {
return `${section}.${method}(${args.join(', ')})`;
}
function doDoubleMap (creator: StorageEntry, args: unknown[]): [StorageEntry, [any, any]] {
function doDoubleMap (registry: Registry, creator: StorageEntry, args: unknown[]): [StorageEntry, [any, any]] {
const { key1, key2 } = creator.meta.type.asDoubleMap;
assert(args.length === 2, () => `${sig(creator, [key1, key2])} is a double map, requiring 2 arguments, ${args.length} found`);
assert(args.length === 2, () => `${sig(registry, creator, [key1, key2])} is a double map, requiring 2 arguments, ${args.length} found`);
// pass as tuple
return [creator, args as [any, any]];
}
function doMap (creator: StorageEntry, args: unknown[]): [StorageEntry] | [StorageEntry, any] {
function doMap (registry: Registry, creator: StorageEntry, args: unknown[]): [StorageEntry] | [StorageEntry, any] {
const { key } = creator.meta.type.asMap;
assert(args.length === 1, () => `${sig(creator, [key])} is a map, requiring 1 argument, ${args.length} found`);
assert(args.length === 1, () => `${sig(registry, creator, [key])} is a map, requiring 1 argument, ${args.length} found`);
// expand
return args.length
@@ -30,10 +31,10 @@ function doMap (creator: StorageEntry, args: unknown[]): [StorageEntry] | [Stora
: [creator];
}
function doNMap (creator: StorageEntry, args: unknown[]): [StorageEntry, any[]] {
function doNMap (registry: Registry, creator: StorageEntry, args: unknown[]): [StorageEntry, any[]] {
const { keyVec } = creator.meta.type.asNMap;
assert(args.length === keyVec.length, () => `${sig(creator, keyVec)} is a multi map, requiring ${keyVec.length} arguments, ${args.length} found`);
assert(args.length === keyVec.length, () => `${sig(registry, creator, keyVec)} is a multi map, requiring ${keyVec.length} arguments, ${args.length} found`);
// pass as tuple
return [creator, args];
@@ -41,18 +42,18 @@ function doNMap (creator: StorageEntry, args: unknown[]): [StorageEntry, any[]]
// sets up the arguments in the form of [creator, args] ready to be used in a storage
// call. Additionally, it verifies that the correct number of arguments have been passed
export function extractStorageArgs (creator: StorageEntry, _args: unknown[]): [StorageEntry, any[]] | [StorageEntry] | [StorageEntry, any] {
export function extractStorageArgs (registry: Registry, creator: StorageEntry, _args: unknown[]): [StorageEntry, any[]] | [StorageEntry] | [StorageEntry, any] {
const args = _args.filter((arg) => !isUndefined(arg));
if (creator.meta.type.isDoubleMap) {
return doDoubleMap(creator, args);
return doDoubleMap(registry, creator, args);
} else if (creator.meta.type.isMap) {
return doMap(creator, args);
return doMap(registry, creator, args);
} else if (creator.meta.type.isNMap) {
return doNMap(creator, args);
return doNMap(registry, creator, args);
}
assert(args.length === 0, () => `${sig(creator, [])} does not take any arguments, ${args.length} found`);
assert(args.length === 0, () => `${sig(registry, creator, [])} does not take any arguments, ${args.length} found`);
// no args
return [creator];
+1 -1
View File
@@ -32,7 +32,7 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: ExtraTypes,
const items = constants
.map(({ docs, name, type }) => {
const returnType = formatType(allDefs, type.toString(), imports);
const returnType = formatType(meta.registry, allDefs, type.toString(), imports);
setImports(allDefs, imports, [returnType]);
+1 -1
View File
@@ -30,7 +30,7 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: ExtraTypes,
.unwrap()
.sort(compareName)
.map(({ args, docs, name }) => {
const types = args.map((type) => formatType(allDefs, type.toString(), imports));
const types = args.map((type) => formatType(meta.registry, allDefs, type.toString(), imports));
setImports(allDefs, imports, types);
+11 -8
View File
@@ -18,12 +18,12 @@ import { ModuleTypes } from '../util/imports';
// From a storage entry metadata, we return [args, returnType]
/** @internal */
function entrySignature (allDefs: Record<string, ModuleTypes>, registry: Registry, storageEntry: StorageEntryMetadataLatest, imports: TypeImports): [string, string, string] {
const outputType = unwrapStorageType(storageEntry.type, storageEntry.modifier.isOptional);
const outputType = unwrapStorageType(registry, storageEntry.type, storageEntry.modifier.isOptional);
if (storageEntry.type.isPlain) {
setImports(allDefs, imports, [storageEntry.type.asPlain.toString()]);
return ['', '', formatType(allDefs, outputType, imports)];
return ['', '', formatType(registry, allDefs, outputType, imports)];
} else if (storageEntry.type.isMap) {
const map = storageEntry.type.asMap;
@@ -36,9 +36,9 @@ function entrySignature (allDefs: Record<string, ModuleTypes>, registry: Registr
]);
return [
formatType(allDefs, map.key.toString(), imports),
formatType(registry, allDefs, map.key.toString(), imports),
`arg: ${similarTypes.join(' | ')}`,
formatType(allDefs, outputType, imports)
formatType(registry, allDefs, outputType, imports)
];
} else if (storageEntry.type.isDoubleMap) {
const dm = storageEntry.type.asDoubleMap;
@@ -57,9 +57,12 @@ function entrySignature (allDefs: Record<string, ModuleTypes>, registry: Registr
const key2Types = similarTypes2.join(' | ');
return [
[formatType(allDefs, dm.key1.toString(), imports), formatType(allDefs, dm.key2.toString(), imports)].join(', '),
[
formatType(registry, allDefs, dm.key1.toString(), imports),
formatType(registry, allDefs, dm.key2.toString(), imports)
].join(', '),
`arg1: ${key1Types}, arg2: ${key2Types}`,
formatType(allDefs, outputType, imports)
formatType(registry, allDefs, outputType, imports)
];
} else if (storageEntry.type.isNMap) {
const nmap = storageEntry.type.asNMap;
@@ -75,9 +78,9 @@ function entrySignature (allDefs: Record<string, ModuleTypes>, registry: Registr
const keyTypes = similarTypes.map((t) => t.join(' | '));
return [
nmap.keyVec.map((k) => formatType(allDefs, k.toString(), imports)).join(', '),
nmap.keyVec.map((k) => formatType(registry, allDefs, k.toString(), imports)).join(', '),
keyTypes.map((t, i) => `arg${i + 1}: ${t}`).join(', '),
formatType(allDefs, outputType, imports)
formatType(registry, allDefs, outputType, imports)
];
}
+1 -1
View File
@@ -90,7 +90,7 @@ export function generateRpcTypes (registry: TypeRegistry, importDefinitions: Rec
return `${param.name}${param.isOptional ? '?' : ''}: ${similarTypes.join(' | ')}`;
});
type = formatType(allDefs, def.type, imports);
type = formatType(registry, allDefs, def.type, imports);
generic = '';
}
+31 -28
View File
@@ -2,12 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
import type { TypeDef } from '@polkadot/types/create/types';
import type { Registry } from '@polkadot/types/types';
import type { ModuleTypes } from '../util/imports';
import Handlebars from 'handlebars';
import path from 'path';
import { getTypeDef } from '@polkadot/types/create';
import { getTypeDef, TypeRegistry } from '@polkadot/types/create';
import { TypeDefInfo } from '@polkadot/types/create/types';
import * as defaultDefinitions from '@polkadot/types/interfaces/definitions';
import { assert, isString, stringCamelCase, stringify, stringUpperFirst } from '@polkadot/util';
@@ -28,13 +29,13 @@ export function createGetter (definitions: Record<string, ModuleTypes>, name = '
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function errorUnhandled (definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
function errorUnhandled (_: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
throw new Error(`Generate: ${def.name || ''}: Unhandled type ${TypeDefInfo[def.info]}`);
}
/** @internal */
function tsExport (definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
return exportInterface(def.name, formatType(definitions, def, imports));
function tsExport (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
return exportInterface(def.name, formatType(registry, definitions, def, imports));
}
const tsBTreeMap = tsExport;
@@ -47,7 +48,7 @@ const tsPlain = tsExport;
const tsTuple = tsExport;
/** @internal */
function tsEnum (definitions: Record<string, ModuleTypes>, { name: enumName, sub }: TypeDef, imports: TypeImports): string {
function tsEnum (registry: Registry, definitions: Record<string, ModuleTypes>, { name: enumName, sub }: TypeDef, imports: TypeImports): string {
setImports(definitions, imports, ['Enum']);
const keys = (sub as TypeDef[]).map((def, index): string => {
@@ -56,7 +57,7 @@ function tsEnum (definitions: Record<string, ModuleTypes>, { name: enumName, sub
const isComplex = [TypeDefInfo.Struct, TypeDefInfo.Tuple, TypeDefInfo.Vec, TypeDefInfo.VecFixed].includes(info);
const asGetter = type === 'Null' || info === TypeDefInfo.DoNotConstruct
? ''
: createGetter(definitions, `as${getter}`, isComplex ? formatType(definitions, info === TypeDefInfo.Struct ? def : type, imports) : type, imports);
: createGetter(definitions, `as${getter}`, isComplex ? formatType(registry, definitions, info === TypeDefInfo.Struct ? def : type, imports) : type, imports);
const isGetter = info === TypeDefInfo.DoNotConstruct
? ''
: createGetter(definitions, `is${getter}`, 'boolean', imports);
@@ -82,18 +83,18 @@ function tsEnum (definitions: Record<string, ModuleTypes>, { name: enumName, sub
return exportInterface(enumName, 'Enum', keys.join(''));
}
function tsInt (definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports, type: 'Int' | 'UInt' = 'Int'): string {
function tsInt (_: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports, type: 'Int' | 'UInt' = 'Int'): string {
setImports(definitions, imports, [type]);
return exportInterface(def.name, type);
}
/** @internal */
function tsResultGetter (definitions: Record<string, ModuleTypes>, resultName = '', getter: 'Ok' | 'Err' | 'Error', def: TypeDef, imports: TypeImports): string {
function tsResultGetter (registry: Registry, definitions: Record<string, ModuleTypes>, resultName = '', getter: 'Ok' | 'Err' | 'Error', def: TypeDef, imports: TypeImports): string {
const { info, type } = def;
const asGetter = type === 'Null'
? ''
: (getter === 'Error' ? ' /** @deprecated Use asErr */\n' : '') + createGetter(definitions, `as${getter}`, info === TypeDefInfo.Tuple ? formatType(definitions, def, imports) : type, imports);
: (getter === 'Error' ? ' /** @deprecated Use asErr */\n' : '') + createGetter(definitions, `as${getter}`, info === TypeDefInfo.Tuple ? formatType(registry, definitions, def, imports) : type, imports);
const isGetter = (getter === 'Error' ? ' /** @deprecated Use isErr */\n' : '') + createGetter(definitions, `is${getter}`, 'boolean', imports);
switch (info) {
@@ -109,28 +110,28 @@ function tsResultGetter (definitions: Record<string, ModuleTypes>, resultName =
}
/** @internal */
function tsResult (definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
function tsResult (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
const [okDef, errorDef] = (def.sub as TypeDef[]);
const inner = [
tsResultGetter(definitions, def.name, 'Err', errorDef, imports),
tsResultGetter(registry, definitions, def.name, 'Err', errorDef, imports),
// @deprecated, use Err
tsResultGetter(definitions, def.name, 'Error', errorDef, imports),
tsResultGetter(definitions, def.name, 'Ok', okDef, imports)
tsResultGetter(registry, definitions, def.name, 'Error', errorDef, imports),
tsResultGetter(registry, definitions, def.name, 'Ok', okDef, imports)
].join('');
setImports(definitions, imports, [def.type]);
return exportInterface(def.name, formatType(definitions, def, imports), inner);
return exportInterface(def.name, formatType(registry, definitions, def, imports), inner);
}
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function tsSi (definitions: Record<string, ModuleTypes>, { type }: TypeDef, imports: TypeImports): string {
function tsSi (registry: Registry, definitions: Record<string, ModuleTypes>, { type }: TypeDef, imports: TypeImports): string {
throw new Error('Unable to generate string definition from TypeDefInfo.Si');
}
/** @internal */
function tsSet (definitions: Record<string, ModuleTypes>, { name: setName, sub }: TypeDef, imports: TypeImports): string {
function tsSet (_: Registry, definitions: Record<string, ModuleTypes>, { name: setName, sub }: TypeDef, imports: TypeImports): string {
setImports(definitions, imports, ['Set']);
const types = (sub as TypeDef[]).map(({ name }): string => {
@@ -143,11 +144,11 @@ function tsSet (definitions: Record<string, ModuleTypes>, { name: setName, sub }
}
/** @internal */
function tsStruct (definitions: Record<string, ModuleTypes>, { name: structName, sub }: TypeDef, imports: TypeImports): string {
function tsStruct (registry: Registry, definitions: Record<string, ModuleTypes>, { name: structName, sub }: TypeDef, imports: TypeImports): string {
setImports(definitions, imports, ['Struct']);
const keys = (sub as TypeDef[]).map((typedef): string => {
const returnType = formatType(definitions, typedef, imports);
const returnType = formatType(registry, definitions, typedef, imports);
return createGetter(definitions, typedef.name, returnType, imports);
});
@@ -156,12 +157,12 @@ function tsStruct (definitions: Record<string, ModuleTypes>, { name: structName,
}
/** @internal */
function tsUInt (definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
return tsInt(definitions, def, imports, 'UInt');
function tsUInt (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
return tsInt(registry, definitions, def, imports, 'UInt');
}
/** @internal */
function tsVec (definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
function tsVec (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports): string {
const type = (def.sub as TypeDef).type;
if (def.info === TypeDefInfo.VecFixed && type === 'u8') {
@@ -170,13 +171,13 @@ function tsVec (definitions: Record<string, ModuleTypes>, def: TypeDef, imports:
return exportType(def.name, 'U8aFixed');
}
return exportInterface(def.name, formatType(definitions, def, imports));
return exportInterface(def.name, formatType(registry, definitions, def, imports));
}
// handlers are defined externally to use - this means that when we do a
// `generators[typedef.info](...)` TS will show any unhandled types. Rather
// we are being explicit in having no handlers where we do not support (yet)
const encoders: Record<TypeDefInfo, (definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports) => string> = {
const encoders: Record<TypeDefInfo, (registry: Registry, definitions: Record<string, ModuleTypes>, def: TypeDef, imports: TypeImports) => string> = {
[TypeDefInfo.BTreeMap]: tsBTreeMap,
[TypeDefInfo.BTreeSet]: tsBTreeSet,
[TypeDefInfo.Compact]: tsCompact,
@@ -199,11 +200,11 @@ const encoders: Record<TypeDefInfo, (definitions: Record<string, ModuleTypes>, d
};
/** @internal */
function generateInterfaces (definitions: Record<string, ModuleTypes>, { types }: { types: Record<string, any> }, imports: Imports): [string, string][] {
function generateInterfaces (registry: Registry, definitions: Record<string, ModuleTypes>, { types }: { types: Record<string, any> }, imports: Imports): [string, string][] {
return Object.entries(types).map(([name, type]): [string, string] => {
const def = getTypeDef(isString(type) ? type : stringify(type), { name });
return [name, encoders[def.info](definitions, def, imports)];
return [name, encoders[def.info](registry, definitions, def, imports)];
});
}
@@ -217,10 +218,10 @@ const templateTypes = readTemplate('tsDef/types');
const generateTsDefTypesTemplate = Handlebars.compile(templateTypes);
/** @internal */
function generateTsDefFor (importDefinitions: { [importPath: string]: Record<string, ModuleTypes> }, defName: string, { types }: { types: Record<string, any> }, outputDir: string): void {
function generateTsDefFor (registry: Registry, importDefinitions: { [importPath: string]: Record<string, ModuleTypes> }, defName: string, { types }: { types: Record<string, any> }, outputDir: string): void {
const imports = { ...createImports(importDefinitions, { types }), interfaces: [] } as Imports;
const definitions = imports.definitions;
const interfaces = generateInterfaces(definitions, { types }, imports);
const interfaces = generateInterfaces(registry, definitions, { types }, imports);
const items = interfaces.sort((a, b): number => a[0].localeCompare(b[0])).map(([, definition]): string => definition);
const importTypes = [
@@ -242,13 +243,15 @@ function generateTsDefFor (importDefinitions: { [importPath: string]: Record<str
/** @internal */
export function generateTsDef (importDefinitions: { [importPath: string]: Record<string, ModuleTypes> }, outputDir: string, generatingPackage: string): void {
const registry = new TypeRegistry();
writeFile(path.join(outputDir, 'types.ts'), (): string => {
const definitions = importDefinitions[generatingPackage];
Object.entries(definitions).forEach(([defName, obj]): void => {
console.log(`\tExtracting interfaces for ${defName}`);
generateTsDefFor(importDefinitions, defName, obj, outputDir);
generateTsDefFor(registry, importDefinitions, defName, obj, outputDir);
});
return generateTsDefTypesTemplate({
+1 -1
View File
@@ -55,7 +55,7 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
.join(', ');
return {
args: args.map(({ type }) => formatType(allDefs, type.toString(), imports)).join(', '),
args: args.map(({ type }) => formatType(registry, allDefs, type.toString(), imports)).join(', '),
docs,
name: stringCamelCase(name),
params
+2 -2
View File
@@ -211,7 +211,7 @@ function addStorage (metadata: MetadataLatest): string {
? ('`' + func.type.asNMap.keyVec.map((k) => k.toString()).join(', ') + '`')
: '';
const methodName = stringLowerFirst(func.name);
const outputType = unwrapStorageType(func.type, func.modifier.isOptional);
const outputType = unwrapStorageType(metadata.registry, func.type, func.modifier.isOptional);
return {
interface: '`' + `api.query.${sectionName}.${methodName}` + '`',
@@ -234,7 +234,7 @@ function addStorage (metadata: MetadataLatest): string {
? ('`' + meta.type.asDoubleMap.key1.toString() + ', ' + meta.type.asDoubleMap.key2.toString() + '`')
: '';
const methodName = stringLowerFirst(name);
const outputType = unwrapStorageType(meta.type, meta.modifier.isOptional);
const outputType = unwrapStorageType(metadata.registry, meta.type, meta.modifier.isOptional);
return {
interface: '`' + `api.query.substrate.${methodName}` + '`',
+2 -2
View File
@@ -54,7 +54,7 @@ export function getDerivedTypes (registry: Registry, definitions: Record<string,
});
}
const result = types.map((t) => formatType(definitions, t, imports)).map((t) => `'${t}': ${t};`);
const result = types.map((t) => formatType(registry, definitions, t, imports)).map((t) => `'${t}': ${t};`);
result.unshift(`${type}: ${type};`);
@@ -68,7 +68,7 @@ export function getDerivedTypes (registry: Registry, definitions: Record<string,
export function getSimilarTypes (registry: Registry, definitions: Record<string, ModuleTypes>, _type: string, imports: TypeImports): string[] {
const typeParts = _type.split('::');
const type = typeParts[typeParts.length - 1];
const possibleTypes = [formatType(definitions, type, imports)];
const possibleTypes = [formatType(registry, definitions, type, imports)];
if (type === 'Extrinsic') {
setImports(definitions, imports, ['IExtrinsic']);
+5 -1
View File
@@ -1,12 +1,16 @@
// Copyright 2017-2021 @polkadot/typegen authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { TypeRegistry } from '@polkadot/types';
import { formatType } from './formatting';
describe('formatType', (): void => {
const registry = new TypeRegistry();
it('handles nested Tuples', (): void => {
expect(
formatType({}, '(AccountId, (Balance, u32), u64)', {
formatType(registry, {}, '(AccountId, (Balance, u32), u64)', {
codecTypes: {},
definitions: {},
extrinsicTypes: {},
+36 -12
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { TypeDef } from '@polkadot/types/create/types';
import type { Registry } from '@polkadot/types/types';
import Handlebars from 'handlebars';
@@ -176,7 +177,7 @@ function formatVec (inner: string): string {
*/
/** @internal */
// eslint-disable-next-line @typescript-eslint/ban-types
export function formatType (definitions: Record<string, ModuleTypes>, type: string | String | TypeDef, imports: TypeImports): string {
export function formatType (registry: Registry, definitions: Record<string, ModuleTypes>, type: string | String | TypeDef, imports: TypeImports): string {
let typeDef: TypeDef;
if (isString(type)) {
@@ -200,7 +201,9 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
case TypeDefInfo.Compact: {
setImports(definitions, imports, ['Compact']);
return formatCompact(formatType(definitions, (typeDef.sub as TypeDef).type, imports));
return formatCompact(
formatType(registry, definitions, (typeDef.sub as TypeDef).type, imports)
);
}
case TypeDefInfo.DoNotConstruct: {
@@ -212,7 +215,9 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
case TypeDefInfo.Option: {
setImports(definitions, imports, ['Option']);
return formatOption(formatType(definitions, (typeDef.sub as TypeDef).type, imports));
return formatOption(
formatType(registry, definitions, (typeDef.sub as TypeDef).type, imports)
);
}
case TypeDefInfo.Plain: {
@@ -225,7 +230,7 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
return formatStruct(
((typeDef.sub as TypeDef[]).map(({ name, type }, index) => [
name || `unknown${index}`,
formatType(definitions, type, imports)
formatType(registry, definitions, type, imports)
]))
);
}
@@ -235,14 +240,18 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
// `(a,b)` gets transformed into `ITuple<[a, b]>`
return formatTuple(
((typeDef.sub as TypeDef[]).map(({ type }) => formatType(definitions, type, imports)))
((typeDef.sub as TypeDef[]).map(({ type }) =>
formatType(registry, definitions, type, imports))
)
);
}
case TypeDefInfo.Vec: {
setImports(definitions, imports, ['Vec']);
return formatVec(formatType(definitions, (typeDef.sub as TypeDef).type, imports));
return formatVec(
formatType(registry, definitions, (typeDef.sub as TypeDef).type, imports)
);
}
case TypeDefInfo.VecFixed: {
@@ -256,7 +265,9 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
setImports(definitions, imports, ['Vec']);
return formatVec(formatType(definitions, type, imports));
return formatVec(
formatType(registry, definitions, type, imports)
);
}
case TypeDefInfo.BTreeMap: {
@@ -264,7 +275,10 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
const [keyDef, valDef] = (typeDef.sub as TypeDef[]);
return formatBTreeMap(formatType(definitions, keyDef.type, imports), formatType(definitions, valDef.type, imports));
return formatBTreeMap(
formatType(registry, definitions, keyDef.type, imports),
formatType(registry, definitions, valDef.type, imports)
);
}
case TypeDefInfo.BTreeSet: {
@@ -272,7 +286,9 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
const valDef = typeDef.sub as TypeDef;
return formatBTreeSet(formatType(definitions, valDef.type, imports));
return formatBTreeSet(
formatType(registry, definitions, valDef.type, imports)
);
}
case TypeDefInfo.HashMap: {
@@ -280,7 +296,10 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
const [keyDef, valDef] = (typeDef.sub as TypeDef[]);
return formatHashMap(formatType(definitions, keyDef.type, imports), formatType(definitions, valDef.type, imports));
return formatHashMap(
formatType(registry, definitions, keyDef.type, imports),
formatType(registry, definitions, valDef.type, imports)
);
}
case TypeDefInfo.Linkage: {
@@ -288,7 +307,9 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
setImports(definitions, imports, ['Linkage']);
return formatLinkage(formatType(definitions, type, imports));
return formatLinkage(
formatType(registry, definitions, type, imports)
);
}
case TypeDefInfo.Result: {
@@ -296,7 +317,10 @@ export function formatType (definitions: Record<string, ModuleTypes>, type: stri
const [okDef, errorDef] = (typeDef.sub as TypeDef[]);
return formatResult(formatType(definitions, okDef.type, imports), formatType(definitions, errorDef.type, imports));
return formatResult(
formatType(registry, definitions, okDef.type, imports),
formatType(registry, definitions, errorDef.type, imports)
);
}
default: {
+2 -1
View File
@@ -1,6 +1,7 @@
// Copyright 2017-2021 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Registry } from '../types/registry';
import type { TypeDef } from './types';
import { assert, isNumber, isUndefined, stringify } from '@polkadot/util';
@@ -140,7 +141,7 @@ export function encodeTypeDef (typeDef: TypeDef): string {
return encodeType(typeDef);
}
export function withTypeString (typeDef: Omit<TypeDef, 'type'>): TypeDef {
export function withTypeString (_: Registry, typeDef: Omit<TypeDef, 'type'>): TypeDef {
return {
...typeDef,
type: encodeType(typeDef as TypeDef)
+1 -1
View File
@@ -54,7 +54,7 @@ export function defaultValues (registry: Registry, rpcData: string, withThrow =
metadata.asLatest.modules.filter(({ storage }): boolean => storage.isSome).forEach((mod): void => {
mod.storage.unwrap().items.forEach(({ fallback, modifier, name, type }): void => {
const inner = unwrapStorageType(type, modifier.isOptional);
const inner = unwrapStorageType(registry, type, modifier.isOptional);
const location = `${mod.name.toString()}.${name.toString()}: ${inner}`;
it(`creates default types for ${location}`, (): void => {
+6 -6
View File
@@ -33,7 +33,7 @@ const HASHER_MAP: Record<keyof typeof AllHashers, [number, boolean]> = {
};
/** @internal */
export function unwrapStorageType (type: StorageEntryTypeLatest, isOptional?: boolean): keyof InterfaceTypes {
export function unwrapStorageType (_: Registry, type: StorageEntryTypeLatest, isOptional?: boolean): keyof InterfaceTypes {
const outputType = type.isPlain
? type.asPlain.toString()
: type.isMap
@@ -142,16 +142,16 @@ function getMeta (value: StorageKey | StorageEntry | [StorageEntry, unknown]): S
}
/** @internal */
function getType (value: StorageKey | StorageEntry | [StorageEntry, unknown]): string {
function getType (registry: Registry, value: StorageKey | StorageEntry | [StorageEntry, unknown]): string {
if (value instanceof StorageKey) {
return value.outputType;
} else if (isFunction(value)) {
return unwrapStorageType(value.meta.type);
return unwrapStorageType(registry, value.meta.type);
} else if (Array.isArray(value)) {
const [fn] = value;
if (fn.meta) {
return unwrapStorageType(fn.meta.type);
return unwrapStorageType(registry, fn.meta.type);
}
}
@@ -183,7 +183,7 @@ export class StorageKey<A extends AnyTuple = AnyTuple> extends Bytes implements
super(registry, key);
this._outputType = getType(value as StorageKey);
this._outputType = getType(registry, value as StorageKey);
// decode the args (as applicable based on the key and the hashers, after all init)
this.setMeta(getMeta(value as StorageKey), override.section || section, override.method || method);
@@ -237,7 +237,7 @@ export class StorageKey<A extends AnyTuple = AnyTuple> extends Bytes implements
this._section = section || this._section;
if (meta) {
this._outputType = unwrapStorageType(meta.type);
this._outputType = unwrapStorageType(this.registry, meta.type);
}
try {