Expand enum & struct defnitions, generator strict mode (#1798)
This commit is contained in:
@@ -203,6 +203,13 @@ export default class Enum extends Base<Codec> {
|
||||
return this.raw instanceof Null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The available keys for this enum
|
||||
*/
|
||||
public get defEntries (): string[] {
|
||||
return Object.keys(this._def);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The available keys for this enum
|
||||
*/
|
||||
@@ -275,7 +282,7 @@ export default class Enum extends Base<Codec> {
|
||||
*/
|
||||
protected toRawStruct (): string[] | Record<string, string> {
|
||||
return this._isBasic
|
||||
? Object.keys(this._def)
|
||||
? this.defKeys
|
||||
: Struct.typesToMap(this.registry, this._def);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,13 @@ export default class Struct<
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The available keys for this enum
|
||||
*/
|
||||
public get defKeys (): string[] {
|
||||
return Object.keys(this._Types);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Checks if the value is an empty value
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@ import { FOOTER, HEADER, TypeImports, createDocComments, createImportCode, creat
|
||||
|
||||
// Generate types for one module
|
||||
/** @internal */
|
||||
function generateModule (allDefs: object, { constants, name }: ModuleMetadataLatest, imports: TypeImports): string[] {
|
||||
function generateModule (allDefs: object, { constants, name }: ModuleMetadataLatest, imports: TypeImports, isStrict: boolean): string[] {
|
||||
if (!constants.length) {
|
||||
return [];
|
||||
}
|
||||
@@ -21,18 +21,18 @@ function generateModule (allDefs: object, { constants, name }: ModuleMetadataLat
|
||||
setImports(allDefs, imports, ['Codec']);
|
||||
|
||||
return [indent(4)(`${stringCamelCase(name.toString())}: {`)]
|
||||
.concat(indent(6)('[index: string]: Codec;'))
|
||||
.concat(isStrict ? '' : indent(6)('[index: string]: Codec;'))
|
||||
.concat(constants.map(({ documentation, name, type }): string => {
|
||||
setImports(allDefs, imports, [type.toString()]);
|
||||
|
||||
return createDocComments(documentation).map((d): string => indent(6)(d)).join('\n') +
|
||||
return createDocComments(6, documentation) +
|
||||
indent(6)(`${stringCamelCase(name.toString())}: AugmentedConst<${type}>;`);
|
||||
}))
|
||||
.concat([indent(4)('};')]);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function generateForMeta (meta: Metadata, dest: string, extraTypes: Record<string, Record<string, object>>): void {
|
||||
function generateForMeta (meta: Metadata, dest: string, extraTypes: Record<string, Record<string, object>>, isStrict: boolean): void {
|
||||
writeFile(dest, (): string => {
|
||||
const allTypes: Record<string, Record<string, object>> = { '@polkadot/types/interfaces': defaultDefs, ...extraTypes };
|
||||
const imports = createImports(allTypes);
|
||||
@@ -40,7 +40,7 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: Record<strin
|
||||
return Object.entries(obj).reduce((defs, [key, value]) => ({ ...defs, [key]: value }), defs);
|
||||
}, {});
|
||||
const body = meta.asLatest.modules.reduce((acc, mod): string[] => {
|
||||
return acc.concat(generateModule(allDefs, mod, imports));
|
||||
return acc.concat(generateModule(allDefs, mod, imports, isStrict));
|
||||
}, [] as string[]);
|
||||
const header = createImportCode(HEADER, imports, [
|
||||
...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({
|
||||
@@ -49,7 +49,7 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: Record<strin
|
||||
}))
|
||||
]);
|
||||
const interfaceStart = [
|
||||
"declare module '@polkadot/metadata/Decorated/types' {",
|
||||
"declare module '@polkadot/metadata/Decorated/consts/types' {",
|
||||
indent(2)('export interface Constants {\n')
|
||||
].join('\n');
|
||||
const interfaceEnd = `\n${indent(2)('}')}\n}`;
|
||||
@@ -64,8 +64,8 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: Record<strin
|
||||
|
||||
// Call `generateForMeta()` with current static metadata
|
||||
/** @internal */
|
||||
export default function generateConsts (dest = 'packages/api/src/types/augment/consts.ts', data = staticData, extraTypes: Record<string, Record<string, object>> = {}): void {
|
||||
export default function generateConsts (dest = 'packages/api/src/types/augment/consts.ts', data = staticData, extraTypes: Record<string, Record<string, object>> = {}, isStrict = false): void {
|
||||
const registry = new TypeRegistry();
|
||||
|
||||
return generateForMeta(new Metadata(registry, data), dest, extraTypes);
|
||||
return generateForMeta(new Metadata(registry, data), dest, extraTypes, isStrict);
|
||||
}
|
||||
|
||||
@@ -68,24 +68,24 @@ function entrySignature (allDefs: object, registry: Registry, storageEntry: Stor
|
||||
|
||||
// Generate types for one module
|
||||
/** @internal */
|
||||
function generateModule (allDefs: object, registry: Registry, { name, storage }: ModuleMetadataLatest, imports: TypeImports): string[] {
|
||||
function generateModule (allDefs: object, registry: Registry, { name, storage }: ModuleMetadataLatest, imports: TypeImports, isStrict: boolean): string[] {
|
||||
if (storage.isNone) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [indent(4)(`${stringLowerFirst(name.toString())}: {`)]
|
||||
.concat(indent(6)('[index: string]: QueryableStorageEntry<ApiType>;'))
|
||||
.concat(isStrict ? '' : indent(6)('[index: string]: QueryableStorageEntry<ApiType>;'))
|
||||
.concat(storage.unwrap().items.map((storageEntry): string => {
|
||||
const [args, returnType] = entrySignature(allDefs, registry, storageEntry, imports);
|
||||
|
||||
return createDocComments(storageEntry.documentation).map((d): string => indent(6)(d)).join('\n') +
|
||||
return createDocComments(6, storageEntry.documentation) +
|
||||
indent(6)(`${stringLowerFirst(storageEntry.name.toString())}: AugmentedQuery<ApiType, (${args}) => Observable<${returnType}>> & QueryableStorageEntry<ApiType>;`);
|
||||
}))
|
||||
.concat([indent(4)('};')]);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function generateForMeta (registry: Registry, meta: Metadata, dest: string, extraTypes: Record<string, Record<string, object>>): void {
|
||||
function generateForMeta (registry: Registry, meta: Metadata, dest: string, extraTypes: Record<string, Record<string, object>>, isStrict: boolean): void {
|
||||
writeFile(dest, (): string => {
|
||||
const allTypes: Record<string, Record<string, object>> = { '@polkadot/types/interfaces': defaultDefs, ...extraTypes };
|
||||
const imports = createImports(allTypes);
|
||||
@@ -93,7 +93,7 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
|
||||
return Object.entries(obj).reduce((defs, [key, value]) => ({ ...defs, [key]: value }), defs);
|
||||
}, {});
|
||||
const body = meta.asLatest.modules.reduce((acc, mod): string[] => {
|
||||
return acc.concat(generateModule(allDefs, registry, mod, imports));
|
||||
return acc.concat(generateModule(allDefs, registry, mod, imports, isStrict));
|
||||
}, [] as string[]);
|
||||
const header = createImportCode(HEADER, imports, [
|
||||
...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({
|
||||
@@ -121,8 +121,8 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
|
||||
|
||||
// Call `generateForMeta()` with current static metadata
|
||||
/** @internal */
|
||||
export default function generateQuery (dest = 'packages/api/src/types/augment/query.ts', data = staticData, extraTypes: Record<string, Record<string, object>> = {}): void {
|
||||
export default function generateQuery (dest = 'packages/api/src/types/augment/query.ts', data = staticData, extraTypes: Record<string, Record<string, object>> = {}, isStrict = false): void {
|
||||
const registry = new TypeRegistry();
|
||||
|
||||
return generateForMeta(registry, new Metadata(registry, data), dest, extraTypes);
|
||||
return generateForMeta(registry, new Metadata(registry, data), dest, extraTypes, isStrict);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import interfaces from '../../../../type-jsonrpc/src';
|
||||
import * as definitions from '../../interfaces/definitions';
|
||||
import { TypeRegistry } from '../../codec/create';
|
||||
import { FOOTER, HEADER, createImportCode, createImports, getSimilarTypes, setImports, writeFile } from '../util';
|
||||
import { FOOTER, HEADER, createDocComments, createImportCode, createImports, getSimilarTypes, setImports, writeFile, indent } from '../util';
|
||||
|
||||
/** @internal */
|
||||
export default function generateRpcTypes (dest = 'packages/api/src/types/augment/rpc.ts'): void {
|
||||
@@ -35,7 +35,7 @@ export default function generateRpcTypes (dest = 'packages/api/src/types/augment
|
||||
return `${param.name}${param.isOptional ? '?' : ''}: ${similarTypes.join(' | ')}`;
|
||||
});
|
||||
|
||||
return ` /**\n * ${method.description}\n **/\n ${method.method}(${args.join(', ')}): Observable<${method.type}>;`;
|
||||
return createDocComments(6, [method.description]) + indent(6)(`${method.method}(${args.join(', ')}): Observable<${method.type}>;`);
|
||||
});
|
||||
|
||||
return allSections.concat(
|
||||
|
||||
@@ -26,7 +26,7 @@ function mapName (_name: Text): string {
|
||||
// Generate types for one module
|
||||
/** @internal */
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function generateModule (registry: Registry, allDefs: object, { calls, name }: ModuleMetadataLatest, imports: TypeImports): string[] {
|
||||
function generateModule (registry: Registry, allDefs: object, { calls, name }: ModuleMetadataLatest, imports: TypeImports, isStrict: boolean): string[] {
|
||||
const allCalls = calls.unwrapOr(null);
|
||||
|
||||
if (!allCalls?.length) {
|
||||
@@ -37,30 +37,33 @@ function generateModule (registry: Registry, allDefs: object, { calls, name }: M
|
||||
|
||||
// NOTE Not removing this concat yet, first see the fallout
|
||||
return [indent(4)(`${stringCamelCase(name.toString())}: {`)]
|
||||
.concat(indent(6)('[index: string]: SubmittableExtrinsicFunction<ApiType>;'))
|
||||
.concat(isStrict ? '' : indent(6)('[index: string]: SubmittableExtrinsicFunction<ApiType>;'))
|
||||
.concat(allCalls.map(({ args, documentation, name }): string => {
|
||||
const params = args.map(({ name, type }): [string, string, string] => {
|
||||
const typeStr = type.toString();
|
||||
const similarTypes = getSimilarTypes(allDefs, registry, typeStr, imports).map((type): string =>
|
||||
type.startsWith('(') || type.startsWith('{')
|
||||
? type
|
||||
: formatType(allDefs, type, imports)
|
||||
);
|
||||
const nameStr = mapName(name);
|
||||
const params = args
|
||||
.map(({ name, type }): [string, string, string] => {
|
||||
const typeStr = type.toString();
|
||||
const similarTypes = getSimilarTypes(allDefs, registry, typeStr, imports).map((type): string =>
|
||||
type.startsWith('(') || type.startsWith('{')
|
||||
? type
|
||||
: formatType(allDefs, type, imports)
|
||||
);
|
||||
const nameStr = mapName(name);
|
||||
|
||||
setImports(allDefs, imports, [...similarTypes.filter((type): boolean => !type.startsWith('(') && !type.startsWith('{')), typeStr]);
|
||||
setImports(allDefs, imports, [...similarTypes.filter((type): boolean => !type.startsWith('(') && !type.startsWith('{')), typeStr]);
|
||||
|
||||
return [`${nameStr}: ${similarTypes.join(' | ')}`, nameStr, typeStr];
|
||||
});
|
||||
return [`${nameStr}: ${similarTypes.join(' | ')}`, nameStr, typeStr];
|
||||
})
|
||||
.map(([full]): string => full)
|
||||
.join(', ');
|
||||
|
||||
return createDocComments(documentation).map((d): string => indent(6)(d)).join('\n') +
|
||||
indent(6)(`${stringCamelCase(name.toString())}: AugmentedSubmittable<(${params.map(([full]): string => full).join(', ')}) => SubmittableExtrinsic<ApiType>>;`);
|
||||
return createDocComments(6, documentation) +
|
||||
indent(6)(`${stringCamelCase(name.toString())}: AugmentedSubmittable<(${params}) => SubmittableExtrinsic<ApiType>>;`);
|
||||
}))
|
||||
.concat([indent(4)('};')]);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function generateForMeta (registry: Registry, meta: Metadata, dest: string, extraTypes: Record<string, Record<string, object>>): void {
|
||||
function generateForMeta (registry: Registry, meta: Metadata, dest: string, extraTypes: Record<string, Record<string, object>>, isStrict: boolean): void {
|
||||
writeFile(dest, (): string => {
|
||||
const allTypes: Record<string, Record<string, object>> = { '@polkadot/types/interfaces': defaultDefs, ...extraTypes };
|
||||
const imports = createImports(allTypes);
|
||||
@@ -68,7 +71,7 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
|
||||
return Object.entries(obj).reduce((defs, [key, value]) => ({ ...defs, [key]: value }), defs);
|
||||
}, {});
|
||||
const body = meta.asLatest.modules.reduce((acc, mod): string[] => {
|
||||
return acc.concat(generateModule(registry, allDefs, mod, imports));
|
||||
return acc.concat(generateModule(registry, allDefs, mod, imports, isStrict));
|
||||
}, [] as string[]);
|
||||
const header = createImportCode(HEADER, imports, [
|
||||
...Object.keys(imports.localTypes).map((moduleName): { file: string; types: string[] } => ({
|
||||
@@ -96,8 +99,8 @@ function generateForMeta (registry: Registry, meta: Metadata, dest: string, extr
|
||||
|
||||
// Call `generateForMeta()` with current static metadata
|
||||
/** @internal */
|
||||
export default function generateTx (dest = 'packages/api/src/types/augment/tx.ts', data = staticData, extraTypes: Record<string, Record<string, object>> = {}): void {
|
||||
export default function generateTx (dest = 'packages/api/src/types/augment/tx.ts', data = staticData, extraTypes: Record<string, Record<string, object>> = {}, isStrict = false): void {
|
||||
const registry = new TypeRegistry();
|
||||
|
||||
return generateForMeta(registry, new Metadata(registry, data), dest, extraTypes);
|
||||
return generateForMeta(registry, new Metadata(registry, data), dest, extraTypes, isStrict);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ const generateConst = require('./generate/consts').default;
|
||||
const generateQuery = require('./generate/query').default;
|
||||
const generateTx = require('./generate/tx').default;
|
||||
|
||||
const { endpoint, output, package } = yargs.strict().options({
|
||||
const { endpoint, output, package, strict: isStrict } = yargs.strict().options({
|
||||
endpoint: {
|
||||
description: 'The endpoint to connect to, e.g. wss://kusama-rpc.polkadot.io or relative file to JSON output',
|
||||
type: 'string',
|
||||
@@ -40,6 +40,10 @@ const { endpoint, output, package } = yargs.strict().options({
|
||||
},
|
||||
package: {
|
||||
description: 'Optional package in output location (for extra definitions)'
|
||||
},
|
||||
strinct: {
|
||||
description: 'Turns on stirct mode, not outputting genric versions',
|
||||
type: 'boolean'
|
||||
}
|
||||
}).argv;
|
||||
let websocket = null;
|
||||
@@ -51,9 +55,9 @@ function generate (metaHex) {
|
||||
? { [package]: require(path.join(process.cwd(), output, 'definitions')) }
|
||||
: {};
|
||||
|
||||
generateConst(path.join(process.cwd(), output, 'augment.consts.ts'), metaHex, extraTypes);
|
||||
generateQuery(path.join(process.cwd(), output, 'augment.query.ts'), metaHex, extraTypes);
|
||||
generateTx(path.join(process.cwd(), output, 'augment.tx.ts'), metaHex, extraTypes);
|
||||
generateConst(path.join(process.cwd(), output, 'augment.consts.ts'), metaHex, extraTypes, isStrict);
|
||||
generateQuery(path.join(process.cwd(), output, 'augment.query.ts'), metaHex, extraTypes, isStrict);
|
||||
generateTx(path.join(process.cwd(), output, 'augment.tx.ts'), metaHex, extraTypes, isStrict);
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import { TypeDef, TypeDefInfo } from '../../codec/types';
|
||||
import { Constructor, Registry } from '../../types';
|
||||
|
||||
import { stringLowerFirst } from '@polkadot/util';
|
||||
import { isChildClass, isCompactEncodable } from './class';
|
||||
import { ClassOf, ClassOfUnsafe, getTypeDef } from '../../codec/create';
|
||||
import AbstractInt from '../../codec/AbstractInt';
|
||||
@@ -13,6 +14,7 @@ import Enum from '../../codec/Enum';
|
||||
import Option from '../../codec/Option';
|
||||
import Struct from '../../codec/Struct';
|
||||
import Vec from '../../codec/Vec';
|
||||
import Null from '../../primitive/Null';
|
||||
import Vote, { convictionNames as _voteConvictions } from '../../primitive/Generic/Vote';
|
||||
import * as primitiveClasses from '../../primitive';
|
||||
import { formatType } from './formatting';
|
||||
@@ -94,19 +96,27 @@ export function getSimilarTypes (definitions: object, registry: Registry, type:
|
||||
const e = new Clazz(registry) as Enum;
|
||||
|
||||
if (e.isBasic) {
|
||||
possibleTypes.push(arrayToStrType(e.defKeys), 'number', 'Uint8Array');
|
||||
possibleTypes.push(arrayToStrType(e.defKeys), 'number');
|
||||
} else {
|
||||
// TODO Handle this more gracefully (expand actual options)
|
||||
possibleTypes.push('object', 'number', 'Uint8Array', 'string');
|
||||
// TODO We don't really want any here, these should be expanded
|
||||
possibleTypes.push(...e.defKeys.map((key): string => `{ ${stringLowerFirst(key)}: any }`), 'string');
|
||||
}
|
||||
|
||||
possibleTypes.push('Uint8Array');
|
||||
} else if (isChildClass(AbstractInt as unknown as Constructor<any>, Clazz) || isChildClass(Compact, Clazz)) {
|
||||
possibleTypes.push('AnyNumber', 'Uint8Array');
|
||||
} else if (isChildClass(ClassOf(registry, 'Address'), Clazz)) {
|
||||
possibleTypes.push('string', 'AccountId', 'AccountIndex', 'Uint8Array');
|
||||
} else if (isChildClass(ClassOf(registry, 'bool'), Clazz)) {
|
||||
possibleTypes.push('boolean', 'Uint8Array');
|
||||
} else if (isChildClass(Null, Clazz)) {
|
||||
possibleTypes.push('null');
|
||||
} else if (isChildClass(Struct, Clazz)) {
|
||||
possibleTypes.push('object', 'string', 'Uint8Array');
|
||||
// TODO We don't really want any here, these should be expanded
|
||||
const s = new Clazz(registry) as Struct;
|
||||
const obj = s.defKeys.map((key): string => `${key}?: any`).join('; ');
|
||||
|
||||
possibleTypes.push(`{ ${obj} }`, 'string', 'Uint8Array');
|
||||
} else if (isChildClass(Option, Clazz)) {
|
||||
// TODO inspect container
|
||||
possibleTypes.push('null', 'object', 'string', 'Uint8Array');
|
||||
|
||||
@@ -4,15 +4,20 @@
|
||||
|
||||
import { Text } from '@polkadot/types';
|
||||
|
||||
type Arg = [Text | string, Text | string];
|
||||
import { indent } from './formatting';
|
||||
|
||||
export function createDocComments (docs: Text[], args: Arg[] = []): string[] {
|
||||
type AnyString = Text | string;
|
||||
type Arg = [AnyString, AnyString];
|
||||
|
||||
export function createDocComments (spaces: number, docs: AnyString[], args: Arg[] = []): string {
|
||||
const contents = [
|
||||
...docs.map((doc): string => doc.toString().trim()).filter((doc): boolean => !!doc).map((doc): string => ` * ${doc}`),
|
||||
...args.map(([name, type]): string => ` * @param ${name} ${type}`)
|
||||
];
|
||||
...docs.map((doc): string => doc.toString().trim()).filter((doc): boolean => !!doc),
|
||||
...args.map(([name, type]): string => `@param ${name} ${type}`)
|
||||
].map((d): string => ` * ${d}`);
|
||||
|
||||
return contents.length
|
||||
? ['/**', ...contents, ' **/\n']
|
||||
: [];
|
||||
.map((s): string => indent(spaces)(s))
|
||||
.join('\n')
|
||||
: '';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user