UNPKG

@andrew_l/service-actor

Version:

Forget about passing data like trace IDs between functions.

106 lines (105 loc) 2.72 kB
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