@andrew_l/service-actor
Version:
Forget about passing data like trace IDs between functions.
106 lines (105 loc) • 2.72 kB
JavaScript
import { hasInjectionContext, inject, provide, withContext } from "@andrew_l/context";
import { isFunction } from "@andrew_l/toolkit";
var SYM_MARKER = Symbol();
var SYM_RAW = Symbol();
var SYM_DATA = Symbol();
var SYM_API = Symbol();
function serviceActor(factory) {
var injectKey = Symbol();
var idSeq = 0;
var createActor = () => {
var actor = createServiceActor();
actor.traceId = `trace-${++idSeq}`;
if (factory) actor.assign(factory());
return actor;
};
var withHook = (fn, params) => {
return withContext(function(...args) {
var parentActor = inject(injectKey);
var actor = createActor();
if (parentActor) actor.assign(parentActor);
if (params) actor.assign(params);
provide(injectKey, actor);
return fn.apply(this, args);
});
};
var injectHook = () => {
return hasInjectionContext() ? inject(injectKey) : void 0;
};
var useHok = () => {
var _actor;
if (!hasInjectionContext()) {
_actor = createActor();
provide(injectKey, _actor, true);
return _actor;
}
_actor = inject(injectKey);
if (_actor) return _actor;
_actor = createActor();
provide(injectKey, _actor);
return _actor;
};
return {
with: withHook,
use: useHok,
inject: injectHook
};
}
function createServiceActor() {
var actor = {
traceId: "",
actorId: null,
actorType: "unknown",
[SYM_API]: { assign },
[SYM_DATA]: {},
[SYM_RAW]: null,
[SYM_MARKER]: true
};
var reservedKeys = new Set(Object.keys(actor));
actor[SYM_RAW] = actor;
var newProxy = new Proxy(actor[SYM_DATA], {
defineProperty(target, key, value) {
if (key in actor) actor[key] = value;
else target[key] = value;
return true;
},
deleteProperty(target, key) {
if (key in actor) delete actor[key];
else delete target[key];
return true;
},
has(target, key) {
return key in actor || key in target;
},
ownKeys(target) {
return [...reservedKeys, ...Object.keys(target)];
},
set: function(target, key, value) {
if (key in actor[SYM_API]) return false;
if (key in actor) Reflect.set(actor, key, value);
else if (isFunction(value)) Reflect.set(actor[SYM_API], key, value);
else Reflect.set(target, key, value);
return true;
},
get: (target, key) => {
var value;
if (key in actor) value = Reflect.get(actor, key, value);
else if (key in actor[SYM_API]) value = Reflect.get(actor[SYM_API], key, value).bind(newProxy);
else value = Reflect.get(target, key);
return value;
},
getOwnPropertyDescriptor(k) {
return {
enumerable: true,
configurable: true
};
}
});
return newProxy;
}
function assign(params) {
Object.assign(this, params);
return this;
}
export { serviceActor };
//# sourceMappingURL=index.mjs.map