{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n  hasInjectionContext,\n  inject,\n  provide,\n  withContext,\n} from '@andrew_l/context';\nimport {\n  type AnyFunction,\n  type OverwriteWith,\n  isFunction,\n} from '@andrew_l/toolkit';\n\ntype ServiceActorInternal = {\n  traceId: unknown;\n  actorId: unknown;\n  actorType: unknown;\n  [SYM_API]: Record<PropertyKey, Function>;\n  [SYM_MARKER]: boolean;\n  [SYM_RAW]: any;\n  [SYM_DATA]: Record<PropertyKey, unknown>;\n};\n\nexport type AnyServiceActor = {\n  traceId: any;\n  actorId: any;\n  actorType: any;\n  [x: PropertyKey]: any;\n};\n\nexport type ServiceActorData<T extends Record<PropertyKey, any> = {}> =\n  OverwriteWith<\n    {\n      traceId: string;\n      actorId: string | null;\n      actorType: 'unknown' | string;\n    },\n    T\n  >;\n\nexport type ServiceActor<T extends Record<PropertyKey, any> = {}> =\n  ServiceActorData<T> & {\n    assign(params: Partial<ServiceActorData<T>>): ServiceActor<T>;\n  };\n\nvar SYM_MARKER = Symbol();\nvar SYM_RAW = Symbol();\nvar SYM_DATA = Symbol();\nvar SYM_API = Symbol();\n\n/**\n * Create service actor hooks\n *\n * @example\n * const { use: useServiceActor, with: withServiceActor } = serviceActor(() => ({\n *   actorType: 'http-request',\n *   ipAddress: '',\n *  }));\n *\n * app.use((ctx, next) => {\n *   return withServiceActor(\n *     {\n *       traceId: ctx.headers['x-request-id'],\n *       ipAddress: ctx.headers['x-forwarded-for'],\n *     },\n *     next,\n *   );\n * });\n *\n * app.get('/', () => {\n *   const actor = useServiceActor();\n *\n *   // { traceId: 'req_35123', actorId: null, actorType: 'http-request', ipAddress: '::' }\n *   console.log(actor);\n * });\n *\n * @group Main\n */\nexport function serviceActor<T extends Record<PropertyKey, any> = {}>(\n  factory?: () => T,\n): {\n  /**\n   * Wrap a function to execute it with service actor providers\n   */\n  with: <Fn extends AnyFunction>(\n    fn: Fn,\n    params?: Partial<ServiceActor<T>>,\n  ) => Fn;\n\n  /**\n   * Returns the service actor instance from the current context.\n   */\n  inject: () => ServiceActor<T> | undefined;\n\n  /**\n   * Returns the service actor instance from the context, or creates and binds a new instance if none exists.\n   */\n  use: () => ServiceActor<T>;\n} {\n  var injectKey = Symbol();\n  var idSeq = 0;\n\n  var createActor = (): AnyServiceActor => {\n    var actor = createServiceActor();\n\n    actor.traceId = `trace-${++idSeq}`;\n\n    if (factory) {\n      actor.assign(factory());\n    }\n\n    return actor;\n  };\n\n  var withHook = <Fn extends AnyFunction>(\n    fn: Fn,\n    params?: Partial<ServiceActor<T>>,\n  ): Fn => {\n    return withContext(function (this: any, ...args: any[]) {\n      var parentActor = inject<ServiceActor>(injectKey);\n      var actor = createActor();\n\n      if (parentActor) {\n        actor.assign(parentActor);\n      }\n\n      if (params) {\n        actor.assign(params);\n      }\n\n      provide(injectKey, actor);\n\n      return fn.apply(this, args);\n    }) as Fn;\n  };\n\n  var injectHook = (): AnyServiceActor | undefined => {\n    return hasInjectionContext() ? inject<ServiceActor>(injectKey) : undefined;\n  };\n\n  var useHok = (): AnyServiceActor => {\n    var _actor: AnyServiceActor | undefined;\n\n    if (!hasInjectionContext()) {\n      _actor = createActor();\n      provide(injectKey, _actor, true);\n\n      return _actor;\n    }\n\n    // check for existed\n    _actor = inject<AnyServiceActor>(injectKey);\n\n    if (_actor) return _actor;\n\n    _actor = createActor();\n    provide(injectKey, _actor);\n\n    return _actor;\n  };\n\n  return { with: withHook, use: useHok as any, inject: injectHook as any };\n}\n\nfunction createServiceActor(): ServiceActor {\n  var actor: ServiceActorInternal = {\n    traceId: '',\n    actorId: null,\n    actorType: 'unknown',\n    [SYM_API]: {\n      assign,\n    },\n    [SYM_DATA]: {},\n    [SYM_RAW]: null,\n    [SYM_MARKER]: true,\n  };\n\n  var reservedKeys = new Set(Object.keys(actor));\n\n  actor[SYM_RAW] = actor;\n\n  var newProxy = new Proxy(actor[SYM_DATA], {\n    defineProperty(target, key, value) {\n      if (key in actor) {\n        (actor as any)[key] = value;\n      } else {\n        target[key] = value;\n      }\n\n      return true;\n    },\n    deleteProperty(target, key) {\n      if (key in actor) {\n        delete (actor as any)[key];\n      } else {\n        delete target[key];\n      }\n\n      return true;\n    },\n    has(target, key) {\n      return key in actor || key in target;\n    },\n    ownKeys(target) {\n      return [...reservedKeys, ...Object.keys(target)];\n    },\n    set: function (target, key, value) {\n      if (key in actor[SYM_API]) return false;\n\n      if (key in actor) {\n        Reflect.set(actor, key, value);\n      } else if (isFunction(value)) {\n        Reflect.set(actor[SYM_API], key, value);\n      } else {\n        Reflect.set(target, key, value);\n      }\n\n      return true;\n    },\n    get: (target, key) => {\n      var value: any;\n\n      if (key in actor) {\n        value = Reflect.get(actor, key, value);\n      } else if (key in actor[SYM_API]) {\n        value = Reflect.get(actor[SYM_API], key, value).bind(newProxy);\n      } else {\n        value = Reflect.get(target, key);\n      }\n\n      return value;\n    },\n    getOwnPropertyDescriptor(k) {\n      return {\n        enumerable: true,\n        configurable: true,\n      };\n    },\n  });\n\n  return newProxy as ServiceActor;\n}\n\nfunction assign(this: ServiceActor, params: Record<any, any>) {\n  Object.assign(this, params);\n  return this;\n}\n"],"mappings":";;AA4CA,IAAI,aAAa,OAAO;AACxB,IAAI,UAAU,OAAO;AACrB,IAAI,WAAW,OAAO;AACtB,IAAI,UAAU,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BrB,OAAgB;EAqBd;EACA,SAAI,OAAQ,SAAA;EAEZ,IAAI,QAAA,OAAA;EACF,SAAI,YAAQ;EAEZ,QAAM,WAAU,MAAS;EAEzB,OAAI;;CAKN,OAAA;EAEA,MAAI;EAIF,KAAA;UACM;;;SAOA,qBACW;KAGf,QAAQ;WAED;EACT,SAAC;EACH,WAAA;GAEA,UAAI,EAAA,OAAA;GACF,WAAO,CAAA;GACT,UAAA;GAEA,aAAI;;KAGF,eAAK,IAAA,IAAoB,OAAG,KAAA,KAAA,CAAA;OAC1B,WAAS;KACT,WAAQ,IAAA,MAAW,MAAQ,WAAI;iBAExB,QAAA,KAAA,OAAA;GACT,IAAA,OAAA,OAAA,MAAA,OAAA;QAGA,OAAS,OAAwB;GAEjC,OAAI;EAEJ;EACA,eAAQ,QAAW,KAAM;GAEzB,IAAA,OAAO,OAAA,OAAA,MAAA;QACT,OAAA,OAAA;GAEA,OAAO;EAAE;EAAgB,IAAA,QAAK,KAAA;GAAe,OAAQ,OAAA,SAAA,OAAA;EAAkB;EACzE,QAAA,QAAA;GAEA,OAAS,CAAA,GAAA,cAAA,GAAmC,OAAA,KAAA,MAAA,CAAA;EAC1C;EACE,KAAA,SAAS,QAAA,KAAA,OAAA;GACT,IAAA,OAAS,MAAA,UAAA,OAAA;GACT,IAAA,OAAW,OAAA,QAAA,IAAA,OAAA,KAAA,KAAA;QACV,IAAA,WAED,KAAA,GAAA,QAAA,IAAA,MAAA,UAAA,KAAA,KAAA;QACC,QAAY,IAAA,QAAA,KAAA,KAAA;GACZ,OAAA;;EAEH,MAAA,QAAA,QAAA;GAEA,IAAI;GAEJ,IAAM,OAAA,OAAW,QAAA,QAAA,IAAA,OAAA,KAAA,KAAA;QAEb,IAAA,OAAW,MAAI,UAAY,QAAW,QAAA,IAAA,MAAA,UAAA,KAAA,KAAA,CAAA,CAAA,KAAA,QAAA;QACxC,QAAA,QAAe,IAAQ,QAAK,GAAO;GACjC,OAAI;;2BAMG,GAAA;GACT,OAAA;IACA,YAAA;IACE,cAAW;;;EAOb;QACI;;SAEJ,OAAA,QAAA;QACA,OAAQ,MAAQ,MAAA;QACd;;SAGI"}