Lazy decoration (part 9, rpc) (#4165)
* Lazy decoration (part 9, rpc) * Flatten * Cleanups (& bump dev, fix copy-to) * Only RPC methods are lazy * Decorate rpc-core lazily * Adjust import * Remove (now) invalid test
This commit is contained in:
@@ -7,12 +7,12 @@ import type { StorageKey, Vec } from '@polkadot/types';
|
||||
import type { Hash } from '@polkadot/types/interfaces';
|
||||
import type { AnyJson, Codec, DefinitionRpc, DefinitionRpcExt, DefinitionRpcSub, Registry } from '@polkadot/types/types';
|
||||
import type { Memoized } from '@polkadot/util/types';
|
||||
import type { RpcInterface, RpcInterfaceMethod } from './types';
|
||||
import type { RpcInterfaceMethod } from './types';
|
||||
|
||||
import { Observable, publishReplay, refCount } from 'rxjs';
|
||||
|
||||
import { rpcDefinitions } from '@polkadot/types';
|
||||
import { assert, hexToU8a, isFunction, isNull, isUndefined, logger, memoize, u8aToU8a } from '@polkadot/util';
|
||||
import { assert, hexToU8a, isFunction, isNull, isUndefined, lazyMethod, logger, memoize, objectSpread, u8aToU8a } from '@polkadot/util';
|
||||
|
||||
import { drr, refCountDelay } from './util';
|
||||
|
||||
@@ -141,44 +141,41 @@ export class RpcCore {
|
||||
});
|
||||
}
|
||||
|
||||
public addUserInterfaces<Section extends keyof RpcInterface> (userRpc: Record<string, Record<string, DefinitionRpc | DefinitionRpcSub>>): void {
|
||||
public addUserInterfaces (userRpc: Record<string, Record<string, DefinitionRpc | DefinitionRpcSub>>): void {
|
||||
// add any extra user-defined sections
|
||||
this.sections.push(...Object.keys(userRpc).filter((key) => !this.sections.includes(key)));
|
||||
this.sections.push(...Object.keys(userRpc).filter((k) => !this.sections.includes(k)));
|
||||
|
||||
// decorate the sections with base and user methods
|
||||
this.sections.forEach((sectionName): void => {
|
||||
(this as Record<string, unknown>)[sectionName as Section] ||= {};
|
||||
for (let s = 0; s < this.sections.length; s++) {
|
||||
const section = this.sections[s];
|
||||
const defs = objectSpread<Record<string, DefinitionRpc | DefinitionRpcSub>>({}, rpcDefinitions[section as 'babe'], userRpc[section]);
|
||||
const methods = Object.keys(defs);
|
||||
|
||||
const section = (this as Record<string, unknown>)[sectionName as Section] as Record<string, unknown>;
|
||||
for (let m = 0; m < methods.length; m++) {
|
||||
const method = methods[m];
|
||||
const def = defs[method];
|
||||
|
||||
Object
|
||||
.entries({
|
||||
...this._createInterface(sectionName, rpcDefinitions[sectionName as 'babe'] || {}),
|
||||
...this._createInterface(sectionName, userRpc[sectionName] || {})
|
||||
})
|
||||
.forEach(([key, value]): void => {
|
||||
section[key] ||= value;
|
||||
});
|
||||
});
|
||||
if (!this.mapping.has(def.endpoint || `${section}_${method}`)) {
|
||||
if (!(this as Record<string, unknown>)[section]) {
|
||||
(this as Record<string, unknown>)[section] = {};
|
||||
}
|
||||
|
||||
lazyMethod(this[section as 'connect'], method, () =>
|
||||
this._createInterface(section, method, def)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _createInterface<Section extends keyof RpcInterface> (section: string, methods: Record<string, DefinitionRpc | DefinitionRpcSub>): RpcInterface[Section] {
|
||||
return Object
|
||||
.entries(methods)
|
||||
.filter(([method, { endpoint }]) => !this.mapping.has(endpoint || `${section}_${method}`))
|
||||
.reduce((exposed, [method, { endpoint }]): RpcInterface[Section] => {
|
||||
const def = methods[method];
|
||||
const isSubscription = !!(def as DefinitionRpcSub).pubsub;
|
||||
const jsonrpc = endpoint || `${section}_${method}`;
|
||||
private _createInterface (section: string, method: string, def: DefinitionRpc | DefinitionRpcSub): RpcInterfaceMethod {
|
||||
const isSubscription = !!(def as DefinitionRpcSub).pubsub;
|
||||
const jsonrpc = def.endpoint || `${section}_${method}`;
|
||||
|
||||
this.mapping.set(jsonrpc, { ...def, isSubscription, jsonrpc, method, section });
|
||||
this.mapping.set(jsonrpc, { ...def, isSubscription, jsonrpc, method, section });
|
||||
|
||||
(exposed as Record<string, unknown>)[method] = isSubscription
|
||||
? this._createMethodSubscribe(section, method, def as DefinitionRpcSub)
|
||||
: this._createMethodSend(section, method, def);
|
||||
|
||||
return exposed;
|
||||
}, {} as RpcInterface[Section]);
|
||||
return isSubscription
|
||||
? this._createMethodSubscribe(section, method, def as DefinitionRpcSub)
|
||||
: this._createMethodSend(section, method, def);
|
||||
}
|
||||
|
||||
private _memomize (creator: <T> (isScale: boolean) => (...values: unknown[]) => Observable<T>, def: DefinitionRpc): Memoized<RpcInterfaceMethod> {
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
// Copyright 2017-2021 @polkadot/rpc-core authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { RpcInterface } from '@polkadot/rpc-core/types.jsonrpc';
|
||||
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import { MockProvider } from '@polkadot/rpc-provider/mock';
|
||||
import { TypeRegistry } from '@polkadot/types/create';
|
||||
|
||||
@@ -25,21 +22,6 @@ describe('replay', (): void => {
|
||||
await provider.disconnect();
|
||||
});
|
||||
|
||||
it('subscribes via the rpc section', (done): void => {
|
||||
// we don't honor types or number of params here
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
(rpc.chain as any).getBlockHash = jest.fn((): Observable<number> => of(1));
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
(rpc.chain as any).getBlockHash(123, false).subscribe((): void => {
|
||||
expect(
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
rpc.chain.getBlockHash
|
||||
).toHaveBeenCalledWith(123, false);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the observable value', (done): void => {
|
||||
rpc.system.chain().subscribe((value: any): void => {
|
||||
if (value) {
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
// FIXME, this whole file needs to move to API
|
||||
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { AnyFunction } from '@polkadot/types/types';
|
||||
import type { AnyFunction, DefinitionRpc } from '@polkadot/types/types';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface RpcInterface {}
|
||||
|
||||
export type AugmentedRpc<F extends AnyFunction> = F & {
|
||||
raw: <T> (...params: Parameters<F>) => Observable<T>;
|
||||
meta: DefinitionRpc;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user