vinext 0.0.14 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/cli.js +21 -11
- package/dist/cli.js.map +1 -1
- package/dist/config/config-matchers.d.ts +4 -1
- package/dist/config/config-matchers.d.ts.map +1 -1
- package/dist/config/config-matchers.js +11 -1
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/next-config.d.ts +2 -0
- package/dist/config/next-config.d.ts.map +1 -1
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +2 -0
- package/dist/deploy.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -59
- package/dist/index.js.map +1 -1
- package/dist/server/app-dev-server.d.ts.map +1 -1
- package/dist/server/app-dev-server.js +29 -13
- package/dist/server/app-dev-server.js.map +1 -1
- package/dist/server/middleware.d.ts +23 -1
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +44 -10
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/prod-server.d.ts.map +1 -1
- package/dist/server/prod-server.js +30 -4
- package/dist/server/prod-server.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts.map +1 -1
- package/dist/shims/fetch-cache.js +73 -41
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/font-google-base.d.ts +68 -0
- package/dist/shims/font-google-base.d.ts.map +1 -0
- package/dist/shims/font-google-base.js +365 -0
- package/dist/shims/font-google-base.js.map +1 -0
- package/dist/shims/font-google.d.ts +2 -121
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.generated.d.ts +1925 -0
- package/dist/shims/font-google.generated.d.ts.map +1 -0
- package/dist/shims/font-google.generated.js +1928 -0
- package/dist/shims/font-google.generated.js.map +1 -0
- package/dist/shims/font-google.js +2 -386
- package/dist/shims/font-google.js.map +1 -1
- package/dist/shims/form.d.ts.map +1 -1
- package/dist/shims/form.js +32 -0
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/link.d.ts.map +1 -1
- package/dist/shims/link.js +11 -0
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/url-safety.d.ts +8 -0
- package/dist/shims/url-safety.d.ts.map +1 -0
- package/dist/shims/url-safety.js +16 -0
- package/dist/shims/url-safety.js.map +1 -0
- package/dist/utils/project.d.ts.map +1 -1
- package/dist/utils/project.js +4 -0
- package/dist/utils/project.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-cache.js","sourceRoot":"","sources":["../../src/shims/fetch-cache.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Extended fetch() with Next.js caching semantics.\n *\n * Patches `globalThis.fetch` during server rendering to support:\n *\n * fetch(url, { next: { revalidate: 60, tags: ['posts'] } })\n * fetch(url, { cache: 'force-cache' })\n * fetch(url, { cache: 'no-store' })\n *\n * Cached responses are stored via the pluggable CacheHandler, so\n * revalidateTag() and revalidatePath() invalidate fetch-level caches.\n *\n * Usage (in server entry):\n * import { withFetchCache, cleanupFetchCache } from './fetch-cache';\n * const cleanup = withFetchCache();\n * try { ... render ... } finally { cleanup(); }\n *\n * Or use the async helper:\n * await runWithFetchCache(async () => { ... render ... });\n */\n\nimport {\n getCacheHandler,\n type CachedFetchValue,\n} from \"./cache.js\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// ---------------------------------------------------------------------------\n// Cache key generation\n// ---------------------------------------------------------------------------\n\n/**\n * Headers excluded from the cache key. These are W3C trace context headers\n * that can break request caching and deduplication.\n * All other headers ARE included in the cache key, matching Next.js behavior.\n */\nconst HEADER_BLOCKLIST = [\"traceparent\", \"tracestate\"];\n\n// Cache key version — bump when changing the key format to bust stale entries\nconst CACHE_KEY_PREFIX = \"v1\";\n\n/**\n * Collect all headers from the request, excluding the blocklist.\n * Merges headers from both the Request object and the init object,\n * with init taking precedence (matching fetch() spec behavior).\n */\nfunction collectHeaders(input: string | URL | Request, init?: RequestInit): Record<string, string> {\n const merged: Record<string, string> = {};\n\n // Start with headers from Request object (if any)\n if (input instanceof Request && input.headers) {\n input.headers.forEach((v, k) => { merged[k] = v; });\n }\n\n // Override with headers from init (init takes precedence per fetch spec)\n if (init?.headers) {\n const headers = init.headers instanceof Headers\n ? init.headers\n : new Headers(init.headers as HeadersInit);\n headers.forEach((v, k) => { merged[k] = v; });\n }\n\n // Remove blocklisted headers\n for (const blocked of HEADER_BLOCKLIST) {\n delete merged[blocked];\n }\n\n return merged;\n}\n\n/**\n * Check whether a fetch request carries any per-user auth headers.\n * Used for the safety bypass (skip caching when auth headers are present\n * without an explicit cache opt-in).\n */\nconst AUTH_HEADERS = [\"authorization\", \"cookie\", \"x-api-key\"];\n\nfunction hasAuthHeaders(input: string | URL | Request, init?: RequestInit): boolean {\n const headers = collectHeaders(input, init);\n return AUTH_HEADERS.some((name) => name in headers);\n}\n\n/**\n * Serialize request body into string chunks for cache key inclusion.\n * Handles all body types: string, Uint8Array, ReadableStream, FormData, Blob.\n * Returns the serialized body chunks and optionally stashes the original body\n * on init as `_ogBody` so it can still be used after stream consumption.\n */\nasync function serializeBody(init?: RequestInit): Promise<string[]> {\n if (!init?.body) return [];\n\n const bodyChunks: string[] = [];\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n\n if (init.body instanceof Uint8Array) {\n bodyChunks.push(decoder.decode(init.body));\n (init as any)._ogBody = init.body;\n } else if (typeof (init.body as any).getReader === \"function\") {\n // ReadableStream\n const readableBody = init.body as ReadableStream<Uint8Array | string>;\n const chunks: Uint8Array[] = [];\n\n try {\n await readableBody.pipeTo(\n new WritableStream({\n write(chunk) {\n if (typeof chunk === \"string\") {\n chunks.push(encoder.encode(chunk));\n bodyChunks.push(chunk);\n } else {\n chunks.push(chunk);\n bodyChunks.push(decoder.decode(chunk, { stream: true }));\n }\n },\n })\n );\n // Flush the decoder\n bodyChunks.push(decoder.decode());\n\n // Reconstruct the body so it can still be sent\n const length = chunks.reduce((total, arr) => total + arr.length, 0);\n const arrayBuffer = new Uint8Array(length);\n let offset = 0;\n for (const chunk of chunks) {\n arrayBuffer.set(chunk, offset);\n offset += chunk.length;\n }\n (init as any)._ogBody = arrayBuffer;\n } catch (err) {\n console.error(\"[vinext] Problem reading body for cache key\", err);\n // Still reconstruct what we have so originalFetch doesn't get a spent stream\n if (chunks.length > 0) {\n const length = chunks.reduce((total, arr) => total + arr.length, 0);\n const partial = new Uint8Array(length);\n let offset = 0;\n for (const chunk of chunks) {\n partial.set(chunk, offset);\n offset += chunk.length;\n }\n (init as any)._ogBody = partial;\n }\n }\n } else if (init.body instanceof URLSearchParams) {\n // URLSearchParams — .toString() gives a stable serialization\n (init as any)._ogBody = init.body;\n bodyChunks.push(init.body.toString());\n } else if (typeof (init.body as any).keys === \"function\") {\n // FormData\n const formData = init.body as FormData;\n (init as any)._ogBody = init.body;\n for (const key of new Set(formData.keys())) {\n const values = formData.getAll(key);\n bodyChunks.push(\n `${key}=${(\n await Promise.all(\n values.map(async (val) => {\n if (typeof val === \"string\") return val;\n // Note: File name/type/lastModified are not included — only content.\n // Two Files with identical content but different names produce the same key.\n return await val.text();\n })\n )\n ).join(\",\")}`\n );\n }\n } else if (typeof (init.body as any).arrayBuffer === \"function\") {\n // Blob\n const blob = init.body as Blob;\n bodyChunks.push(await blob.text());\n const arrayBuffer = await blob.arrayBuffer();\n (init as any)._ogBody = new Blob([arrayBuffer], { type: blob.type });\n } else if (typeof init.body === \"string\") {\n bodyChunks.push(init.body);\n (init as any)._ogBody = init.body;\n }\n\n return bodyChunks;\n}\n\n/**\n * Generate a deterministic cache key from a fetch request.\n *\n * Matches Next.js behavior: the key is a SHA-256 hash of a JSON array\n * containing URL, method, all headers (minus blocklist), all RequestInit\n * options, and the serialized body.\n */\nasync function buildFetchCacheKey(input: string | URL | Request, init?: RequestInit & { next?: NextFetchOptions }): Promise<string> {\n let url: string;\n let method = \"GET\";\n\n if (typeof input === \"string\") {\n url = input;\n } else if (input instanceof URL) {\n url = input.toString();\n } else {\n // Request object\n url = input.url;\n method = input.method || \"GET\";\n }\n\n if (init?.method) method = init.method;\n\n const headers = collectHeaders(input, init);\n const bodyChunks = await serializeBody(init);\n\n const cacheString = JSON.stringify([\n CACHE_KEY_PREFIX,\n url,\n method,\n headers,\n init?.mode,\n init?.redirect,\n init?.credentials,\n init?.referrer,\n init?.referrerPolicy,\n init?.integrity,\n init?.cache,\n bodyChunks,\n ]);\n\n const encoder = new TextEncoder();\n const buffer = encoder.encode(cacheString);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", buffer);\n return Array.prototype.map\n .call(new Uint8Array(hashBuffer), (b: number) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface NextFetchOptions {\n revalidate?: number | false;\n tags?: string[];\n}\n\n// Extend the standard RequestInit to include `next`\ndeclare global {\n interface RequestInit {\n next?: NextFetchOptions;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Patching\n// ---------------------------------------------------------------------------\n\n// Capture the real (unpatched) fetch once, shared across Vite's\n// multi-environment module instances via Symbol.for().\nconst _ORIG_FETCH_KEY = Symbol.for(\"vinext.fetchCache.originalFetch\");\nconst _gFetch = globalThis as unknown as Record<PropertyKey, unknown>;\nconst originalFetch: typeof globalThis.fetch = (_gFetch[_ORIG_FETCH_KEY] ??= globalThis.fetch) as typeof globalThis.fetch;\n\n// ---------------------------------------------------------------------------\n// AsyncLocalStorage for request-scoped fetch cache state.\n// Uses Symbol.for() on globalThis so the storage is shared across Vite's\n// multi-environment module instances.\n// ---------------------------------------------------------------------------\ninterface FetchCacheState {\n currentRequestTags: string[];\n}\n\nconst _ALS_KEY = Symbol.for(\"vinext.fetchCache.als\");\nconst _FALLBACK_KEY = Symbol.for(\"vinext.fetchCache.fallback\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage<FetchCacheState>()) as AsyncLocalStorage<FetchCacheState>;\n\nconst _fallbackState = (_g[_FALLBACK_KEY] ??= {\n currentRequestTags: [],\n} satisfies FetchCacheState) as FetchCacheState;\n\nfunction _getState(): FetchCacheState {\n return _als.getStore() ?? _fallbackState;\n}\n\n/**\n * Reset the fallback state for a new request. Used by `withFetchCache()`\n * in single-threaded contexts where ALS.run() isn't used.\n */\nfunction _resetFallbackState(): void {\n _fallbackState.currentRequestTags = [];\n}\n\n/**\n * Get tags collected during the current render pass.\n * Useful for associating page-level cache entries with all the\n * fetch tags used during rendering.\n */\nexport function getCollectedFetchTags(): string[] {\n return [..._getState().currentRequestTags];\n}\n\n/**\n * Create a patched fetch function with Next.js caching semantics.\n *\n * The patched fetch:\n * 1. Checks `cache` and `next` options to determine caching behavior\n * 2. On cache hit, returns the cached response without hitting the network\n * 3. On cache miss, fetches from network, stores in cache, returns response\n * 4. Respects `next.revalidate` for TTL-based revalidation\n * 5. Respects `next.tags` for tag-based invalidation via revalidateTag()\n */\nfunction createPatchedFetch(): typeof globalThis.fetch {\n return async function patchedFetch(\n input: string | URL | Request,\n init?: RequestInit,\n ): Promise<Response> {\n const nextOpts = init?.next as NextFetchOptions | undefined;\n const cacheDirective = init?.cache;\n\n // Determine caching behavior:\n // - cache: 'no-store' → skip cache entirely\n // - cache: 'force-cache' → cache indefinitely (revalidate = Infinity)\n // - next.revalidate: false → same as 'no-store'\n // - next.revalidate: 0 → same as 'no-store'\n // - next.revalidate: N → cache for N seconds\n // - No cache/next options → default behavior (no caching, pass-through)\n\n // If no caching options at all, just pass through to original fetch\n if (!nextOpts && !cacheDirective) {\n return originalFetch(input, init);\n }\n\n // Explicit no-store or no-cache — bypass cache entirely\n if (cacheDirective === \"no-store\" || cacheDirective === \"no-cache\" || nextOpts?.revalidate === false || nextOpts?.revalidate === 0) {\n // Strip the `next` property before passing to real fetch\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n\n // Safety: when per-user auth headers are present and the developer hasn't\n // explicitly opted into caching with `cache: 'force-cache'` or an explicit\n // `next.revalidate`, skip caching to prevent accidental cross-user data\n // leakage. Developers who understand the implications can still force\n // caching by using `cache: 'force-cache'` or `next: { revalidate: N }`.\n const hasExplicitCacheOpt =\n cacheDirective === \"force-cache\" ||\n (typeof nextOpts?.revalidate === \"number\" && nextOpts.revalidate > 0);\n if (!hasExplicitCacheOpt && hasAuthHeaders(input, init)) {\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n\n // Determine revalidation period\n let revalidateSeconds: number;\n if (cacheDirective === \"force-cache\") {\n // force-cache means cache indefinitely (we use a very large number)\n revalidateSeconds = nextOpts?.revalidate && typeof nextOpts.revalidate === \"number\"\n ? nextOpts.revalidate\n : 31536000; // 1 year\n } else if (typeof nextOpts?.revalidate === \"number\" && nextOpts.revalidate > 0) {\n revalidateSeconds = nextOpts.revalidate;\n } else {\n // Has `next` options but no explicit revalidate — Next.js defaults to\n // caching when `next` is present (force-cache behavior).\n // If only tags are specified, cache indefinitely.\n if (nextOpts?.tags && nextOpts.tags.length > 0) {\n revalidateSeconds = 31536000;\n } else {\n // next: {} with no revalidate or tags — pass through\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n }\n\n const tags = nextOpts?.tags ?? [];\n const cacheKey = await buildFetchCacheKey(input, init);\n const handler = getCacheHandler();\n\n // Collect tags for this render pass\n const reqTags = _getState().currentRequestTags;\n if (tags.length > 0) {\n for (const tag of tags) {\n if (!reqTags.includes(tag)) {\n reqTags.push(tag);\n }\n }\n }\n\n // Try cache first\n try {\n const cached = await handler.get(cacheKey, { kind: \"FETCH\", tags });\n if (cached?.value && cached.value.kind === \"FETCH\" && cached.cacheState !== \"stale\") {\n const cachedData = cached.value.data;\n // Reconstruct a Response from the cached data\n return new Response(cachedData.body, {\n status: cachedData.status ?? 200,\n headers: cachedData.headers,\n });\n }\n\n // Stale entry — we could do stale-while-revalidate here, but for fetch()\n // the simpler approach is to just re-fetch (the page-level ISR handles SWR).\n // However, if we have a stale entry, return it and trigger background refetch.\n if (cached?.value && cached.value.kind === \"FETCH\" && cached.cacheState === \"stale\") {\n const staleData = cached.value.data;\n\n // Background refetch\n const cleanInit = stripNextFromInit(init);\n originalFetch(input, cleanInit).then(async (freshResp) => {\n const freshBody = await freshResp.text();\n const freshHeaders: Record<string, string> = {};\n freshResp.headers.forEach((v, k) => { freshHeaders[k] = v; });\n\n const freshValue: CachedFetchValue = {\n kind: \"FETCH\",\n data: {\n headers: freshHeaders,\n body: freshBody,\n url: typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url,\n status: freshResp.status,\n },\n tags,\n revalidate: revalidateSeconds,\n };\n await handler.set(cacheKey, freshValue, {\n fetchCache: true,\n tags,\n revalidate: revalidateSeconds,\n });\n }).catch((err) => {\n console.error(\"[vinext] fetch cache background revalidation failed:\", err);\n });\n\n // Return stale data immediately\n return new Response(staleData.body, {\n status: staleData.status ?? 200,\n headers: staleData.headers,\n });\n }\n } catch (cacheErr) {\n // Cache read failed — fall through to network\n console.error(\"[vinext] fetch cache read error:\", cacheErr);\n }\n\n // Cache miss — fetch from network\n const cleanInit = stripNextFromInit(init);\n const response = await originalFetch(input, cleanInit);\n\n // Only cache successful responses (2xx)\n if (response.ok) {\n // Clone before reading body\n const cloned = response.clone();\n const body = await cloned.text();\n const headers: Record<string, string> = {};\n cloned.headers.forEach((v, k) => { headers[k] = v; });\n\n const cacheValue: CachedFetchValue = {\n kind: \"FETCH\",\n data: {\n headers,\n body,\n url: typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url,\n status: cloned.status,\n },\n tags,\n revalidate: revalidateSeconds,\n };\n\n // Store in cache (fire-and-forget)\n handler.set(cacheKey, cacheValue, {\n fetchCache: true,\n tags,\n revalidate: revalidateSeconds,\n }).catch((err) => {\n console.error(\"[vinext] fetch cache write error:\", err);\n });\n }\n\n return response;\n } as typeof globalThis.fetch;\n}\n\n/**\n * Strip the `next` property from RequestInit before passing to real fetch.\n * The `next` property is not a standard fetch option and would cause warnings\n * in some environments.\n */\nfunction stripNextFromInit(init?: RequestInit): RequestInit | undefined {\n if (!init) return init;\n const castInit = init as RequestInit & { next?: unknown; _ogBody?: BodyInit };\n const { next: _next, _ogBody, ...rest } = castInit;\n // Restore the original body if it was stashed by serializeBody (e.g. after\n // consuming a ReadableStream for cache key generation).\n if (_ogBody !== undefined) {\n rest.body = _ogBody;\n }\n return Object.keys(rest).length > 0 ? rest : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Fetch patching — install once, not per-request.\n// The patched fetch uses _getState() internally, which reads from ALS\n// (concurrent) or _fallbackState (single-threaded), so per-request\n// isolation is handled at the state level, not by swapping globalThis.fetch.\n// ---------------------------------------------------------------------------\n\nconst _PATCH_KEY = Symbol.for(\"vinext.fetchCache.patchInstalled\");\n\nfunction _ensurePatchInstalled(): void {\n if (_g[_PATCH_KEY]) return;\n _g[_PATCH_KEY] = true;\n globalThis.fetch = createPatchedFetch();\n}\n\n/**\n * Install the patched fetch and reset per-request tag state.\n * Returns a cleanup function that clears tags.\n *\n * @deprecated Prefer `runWithFetchCache()` which uses `AsyncLocalStorage.run()`\n * for proper per-request isolation in concurrent environments.\n *\n * Usage:\n * const cleanup = withFetchCache();\n * try { await render(); } finally { cleanup(); }\n */\nexport function withFetchCache(): () => void {\n _ensurePatchInstalled();\n _resetFallbackState();\n\n return () => {\n _resetFallbackState();\n };\n}\n\n/**\n * Run an async function with patched fetch caching enabled.\n * Uses `AsyncLocalStorage.run()` for proper per-request isolation\n * of collected fetch tags in concurrent server environments.\n */\nexport async function runWithFetchCache<T>(fn: () => Promise<T>): Promise<T> {\n _ensurePatchInstalled();\n return _als.run({ currentRequestTags: [] }, fn);\n}\n\n/**\n * Get the original (unpatched) fetch function.\n * Useful for internal code that should bypass caching.\n */\nexport function getOriginalFetch(): typeof globalThis.fetch {\n return originalFetch;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fetch-cache.js","sourceRoot":"","sources":["../../src/shims/fetch-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,eAAe,GAEhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;AAEvD,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,wBAAwB,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,QAAQ;AAEtD,MAAM,4BAA6B,SAAQ,KAAK;IAC9C;QACE,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACzD,CAAC;CACF;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,KAA6B,EAAE,IAAkB;IACvE,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,kDAAkD;IAClD,IAAI,KAAK,YAAY,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAC9C,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,yEAAyE;IACzE,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,YAAY,OAAO;YAC7C,CAAC,CAAC,IAAI,CAAC,OAAO;YACd,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAsB,CAAC,CAAC;QAC7C,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,6BAA6B;IAC7B,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;QACvC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,YAAY,GAAG,CAAC,eAAe,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAE9D,SAAS,cAAc,CAAC,KAA6B,EAAE,IAAkB;IACvE,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5C,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC;AACtD,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAAC,IAAkB;IAC7C,IAAI,CAAC,IAAI,EAAE,IAAI;QAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,cAAc,GAAG,CAAC,CAAC;IAEvB,MAAM,aAAa,GAAG,CAAC,KAAa,EAAQ,EAAE;QAC5C,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC;QACnD,IAAI,cAAc,GAAG,wBAAwB,EAAE,CAAC;YAC9C,MAAM,IAAI,4BAA4B,EAAE,CAAC;QAC3C,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,IAAI,IAAI,CAAC,IAAI,YAAY,UAAU,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,wBAAwB,EAAE,CAAC;YACpD,MAAM,IAAI,4BAA4B,EAAE,CAAC;QAC3C,CAAC;QACD,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACxC,IAAY,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;IACpC,CAAC;SAAM,IAAI,OAAQ,IAAI,CAAC,IAAY,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;QAC9D,iBAAiB;QACjB,MAAM,YAAY,GAAG,IAAI,CAAC,IAA2C,CAAC;QACtE,MAAM,CAAC,cAAc,EAAE,YAAY,CAAC,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC;QACzD,IAAY,CAAC,OAAO,GAAG,YAAY,CAAC;QACrC,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,CAAC;QAE1C,IAAI,CAAC;YACH,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI;oBAAE,MAAM;gBAChB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC9B,aAAa,CAAC,KAAK,CAAC,CAAC;gBACvB,CAAC;qBAAM,CAAC;oBACN,6DAA6D;oBAC7D,qCAAqC;oBACrC,cAAc,IAAI,KAAK,CAAC,UAAU,CAAC;oBACnC,IAAI,cAAc,GAAG,wBAAwB,EAAE,CAAC;wBAC9C,MAAM,IAAI,4BAA4B,EAAE,CAAC;oBAC3C,CAAC;oBACD,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC3D,CAAC;YACH,CAAC;YACD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YACpC,IAAI,UAAU,EAAE,CAAC;gBACf,aAAa,CAAC,UAAU,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,IAAI,GAAG,YAAY,4BAA4B,EAAE,CAAC;gBAChD,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,GAAG,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,YAAY,eAAe,EAAE,CAAC;QAChD,6DAA6D;QAC5D,IAAY,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;QAClC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,OAAQ,IAAI,CAAC,IAAY,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACzD,WAAW;QACX,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAgB,CAAC;QACtC,IAAY,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;QAClC,KAAK,MAAM,GAAG,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,GAAG,CACxC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBACvB,IAAI,OAAO,GAAG,KAAK,QAAQ;oBAAE,OAAO,GAAG,CAAC;gBACxC,IAAI,GAAG,CAAC,IAAI,GAAG,wBAAwB,IAAI,cAAc,GAAG,GAAG,CAAC,IAAI,GAAG,wBAAwB,EAAE,CAAC;oBAChG,MAAM,IAAI,4BAA4B,EAAE,CAAC;gBAC3C,CAAC;gBACD,qEAAqE;gBACrE,6EAA6E;gBAC7E,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC1B,CAAC,CAAC,CACH,CAAC;YACF,aAAa,CAAC,GAAG,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;SAAM,IAAI,OAAQ,IAAI,CAAC,IAAY,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QAChE,OAAO;QACP,MAAM,IAAI,GAAG,IAAI,CAAC,IAAY,CAAC;QAC/B,IAAI,IAAI,CAAC,IAAI,GAAG,wBAAwB,EAAE,CAAC;YACzC,MAAM,IAAI,4BAA4B,EAAE,CAAC;QAC3C,CAAC;QACD,aAAa,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAY,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACvE,CAAC;SAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACzC,6DAA6D;QAC7D,yEAAyE;QACzE,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,wBAAwB,EAAE,CAAC;YAChD,MAAM,IAAI,4BAA4B,EAAE,CAAC;QAC3C,CAAC;QACD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,IAAY,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;IACpC,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,kBAAkB,CAAC,KAA6B,EAAE,IAAgD;IAC/G,IAAI,GAAW,CAAC;IAChB,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,GAAG,GAAG,KAAK,CAAC;IACd,CAAC;SAAM,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;QAChC,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,iBAAiB;QACjB,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QAChB,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC;IACjC,CAAC;IAED,IAAI,IAAI,EAAE,MAAM;QAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAEvC,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAE7C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,gBAAgB;QAChB,GAAG;QACH,MAAM;QACN,OAAO;QACP,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,KAAK;QACX,UAAU;KACX,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACjE,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG;SACvB,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAChF,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAkBD,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,gEAAgE;AAChE,uDAAuD;AACvD,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;AACtE,MAAM,OAAO,GAAG,UAAqD,CAAC;AACtE,MAAM,aAAa,GAA4B,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,UAAU,CAAC,KAAK,CAA4B,CAAC;AAW1H,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AACrD,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAC/D,MAAM,EAAE,GAAG,UAAqD,CAAC;AACjE,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,IAAI,iBAAiB,EAAmB,CAAuC,CAAC;AAE/G,MAAM,cAAc,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK;IAC5C,kBAAkB,EAAE,EAAE;CACG,CAAoB,CAAC;AAEhD,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,cAAc,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB;IAC1B,cAAc,CAAC,kBAAkB,GAAG,EAAE,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,SAAS,EAAE,CAAC,kBAAkB,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,kBAAkB;IACzB,OAAO,KAAK,UAAU,YAAY,CAChC,KAA6B,EAC7B,IAAkB;QAElB,MAAM,QAAQ,GAAG,IAAI,EAAE,IAAoC,CAAC;QAC5D,MAAM,cAAc,GAAG,IAAI,EAAE,KAAK,CAAC;QAEnC,8BAA8B;QAC9B,4CAA4C;QAC5C,sEAAsE;QACtE,gDAAgD;QAChD,4CAA4C;QAC5C,6CAA6C;QAC7C,wEAAwE;QAExE,oEAAoE;QACpE,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc,EAAE,CAAC;YACjC,OAAO,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,wDAAwD;QACxD,IAAI,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU,IAAI,QAAQ,EAAE,UAAU,KAAK,KAAK,IAAI,QAAQ,EAAE,UAAU,KAAK,CAAC,EAAE,CAAC;YACnI,yDAAyD;YACzD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACzC,CAAC;QAED,0EAA0E;QAC1E,2EAA2E;QAC3E,wEAAwE;QACxE,sEAAsE;QACtE,wEAAwE;QACxE,MAAM,mBAAmB,GACvB,cAAc,KAAK,aAAa;YAChC,CAAC,OAAO,QAAQ,EAAE,UAAU,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,mBAAmB,IAAI,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;YACxD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACzC,CAAC;QAED,gCAAgC;QAChC,IAAI,iBAAyB,CAAC;QAC9B,IAAI,cAAc,KAAK,aAAa,EAAE,CAAC;YACrC,oEAAoE;YACpE,iBAAiB,GAAG,QAAQ,EAAE,UAAU,IAAI,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ;gBACjF,CAAC,CAAC,QAAQ,CAAC,UAAU;gBACrB,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAS;QACzB,CAAC;aAAM,IAAI,OAAO,QAAQ,EAAE,UAAU,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YAC/E,iBAAiB,GAAG,QAAQ,CAAC,UAAU,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,sEAAsE;YACtE,yDAAyD;YACzD,kDAAkD;YAClD,IAAI,QAAQ,EAAE,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/C,iBAAiB,GAAG,QAAQ,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,qDAAqD;gBACrD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC1C,OAAO,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC;QAClC,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,4BAA4B,EAAE,CAAC;gBAChD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC1C,OAAO,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YACzC,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;QAElC,oCAAoC;QACpC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC,kBAAkB,CAAC;QAC/C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC3B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACpE,IAAI,MAAM,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACpF,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;gBACrC,8CAA8C;gBAC9C,OAAO,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE;oBACnC,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,GAAG;oBAChC,OAAO,EAAE,UAAU,CAAC,OAAO;iBAC5B,CAAC,CAAC;YACL,CAAC;YAED,yEAAyE;YACzE,6EAA6E;YAC7E,+EAA+E;YAC/E,IAAI,MAAM,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACpF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;gBAEpC,qBAAqB;gBACrB,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAC1C,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;oBACvD,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;oBACzC,MAAM,YAAY,GAA2B,EAAE,CAAC;oBAChD,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAE9D,MAAM,UAAU,GAAqB;wBACnC,IAAI,EAAE,OAAO;wBACb,IAAI,EAAE;4BACJ,OAAO,EAAE,YAAY;4BACrB,IAAI,EAAE,SAAS;4BACf,GAAG,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;4BAC5F,MAAM,EAAE,SAAS,CAAC,MAAM;yBACzB;wBACD,IAAI;wBACJ,UAAU,EAAE,iBAAiB;qBAC9B,CAAC;oBACF,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE;wBACtC,UAAU,EAAE,IAAI;wBAChB,IAAI;wBACJ,UAAU,EAAE,iBAAiB;qBAC9B,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;oBACf,OAAO,CAAC,KAAK,CAAC,sDAAsD,EAAE,GAAG,CAAC,CAAC;gBAC7E,CAAC,CAAC,CAAC;gBAEH,gCAAgC;gBAChC,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE;oBAClC,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,GAAG;oBAC/B,OAAO,EAAE,SAAS,CAAC,OAAO;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,QAAQ,EAAE,CAAC;YAClB,8CAA8C;YAC9C,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,QAAQ,CAAC,CAAC;QAC9D,CAAC;QAED,kCAAkC;QAClC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAEvD,wCAAwC;QACxC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,4BAA4B;YAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,OAAO,GAA2B,EAAE,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEtD,MAAM,UAAU,GAAqB;gBACnC,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE;oBACJ,OAAO;oBACP,IAAI;oBACJ,GAAG,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;oBAC5F,MAAM,EAAE,MAAM,CAAC,MAAM;iBACtB;gBACD,IAAI;gBACJ,UAAU,EAAE,iBAAiB;aAC9B,CAAC;YAEF,mCAAmC;YACnC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE;gBAChC,UAAU,EAAE,IAAI;gBAChB,IAAI;gBACJ,UAAU,EAAE,iBAAiB;aAC9B,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAA4B,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,IAAkB;IAC3C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,QAAQ,GAAG,IAA4D,CAAC;IAC9E,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;IACnD,2EAA2E;IAC3E,wDAAwD;IACxD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC;IACtB,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,8EAA8E;AAC9E,kDAAkD;AAClD,sEAAsE;AACtE,mEAAmE;AACnE,6EAA6E;AAC7E,8EAA8E;AAE9E,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAElE,SAAS,qBAAqB;IAC5B,IAAI,EAAE,CAAC,UAAU,CAAC;QAAE,OAAO;IAC3B,EAAE,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,KAAK,GAAG,kBAAkB,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc;IAC5B,qBAAqB,EAAE,CAAC;IACxB,mBAAmB,EAAE,CAAC;IAEtB,OAAO,GAAG,EAAE;QACV,mBAAmB,EAAE,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAI,EAAoB;IAC7D,qBAAqB,EAAE,CAAC;IACxB,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["/**\n * Extended fetch() with Next.js caching semantics.\n *\n * Patches `globalThis.fetch` during server rendering to support:\n *\n * fetch(url, { next: { revalidate: 60, tags: ['posts'] } })\n * fetch(url, { cache: 'force-cache' })\n * fetch(url, { cache: 'no-store' })\n *\n * Cached responses are stored via the pluggable CacheHandler, so\n * revalidateTag() and revalidatePath() invalidate fetch-level caches.\n *\n * Usage (in server entry):\n * import { withFetchCache, cleanupFetchCache } from './fetch-cache';\n * const cleanup = withFetchCache();\n * try { ... render ... } finally { cleanup(); }\n *\n * Or use the async helper:\n * await runWithFetchCache(async () => { ... render ... });\n */\n\nimport {\n getCacheHandler,\n type CachedFetchValue,\n} from \"./cache.js\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// ---------------------------------------------------------------------------\n// Cache key generation\n// ---------------------------------------------------------------------------\n\n/**\n * Headers excluded from the cache key. These are W3C trace context headers\n * that can break request caching and deduplication.\n * All other headers ARE included in the cache key, matching Next.js behavior.\n */\nconst HEADER_BLOCKLIST = [\"traceparent\", \"tracestate\"];\n\n// Cache key version — bump when changing the key format to bust stale entries\nconst CACHE_KEY_PREFIX = \"v2\";\nconst MAX_CACHE_KEY_BODY_BYTES = 1024 * 1024; // 1 MiB\n\nclass BodyTooLargeForCacheKeyError extends Error {\n constructor() {\n super(\"Fetch body too large for cache key generation\");\n }\n}\n\n/**\n * Collect all headers from the request, excluding the blocklist.\n * Merges headers from both the Request object and the init object,\n * with init taking precedence (matching fetch() spec behavior).\n */\nfunction collectHeaders(input: string | URL | Request, init?: RequestInit): Record<string, string> {\n const merged: Record<string, string> = {};\n\n // Start with headers from Request object (if any)\n if (input instanceof Request && input.headers) {\n input.headers.forEach((v, k) => { merged[k] = v; });\n }\n\n // Override with headers from init (init takes precedence per fetch spec)\n if (init?.headers) {\n const headers = init.headers instanceof Headers\n ? init.headers\n : new Headers(init.headers as HeadersInit);\n headers.forEach((v, k) => { merged[k] = v; });\n }\n\n // Remove blocklisted headers\n for (const blocked of HEADER_BLOCKLIST) {\n delete merged[blocked];\n }\n\n return merged;\n}\n\n/**\n * Check whether a fetch request carries any per-user auth headers.\n * Used for the safety bypass (skip caching when auth headers are present\n * without an explicit cache opt-in).\n */\nconst AUTH_HEADERS = [\"authorization\", \"cookie\", \"x-api-key\"];\n\nfunction hasAuthHeaders(input: string | URL | Request, init?: RequestInit): boolean {\n const headers = collectHeaders(input, init);\n return AUTH_HEADERS.some((name) => name in headers);\n}\n\n/**\n * Serialize request body into string chunks for cache key inclusion.\n * Handles all body types: string, Uint8Array, ReadableStream, FormData, Blob.\n * Returns the serialized body chunks and optionally stashes the original body\n * on init as `_ogBody` so it can still be used after stream consumption.\n */\nasync function serializeBody(init?: RequestInit): Promise<string[]> {\n if (!init?.body) return [];\n\n const bodyChunks: string[] = [];\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n let totalBodyBytes = 0;\n\n const pushBodyChunk = (chunk: string): void => {\n totalBodyBytes += encoder.encode(chunk).byteLength;\n if (totalBodyBytes > MAX_CACHE_KEY_BODY_BYTES) {\n throw new BodyTooLargeForCacheKeyError();\n }\n bodyChunks.push(chunk);\n };\n\n if (init.body instanceof Uint8Array) {\n if (init.body.byteLength > MAX_CACHE_KEY_BODY_BYTES) {\n throw new BodyTooLargeForCacheKeyError();\n }\n pushBodyChunk(decoder.decode(init.body));\n (init as any)._ogBody = init.body;\n } else if (typeof (init.body as any).getReader === \"function\") {\n // ReadableStream\n const readableBody = init.body as ReadableStream<Uint8Array | string>;\n const [bodyForHashing, bodyForFetch] = readableBody.tee();\n (init as any)._ogBody = bodyForFetch;\n const reader = bodyForHashing.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (typeof value === \"string\") {\n pushBodyChunk(value);\n } else {\n // Check raw byte size before the expensive decode to prevent\n // OOM from a single oversized chunk.\n totalBodyBytes += value.byteLength;\n if (totalBodyBytes > MAX_CACHE_KEY_BODY_BYTES) {\n throw new BodyTooLargeForCacheKeyError();\n }\n bodyChunks.push(decoder.decode(value, { stream: true }));\n }\n }\n const finalChunk = decoder.decode();\n if (finalChunk) {\n pushBodyChunk(finalChunk);\n }\n } catch (err) {\n await reader.cancel();\n if (err instanceof BodyTooLargeForCacheKeyError) {\n throw err;\n }\n console.error(\"[vinext] Problem reading body for cache key\", err);\n }\n } else if (init.body instanceof URLSearchParams) {\n // URLSearchParams — .toString() gives a stable serialization\n (init as any)._ogBody = init.body;\n pushBodyChunk(init.body.toString());\n } else if (typeof (init.body as any).keys === \"function\") {\n // FormData\n const formData = init.body as FormData;\n (init as any)._ogBody = init.body;\n for (const key of new Set(formData.keys())) {\n const values = formData.getAll(key);\n const serializedValues = await Promise.all(\n values.map(async (val) => {\n if (typeof val === \"string\") return val;\n if (val.size > MAX_CACHE_KEY_BODY_BYTES || totalBodyBytes + val.size > MAX_CACHE_KEY_BODY_BYTES) {\n throw new BodyTooLargeForCacheKeyError();\n }\n // Note: File name/type/lastModified are not included — only content.\n // Two Files with identical content but different names produce the same key.\n return await val.text();\n })\n );\n pushBodyChunk(`${key}=${serializedValues.join(\",\")}`);\n }\n } else if (typeof (init.body as any).arrayBuffer === \"function\") {\n // Blob\n const blob = init.body as Blob;\n if (blob.size > MAX_CACHE_KEY_BODY_BYTES) {\n throw new BodyTooLargeForCacheKeyError();\n }\n pushBodyChunk(await blob.text());\n const arrayBuffer = await blob.arrayBuffer();\n (init as any)._ogBody = new Blob([arrayBuffer], { type: blob.type });\n } else if (typeof init.body === \"string\") {\n // String length is always <= UTF-8 byte length, so this is a\n // cheap lower-bound check that avoids encoder.encode() for huge strings.\n if (init.body.length > MAX_CACHE_KEY_BODY_BYTES) {\n throw new BodyTooLargeForCacheKeyError();\n }\n pushBodyChunk(init.body);\n (init as any)._ogBody = init.body;\n }\n\n return bodyChunks;\n}\n\n/**\n * Generate a deterministic cache key from a fetch request.\n *\n * Matches Next.js behavior: the key is a SHA-256 hash of a JSON array\n * containing URL, method, all headers (minus blocklist), all RequestInit\n * options, and the serialized body.\n */\nasync function buildFetchCacheKey(input: string | URL | Request, init?: RequestInit & { next?: NextFetchOptions }): Promise<string> {\n let url: string;\n let method = \"GET\";\n\n if (typeof input === \"string\") {\n url = input;\n } else if (input instanceof URL) {\n url = input.toString();\n } else {\n // Request object\n url = input.url;\n method = input.method || \"GET\";\n }\n\n if (init?.method) method = init.method;\n\n const headers = collectHeaders(input, init);\n const bodyChunks = await serializeBody(init);\n\n const cacheString = JSON.stringify([\n CACHE_KEY_PREFIX,\n url,\n method,\n headers,\n init?.mode,\n init?.redirect,\n init?.credentials,\n init?.referrer,\n init?.referrerPolicy,\n init?.integrity,\n init?.cache,\n bodyChunks,\n ]);\n\n const encoder = new TextEncoder();\n const buffer = encoder.encode(cacheString);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", buffer);\n return Array.prototype.map\n .call(new Uint8Array(hashBuffer), (b: number) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface NextFetchOptions {\n revalidate?: number | false;\n tags?: string[];\n}\n\n// Extend the standard RequestInit to include `next`\ndeclare global {\n interface RequestInit {\n next?: NextFetchOptions;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Patching\n// ---------------------------------------------------------------------------\n\n// Capture the real (unpatched) fetch once, shared across Vite's\n// multi-environment module instances via Symbol.for().\nconst _ORIG_FETCH_KEY = Symbol.for(\"vinext.fetchCache.originalFetch\");\nconst _gFetch = globalThis as unknown as Record<PropertyKey, unknown>;\nconst originalFetch: typeof globalThis.fetch = (_gFetch[_ORIG_FETCH_KEY] ??= globalThis.fetch) as typeof globalThis.fetch;\n\n// ---------------------------------------------------------------------------\n// AsyncLocalStorage for request-scoped fetch cache state.\n// Uses Symbol.for() on globalThis so the storage is shared across Vite's\n// multi-environment module instances.\n// ---------------------------------------------------------------------------\ninterface FetchCacheState {\n currentRequestTags: string[];\n}\n\nconst _ALS_KEY = Symbol.for(\"vinext.fetchCache.als\");\nconst _FALLBACK_KEY = Symbol.for(\"vinext.fetchCache.fallback\");\nconst _g = globalThis as unknown as Record<PropertyKey, unknown>;\nconst _als = (_g[_ALS_KEY] ??= new AsyncLocalStorage<FetchCacheState>()) as AsyncLocalStorage<FetchCacheState>;\n\nconst _fallbackState = (_g[_FALLBACK_KEY] ??= {\n currentRequestTags: [],\n} satisfies FetchCacheState) as FetchCacheState;\n\nfunction _getState(): FetchCacheState {\n return _als.getStore() ?? _fallbackState;\n}\n\n/**\n * Reset the fallback state for a new request. Used by `withFetchCache()`\n * in single-threaded contexts where ALS.run() isn't used.\n */\nfunction _resetFallbackState(): void {\n _fallbackState.currentRequestTags = [];\n}\n\n/**\n * Get tags collected during the current render pass.\n * Useful for associating page-level cache entries with all the\n * fetch tags used during rendering.\n */\nexport function getCollectedFetchTags(): string[] {\n return [..._getState().currentRequestTags];\n}\n\n/**\n * Create a patched fetch function with Next.js caching semantics.\n *\n * The patched fetch:\n * 1. Checks `cache` and `next` options to determine caching behavior\n * 2. On cache hit, returns the cached response without hitting the network\n * 3. On cache miss, fetches from network, stores in cache, returns response\n * 4. Respects `next.revalidate` for TTL-based revalidation\n * 5. Respects `next.tags` for tag-based invalidation via revalidateTag()\n */\nfunction createPatchedFetch(): typeof globalThis.fetch {\n return async function patchedFetch(\n input: string | URL | Request,\n init?: RequestInit,\n ): Promise<Response> {\n const nextOpts = init?.next as NextFetchOptions | undefined;\n const cacheDirective = init?.cache;\n\n // Determine caching behavior:\n // - cache: 'no-store' → skip cache entirely\n // - cache: 'force-cache' → cache indefinitely (revalidate = Infinity)\n // - next.revalidate: false → same as 'no-store'\n // - next.revalidate: 0 → same as 'no-store'\n // - next.revalidate: N → cache for N seconds\n // - No cache/next options → default behavior (no caching, pass-through)\n\n // If no caching options at all, just pass through to original fetch\n if (!nextOpts && !cacheDirective) {\n return originalFetch(input, init);\n }\n\n // Explicit no-store or no-cache — bypass cache entirely\n if (cacheDirective === \"no-store\" || cacheDirective === \"no-cache\" || nextOpts?.revalidate === false || nextOpts?.revalidate === 0) {\n // Strip the `next` property before passing to real fetch\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n\n // Safety: when per-user auth headers are present and the developer hasn't\n // explicitly opted into caching with `cache: 'force-cache'` or an explicit\n // `next.revalidate`, skip caching to prevent accidental cross-user data\n // leakage. Developers who understand the implications can still force\n // caching by using `cache: 'force-cache'` or `next: { revalidate: N }`.\n const hasExplicitCacheOpt =\n cacheDirective === \"force-cache\" ||\n (typeof nextOpts?.revalidate === \"number\" && nextOpts.revalidate > 0);\n if (!hasExplicitCacheOpt && hasAuthHeaders(input, init)) {\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n\n // Determine revalidation period\n let revalidateSeconds: number;\n if (cacheDirective === \"force-cache\") {\n // force-cache means cache indefinitely (we use a very large number)\n revalidateSeconds = nextOpts?.revalidate && typeof nextOpts.revalidate === \"number\"\n ? nextOpts.revalidate\n : 31536000; // 1 year\n } else if (typeof nextOpts?.revalidate === \"number\" && nextOpts.revalidate > 0) {\n revalidateSeconds = nextOpts.revalidate;\n } else {\n // Has `next` options but no explicit revalidate — Next.js defaults to\n // caching when `next` is present (force-cache behavior).\n // If only tags are specified, cache indefinitely.\n if (nextOpts?.tags && nextOpts.tags.length > 0) {\n revalidateSeconds = 31536000;\n } else {\n // next: {} with no revalidate or tags — pass through\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n }\n\n const tags = nextOpts?.tags ?? [];\n let cacheKey: string;\n try {\n cacheKey = await buildFetchCacheKey(input, init);\n } catch (err) {\n if (err instanceof BodyTooLargeForCacheKeyError) {\n const cleanInit = stripNextFromInit(init);\n return originalFetch(input, cleanInit);\n }\n throw err;\n }\n const handler = getCacheHandler();\n\n // Collect tags for this render pass\n const reqTags = _getState().currentRequestTags;\n if (tags.length > 0) {\n for (const tag of tags) {\n if (!reqTags.includes(tag)) {\n reqTags.push(tag);\n }\n }\n }\n\n // Try cache first\n try {\n const cached = await handler.get(cacheKey, { kind: \"FETCH\", tags });\n if (cached?.value && cached.value.kind === \"FETCH\" && cached.cacheState !== \"stale\") {\n const cachedData = cached.value.data;\n // Reconstruct a Response from the cached data\n return new Response(cachedData.body, {\n status: cachedData.status ?? 200,\n headers: cachedData.headers,\n });\n }\n\n // Stale entry — we could do stale-while-revalidate here, but for fetch()\n // the simpler approach is to just re-fetch (the page-level ISR handles SWR).\n // However, if we have a stale entry, return it and trigger background refetch.\n if (cached?.value && cached.value.kind === \"FETCH\" && cached.cacheState === \"stale\") {\n const staleData = cached.value.data;\n\n // Background refetch\n const cleanInit = stripNextFromInit(init);\n originalFetch(input, cleanInit).then(async (freshResp) => {\n const freshBody = await freshResp.text();\n const freshHeaders: Record<string, string> = {};\n freshResp.headers.forEach((v, k) => { freshHeaders[k] = v; });\n\n const freshValue: CachedFetchValue = {\n kind: \"FETCH\",\n data: {\n headers: freshHeaders,\n body: freshBody,\n url: typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url,\n status: freshResp.status,\n },\n tags,\n revalidate: revalidateSeconds,\n };\n await handler.set(cacheKey, freshValue, {\n fetchCache: true,\n tags,\n revalidate: revalidateSeconds,\n });\n }).catch((err) => {\n console.error(\"[vinext] fetch cache background revalidation failed:\", err);\n });\n\n // Return stale data immediately\n return new Response(staleData.body, {\n status: staleData.status ?? 200,\n headers: staleData.headers,\n });\n }\n } catch (cacheErr) {\n // Cache read failed — fall through to network\n console.error(\"[vinext] fetch cache read error:\", cacheErr);\n }\n\n // Cache miss — fetch from network\n const cleanInit = stripNextFromInit(init);\n const response = await originalFetch(input, cleanInit);\n\n // Only cache successful responses (2xx)\n if (response.ok) {\n // Clone before reading body\n const cloned = response.clone();\n const body = await cloned.text();\n const headers: Record<string, string> = {};\n cloned.headers.forEach((v, k) => { headers[k] = v; });\n\n const cacheValue: CachedFetchValue = {\n kind: \"FETCH\",\n data: {\n headers,\n body,\n url: typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url,\n status: cloned.status,\n },\n tags,\n revalidate: revalidateSeconds,\n };\n\n // Store in cache (fire-and-forget)\n handler.set(cacheKey, cacheValue, {\n fetchCache: true,\n tags,\n revalidate: revalidateSeconds,\n }).catch((err) => {\n console.error(\"[vinext] fetch cache write error:\", err);\n });\n }\n\n return response;\n } as typeof globalThis.fetch;\n}\n\n/**\n * Strip the `next` property from RequestInit before passing to real fetch.\n * The `next` property is not a standard fetch option and would cause warnings\n * in some environments.\n */\nfunction stripNextFromInit(init?: RequestInit): RequestInit | undefined {\n if (!init) return init;\n const castInit = init as RequestInit & { next?: unknown; _ogBody?: BodyInit };\n const { next: _next, _ogBody, ...rest } = castInit;\n // Restore the original body if it was stashed by serializeBody (e.g. after\n // consuming a ReadableStream for cache key generation).\n if (_ogBody !== undefined) {\n rest.body = _ogBody;\n }\n return Object.keys(rest).length > 0 ? rest : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Fetch patching — install once, not per-request.\n// The patched fetch uses _getState() internally, which reads from ALS\n// (concurrent) or _fallbackState (single-threaded), so per-request\n// isolation is handled at the state level, not by swapping globalThis.fetch.\n// ---------------------------------------------------------------------------\n\nconst _PATCH_KEY = Symbol.for(\"vinext.fetchCache.patchInstalled\");\n\nfunction _ensurePatchInstalled(): void {\n if (_g[_PATCH_KEY]) return;\n _g[_PATCH_KEY] = true;\n globalThis.fetch = createPatchedFetch();\n}\n\n/**\n * Install the patched fetch and reset per-request tag state.\n * Returns a cleanup function that clears tags.\n *\n * @deprecated Prefer `runWithFetchCache()` which uses `AsyncLocalStorage.run()`\n * for proper per-request isolation in concurrent environments.\n *\n * Usage:\n * const cleanup = withFetchCache();\n * try { await render(); } finally { cleanup(); }\n */\nexport function withFetchCache(): () => void {\n _ensurePatchInstalled();\n _resetFallbackState();\n\n return () => {\n _resetFallbackState();\n };\n}\n\n/**\n * Run an async function with patched fetch caching enabled.\n * Uses `AsyncLocalStorage.run()` for proper per-request isolation\n * of collected fetch tags in concurrent server environments.\n */\nexport async function runWithFetchCache<T>(fn: () => Promise<T>): Promise<T> {\n _ensurePatchInstalled();\n return _als.run({ currentRequestTags: [] }, fn);\n}\n\n/**\n * Get the original (unpatched) fetch function.\n * Useful for internal code that should bypass caching.\n */\nexport function getOriginalFetch(): typeof globalThis.fetch {\n return originalFetch;\n}\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* next/font/google shim
|
|
3
|
+
*
|
|
4
|
+
* Provides a compatible shim for Next.js Google Fonts.
|
|
5
|
+
*
|
|
6
|
+
* Two modes:
|
|
7
|
+
* 1. **Dev / CDN mode** (default): Loads fonts from Google Fonts CDN via <link> tags.
|
|
8
|
+
* 2. **Self-hosted mode** (production build): The vinext:google-fonts Vite plugin
|
|
9
|
+
* fetches font CSS + .woff2 files at build time, caches them locally, and injects
|
|
10
|
+
* @font-face CSS pointing at local assets. No requests to Google at runtime.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* import { Inter } from 'next/font/google';
|
|
14
|
+
* const inter = Inter({ subsets: ['latin'], weight: ['400', '700'] });
|
|
15
|
+
* // inter.className -> unique CSS class
|
|
16
|
+
* // inter.style -> { fontFamily: "'Inter', sans-serif" }
|
|
17
|
+
* // inter.variable -> CSS variable name like '--font-inter'
|
|
18
|
+
*/
|
|
19
|
+
export interface FontOptions {
|
|
20
|
+
weight?: string | string[];
|
|
21
|
+
style?: string | string[];
|
|
22
|
+
subsets?: string[];
|
|
23
|
+
display?: string;
|
|
24
|
+
preload?: boolean;
|
|
25
|
+
fallback?: string[];
|
|
26
|
+
adjustFontFallback?: boolean | string;
|
|
27
|
+
variable?: string;
|
|
28
|
+
axes?: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface FontResult {
|
|
31
|
+
className: string;
|
|
32
|
+
style: {
|
|
33
|
+
fontFamily: string;
|
|
34
|
+
};
|
|
35
|
+
variable?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build a Google Fonts CSS URL.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildGoogleFontsUrl(family: string, options: FontOptions): string;
|
|
41
|
+
/**
|
|
42
|
+
* Get collected SSR font class styles (used by the renderer).
|
|
43
|
+
* Note: We don't clear the arrays because fonts are loaded at module import
|
|
44
|
+
* time and need to persist across all requests in the Workers environment.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getSSRFontStyles(): string[];
|
|
47
|
+
/**
|
|
48
|
+
* Get collected SSR font URLs (used by the renderer).
|
|
49
|
+
* Note: We don't clear the arrays because fonts are loaded at module import
|
|
50
|
+
* time and need to persist across all requests in the Workers environment.
|
|
51
|
+
*/
|
|
52
|
+
export declare function getSSRFontLinks(): string[];
|
|
53
|
+
/**
|
|
54
|
+
* Get collected SSR font preload data (used by the renderer).
|
|
55
|
+
* Returns an array of { href, type } objects for emitting
|
|
56
|
+
* <link rel="preload" as="font" ...> tags.
|
|
57
|
+
*/
|
|
58
|
+
export declare function getSSRFontPreloads(): Array<{
|
|
59
|
+
href: string;
|
|
60
|
+
type: string;
|
|
61
|
+
}>;
|
|
62
|
+
export type FontLoader = (options?: FontOptions & {
|
|
63
|
+
_selfHostedCSS?: string;
|
|
64
|
+
}) => FontResult;
|
|
65
|
+
export declare function createFontLoader(family: string): FontLoader;
|
|
66
|
+
declare const googleFonts: Record<string, (options?: FontOptions) => FontResult>;
|
|
67
|
+
export default googleFonts;
|
|
68
|
+
//# sourceMappingURL=font-google-base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-google-base.d.ts","sourceRoot":"","sources":["../../src/shims/font-google-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAwDH,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAUD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CA8ChF;AAyGD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C;AAKD;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAMD;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAE1E;AA0ED,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,UAAU,CAAC;AAE7F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CA6C3D;AAKD,QAAA,MAAM,WAAW,4BACiB,WAAW,KAAK,UAAU,CAW3D,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* next/font/google shim
|
|
3
|
+
*
|
|
4
|
+
* Provides a compatible shim for Next.js Google Fonts.
|
|
5
|
+
*
|
|
6
|
+
* Two modes:
|
|
7
|
+
* 1. **Dev / CDN mode** (default): Loads fonts from Google Fonts CDN via <link> tags.
|
|
8
|
+
* 2. **Self-hosted mode** (production build): The vinext:google-fonts Vite plugin
|
|
9
|
+
* fetches font CSS + .woff2 files at build time, caches them locally, and injects
|
|
10
|
+
* @font-face CSS pointing at local assets. No requests to Google at runtime.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* import { Inter } from 'next/font/google';
|
|
14
|
+
* const inter = Inter({ subsets: ['latin'], weight: ['400', '700'] });
|
|
15
|
+
* // inter.className -> unique CSS class
|
|
16
|
+
* // inter.style -> { fontFamily: "'Inter', sans-serif" }
|
|
17
|
+
* // inter.variable -> CSS variable name like '--font-inter'
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Escape a string for safe interpolation inside a CSS single-quoted string.
|
|
21
|
+
*
|
|
22
|
+
* Prevents CSS injection by escaping characters that could break out of
|
|
23
|
+
* a `'...'` CSS string context: backslashes, single quotes, and newlines.
|
|
24
|
+
*/
|
|
25
|
+
function escapeCSSString(value) {
|
|
26
|
+
return value
|
|
27
|
+
.replace(/\\/g, "\\\\")
|
|
28
|
+
.replace(/'/g, "\\'")
|
|
29
|
+
.replace(/\n/g, "\\a ")
|
|
30
|
+
.replace(/\r/g, "\\d ");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validate a CSS custom property name (e.g. `--font-inter`).
|
|
34
|
+
*
|
|
35
|
+
* Custom properties must start with `--` and only contain alphanumeric
|
|
36
|
+
* characters, hyphens, and underscores. Anything else could be used to
|
|
37
|
+
* break out of the CSS declaration and inject arbitrary rules.
|
|
38
|
+
*
|
|
39
|
+
* Returns the name if valid, undefined otherwise.
|
|
40
|
+
*/
|
|
41
|
+
function sanitizeCSSVarName(name) {
|
|
42
|
+
if (/^--[a-zA-Z0-9_-]+$/.test(name))
|
|
43
|
+
return name;
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sanitize a CSS font-family fallback name.
|
|
48
|
+
*
|
|
49
|
+
* Generic family names (sans-serif, serif, monospace, etc.) are used as-is.
|
|
50
|
+
* Named families are wrapped in escaped quotes. This prevents injection via
|
|
51
|
+
* crafted fallback values like `); } body { color: red; } .x {`.
|
|
52
|
+
*/
|
|
53
|
+
function sanitizeFallback(name) {
|
|
54
|
+
// CSS generic font families — safe to use unquoted
|
|
55
|
+
const generics = new Set([
|
|
56
|
+
"serif", "sans-serif", "monospace", "cursive", "fantasy",
|
|
57
|
+
"system-ui", "ui-serif", "ui-sans-serif", "ui-monospace", "ui-rounded",
|
|
58
|
+
"emoji", "math", "fangsong",
|
|
59
|
+
]);
|
|
60
|
+
const trimmed = name.trim();
|
|
61
|
+
if (generics.has(trimmed))
|
|
62
|
+
return trimmed;
|
|
63
|
+
// Wrap in single quotes with escaping to prevent CSS injection
|
|
64
|
+
return `'${escapeCSSString(trimmed)}'`;
|
|
65
|
+
}
|
|
66
|
+
// Counter for generating unique class names
|
|
67
|
+
let classCounter = 0;
|
|
68
|
+
// Track which font stylesheets have been injected (SSR + client)
|
|
69
|
+
const injectedFonts = new Set();
|
|
70
|
+
/**
|
|
71
|
+
* Convert a font family name to a CSS variable name.
|
|
72
|
+
* e.g., "Inter" -> "--font-inter", "Roboto Mono" -> "--font-roboto-mono"
|
|
73
|
+
*/
|
|
74
|
+
function toVarName(family) {
|
|
75
|
+
return "--font-" + family.toLowerCase().replace(/\s+/g, "-");
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Build a Google Fonts CSS URL.
|
|
79
|
+
*/
|
|
80
|
+
export function buildGoogleFontsUrl(family, options) {
|
|
81
|
+
const params = new URLSearchParams();
|
|
82
|
+
// Don't pre-replace spaces with "+". URLSearchParams handles encoding:
|
|
83
|
+
// spaces become "+" in application/x-www-form-urlencoded format.
|
|
84
|
+
// Pre-replacing would cause double-encoding: "+" -> "%2B" (400 error).
|
|
85
|
+
let spec = family;
|
|
86
|
+
// Build weight/style specs
|
|
87
|
+
const weights = options.weight
|
|
88
|
+
? Array.isArray(options.weight)
|
|
89
|
+
? options.weight
|
|
90
|
+
: [options.weight]
|
|
91
|
+
: [];
|
|
92
|
+
const styles = options.style
|
|
93
|
+
? Array.isArray(options.style)
|
|
94
|
+
? options.style
|
|
95
|
+
: [options.style]
|
|
96
|
+
: [];
|
|
97
|
+
if (weights.length > 0 || styles.length > 0) {
|
|
98
|
+
const hasItalic = styles.includes("italic");
|
|
99
|
+
if (weights.length > 0) {
|
|
100
|
+
if (hasItalic) {
|
|
101
|
+
// Use ital axis: ital,wght@0,400;0,700;1,400;1,700
|
|
102
|
+
const pairs = [];
|
|
103
|
+
for (const w of weights) {
|
|
104
|
+
pairs.push(`0,${w}`);
|
|
105
|
+
pairs.push(`1,${w}`);
|
|
106
|
+
}
|
|
107
|
+
spec += `:ital,wght@${pairs.join(";")}`;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
spec += `:wght@${weights.join(";")}`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// When no weight is specified, request the full variable weight range.
|
|
116
|
+
// Without this, Google Fonts returns only weight 400 (the default).
|
|
117
|
+
// Next.js loads the full variable font by default, so we match that
|
|
118
|
+
// behavior to ensure all font weights render correctly.
|
|
119
|
+
spec += `:wght@100..900`;
|
|
120
|
+
}
|
|
121
|
+
params.set("family", spec);
|
|
122
|
+
params.set("display", options.display ?? "swap");
|
|
123
|
+
return `https://fonts.googleapis.com/css2?${params.toString()}`;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Inject a <link> tag for the font (client-side only).
|
|
127
|
+
* On the server, we track font URLs for SSR head injection.
|
|
128
|
+
*/
|
|
129
|
+
function injectFontStylesheet(url) {
|
|
130
|
+
if (injectedFonts.has(url))
|
|
131
|
+
return;
|
|
132
|
+
injectedFonts.add(url);
|
|
133
|
+
if (typeof document !== "undefined") {
|
|
134
|
+
const link = document.createElement("link");
|
|
135
|
+
link.rel = "stylesheet";
|
|
136
|
+
link.href = url;
|
|
137
|
+
document.head.appendChild(link);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** Track which className CSS rules have been injected. */
|
|
141
|
+
const injectedClassRules = new Set();
|
|
142
|
+
/**
|
|
143
|
+
* Inject a CSS rule that maps a className to a font-family.
|
|
144
|
+
*
|
|
145
|
+
* This is what makes `<div className={inter.className}>` apply the font.
|
|
146
|
+
* Next.js generates equivalent rules at build time.
|
|
147
|
+
*
|
|
148
|
+
* In Next.js, the .className class ONLY sets font-family — it does NOT
|
|
149
|
+
* set CSS variables. CSS variables are handled separately by the .variable class.
|
|
150
|
+
*/
|
|
151
|
+
function injectClassNameRule(className, fontFamily) {
|
|
152
|
+
if (injectedClassRules.has(className))
|
|
153
|
+
return;
|
|
154
|
+
injectedClassRules.add(className);
|
|
155
|
+
const css = `.${className} { font-family: ${fontFamily}; }\n`;
|
|
156
|
+
// On server, store the CSS for SSR injection
|
|
157
|
+
if (typeof document === "undefined") {
|
|
158
|
+
ssrFontStyles.push(css);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// On client, inject a <style> tag
|
|
162
|
+
const style = document.createElement("style");
|
|
163
|
+
style.textContent = css;
|
|
164
|
+
style.setAttribute("data-vinext-font-class", className);
|
|
165
|
+
document.head.appendChild(style);
|
|
166
|
+
}
|
|
167
|
+
/** Track which variable class CSS rules have been injected. */
|
|
168
|
+
const injectedVariableRules = new Set();
|
|
169
|
+
/** Track which :root CSS variable rules have been injected. */
|
|
170
|
+
const injectedRootVariables = new Set();
|
|
171
|
+
/**
|
|
172
|
+
* Inject a CSS rule that sets a CSS variable on an element.
|
|
173
|
+
* This is what makes `<html className={inter.variable}>` set the CSS variable
|
|
174
|
+
* that can be referenced by other styles (e.g., Tailwind's font-sans).
|
|
175
|
+
*
|
|
176
|
+
* In Next.js, the .variable class ONLY sets the CSS variable — it does NOT
|
|
177
|
+
* set font-family. This is critical because apps commonly apply multiple
|
|
178
|
+
* .variable classes to <body> (e.g., geistSans.variable + geistMono.variable).
|
|
179
|
+
* If we also set font-family here, the last class wins due to CSS cascade,
|
|
180
|
+
* causing all text to use that font (e.g., everything becomes monospace).
|
|
181
|
+
*/
|
|
182
|
+
function injectVariableClassRule(variableClassName, cssVarName, fontFamily) {
|
|
183
|
+
if (injectedVariableRules.has(variableClassName))
|
|
184
|
+
return;
|
|
185
|
+
injectedVariableRules.add(variableClassName);
|
|
186
|
+
// Only set the CSS variable — do NOT set font-family.
|
|
187
|
+
// This matches Next.js behavior where .variable classes only define CSS variables.
|
|
188
|
+
let css = `.${variableClassName} { ${cssVarName}: ${fontFamily}; }\n`;
|
|
189
|
+
// Also inject at :root so CSS variable inheritance works throughout the page.
|
|
190
|
+
// This ensures Tailwind utilities like `font-sans` that reference these
|
|
191
|
+
// variables via var(--font-geist-sans) work correctly.
|
|
192
|
+
if (!injectedRootVariables.has(cssVarName)) {
|
|
193
|
+
injectedRootVariables.add(cssVarName);
|
|
194
|
+
css += `:root { ${cssVarName}: ${fontFamily}; }\n`;
|
|
195
|
+
}
|
|
196
|
+
// On server, store the CSS for SSR injection
|
|
197
|
+
if (typeof document === "undefined") {
|
|
198
|
+
ssrFontStyles.push(css);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// On client, inject a <style> tag
|
|
202
|
+
const style = document.createElement("style");
|
|
203
|
+
style.textContent = css;
|
|
204
|
+
style.setAttribute("data-vinext-font-variable", variableClassName);
|
|
205
|
+
document.head.appendChild(style);
|
|
206
|
+
}
|
|
207
|
+
// SSR: collect font class CSS for injection in <head>
|
|
208
|
+
const ssrFontStyles = [];
|
|
209
|
+
/**
|
|
210
|
+
* Get collected SSR font class styles (used by the renderer).
|
|
211
|
+
* Note: We don't clear the arrays because fonts are loaded at module import
|
|
212
|
+
* time and need to persist across all requests in the Workers environment.
|
|
213
|
+
*/
|
|
214
|
+
export function getSSRFontStyles() {
|
|
215
|
+
return [...ssrFontStyles];
|
|
216
|
+
}
|
|
217
|
+
// SSR: collect font URLs to inject in <head>
|
|
218
|
+
const ssrFontUrls = [];
|
|
219
|
+
/**
|
|
220
|
+
* Get collected SSR font URLs (used by the renderer).
|
|
221
|
+
* Note: We don't clear the arrays because fonts are loaded at module import
|
|
222
|
+
* time and need to persist across all requests in the Workers environment.
|
|
223
|
+
*/
|
|
224
|
+
export function getSSRFontLinks() {
|
|
225
|
+
return [...ssrFontUrls];
|
|
226
|
+
}
|
|
227
|
+
// SSR: collect font file URLs for <link rel="preload"> injection (self-hosted Google fonts)
|
|
228
|
+
const ssrFontPreloads = [];
|
|
229
|
+
const ssrFontPreloadHrefs = new Set();
|
|
230
|
+
/**
|
|
231
|
+
* Get collected SSR font preload data (used by the renderer).
|
|
232
|
+
* Returns an array of { href, type } objects for emitting
|
|
233
|
+
* <link rel="preload" as="font" ...> tags.
|
|
234
|
+
*/
|
|
235
|
+
export function getSSRFontPreloads() {
|
|
236
|
+
return [...ssrFontPreloads];
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Determine the MIME type for a font file based on its extension.
|
|
240
|
+
*/
|
|
241
|
+
function getFontMimeType(pathOrUrl) {
|
|
242
|
+
if (pathOrUrl.endsWith(".woff2"))
|
|
243
|
+
return "font/woff2";
|
|
244
|
+
if (pathOrUrl.endsWith(".woff"))
|
|
245
|
+
return "font/woff";
|
|
246
|
+
if (pathOrUrl.endsWith(".ttf"))
|
|
247
|
+
return "font/ttf";
|
|
248
|
+
if (pathOrUrl.endsWith(".otf"))
|
|
249
|
+
return "font/opentype";
|
|
250
|
+
return "font/woff2";
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Extract font file URLs from @font-face CSS rules.
|
|
254
|
+
* Parses url('...') references from the CSS text.
|
|
255
|
+
*/
|
|
256
|
+
function extractFontUrlsFromCSS(css) {
|
|
257
|
+
const urls = [];
|
|
258
|
+
const urlRegex = /url\(['"]?([^'")]+)['"]?\)/g;
|
|
259
|
+
let match;
|
|
260
|
+
while ((match = urlRegex.exec(css)) !== null) {
|
|
261
|
+
const url = match[1];
|
|
262
|
+
// Only collect absolute paths (starting with /) — these are self-hosted font files
|
|
263
|
+
if (url && url.startsWith("/")) {
|
|
264
|
+
urls.push(url);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return urls;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Collect font file URLs from self-hosted CSS for preload link generation.
|
|
271
|
+
* Only collects on the server (SSR). Deduplicates by href using a Set for O(1) lookups.
|
|
272
|
+
*/
|
|
273
|
+
function collectFontPreloadsFromCSS(css) {
|
|
274
|
+
if (typeof document !== "undefined")
|
|
275
|
+
return; // client-side, skip
|
|
276
|
+
const urls = extractFontUrlsFromCSS(css);
|
|
277
|
+
for (const href of urls) {
|
|
278
|
+
if (!ssrFontPreloadHrefs.has(href)) {
|
|
279
|
+
ssrFontPreloadHrefs.add(href);
|
|
280
|
+
ssrFontPreloads.push({ href, type: getFontMimeType(href) });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/** Track injected self-hosted @font-face blocks (deduplicate) */
|
|
285
|
+
const injectedSelfHosted = new Set();
|
|
286
|
+
/**
|
|
287
|
+
* Inject self-hosted @font-face CSS (from the build plugin).
|
|
288
|
+
* This replaces the CDN <link> tag with inline CSS.
|
|
289
|
+
*/
|
|
290
|
+
function injectSelfHostedCSS(css) {
|
|
291
|
+
if (injectedSelfHosted.has(css))
|
|
292
|
+
return;
|
|
293
|
+
injectedSelfHosted.add(css);
|
|
294
|
+
// Extract font file URLs for preload hints (SSR only)
|
|
295
|
+
collectFontPreloadsFromCSS(css);
|
|
296
|
+
if (typeof document === "undefined") {
|
|
297
|
+
// SSR: add to collected styles
|
|
298
|
+
ssrFontStyles.push(css);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
// Client: inject <style> tag
|
|
302
|
+
const style = document.createElement("style");
|
|
303
|
+
style.textContent = css;
|
|
304
|
+
style.setAttribute("data-vinext-font-selfhosted", "true");
|
|
305
|
+
document.head.appendChild(style);
|
|
306
|
+
}
|
|
307
|
+
export function createFontLoader(family) {
|
|
308
|
+
return function fontLoader(options = {}) {
|
|
309
|
+
const id = classCounter++;
|
|
310
|
+
const className = `__font_${family.toLowerCase().replace(/\s+/g, "_")}_${id}`;
|
|
311
|
+
const fallback = options.fallback ?? ["sans-serif"];
|
|
312
|
+
// Sanitize each fallback name to prevent CSS injection via crafted values
|
|
313
|
+
const fontFamily = `'${escapeCSSString(family)}', ${fallback.map(sanitizeFallback).join(", ")}`;
|
|
314
|
+
// Validate CSS variable name — reject anything that could inject CSS.
|
|
315
|
+
// Fall back to auto-generated name if invalid.
|
|
316
|
+
const defaultVarName = toVarName(family);
|
|
317
|
+
const cssVarName = options.variable ? (sanitizeCSSVarName(options.variable) ?? defaultVarName) : defaultVarName;
|
|
318
|
+
// In Next.js, `variable` returns a CLASS NAME that sets the CSS variable.
|
|
319
|
+
// Users apply this class to set the CSS variable on that element.
|
|
320
|
+
const variableClassName = `__variable_${family.toLowerCase().replace(/\s+/g, "_")}_${id}`;
|
|
321
|
+
if (options._selfHostedCSS) {
|
|
322
|
+
// Self-hosted mode: inject local @font-face CSS instead of CDN link
|
|
323
|
+
injectSelfHostedCSS(options._selfHostedCSS);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
// CDN mode: inject <link> to Google Fonts
|
|
327
|
+
const url = buildGoogleFontsUrl(family, options);
|
|
328
|
+
injectFontStylesheet(url);
|
|
329
|
+
// On SSR, collect the URL for head injection
|
|
330
|
+
if (typeof document === "undefined") {
|
|
331
|
+
if (!ssrFontUrls.includes(url)) {
|
|
332
|
+
ssrFontUrls.push(url);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
// Inject a CSS rule that maps className to font-family.
|
|
337
|
+
// This is what makes `<div className={inter.className}>` work.
|
|
338
|
+
injectClassNameRule(className, fontFamily);
|
|
339
|
+
// Inject a CSS rule for the variable class name.
|
|
340
|
+
// This is what makes `<html className={inter.variable}>` set the CSS variable.
|
|
341
|
+
injectVariableClassRule(variableClassName, cssVarName, fontFamily);
|
|
342
|
+
return {
|
|
343
|
+
className,
|
|
344
|
+
style: { fontFamily },
|
|
345
|
+
variable: variableClassName,
|
|
346
|
+
};
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
// Export a Proxy that creates font loaders for any Google Font family.
|
|
350
|
+
// Usage: import { Inter } from 'next/font/google'
|
|
351
|
+
// The proxy intercepts property access and returns a loader for that font.
|
|
352
|
+
const googleFonts = new Proxy({}, {
|
|
353
|
+
get(_target, prop) {
|
|
354
|
+
if (prop === "__esModule")
|
|
355
|
+
return true;
|
|
356
|
+
if (prop === "default")
|
|
357
|
+
return googleFonts;
|
|
358
|
+
// Convert camelCase/PascalCase to proper font family name
|
|
359
|
+
// e.g., "Inter" -> "Inter", "RobotoMono" -> "Roboto Mono"
|
|
360
|
+
const family = prop.replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
361
|
+
return createFontLoader(family);
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
export default googleFonts;
|
|
365
|
+
//# sourceMappingURL=font-google-base.js.map
|