@devgrid/netron
Version:
A powerful TypeScript library for building distributed systems with event bus, streaming capabilities, and remote object invocation. Features WebSocket-based bidirectional communication between Node.js and browser environments, service discovery, and type
102 lines • 4.16 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Interface = void 0;
const reference_1 = require("./reference");
const stream_reference_1 = require("./stream-reference");
const predicates_1 = require("./predicates");
const INTERNAL_READ_PROPERTIES = ['$def', '$peer', 'waitForAssigned', '$pendingPromises', 'then'];
const INTERNAL_WRITE_PROPERTIES = ['$def', '$peer'];
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: Service definition is missing');
}
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}' is not defined in the service interface`);
}
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: Service definition is missing');
}
if (!$def?.meta.properties[prop]) {
throw new Error(`Unknown member: '${prop}' is not defined in the service interface`);
}
if (this.$def?.meta.properties[prop]?.readonly) {
throw new Error(`Property is not writable: '${prop}' is marked as readonly`);
}
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 ((0, predicates_1.isServiceInterface)(value)) {
if (!value.$def) {
throw new Error('Service interface is not valid: Missing service definition');
}
return new reference_1.Reference(value.$def.id);
}
else if ((0, predicates_1.isNetronService)(value)) {
throw Error('Unsupported value type: Direct service exposure is not yet implemented');
}
else if ((0, predicates_1.isNetronStream)(value)) {
return stream_reference_1.StreamReference.from(value);
}
return value;
}
$processArgs(args) {
return args.map((arg) => this.$processValue(arg));
}
static create(def, peer) {
return new Interface(def, peer);
}
}
exports.Interface = Interface;
//# sourceMappingURL=interface.js.map