{"version":3,"file":"ambientLocale.cjs","names":["getServerContext","IntlayerServer","createSuspendingReader","getLocale"],"sources":["../../../src/server/ambientLocale.ts"],"sourcesContent":["import { registerAsyncAmbientLocaleResolver } from '@intlayer/core/interpreter';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { getServerContext, IntlayerServer } from 'react-intlayer/server';\nimport { getLocale } from './getLocale';\nimport { createSuspendingReader } from './suspendingReader';\n\n/**\n * Whether the call site already carries a locale — either a plain locale\n * argument or a selector object with an explicit `locale` field.\n */\nconst hasExplicitLocale = (localeOrSelector?: unknown): boolean =>\n  typeof localeOrSelector === 'string' ||\n  (typeof localeOrSelector === 'object' &&\n    localeOrSelector !== null &&\n    Boolean((localeOrSelector as { locale?: unknown }).locale));\n\n/**\n * Whether the request-derived locale is worth reading at all.\n *\n * The base hooks in `react-intlayer/server` already prefer, in order, the\n * locale passed at the call site and the request-scoped server context seeded\n * by `IntlayerProvider`; they only fall back to the third argument these\n * helpers produce. Reading request storage means calling `headers()` /\n * `cookies()`, which opts the route into dynamic rendering — so it must stay\n * behind both of those, and never run when either already answers.\n */\nconst needsRequestLocale = (localeOrSelector?: unknown): boolean =>\n  !hasExplicitLocale(localeOrSelector) && !getServerContext(IntlayerServer);\n\n/**\n * Reads the locale carried by the request: the `x-intlayer-locale` header set\n * by the intlayer proxy, then the locale cookie, then `accept-language`.\n *\n * Errors are not swallowed — during prerendering Next.js relies on the throw\n * from `headers()` to mark the route dynamic.\n */\nconst readStoredLocale = createSuspendingReader<Locale>(getLocale);\n\n/**\n * Resolves after one macrotask.\n *\n * Next.js renders a page concurrently with its layout, and the layout usually\n * awaits `params` before `IntlayerProvider` renders and seeds the server\n * context. A synchronous page therefore reads the context before it is seeded.\n * Yielding once lets the provider run first, so a full render (including the\n * build-time prerender) never reaches request storage and stays static.\n */\nconst yieldToProvider = (): Promise<true> =>\n  new Promise((resolve) => setTimeout(() => resolve(true), 0));\n\nconst waitForProvider = createSuspendingReader<true>(yieldToProvider);\n\n/**\n * Fallback locale for the synchronous server hooks, so a page does not need a\n * provider of its own. Not a React hook despite suspending — it holds no\n * positional state, which is what lets it run conditionally (see\n * {@link createSuspendingReader}): on a client-side navigation that re-renders only the\n * page segment, the layout — and with it `IntlayerProvider` — does not re-run,\n * and the locale carried by the request takes over.\n *\n * On a context miss, first suspends once so a concurrently rendering provider\n * can seed the context, then suspends until the request storage resolves.\n * Returns `undefined` when the call site or the server context already carries\n * the locale.\n */\nexport const resolveFallbackLocale = (\n  localeOrSelector?: unknown\n): Locale | undefined => {\n  if (!needsRequestLocale(localeOrSelector)) return undefined;\n\n  waitForProvider();\n\n  return needsRequestLocale(localeOrSelector) ? readStoredLocale() : undefined;\n};\n\n/**\n * Asynchronous twin of {@link resolveFallbackLocale}, for the hooks that are\n * already async and can await the request storage instead of suspending on it.\n */\nexport const getFallbackLocale = async (\n  localeOrSelector?: unknown\n): Promise<Locale | undefined> => {\n  if (!needsRequestLocale(localeOrSelector)) return undefined;\n\n  await yieldToProvider();\n\n  return needsRequestLocale(localeOrSelector) ? await getLocale() : undefined;\n};\n\n/**\n * Full ambient locale for the server APIs that take a plain locale argument\n * (or none at all): call site → server context → locale carried by the\n * request.\n *\n * {@link resolveFallbackLocale} only yields the last rung, because the base hooks\n * in `react-intlayer/server` consult the first two themselves. The APIs\n * reimplemented here have no such fallback slot, so they need the resolved\n * value.\n */\nexport const resolveAmbientLocale = (\n  locale?: LocalesValues\n): LocalesValues | undefined =>\n  locale ??\n  getServerContext<LocalesValues>(IntlayerServer) ??\n  resolveFallbackLocale(locale);\n\n/**\n * Whether `error` is one Next.js throws for control flow (dynamic usage,\n * postpone, bailout…) and must therefore reach the framework.\n */\nconst isNextControlFlowError = (error: unknown): boolean =>\n  typeof error === 'object' &&\n  error !== null &&\n  ('digest' in error || '$$typeof' in error);\n\n/**\n * Locale carried by the request, for `getIntlayerAsync` / `getDictionaryAsync`\n * calls without a locale. Read per request from the incoming headers and\n * cookies, never from shared module state.\n *\n * Outside of a request scope (e.g. `generateStaticParams`) the locale is\n * unknown rather than an error.\n */\nconst readRequestLocale = async (): Promise<Locale | undefined> => {\n  try {\n    return await getFallbackLocale();\n  } catch (error) {\n    if (isNextControlFlowError(error)) throw error;\n\n    return undefined;\n  }\n};\n\n/**\n * Lets the asynchronous core reads resolve to the request locale. Idempotent;\n * a no-op in the browser, where `next/headers` is unavailable.\n */\nexport const registerRequestLocaleResolver = (): void => {\n  if (typeof window !== 'undefined') return;\n\n  registerAsyncAmbientLocaleResolver(readRequestLocale);\n};\n\nregisterRequestLocaleResolver();\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,qBAAqB,qBACzB,OAAO,qBAAqB,YAC3B,OAAO,qBAAqB,YAC3B,qBAAqB,QACrB,QAAS,iBAA0C,MAAM;;;;;;;;;;;AAY7D,MAAM,sBAAsB,qBAC1B,CAAC,kBAAkB,gBAAgB,KAAK,KAACA,wCAAiBC,oCAAc;;;;;;;;AAS1E,MAAM,mBAAmBC,uDAA+BC,kCAAS;;;;;;;;;;AAWjE,MAAM,wBACJ,IAAI,SAAS,YAAY,iBAAiB,QAAQ,IAAI,GAAG,CAAC,CAAC;AAE7D,MAAM,kBAAkBD,uDAA6B,eAAe;;;;;;;;;;;;;;AAepE,MAAa,yBACX,qBACuB;CACvB,IAAI,CAAC,mBAAmB,gBAAgB,GAAG,OAAO;CAElD,gBAAgB;CAEhB,OAAO,mBAAmB,gBAAgB,IAAI,iBAAiB,IAAI;AACrE;;;;;AAMA,MAAa,oBAAoB,OAC/B,qBACgC;CAChC,IAAI,CAAC,mBAAmB,gBAAgB,GAAG,OAAO;CAElD,MAAM,gBAAgB;CAEtB,OAAO,mBAAmB,gBAAgB,IAAI,MAAMC,mCAAU,IAAI;AACpE;;;;;;;;;;;AAYA,MAAa,wBACX,WAEA,cACAH,wCAAgCC,oCAAc,KAC9C,sBAAsB,MAAM;;;;;AAM9B,MAAM,0BAA0B,UAC9B,OAAO,UAAU,YACjB,UAAU,SACT,YAAY,SAAS,cAAc;;;;;;;;;AAUtC,MAAM,oBAAoB,YAAyC;CACjE,IAAI;EACF,OAAO,MAAM,kBAAkB;CACjC,SAAS,OAAO;EACd,IAAI,uBAAuB,KAAK,GAAG,MAAM;EAEzC;CACF;AACF;;;;;AAMA,MAAa,sCAA4C;CACvD,IAAI,OAAO,WAAW,aAAa;CAEnC,mEAAmC,iBAAiB;AACtD;AAEA,8BAA8B"}