{"version":3,"file":"async-context.mjs","names":[],"sources":["../../src/browser/async-context.ts"],"sourcesContent":["/**\n * Browser-safe fallback for AsyncLocalStorage.\n *\n * Uses a simple last-set-wins store. This is correct for browser usage\n * where CLI execution is single-threaded/sequential.\n *\n * Swapped in via browserAlias in tsdown.config.mjs.\n */\n\nexport interface ForgeContextData {\n  args: Record<string, unknown>;\n  commandChain: string[];\n  commandIdChain: string[];\n  providers: Map<string, unknown>;\n  providerFactories: Map<string, { factory: Function; lifetime: string }>;\n  handlerPhase: boolean;\n  /** Keys whose factories are currently being resolved — used for cycle detection */\n  resolving: Set<string>;\n}\n\nlet currentStore: ForgeContextData | undefined;\nlet activeRuns = 0;\nlet warnedAboutConcurrency = false;\n\n/**\n * Emit a one-shot warning when a second `forge()`/`sdk()` call starts while\n * another is still on the stack. Real async-boundary isolation needs\n * `AsyncLocalStorage`, which browsers don't provide — this store is just a\n * last-set-wins global. The warning exists so misuse fails loudly instead of\n * silently leaking providers between concurrent executions.\n */\nfunction warnOnceAboutConcurrency(): void {\n  if (warnedAboutConcurrency) return;\n  warnedAboutConcurrency = true;\n  // eslint-disable-next-line no-console\n  console.warn(\n    '[cli-forge] Concurrent forge()/sdk() execution detected in the browser. ' +\n      'The browser build uses a last-set-wins context store because ' +\n      'AsyncLocalStorage is unavailable, so DI providers may leak between ' +\n      'overlapping executions. See docs: \"DI and the browser runtime\".'\n  );\n}\n\nexport const contextStorage = {\n  run<T>(\n    store: ForgeContextData,\n    fn: (...args: unknown[]) => T,\n    ...args: unknown[]\n  ): T {\n    if (activeRuns > 0) {\n      warnOnceAboutConcurrency();\n    }\n    const prev = currentStore;\n    currentStore = store;\n    activeRuns++;\n    try {\n      return fn(...args);\n    } finally {\n      currentStore = prev;\n      activeRuns--;\n    }\n  },\n  getStore(): ForgeContextData | undefined {\n    return currentStore;\n  },\n  enterWith(store: ForgeContextData | undefined): void {\n    currentStore = store;\n  },\n};\n"],"mappings":";AAoBA,IAAI;AACJ,IAAI,aAAa;AACjB,IAAI,yBAAyB;;;;;;;;AAS7B,SAAS,2BAAiC;AACxC,KAAI,uBAAwB;AAC5B,0BAAyB;AAEzB,SAAQ,KACN,4QAID;;AAGH,MAAa,iBAAiB;CAC5B,IACE,OACA,IACA,GAAG,MACA;AACH,MAAI,aAAa,EACf,2BAA0B;EAE5B,MAAM,OAAO;AACb,iBAAe;AACf;AACA,MAAI;AACF,UAAO,GAAG,GAAG,KAAK;YACV;AACR,kBAAe;AACf;;;CAGJ,WAAyC;AACvC,SAAO;;CAET,UAAU,OAA2C;AACnD,iBAAe;;CAElB"}