{"version":3,"file":"context.cjs","names":["contextValue: T | symbol"],"sources":["../src/context.ts"],"sourcesContent":["import type { CB, Maybe } from 'vest-utils';\nimport {\n  assign,\n  defaultTo,\n  invariant,\n  dynamicValue,\n  Nullable,\n} from 'vest-utils';\n\nconst USEX_DEFAULT_ERROR_MESSAGE = 'Not inside of a running context.';\nconst EMPTY_CONTEXT = Symbol();\n\n/**\n * Base context interface.\n */\nexport function createContext<T>(defaultContextValue?: T): CtxApi<T> {\n  let contextValue: T | symbol = EMPTY_CONTEXT;\n\n  return {\n    run,\n    use,\n    useX,\n  };\n\n  function use(): T {\n    return (isInsideContext() ? contextValue : defaultContextValue) as T;\n  }\n\n  function useX(errorMessage?: string): T {\n    invariant(\n      isInsideContext(),\n      defaultTo(errorMessage, USEX_DEFAULT_ERROR_MESSAGE),\n    );\n    return contextValue as T;\n  }\n\n  function run<R>(value: T, cb: () => R): R {\n    const parentContext = isInsideContext() ? use() : EMPTY_CONTEXT;\n\n    contextValue = value;\n\n    const res = cb();\n\n    contextValue = parentContext;\n    return res;\n  }\n\n  function isInsideContext(): boolean {\n    return contextValue !== EMPTY_CONTEXT;\n  }\n}\n\n/**\n * Cascading context - another implementation of context, that assumes the context value is an object.\n * When nesting context runs, the the values of the current layer merges with the layers above it.\n */\nexport function createCascade<T extends Record<string, unknown>>(\n  init?: (value: Partial<T>, parentContext: Maybe<T>) => Nullable<T>,\n): CtxCascadeApi<T> {\n  const ctx = createContext<T>();\n\n  return {\n    bind,\n    run,\n    use: ctx.use,\n    useX: ctx.useX,\n  };\n\n  function run<R>(value: Partial<T>, fn: () => R): R {\n    const parentContext = ctx.use();\n\n    const initResult = dynamicValue(init, value, parentContext) ?? value;\n\n    const out = assign({}, parentContext ? parentContext : {}, initResult) as T;\n\n    return ctx.run(Object.freeze(out), fn) as R;\n  }\n\n  function bind<Fn extends CB>(value: Partial<T>, fn: Fn) {\n    return function (...runTimeArgs: Parameters<Fn>) {\n      return run<ReturnType<Fn>>(value, function () {\n        return fn(...runTimeArgs);\n      });\n    } as Fn;\n  }\n}\n\ntype ContextConsumptionApi<T> = {\n  use: () => T;\n  useX: (errorMessage?: string) => T;\n};\n\nexport type CtxApi<T> = ContextConsumptionApi<T> & {\n  run: <R>(value: T, cb: () => R) => R;\n};\n\nexport type CtxCascadeApi<T> = ContextConsumptionApi<T> & {\n  run: <R>(value: Partial<T>, fn: () => R) => R;\n  bind: <Fn extends CB>(value: Partial<T>, fn: Fn) => Fn;\n};\n"],"mappings":";;;AASA,MAAM,6BAA6B;AACnC,MAAM,gBAAgB,QAAQ;;;;AAK9B,SAAgB,cAAiB,qBAAoC;CACnE,IAAIA,eAA2B;AAE/B,QAAO;EACL;EACA;EACA;EACD;CAED,SAAS,MAAS;AAChB,SAAQ,iBAAiB,GAAG,eAAe;;CAG7C,SAAS,KAAK,cAA0B;AACtC,4BACE,iBAAiB,4BACP,cAAc,2BAA2B,CACpD;AACD,SAAO;;CAGT,SAAS,IAAO,OAAU,IAAgB;EACxC,MAAM,gBAAgB,iBAAiB,GAAG,KAAK,GAAG;AAElD,iBAAe;EAEf,MAAM,MAAM,IAAI;AAEhB,iBAAe;AACf,SAAO;;CAGT,SAAS,kBAA2B;AAClC,SAAO,iBAAiB;;;;;;;AAQ5B,SAAgB,cACd,MACkB;CAClB,MAAM,MAAM,eAAkB;AAE9B,QAAO;EACL;EACA;EACA,KAAK,IAAI;EACT,MAAM,IAAI;EACX;CAED,SAAS,IAAO,OAAmB,IAAgB;EACjD,MAAM,gBAAgB,IAAI,KAAK;EAE/B,MAAM,0CAA0B,MAAM,OAAO,cAAc,IAAI;EAE/D,MAAM,6BAAa,EAAE,EAAE,gBAAgB,gBAAgB,EAAE,EAAE,WAAW;AAEtE,SAAO,IAAI,IAAI,OAAO,OAAO,IAAI,EAAE,GAAG;;CAGxC,SAAS,KAAoB,OAAmB,IAAQ;AACtD,SAAO,SAAU,GAAG,aAA6B;AAC/C,UAAO,IAAoB,OAAO,WAAY;AAC5C,WAAO,GAAG,GAAG,YAAY;KACzB"}