@devgrid/netron
Version:
Event bus, streams and remote object invocation.
94 lines • 3.56 kB
JavaScript
import { Reference } from './reference';
import { isNetronService, isServiceInterface } from './predicates';
const INTERNAL_READ_PROPERTIES = ['$def', '$peer', 'waitForAssigned', '$pendingPromises', 'then'];
const INTERNAL_WRITE_PROPERTIES = ['$def', '$peer'];
export class Interface {
constructor($def, $peer) {
this.$def = $def;
this.$peer = $peer;
this.$pendingPromises = new Map();
return new Proxy(this, {
get: (target, prop) => {
if (!this.$def) {
throw new Error('Invalid interface');
}
if (this.$def?.meta.methods[prop]) {
return async function (...args) {
const processedArgs = target.$processArgs(args);
return $peer?.call($def.id, prop, processedArgs);
};
}
if ($def?.meta.properties[prop]) {
return $peer?.get($def.id, prop);
}
if (!INTERNAL_READ_PROPERTIES.includes(prop)) {
throw new Error(`Unknown member: '${prop}'`);
}
return Reflect.get(target, prop);
},
set: (target, prop, value) => {
if (INTERNAL_WRITE_PROPERTIES.includes(prop)) {
Reflect.set(target, prop, value);
return true;
}
if (!this.$def) {
throw new Error('Invalid interface');
}
if (!$def?.meta.properties[prop]) {
throw new Error(`Unknown member: '${prop}'`);
}
if (this.$def?.meta.properties[prop]?.readonly) {
throw new Error(`Property is not writable: ${prop}`);
}
let resolvePromise = () => { };
let rejectPromise = () => { };
const promise = new Promise((resolve, reject) => {
resolvePromise = resolve;
rejectPromise = reject;
});
this.$pendingPromises.set(prop, promise);
(async () => {
try {
value = await this.$processValue(value);
await $peer?.set($def.id, prop, value);
resolvePromise();
this.$pendingPromises.delete(prop);
}
catch (error) {
rejectPromise(error);
}
})();
return true;
},
});
}
async waitForAssigned(prop) {
try {
const promise = this.$pendingPromises.get(prop);
return promise ? await promise : Promise.resolve();
}
catch (error) {
this.$pendingPromises.delete(prop);
return Promise.reject(error);
}
}
$processValue(value) {
if (isServiceInterface(value)) {
if (!value.$def) {
throw new Error('Service interface is not valid');
}
return new Reference(value.$def.id);
}
else if (isNetronService(value)) {
throw Error('Unsupported value type');
}
return value;
}
$processArgs(args) {
return args.map((arg) => this.$processValue(arg));
}
static create(def, peer) {
return new Interface(def, peer);
}
}
//# sourceMappingURL=interface.js.map