@polkadot/api
Version:
Promise and RxJS wrappers around the Polkadot JS RPC
100 lines (77 loc) • 3.29 kB
JavaScript
// Copyright 2017-2022 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { lazyMethod, logger, objectClear } from '@polkadot/util';
const l = logger('api/augment');
function logLength(type, values, and = []) {
return values.length ? ` ${values.length} ${type}${and.length ? ' and' : ''}` : '';
}
function logValues(type, values) {
return values.length ? `\n\t${type.padStart(7)}: ${values.sort().join(', ')}` : '';
} // log details to console
function warn(prefix, type, [added, removed]) {
if (added.length || removed.length) {
l.warn(`api.${prefix}: Found${logLength('added', added, removed)}${logLength('removed', removed)} ${type}:${logValues('added', added)}${logValues('removed', removed)}`);
}
}
function findSectionExcludes(a, b) {
return a.filter(s => !b.includes(s));
}
function findSectionIncludes(a, b) {
return a.filter(s => b.includes(s));
}
function extractSections(src, dst) {
const srcSections = Object.keys(src);
const dstSections = Object.keys(dst);
return [findSectionExcludes(srcSections, dstSections), findSectionExcludes(dstSections, srcSections)];
}
function findMethodExcludes(src, dst) {
const srcSections = Object.keys(src);
const dstSections = findSectionIncludes(Object.keys(dst), srcSections);
const excludes = [];
for (let s = 0; s < dstSections.length; s++) {
const section = dstSections[s];
const srcMethods = Object.keys(src[section]);
const dstMethods = Object.keys(dst[section]);
excludes.push(...dstMethods.filter(m => !srcMethods.includes(m)).map(m => `${section}.${m}`));
}
return excludes;
}
function extractMethods(src, dst) {
return [findMethodExcludes(dst, src), findMethodExcludes(src, dst)];
}
function lazySection(src, dst) {
const creator = m => src[m];
const methods = Object.keys(src);
for (let i = 0; i < methods.length; i++) {
const method = methods[i]; // We use hasOwnproperty here to only check for the existence of the key,
// instead of reading dst[section][method] which will evaluate when already
// set as a lazy value previously
if (!Object.prototype.hasOwnProperty.call(dst, method)) {
lazyMethod(dst, method, creator);
}
}
}
/**
* @description Takes a decorated api section (e.g. api.tx) and augment it with the details. It does not override what is
* already available, but rather just adds new missing items into the result object.
* @internal
*/
export function augmentObject(prefix, src, dst, fromEmpty = false) {
fromEmpty && objectClear(dst); // NOTE: This part is slightly problematic since it will get the
// values for at least all the sections and the names of the methods
// (Since methods won't be decorated before lazy, this _may_ be ok)
if (prefix && Object.keys(dst).length) {
warn(prefix, 'modules', extractSections(src, dst));
warn(prefix, 'calls', extractMethods(src, dst));
}
const sections = Object.keys(src);
for (let i = 0; i < sections.length; i++) {
const section = sections[i]; // We don't set here with a lazy interface, we decorate based
// on the top-level structure (this bypasses adding lazy onto lazy)
if (!dst[section]) {
dst[section] = {};
}
lazySection(src[section], dst[section]);
}
return dst;
}