veryfront 0.1.1180 → 0.1.1182
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/esm/deno.js +1 -1
- package/esm/src/html/hydration-script-builder/hydration-runtime.generated.js +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/http-bundle-helpers.d.ts.map +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/http-bundle-helpers.js +17 -8
- package/esm/src/platform/compat/path/url-conversion.d.ts.map +1 -1
- package/esm/src/platform/compat/path/url-conversion.js +17 -9
- package/esm/src/rendering/orchestrator/module-loader/dependency-resolver.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/module-loader/dependency-resolver.js +12 -9
- package/esm/src/rendering/orchestrator/module-loader/index.js +4 -4
- package/esm/src/rendering/renderer.d.ts.map +1 -1
- package/esm/src/rendering/renderer.js +2 -0
- package/esm/src/server/handlers/utils/dependency-pinning-source.d.ts.map +1 -1
- package/esm/src/server/handlers/utils/dependency-pinning-source.js +1 -0
- package/esm/src/transforms/esm/npm-registry-client.d.ts +8 -5
- package/esm/src/transforms/esm/npm-registry-client.d.ts.map +1 -1
- package/esm/src/transforms/esm/npm-registry-client.js +12 -6
- package/esm/src/transforms/esm/package-registry.d.ts +3 -0
- package/esm/src/transforms/esm/package-registry.d.ts.map +1 -1
- package/esm/src/transforms/esm/package-registry.js +1 -0
- package/esm/src/transforms/import-rewriter/dependency-resolution.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/dependency-resolution.js +5 -0
- package/esm/src/transforms/mdx/esm-module-loader/cache/index.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/cache/index.js +20 -6
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -5
package/esm/deno.js
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
* `deno task generate` to regenerate.
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
|
-
export const HYDRATION_RUNTIME_BUNDLE = '// src/html/hydration-script-builder/runtime/main.ts\nimport * as React from "react";\nimport { createRoot } from "react-dom/client";\nimport { RouterProvider, useRouter as useRouterFromModule } from "veryfront/router";\nimport * as RouterRuntime from "veryfront/router";\nimport { PageContextProvider } from "veryfront/context";\n\n// src/routing/flatten-route-params.ts\nfunction flattenRouteParams(params) {\n if (!params) return {};\n const flat = {};\n for (const [key, value] of Object.entries(params)) {\n if (value === void 0) continue;\n flat[key] = Array.isArray(value) ? value.join("/") : value;\n }\n return flat;\n}\n\n// src/html/hydration-script-builder/runtime/shared.ts\nfunction moduleServerUrl(window) {\n return window.location.origin + "/_vf_modules";\n}\nfunction createLogging(window) {\n const DEBUG = Boolean(\n window.__VERYFRONT_DEBUG__ || new URLSearchParams(window.location.search).has("vf_debug")\n );\n const log = DEBUG ? console.log.bind(console, "[Veryfront]") : () => {\n };\n const logError = console.error.bind(console, "[Veryfront]");\n function logBackgroundFetchFailure(reason, path, error) {\n const message = error?.message ?? String(error);\n log(reason + " failed:", path, message);\n }\n const perfTimers = /* @__PURE__ */ new Map();\n const perfStart = DEBUG ? (label) => {\n perfTimers.set(label, performance.now());\n } : () => {\n };\n const perfEnd = DEBUG ? (label) => {\n const start = perfTimers.get(label);\n if (start === void 0) return 0;\n const duration = performance.now() - start;\n perfTimers.delete(label);\n console.log(\n "[Veryfront Perf] %c" + label + ": %c" + duration.toFixed(2) + "ms",\n "color: #888",\n duration > 100 ? "color: #f00; font-weight: bold" : "color: #0a0"\n );\n return duration;\n } : () => 0;\n return { DEBUG, log, logError, logBackgroundFetchFailure, perfStart, perfEnd };\n}\nfunction isAbortError(error) {\n return error?.name === "AbortError";\n}\nfunction resolveDocumentNavigationUrl(target, origin) {\n try {\n const url = new URL(target, origin);\n if (url.protocol === "http:" || url.protocol === "https:") return url.href;\n } catch (_) {\n }\n return null;\n}\nfunction getDocumentNonce(document) {\n const element = document.querySelector("script[nonce], style[nonce], link[nonce]");\n if (!element) return void 0;\n return element.nonce || element.getAttribute("nonce") || void 0;\n}\n\n// src/html/hydration-script-builder/runtime/hydration-data.ts\nvar HYDRATION_DATA_ELEMENT_ID = "veryfront-hydration-data";\nfunction readInitialHydrationData(document) {\n try {\n const element = document.getElementById(HYDRATION_DATA_ELEMENT_ID);\n return JSON.parse(element && element.textContent ? element.textContent : "{}") || {};\n } catch (_) {\n return {};\n }\n}\nfunction readDocumentDependencyPinningCacheKey(initialHydrationData2) {\n return typeof initialHydrationData2.dependencyPinningCacheKey === "string" && initialHydrationData2.dependencyPinningCacheKey.startsWith("on:") ? initialHydrationData2.dependencyPinningCacheKey : null;\n}\n\n// src/html/hydration-script-builder/runtime/snapshot-modules.ts\nvar RECOVERY_STATE_KEY = "__VF_DEPENDENCY_SNAPSHOT_RECOVERY_STARTED__";\nasync function isDependencySnapshotConflictResponse(response) {\n if (!response || response.status !== 409) return false;\n try {\n const clone = response.clone?.() ?? response;\n const body = (await clone.text?.() ?? "").trim();\n return body === "Unknown dependency snapshot" || body === "export default null; // Unknown dependency snapshot";\n } catch (_) {\n return false;\n }\n}\nfunction createSnapshotModuleImporter(deps) {\n async function recoverFromSnapshotBoundModuleFailure(moduleUrl, allowDocumentReload = true) {\n try {\n const parsedUrl = new URL(moduleUrl, "http://veryfront.local");\n const snapshotKeys = parsedUrl.searchParams.getAll("pins");\n const pathMatch = parsedUrl.pathname.match(\n /^\\/_vf_modules\\/_pins\\/([^/]+)(?:\\/|$)/\n );\n if (pathMatch) {\n try {\n snapshotKeys.push(decodeURIComponent(pathMatch[1]));\n } catch (_) {\n return false;\n }\n }\n if (snapshotKeys.length !== 1 || !/^on:[A-Za-z0-9._-]+$/.test(snapshotKeys[0])) return false;\n const response = await deps.fetchModule(moduleUrl, { cache: "no-store" });\n if (!await isDependencySnapshotConflictResponse(response)) return false;\n if (!allowDocumentReload) return true;\n if (deps.recoveryState[RECOVERY_STATE_KEY] === true) return true;\n deps.recoveryState[RECOVERY_STATE_KEY] = true;\n try {\n deps.reloadDocument();\n } catch (_) {\n delete deps.recoveryState[RECOVERY_STATE_KEY];\n return false;\n }\n return true;\n } catch (_) {\n return false;\n }\n }\n async function importSnapshotBoundModule(moduleUrl, allowDocumentReload = true) {\n try {\n return await deps.importModule(moduleUrl);\n } catch (error) {\n const snapshotConflict = await recoverFromSnapshotBoundModuleFailure(\n moduleUrl,\n allowDocumentReload\n );\n if (snapshotConflict && !allowDocumentReload) {\n const conflictError = new Error(\n "Dependency snapshot is unavailable during speculative module prefetch"\n );\n conflictError.name = "DependencySnapshotConflictError";\n conflictError.dependencySnapshotConflict = true;\n conflictError.cause = error;\n throw conflictError;\n }\n throw error;\n }\n }\n return { importSnapshotBoundModule, recoverFromSnapshotBoundModuleFailure };\n}\nfunction isDependencySnapshotConflict(error) {\n return Boolean(error?.dependencySnapshotConflict);\n}\n\n// src/utils/version-constant.ts\nvar VERSION = "0.1.1180";\n\n// src/html/hydration-script-builder/runtime/module-urls.ts\nfunction appendQueryParam(url, key, value) {\n return url + (url.includes("?") ? "&" : "?") + key + "=" + value;\n}\nfunction appendDependencyPinningVersion(url, moduleData) {\n const pinKey = moduleData && moduleData.dependencyPinningCacheKey;\n if (typeof pinKey !== "string" || !pinKey.startsWith("on:")) return url;\n const hashIndex = url.indexOf("#");\n const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";\n const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;\n const queryIndex = withoutHash.indexOf("?");\n const base = queryIndex >= 0 ? withoutHash.slice(0, queryIndex) : withoutHash;\n const params = new URLSearchParams(queryIndex >= 0 ? withoutHash.slice(queryIndex + 1) : "");\n const modulePrefix = "/_vf_modules/";\n const prefixIndex = base.indexOf(modulePrefix);\n const origin = prefixIndex >= 0 ? base.slice(0, prefixIndex) : "";\n if (prefixIndex >= 0 && (origin === "" || /^https?:\\/\\/[^/]+$/i.test(origin))) {\n const pathStart = prefixIndex + modulePrefix.length;\n let modulePath = base.slice(pathStart);\n if (modulePath.startsWith("_pins/")) {\n const existingKeyEnd = modulePath.indexOf("/", "_pins/".length);\n const encodedExistingKey = existingKeyEnd < 0 ? modulePath.slice("_pins/".length) : modulePath.slice("_pins/".length, existingKeyEnd);\n let existingKey;\n try {\n existingKey = decodeURIComponent(encodedExistingKey);\n } catch {\n existingKey = void 0;\n }\n if (existingKey && /^on:[A-Za-z0-9._-]+$/.test(existingKey)) {\n if (existingKeyEnd < 0) return url;\n modulePath = modulePath.slice(existingKeyEnd + 1);\n }\n }\n params.delete("pins");\n const query = params.toString();\n return base.slice(0, pathStart) + "_pins/" + encodeURIComponent(pinKey) + "/" + modulePath + (query ? "?" + query : "") + hash;\n }\n params.set("pins", pinKey);\n return base + "?" + params.toString() + hash;\n}\nfunction componentCacheKey(path, moduleData) {\n const pinKey = moduleData && moduleData.dependencyPinningCacheKey;\n return typeof pinKey === "string" && pinKey.startsWith("on:") ? path + "|vf_pins|" + pinKey : path;\n}\nfunction normalizeReleaseAssetModulePath(path) {\n return String(path || "").replace(/^\\/?_vf_modules\\//, "").replace(/^\\/+/, "").replace(/[?#].*$/, "");\n}\nfunction buildPinnedRscModuleUrl(path, moduleData) {\n let moduleUrl = "/_veryfront/rsc/module?rel=" + encodeURIComponent(path);\n const pinKey = moduleData && moduleData.dependencyPinningCacheKey;\n if (typeof pinKey === "string" && pinKey.startsWith("on:")) {\n moduleUrl += "&pins=" + encodeURIComponent(pinKey);\n }\n return moduleUrl;\n}\nfunction buildPageDataEndpoint(path, origin) {\n const targetUrl = new URL(path, origin);\n const normalizedPath = targetUrl.pathname === "/" ? "" : targetUrl.pathname.replace(/^\\//, "");\n const endpointUrl = new URL(\n "/_veryfront/page-data/" + normalizedPath + ".json",\n origin\n );\n endpointUrl.search = targetUrl.search;\n return endpointUrl.pathname + endpointUrl.search;\n}\nfunction pageDataCacheIdentity(path, documentDependencyPinningCacheKey2) {\n return documentDependencyPinningCacheKey2 ? documentDependencyPinningCacheKey2 + "|path:" + path : path;\n}\nfunction assertPageDataMatchesDocumentSnapshot(path, data, documentDependencyPinningCacheKey2) {\n if (!documentDependencyPinningCacheKey2) return data;\n if (data && data.dependencyPinningCacheKey === documentDependencyPinningCacheKey2) {\n return data;\n }\n const error = new Error("Page data dependency snapshot does not match the document");\n error.status = 409;\n error.dependencySnapshotMismatch = true;\n error.path = path;\n throw error;\n}\n\n// src/html/hydration-script-builder/runtime/component-loader.ts\nvar VERYFRONT_RUNTIME_VERSION = VERSION;\nfunction createComponentLoader(deps) {\n const { window, moduleServerUrl: moduleServerUrl2 } = deps;\n const { DEBUG, log, logError } = deps.logging;\n const componentCache = /* @__PURE__ */ new Map();\n const loadingPromises = /* @__PURE__ */ new Map();\n let releaseId = null;\n let releaseAssetModules = null;\n let studioEmbed = false;\n let hmrRefreshTimestamp = null;\n function clearComponentCache(path) {\n if (!path) {\n componentCache.clear();\n loadingPromises.clear();\n log("Cleared all component caches");\n return;\n }\n for (const key of componentCache.keys()) {\n if (key === path || key.startsWith(path + "|vf_pins|")) {\n componentCache.delete(key);\n }\n }\n for (const key of loadingPromises.keys()) {\n if (key === path || key.startsWith(path + "|vf_pins|")) {\n loadingPromises.delete(key);\n }\n }\n log("Cleared component cache for:", path);\n }\n function setReleaseId(value) {\n releaseId = typeof value === "string" && value ? value : null;\n window.__veryfrontReleaseId = releaseId;\n }\n function appendReleaseModuleVersion(url) {\n if (!releaseId || url.includes("vf_release=")) return url;\n let versionedUrl = appendQueryParam(url, "vf_release", encodeURIComponent(releaseId));\n versionedUrl = appendQueryParam(\n versionedUrl,\n "vf_runtime",\n encodeURIComponent(VERYFRONT_RUNTIME_VERSION)\n );\n return versionedUrl;\n }\n function setReleaseAssetModules(value) {\n releaseAssetModules = value && typeof value === "object" && !Array.isArray(value) ? value : null;\n window.__veryfrontReleaseAssetModules = releaseAssetModules;\n }\n function resolveReleaseAssetModuleUrl(path) {\n if (!releaseAssetModules || studioEmbed || hmrRefreshTimestamp) return null;\n const key = normalizeReleaseAssetModulePath(path);\n if (releaseAssetModules[key]) return releaseAssetModules[key];\n const withoutExt = key.replace(/\\.(tsx|ts|jsx|mdx|js|mjs)$/, "");\n const extensions = [".tsx", ".ts", ".jsx", ".mdx", ".js"];\n for (const ext of extensions) {\n const candidate = withoutExt + ext;\n if (releaseAssetModules[candidate]) return releaseAssetModules[candidate];\n }\n return null;\n }\n function pathToModuleUrl(path, embedInStudio, moduleData) {\n const releaseAssetUrl = resolveReleaseAssetModuleUrl(path);\n if (releaseAssetUrl) return releaseAssetUrl;\n const pattern = /(pages|components|app|lib|layouts|shared|features)\\/(.+)\\.(tsx|ts|jsx|mdx)$/;\n const match = path.match(new RegExp("/" + pattern.source)) || path.match(new RegExp("^" + pattern.source));\n let url;\n if (match) {\n url = moduleServerUrl2 + "/" + match[1] + "/" + match[2] + ".js";\n } else {\n const hasKnownExt = /\\.(tsx|ts|jsx|mdx|js|mjs)$/.test(path);\n url = moduleServerUrl2 + "/" + (hasKnownExt ? path.replace(/\\.(tsx|ts|jsx|mdx)$/, ".js") : path + ".js");\n }\n if (embedInStudio) url = appendQueryParam(url, "studio_embed", "true");\n if (hmrRefreshTimestamp) url = appendQueryParam(url, "t", hmrRefreshTimestamp);\n if (!embedInStudio && !hmrRefreshTimestamp) url = appendReleaseModuleVersion(url);\n url = appendDependencyPinningVersion(url, moduleData);\n return url;\n }\n function setStudioEmbed(value) {\n studioEmbed = value;\n window.__veryfrontStudioEmbed = value;\n }\n function setHMRRefreshTimestamp(timestamp) {\n hmrRefreshTimestamp = timestamp;\n window.__veryfrontHMRRefreshTimestamp = timestamp;\n }\n async function loadComponent(path, moduleData, options = {}) {\n if (!path) return null;\n const cacheKey = componentCacheKey(path, moduleData);\n if (componentCache.has(cacheKey)) {\n log("Component cached:", path);\n return componentCache.get(cacheKey);\n }\n const existingPromise = loadingPromises.get(cacheKey);\n if (existingPromise) return existingPromise;\n const loadPromise = (async () => {\n try {\n const moduleUrl = pathToModuleUrl(path, studioEmbed, moduleData);\n const start = DEBUG ? performance.now() : 0;\n log("Loading component:", moduleUrl);\n const module = await deps.snapshotModules.importSnapshotBoundModule(\n moduleUrl,\n options.allowDocumentReload !== false\n );\n const component = module.MDXLayout || module.MainLayout || module.default || module;\n if (DEBUG) {\n const duration = performance.now() - start;\n console.log(\n "[Veryfront Perf] %cimport:" + path.split("/").pop() + ": %c" + duration.toFixed(2) + "ms",\n "color: #888",\n duration > 50 ? "color: #f00; font-weight: bold" : "color: #0a0"\n );\n }\n componentCache.set(cacheKey, component);\n return component;\n } catch (error) {\n if (isDependencySnapshotConflict(error)) throw error;\n logError("Failed to load component:", path, error);\n return null;\n } finally {\n loadingPromises.delete(cacheKey);\n }\n })();\n loadingPromises.set(cacheKey, loadPromise);\n return loadPromise;\n }\n return {\n loadComponent,\n pathToModuleUrl,\n clearComponentCache,\n setStudioEmbed,\n setReleaseId,\n setReleaseAssetModules,\n setHMRRefreshTimestamp\n };\n}\n\n// src/html/hydration-script-builder/runtime/route-timing.ts\nvar MAX_ROUTE_TIMINGS = 100;\nvar MAX_SERVER_TIMING_LENGTH = 1024;\nfunction routeTimingNow() {\n return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();\n}\nfunction sanitizeServerTimingMetricName(name) {\n return String(name || "").trim().replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 128);\n}\nfunction sanitizeServerTimingHeader(value) {\n if (!value) return null;\n const metrics = [];\n const printable = String(value).replace(/[^\\x20-\\x7E]/g, " ").trim();\n if (!printable) return null;\n for (const item of printable.split(",")) {\n const segments = item.split(";").map((segment) => segment.trim()).filter(Boolean);\n const name = sanitizeServerTimingMetricName(segments[0]);\n if (!name) continue;\n for (const segment of segments.slice(1)) {\n const [key, rawValue = ""] = segment.split("=");\n if ((key ?? "").trim().toLowerCase() !== "dur") continue;\n const duration = Number(rawValue.trim().replace(/^"|"$/g, ""));\n if (!Number.isFinite(duration) || duration < 0) continue;\n metrics.push(name + ";dur=" + (Math.round(duration * 100) / 100).toFixed(2));\n break;\n }\n }\n const sanitized = metrics.join(", ");\n return sanitized ? sanitized.slice(0, MAX_SERVER_TIMING_LENGTH) : null;\n}\nfunction parseServerTimingMetrics(value) {\n const header = sanitizeServerTimingHeader(value);\n if (!header) return null;\n const metrics = {};\n for (const item of header.split(",")) {\n const segments = item.split(";").map((segment) => segment.trim()).filter(Boolean);\n const name = sanitizeServerTimingMetricName(segments[0]);\n if (!name) continue;\n for (const segment of segments.slice(1)) {\n const [key, rawValue = ""] = segment.split("=");\n if ((key ?? "").trim().toLowerCase() !== "dur") continue;\n const duration = Number(rawValue.trim().replace(/^"|"$/g, ""));\n if (Number.isFinite(duration) && duration >= 0) {\n metrics[name] = Math.round(duration * 100) / 100;\n }\n }\n }\n return Object.keys(metrics).length ? metrics : null;\n}\nfunction readResponseServerTiming(response) {\n try {\n return sanitizeServerTimingHeader(response.headers?.get("server-timing"));\n } catch (_) {\n return null;\n }\n}\nfunction roundRouteTimingValue(value) {\n return Math.round(value * 100) / 100;\n}\nfunction extractResourceTiming(entry) {\n const fields = [\n "startTime",\n "requestStart",\n "responseStart",\n "responseEnd",\n "duration",\n "transferSize",\n "encodedBodySize",\n "decodedBodySize"\n ];\n const timing = {};\n for (const field of fields) {\n const value = entry?.[field];\n if (typeof value === "number" && Number.isFinite(value) && value >= 0) {\n timing[field] = roundRouteTimingValue(value);\n }\n }\n return Object.keys(timing).length ? timing : null;\n}\nfunction createRouteTimingRecorder(window, logging2) {\n const { log } = logging2;\n function emitRouteTiming(phase, path, startedAt, detail = {}) {\n const entry = {\n phase,\n path,\n duration: Math.max(0, routeTimingNow() - startedAt),\n timestamp: Date.now(),\n ...detail\n };\n const timings = Array.isArray(window.__veryfrontRouteTimings) ? window.__veryfrontRouteTimings : [];\n timings.push(entry);\n if (timings.length > MAX_ROUTE_TIMINGS) {\n timings.splice(0, timings.length - MAX_ROUTE_TIMINGS);\n }\n window.__veryfrontRouteTimings = timings;\n try {\n window.dispatchEvent(new CustomEvent("veryfront:route-timing", { detail: entry }));\n } catch (_) {\n }\n log("Route timing:", entry);\n return entry;\n }\n function getPageDataResourceTiming(endpoint, fetchStartedAt) {\n try {\n if (typeof performance === "undefined" || typeof performance.getEntriesByName !== "function") {\n return null;\n }\n const href = new URL(endpoint, window.location.href).href;\n const entries = performance.getEntriesByName(href, "resource");\n if (!entries.length) return null;\n for (let index = entries.length - 1; index >= 0; index--) {\n const entry = entries[index];\n const responseEnd = entry?.responseEnd;\n if (typeof responseEnd === "number" && Number.isFinite(responseEnd) && responseEnd + 1 >= fetchStartedAt) {\n return extractResourceTiming(entry);\n }\n }\n return null;\n } catch (_) {\n return null;\n }\n }\n function buildPageDataTimingDetail(response, endpoint, fetchStartedAt, source) {\n const detail = { source, status: response.status };\n const serverTiming = readResponseServerTiming(response);\n if (serverTiming) {\n detail.serverTiming = serverTiming;\n const serverTimingMetrics = parseServerTimingMetrics(serverTiming);\n if (serverTimingMetrics) detail.serverTimingMetrics = serverTimingMetrics;\n }\n const resourceTiming = getPageDataResourceTiming(response.url || endpoint, fetchStartedAt);\n if (resourceTiming) detail.resourceTiming = resourceTiming;\n return detail;\n }\n return { emitRouteTiming, buildPageDataTimingDetail };\n}\n\n// src/html/hydration-script-builder/runtime/router.ts\nvar FETCH_TIMEOUT_MS = 1e4;\nvar MAX_RETRIES = 2;\nvar MAX_CACHE_SIZE = 50;\nvar CACHE_TTL_MS = 5 * 60 * 1e3;\nvar BACKGROUND_REFRESH_INTERVAL_MS = 30 * 1e3;\nvar PREFETCH_DELAY_MS = 100;\nvar MAX_PREFETCH_PATHS = 100;\nvar IDLE_PREFETCH_DELAY_MS = 1200;\nvar IDLE_PREFETCH_MAX_LINKS = 4;\nvar VIEWPORT_PREFETCH_MAX_LINKS = 8;\nvar PAGE_DATA_PREFETCH_CONCURRENCY = 2;\nvar VIEWPORT_PREFETCH_ROOT_MARGIN = "200px";\nvar MAX_SCROLL_POSITIONS = 100;\nfunction createRouterRuntime(deps) {\n const { env: env2, logging: logging2, routeTiming: routeTiming2, componentLoader: componentLoader2, snapshotModules: snapshotModules2 } = deps;\n const { window, document, React: React2, RouterProvider: RouterProvider2, PageContextProvider: PageContextProvider2 } = env2;\n const { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = env2;\n const { log, logError, logBackgroundFetchFailure, perfStart, perfEnd } = logging2;\n const { emitRouteTiming, buildPageDataTimingDetail } = routeTiming2;\n const { loadComponent } = componentLoader2;\n const documentPinKey = deps.documentDependencyPinningCacheKey;\n let hydrationResolve;\n let hydrationReject;\n const hydrationPromise = new Promise((resolve, reject) => {\n hydrationResolve = resolve;\n hydrationReject = reject;\n });\n let hydrationCompleted = false;\n let hydrationFailed = false;\n function signalHydrationComplete() {\n hydrationCompleted = true;\n hydrationResolve();\n log("Hydration complete signal received");\n }\n function signalHydrationFailed(error) {\n hydrationFailed = true;\n hydrationReject(error);\n logError("Hydration failed signal received:", error);\n }\n window.__veryfrontHydrationComplete = signalHydrationComplete;\n window.__veryfrontHydrationFailed = signalHydrationFailed;\n function pageDataCacheIdentity2(path) {\n return pageDataCacheIdentity(path, documentPinKey);\n }\n function navigateDocument(target) {\n const safeUrl = resolveDocumentNavigationUrl(target, window.location.origin);\n if (safeUrl) {\n window.location.href = safeUrl;\n return;\n }\n logError("Refusing an unsafe document navigation:", target);\n window.location.reload();\n }\n let clientBuildVersion = null;\n function checkVersionMismatch(newVersion) {\n if (!clientBuildVersion) {\n clientBuildVersion = newVersion;\n log("Build version initialized:", newVersion);\n return false;\n }\n if (newVersion.serverStart !== clientBuildVersion.serverStart) {\n log("Server restarted, reloading...", {\n old: clientBuildVersion.serverStart,\n new: newVersion.serverStart\n });\n return true;\n }\n if (newVersion.framework !== clientBuildVersion.framework) {\n log("Framework version changed, reloading...", {\n old: clientBuildVersion.framework,\n new: newVersion.framework\n });\n return true;\n }\n if (newVersion.projectUpdated && clientBuildVersion.projectUpdated && newVersion.projectUpdated !== clientBuildVersion.projectUpdated) {\n log("Project content updated, reloading...", {\n old: clientBuildVersion.projectUpdated,\n new: newVersion.projectUpdated\n });\n return true;\n }\n return false;\n }\n const pageDataCache = /* @__PURE__ */ new Map();\n const pendingPageDataFetches = /* @__PURE__ */ new Map();\n const backgroundRefreshTimestamps = /* @__PURE__ */ new Map();\n function getCachedPageData(path) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n const entry = pageDataCache.get(cacheIdentity);\n if (!entry) return null;\n if (Date.now() - entry.timestamp < CACHE_TTL_MS) return entry.data;\n pageDataCache.delete(cacheIdentity);\n backgroundRefreshTimestamps.delete(cacheIdentity);\n return null;\n }\n function setCachedPageData(path, data) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n if (pageDataCache.size >= MAX_CACHE_SIZE) {\n const oldest = pageDataCache.keys().next().value;\n if (oldest) {\n pageDataCache.delete(oldest);\n backgroundRefreshTimestamps.delete(oldest);\n }\n }\n pageDataCache.set(cacheIdentity, { data, timestamp: Date.now() });\n }\n const scrollPositions = /* @__PURE__ */ new Map();\n function saveScrollPosition(path) {\n if (scrollPositions.size >= MAX_SCROLL_POSITIONS) {\n const oldest = scrollPositions.keys().next().value;\n if (oldest) scrollPositions.delete(oldest);\n }\n scrollPositions.set(path, window.scrollY);\n }\n function restoreScrollPosition(path) {\n const savedY = scrollPositions.get(path);\n if (savedY === void 0) return false;\n requestAnimationFrame(() => window.scrollTo(0, savedY));\n return true;\n }\n let progressBar = null;\n let progressTimeout = null;\n function showNavigationProgress() {\n if (!progressBar) {\n progressBar = document.createElement("div");\n progressBar.id = "vf-nav-progress";\n progressBar.style.cssText = "position:fixed;top:0;left:0;height:3px;width:0;background:linear-gradient(90deg,#0066ff,#00aaff);z-index:99999;transition:width 0.3s ease-out,opacity 0.2s;opacity:1;";\n document.body.prepend(progressBar);\n }\n progressBar.style.opacity = "1";\n progressBar.style.width = "30%";\n progressTimeout = setTimeout2(() => {\n if (progressBar?.style) progressBar.style.width = "70%";\n }, 300);\n document.body.setAttribute("aria-busy", "true");\n }\n function hideNavigationProgress() {\n if (progressTimeout) {\n clearTimeout2(progressTimeout);\n progressTimeout = null;\n }\n if (progressBar) {\n progressBar.style.width = "100%";\n setTimeout2(() => {\n if (!progressBar) return;\n progressBar.style.opacity = "0";\n setTimeout2(() => {\n if (progressBar) progressBar.style.width = "0";\n }, 200);\n }, 150);\n }\n document.body.removeAttribute("aria-busy");\n }\n let currentAbortController = null;\n function sleep(ms) {\n return new Promise((resolve) => setTimeout2(resolve, ms));\n }\n async function fetchWithRetry(url, options, maxRetries = MAX_RETRIES) {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new AbortController();\n const callerSignal = options.signal;\n const abortFromCaller = () => controller.abort();\n if (callerSignal?.aborted) controller.abort();\n callerSignal?.addEventListener("abort", abortFromCaller, { once: true });\n const timeout = setTimeout2(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const response = await env2.fetch(url, { ...options, signal: controller.signal });\n clearTimeout2(timeout);\n callerSignal?.removeEventListener("abort", abortFromCaller);\n if (response.ok) return response;\n if (response.status >= 500 && attempt < maxRetries) {\n log("Server error, retrying...", response.status);\n await sleep(Math.pow(2, attempt) * 500);\n continue;\n }\n return response;\n } catch (error) {\n clearTimeout2(timeout);\n callerSignal?.removeEventListener("abort", abortFromCaller);\n if (error.name === "AbortError" && callerSignal?.aborted) throw error;\n if (attempt === maxRetries) throw error;\n log("Fetch failed, retrying...", error.message);\n await sleep(Math.pow(2, attempt) * 500);\n }\n }\n throw new Error("Failed to fetch page data");\n }\n async function fetchPageDataFresh(path, signal, options = {}) {\n const {\n triggerReloadOnVersionMismatch = false,\n recordRouteTiming = false,\n timingSource = "network"\n } = options;\n const endpoint = buildPageDataEndpoint(path, window.location.origin);\n const startedAt = recordRouteTiming ? routeTimingNow() : 0;\n log("Fetching page data:", path);\n perfStart("fetch:" + path);\n const headers = options.prefetch ? { "X-Veryfront-Prefetch": "1" } : { "X-Veryfront-Navigation": "spa" };\n if (documentPinKey) {\n headers["X-Veryfront-Dependency-Pins"] = documentPinKey;\n }\n const response = await fetchWithRetry(endpoint, {\n headers,\n signal\n }, options.prefetch ? 0 : MAX_RETRIES);\n if (!response.ok) {\n perfEnd("fetch:" + path);\n if (recordRouteTiming) {\n emitRouteTiming(\n "page-data",\n path,\n startedAt,\n buildPageDataTimingDetail(response, endpoint, startedAt, timingSource)\n );\n }\n const error = new Error("Failed to fetch page data: " + response.status);\n error.status = response.status;\n throw error;\n }\n perfStart("parse:" + path);\n const data = assertPageDataMatchesDocumentSnapshot(\n path,\n await response.json(),\n documentPinKey\n );\n perfEnd("parse:" + path);\n perfEnd("fetch:" + path);\n if (recordRouteTiming) {\n emitRouteTiming(\n "page-data",\n path,\n startedAt,\n buildPageDataTimingDetail(response, endpoint, startedAt, timingSource)\n );\n }\n if (triggerReloadOnVersionMismatch) {\n const checkedData = handlePageDataVersionMismatch(path, data);\n if (checkedData !== data) return checkedData;\n }\n setCachedPageData(path, data);\n return data;\n }\n function handlePageDataVersionMismatch(path, data) {\n if (data.buildVersion && checkVersionMismatch(data.buildVersion)) {\n log("Version mismatch detected, performing full page reload to:", path);\n navigateDocument(path);\n return new Promise(() => {\n });\n }\n return data;\n }\n function startPageDataFetch(path, signal, options = {}) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n const request = fetchPageDataFresh(path, signal, options).finally(() => {\n if (options.trackPending !== false && pendingPageDataFetches.get(cacheIdentity) === request) {\n pendingPageDataFetches.delete(cacheIdentity);\n }\n });\n if (options.trackPending !== false) {\n pendingPageDataFetches.set(cacheIdentity, request);\n }\n return request;\n }\n function fetchPageDataDeduped(path) {\n const pending = pendingPageDataFetches.get(pageDataCacheIdentity2(path));\n if (pending) return pending;\n return startPageDataFetch(path, null);\n }\n function refreshPageDataInBackground(path) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n const lastRefreshAt = backgroundRefreshTimestamps.get(cacheIdentity) || 0;\n const now = Date.now();\n if (now - lastRefreshAt < BACKGROUND_REFRESH_INTERVAL_MS) return;\n backgroundRefreshTimestamps.set(cacheIdentity, now);\n fetchPageDataDeduped(path).catch((error) => {\n logBackgroundFetchFailure("Stale page data refresh", path, error);\n });\n }\n async function fetchPageDataForNavigation(path, signal) {\n const startedAt = routeTimingNow();\n const cached = getCachedPageData(path);\n if (cached) {\n log("Using cached page data:", path);\n refreshPageDataInBackground(path);\n emitRouteTiming("page-data", path, startedAt, { source: "cache" });\n return cached;\n }\n const pending = pendingPageDataFetches.get(pageDataCacheIdentity2(path));\n if (pending) {\n log("Reusing pending page data fetch for navigation:", path);\n const data = await pending;\n emitRouteTiming("page-data", path, startedAt, { source: "deduped" });\n return handlePageDataVersionMismatch(path, data);\n }\n return startPageDataFetch(path, signal, {\n triggerReloadOnVersionMismatch: true,\n recordRouteTiming: true,\n timingSource: "network"\n });\n }\n function fetchPageDataForPrefetch(path, signal) {\n if (getCachedPageData(path)) return Promise.resolve();\n return startPageDataFetch(path, signal, { prefetch: true, trackPending: false }).then((data) => preloadModulesForPageData(data, path)).catch((error) => {\n if (!isAbortError(error)) {\n logBackgroundFetchFailure("Page data prefetch", path, error);\n }\n throw error;\n });\n }\n let currentPath = window.location.pathname;\n let isNavigating = false;\n async function navigateSPA(href, historyMode = "push", restoreScroll = false) {\n currentAbortController?.abort();\n if (isNavigating) return;\n isNavigating = true;\n const [navigationPath] = href.split("#");\n removeQueuedPrefetch(navigationPath || href);\n abortActiveSpeculativePrefetches();\n currentAbortController = new AbortController();\n const signal = currentAbortController.signal;\n const navigationStartedAt = routeTimingNow();\n showNavigationProgress();\n perfStart("nav:total:" + href);\n try {\n log("SPA navigating to:", href);\n saveScrollPosition(currentPath);\n const [path, hash] = href.split("#");\n const targetPath = path || currentPath;\n perfStart("nav:fetchData:" + href);\n const pageData = await fetchPageDataForNavigation(targetPath, signal);\n perfEnd("nav:fetchData:" + href);\n if (signal.aborted) return;\n if (pageData && pageData.redirect && typeof pageData.redirect.destination === "string") {\n const redirectUrl = resolveDocumentNavigationUrl(\n pageData.redirect.destination,\n window.location.origin\n );\n if (redirectUrl) {\n log("SPA navigation redirect -> " + redirectUrl);\n window.location.href = redirectUrl;\n return;\n }\n }\n if (historyMode === "push") {\n window.history.pushState({ pageData, scrollY: 0 }, "", href);\n } else if (historyMode === "replace") {\n window.history.replaceState({ pageData, scrollY: 0 }, "", href);\n }\n currentPath = targetPath;\n router.pathname = targetPath;\n router.query = Object.fromEntries(new URLSearchParams(window.location.search));\n router.params = flattenRouteParams(pageData.params);\n perfStart("nav:render:" + href);\n await renderPageFromData(pageData, targetPath);\n perfEnd("nav:render:" + href);\n if (restoreScroll) {\n restoreScrollPosition(targetPath);\n } else if (hash) {\n requestAnimationFrame(() => {\n const target = document.getElementById(hash);\n if (target) {\n target.scrollIntoView({ behavior: "smooth" });\n return;\n }\n window.scrollTo(0, 0);\n });\n } else {\n window.scrollTo(0, 0);\n }\n hideNavigationProgress();\n perfEnd("nav:total:" + href);\n emitRouteTiming("total", targetPath, navigationStartedAt, {\n href,\n historyMode,\n restoreScroll\n });\n log("SPA navigation complete");\n } catch (error) {\n hideNavigationProgress();\n if (error.name === "AbortError") {\n log("Navigation aborted");\n return;\n }\n logError("SPA navigation failed:", error.message);\n if (error.status === 404) {\n logError("Page not found:", href);\n }\n navigateDocument(href);\n } finally {\n isNavigating = false;\n currentAbortController = null;\n processPageDataPrefetchQueue();\n }\n }\n async function loadPageDataComponent(pageData, path, options = {}) {\n if (!pageData.isolatedClientPage) return loadComponent(path, pageData, options);\n const moduleUrl = buildPinnedRscModuleUrl(path, pageData);\n const module = await snapshotModules2.importSnapshotBoundModule(\n moduleUrl,\n options.allowDocumentReload !== false\n );\n return module.MDXLayout || module.MainLayout || module.default || module;\n }\n async function renderPageFromData(pageData, targetPath) {\n if (pageData.requiresFullDocumentNavigation) {\n throw new Error("Server layout requires full document navigation");\n }\n if (window.__veryfrontSetReleaseId) {\n window.__veryfrontSetReleaseId(pageData.releaseId || null);\n }\n if (window.__veryfrontSetReleaseAssetModules) {\n window.__veryfrontSetReleaseAssetModules(pageData.releaseAssetModules || null);\n }\n perfStart("render:loadAll");\n const allPaths = getPageDataModulePaths(pageData);\n const modulesStartedAt = routeTimingNow();\n const components = await Promise.all(\n allPaths.map((path) => loadPageDataComponent(pageData, path))\n );\n emitRouteTiming("modules", targetPath, modulesStartedAt, { count: allPaths.length });\n perfEnd("render:loadAll");\n const [PageComponent, ...rest] = components;\n const ErrorComponent = pageData.errorPath ? rest.pop() : null;\n const AppComponent = pageData.appPath ? rest.pop() : null;\n const LayoutComponents = rest;\n if (!PageComponent) {\n throw new Error("Failed to load page component: " + pageData.pagePath);\n }\n if (pageData.frontmatter?.title) {\n document.title = pageData.frontmatter.title;\n }\n if (pageData.frontmatter?.description) {\n const metaDesc = document.querySelector(\'meta[name="description"]\');\n metaDesc?.setAttribute("content", pageData.frontmatter.description);\n }\n if (pageData.css) {\n const existingStyle = document.getElementById("veryfront-spa-css");\n if (existingStyle) {\n existingStyle.textContent = pageData.css;\n } else {\n const styleEl = document.createElement("style");\n const nonce = getDocumentNonce(document);\n if (nonce) styleEl.setAttribute("nonce", nonce);\n styleEl.id = "veryfront-spa-css";\n styleEl.textContent = pageData.css;\n document.head.appendChild(styleEl);\n }\n log("Injected CSS for SPA navigation", { cssLength: pageData.css.length });\n } else if (pageData.cssAction === "clear") {\n const existingStyle = document.getElementById("veryfront-spa-css");\n if (existingStyle) {\n existingStyle.remove();\n log("Cleared SPA CSS for release stylesheet navigation");\n }\n }\n const normalizedParams = flattenRouteParams(pageData.params);\n let tree = React2.createElement(PageComponent, {\n ...pageData.props,\n params: normalizedParams\n });\n if (pageData.layouts?.length) {\n for (let i = pageData.layouts.length - 1; i >= 0; i--) {\n const layout = pageData.layouts[i];\n const LayoutComponent = LayoutComponents[i];\n if (!LayoutComponent || !layout) continue;\n const layoutProps = pageData.layoutProps?.[layout.path] || {};\n tree = React2.createElement(LayoutComponent, { ...layoutProps, children: tree });\n }\n }\n if (AppComponent) {\n tree = React2.createElement(AppComponent, { children: tree });\n log("Wrapped with App component for SPA navigation");\n }\n if (ErrorComponent) {\n class AppRouterErrorBoundary extends React2.Component {\n constructor(props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n static getDerivedStateFromError(error) {\n return { hasError: true, error };\n }\n render() {\n if (this.state.hasError) {\n return React2.createElement(ErrorComponent, {\n error: this.state.error,\n reset: () => this.setState({ hasError: false, error: null })\n });\n }\n return this.props.children;\n }\n }\n tree = React2.createElement(AppRouterErrorBoundary, null, tree);\n }\n const headingsArray = pageData.headings || [];\n const pageContext = {\n slug: pageData.slug || "",\n path: pageData.pagePath || targetPath,\n params: normalizedParams,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n frontmatter: pageData.frontmatter || {},\n data: pageData.props || {},\n headings: headingsArray,\n mdxHeadings: headingsArray\n };\n tree = React2.createElement(PageContextProvider2, { pageContext, children: tree });\n tree = React2.createElement(RouterProvider2, { router, children: tree });\n const container = pageData.isolatedClientPage ? document.getElementById("veryfront-page-island") : document.getElementById("root");\n if (!hydrationCompleted && !hydrationFailed) {\n log("Waiting for hydration to complete before SPA render...");\n try {\n await Promise.race([\n hydrationPromise,\n new Promise(\n (_, reject) => setTimeout2(() => reject(new Error("Hydration timeout")), 1e4)\n )\n ]);\n } catch (waitError) {\n log("Hydration wait failed:", waitError.message);\n }\n }\n if (container?.__reactRoot) {\n perfStart("render:reactRender");\n container.__reactRoot.render(tree);\n perfEnd("render:reactRender");\n log("Page re-rendered via SPA");\n scheduleRoutePrefetchRefresh();\n return;\n }\n if (hydrationFailed) {\n throw new Error(\n "React root not found - hydration failed, falling back to full page navigation"\n );\n }\n throw new Error("React root not found");\n }\n let prefetchTimeout = null;\n let currentHoverLink = null;\n let routePrefetchRefreshPending = false;\n let viewportPrefetchObserver = null;\n const observedPrefetchLinks = /* @__PURE__ */ new WeakSet();\n const prefetchedPaths = /* @__PURE__ */ new Set();\n const inFlightPrefetches = /* @__PURE__ */ new Set();\n const queuedPrefetchPaths = /* @__PURE__ */ new Set();\n const pageDataPrefetchQueue = [];\n const activePageDataPrefetchControllers = /* @__PURE__ */ new Map();\n function cancelScheduledPrefetch() {\n if (prefetchTimeout) {\n clearTimeout2(prefetchTimeout);\n prefetchTimeout = null;\n }\n currentHoverLink = null;\n }\n function getPageDataModulePaths(pageData) {\n const layoutPaths = (pageData.layouts || []).map((l) => l.path).filter(Boolean);\n const allPaths = [pageData.pagePath, ...layoutPaths].filter(Boolean);\n if (pageData.appPath) allPaths.push(pageData.appPath);\n if (pageData.errorPath) allPaths.push(pageData.errorPath);\n return allPaths;\n }\n function getCurrentRouteHref() {\n return window.location.pathname + window.location.search;\n }\n function getInternalRouteHrefFromLink(link) {\n if (!link || link.target === "_blank" || link.hasAttribute("download") || link.getAttribute("data-prefetch") === "false") {\n return null;\n }\n const href = link.getAttribute("href");\n if (!href || href.startsWith("#") || href.startsWith("//") || !href.startsWith("/")) {\n return null;\n }\n try {\n const url = new URL(href, window.location.origin);\n if (url.origin !== window.location.origin) return null;\n const routeHref = url.pathname + url.search;\n return routeHref === getCurrentRouteHref() ? null : routeHref;\n } catch (_) {\n return null;\n }\n }\n function getEligiblePrefetchLinks(limit) {\n const links = [];\n const seenHrefs = /* @__PURE__ */ new Set();\n for (const link of document.querySelectorAll("a[href]")) {\n const href = getInternalRouteHrefFromLink(link);\n if (!href || seenHrefs.has(href)) continue;\n seenHrefs.add(href);\n links.push({ link, href });\n if (links.length >= limit) break;\n }\n return links;\n }\n async function preloadModulesForPageData(pageData, path) {\n if (!pageData || pageData.requiresFullDocumentNavigation) return;\n if (pageData.releaseId && window.__veryfrontSetReleaseId) {\n window.__veryfrontSetReleaseId(pageData.releaseId);\n }\n if (pageData.releaseAssetModules && window.__veryfrontSetReleaseAssetModules) {\n window.__veryfrontSetReleaseAssetModules(pageData.releaseAssetModules);\n }\n const modulePaths = getPageDataModulePaths(pageData);\n if (modulePaths.length === 0) return;\n try {\n await Promise.all(\n modulePaths.map(\n (modulePath) => loadPageDataComponent(pageData, modulePath, { allowDocumentReload: false })\n )\n );\n } catch (error) {\n if (isDependencySnapshotConflict(error)) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n pageDataCache.delete(cacheIdentity);\n backgroundRefreshTimestamps.delete(cacheIdentity);\n prefetchedPaths.delete(path);\n throw error;\n }\n logBackgroundFetchFailure("Module prefetch", path, error);\n }\n }\n function removeQueuedPrefetch(path) {\n queuedPrefetchPaths.delete(path);\n for (let i = pageDataPrefetchQueue.length - 1; i >= 0; i--) {\n if (pageDataPrefetchQueue[i] === path) pageDataPrefetchQueue.splice(i, 1);\n }\n }\n function abortActiveSpeculativePrefetches() {\n for (const controller of activePageDataPrefetchControllers.values()) {\n controller.abort();\n }\n }\n function processPageDataPrefetchQueue() {\n if (isNavigating) return;\n while (activePageDataPrefetchControllers.size < PAGE_DATA_PREFETCH_CONCURRENCY && pageDataPrefetchQueue.length > 0) {\n const href = pageDataPrefetchQueue.shift();\n queuedPrefetchPaths.delete(href);\n if (prefetchedPaths.has(href) || inFlightPrefetches.has(href) || getCachedPageData(href)) {\n continue;\n }\n if (prefetchedPaths.size >= MAX_PREFETCH_PATHS) {\n const oldest = prefetchedPaths.values().next().value;\n if (oldest) prefetchedPaths.delete(oldest);\n }\n const controller = new AbortController();\n prefetchedPaths.add(href);\n inFlightPrefetches.add(href);\n activePageDataPrefetchControllers.set(href, controller);\n fetchPageDataForPrefetch(href, controller.signal).catch((error) => {\n prefetchedPaths.delete(href);\n if (isDependencySnapshotConflict(error)) {\n logBackgroundFetchFailure("Module prefetch", href, error);\n }\n }).finally(() => {\n inFlightPrefetches.delete(href);\n activePageDataPrefetchControllers.delete(href);\n processPageDataPrefetchQueue();\n });\n }\n }\n function prefetchPage(href) {\n if (isNavigating) return;\n if (prefetchedPaths.has(href) || inFlightPrefetches.has(href) || queuedPrefetchPaths.has(href)) return;\n const cachedPageData = getCachedPageData(href);\n if (cachedPageData) {\n preloadModulesForPageData(cachedPageData, href).catch((error) => {\n logBackgroundFetchFailure("Module prefetch", href, error);\n });\n return;\n }\n queuedPrefetchPaths.add(href);\n pageDataPrefetchQueue.push(href);\n processPageDataPrefetchQueue();\n }\n function prefetchEligibleRouteLinks(limit) {\n for (const { href } of getEligiblePrefetchLinks(limit)) {\n prefetchPage(href);\n }\n }\n function ensureViewportPrefetchObserver() {\n if (viewportPrefetchObserver || typeof IntersectionObserver !== "function") {\n return viewportPrefetchObserver;\n }\n viewportPrefetchObserver = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n if (!entry.isIntersecting) continue;\n viewportPrefetchObserver?.unobserve(entry.target);\n const href = getInternalRouteHrefFromLink(\n entry.target\n );\n if (href) prefetchPage(href);\n }\n }, { rootMargin: VIEWPORT_PREFETCH_ROOT_MARGIN });\n return viewportPrefetchObserver;\n }\n function observeViewportPrefetchLinks() {\n const observer = ensureViewportPrefetchObserver();\n if (!observer) return;\n for (const { link } of getEligiblePrefetchLinks(VIEWPORT_PREFETCH_MAX_LINKS)) {\n if (observedPrefetchLinks.has(link)) continue;\n observedPrefetchLinks.add(link);\n observer.observe(link);\n }\n }\n function runRoutePrefetchRefresh() {\n routePrefetchRefreshPending = false;\n prefetchEligibleRouteLinks(IDLE_PREFETCH_MAX_LINKS);\n observeViewportPrefetchLinks();\n }\n function scheduleRoutePrefetchRefresh() {\n if (routePrefetchRefreshPending) return;\n routePrefetchRefreshPending = true;\n setTimeout2(() => {\n if (typeof requestIdleCallback === "function") {\n requestIdleCallback(runRoutePrefetchRefresh, { timeout: IDLE_PREFETCH_DELAY_MS });\n return;\n }\n runRoutePrefetchRefresh();\n }, IDLE_PREFETCH_DELAY_MS);\n }\n const router = {\n domain: window.location.origin,\n path: window.location.pathname,\n push: (path) => {\n void navigateSPA(path, "push");\n },\n replace: (path) => {\n void navigateSPA(path, "replace");\n },\n back: () => {\n window.history.back();\n },\n forward: () => {\n window.history.forward();\n },\n prefetch: (path) => {\n prefetchPage(path);\n },\n pathname: window.location.pathname,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n // Seed route params from the hydration data (issue #2741). Catch-all\n // segments arrive as arrays and are joined so no path info is lost.\n params: flattenRouteParams(deps.initialHydrationData.params || {}),\n isPreview: false,\n isMounted: true,\n navigate: (path) => navigateSPA(path, "push"),\n reload: () => window.location.reload()\n };\n window.__veryfrontRouter = router;\n if (deps.navigationStoreUsesRegistryFallback) {\n log("Router runtime does not export getNavigationStore; using shared v1 registry fallback");\n }\n if (typeof deps.getNavigationStore === "function") {\n deps.getNavigationStore().setNavigator((href, options) => {\n const mode = options && options.history;\n const historyMode = mode === "replace" ? "replace" : mode === "none" ? "none" : "push";\n return navigateSPA(href, historyMode);\n });\n }\n window.addEventListener("popstate", async (e) => {\n const path = window.location.pathname;\n log("Popstate:", path);\n saveScrollPosition(currentPath);\n if (!e.state?.pageData) {\n await navigateSPA(path, "none", true);\n return;\n }\n showNavigationProgress();\n try {\n currentPath = path;\n router.pathname = path;\n router.query = Object.fromEntries(new URLSearchParams(window.location.search));\n router.params = flattenRouteParams(e.state.pageData.params);\n await renderPageFromData(e.state.pageData, path);\n restoreScrollPosition(path);\n hideNavigationProgress();\n } catch (error) {\n hideNavigationProgress();\n logError("Popstate render failed:", error.message);\n window.location.reload();\n }\n });\n document.addEventListener("click", (e) => {\n const link = e.target?.closest("a[href]");\n if (!link) return;\n const href = link.getAttribute("href");\n if (!href) return;\n if (href.startsWith("#")) {\n const target = document.getElementById(href.slice(1));\n if (!target) return;\n e.preventDefault();\n target.scrollIntoView({ behavior: "smooth" });\n window.history.pushState(null, "", href);\n return;\n }\n if (link.target === "_blank" || link.hasAttribute("download") || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || !href.startsWith("/") || href.startsWith("//")) {\n return;\n }\n e.preventDefault();\n cancelScheduledPrefetch();\n void navigateSPA(href, "push");\n });\n document.addEventListener(\n "mouseenter",\n (e) => {\n if (!e.target || typeof e.target.closest !== "function") return;\n const link = e.target.closest("a[href]");\n if (!link) return;\n const href = getInternalRouteHrefFromLink(link);\n if (!href) return;\n if (currentHoverLink === link) return;\n if (prefetchTimeout) {\n clearTimeout2(prefetchTimeout);\n prefetchTimeout = null;\n }\n currentHoverLink = link;\n prefetchTimeout = setTimeout2(() => {\n prefetchPage(href);\n prefetchTimeout = null;\n }, PREFETCH_DELAY_MS);\n },\n true\n );\n document.addEventListener(\n "mouseleave",\n (e) => {\n if (!e.target || typeof e.target.closest !== "function") return;\n const relatedTarget = e.relatedTarget;\n if (currentHoverLink && relatedTarget && currentHoverLink.contains(relatedTarget)) return;\n cancelScheduledPrefetch();\n },\n true\n );\n if (document.readyState === "loading") {\n document.addEventListener("DOMContentLoaded", scheduleRoutePrefetchRefresh, { once: true });\n } else {\n scheduleRoutePrefetchRefresh();\n }\n window.useRouter = () => {\n try {\n return env2.useRouterFromModule();\n } catch (_) {\n return window.__veryfrontRouter;\n }\n };\n return {\n router,\n navigateSPA,\n renderPageFromData,\n prefetchPage,\n signalHydrationComplete,\n signalHydrationFailed\n };\n}\n\n// src/html/hydration-script-builder/runtime/renderer.ts\nfunction isModuleNotFoundError(error) {\n if (!error) return false;\n if (error instanceof SyntaxError) return false;\n const message = String(error.message || error);\n return /(?:dynamically imported module|Importing a module script failed|Failed to load module script)/i.test(message);\n}\nfunction preferReachedModuleError(earlier, later) {\n if (!earlier) return later;\n if (!later) return earlier;\n if (isModuleNotFoundError(earlier) && !isModuleNotFoundError(later)) return later;\n return earlier;\n}\nasync function loadPageModuleWithIndexFallback(basePath, pageSlug, pageModuleError, importModule) {\n try {\n return await importModule(basePath + ".js");\n } catch (error) {\n const routeError = preferReachedModuleError(pageModuleError, error);\n if (pageSlug === "index" || pageSlug.endsWith("/index")) throw routeError;\n try {\n return await importModule(basePath + "/index.js");\n } catch (indexError) {\n throw preferReachedModuleError(routeError, indexError);\n }\n }\n}\nfunction isAppRouterPath(path, appRouterRoot) {\n const normalizedPath = typeof path === "string" ? path.replace(/^\\/+/, "") : "";\n return normalizedPath === appRouterRoot || normalizedPath.startsWith(appRouterRoot + "/");\n}\nfunction isRootAppLayoutPath(path, appRouterRoot) {\n const normalizedPath = typeof path === "string" ? path.replace(/^\\/+/, "") : "";\n const pathWithoutExtension = normalizedPath.replace(/\\.(?:tsx|jsx|ts|js)$/, "");\n return pathWithoutExtension === appRouterRoot + "/layout";\n}\nfunction unwrapAppRouterDocumentLayout(LayoutComponent, React2) {\n return function AppRouterDocumentLayout(props) {\n const element = LayoutComponent(props);\n const asElement = element;\n if (!React2.isValidElement(element) || asElement.type !== "html") {\n return element;\n }\n const body = React2.Children.toArray(asElement.props?.children).find(\n (child) => React2.isValidElement(child) && child.type === "body"\n );\n return body?.props?.children ?? props.children;\n };\n}\nfunction createHydrationRenderer(deps) {\n const { env: env2, logging: logging2, componentLoader: componentLoader2, snapshotModules: snapshotModules2, moduleServerUrl: moduleServerUrl2 } = deps;\n const { window, document, React: React2, RouterProvider: RouterProvider2, PageContextProvider: PageContextProvider2 } = env2;\n const { DEBUG, log, logError } = logging2;\n const { loadComponent, pathToModuleUrl } = componentLoader2;\n const { importSnapshotBoundModule } = snapshotModules2;\n async function renderPage(pathname) {\n const resolvedPathname = (() => {\n const input = typeof pathname === "string" ? pathname : window.location.pathname;\n try {\n return new URL(input, window.location.origin).pathname || "/";\n } catch (_) {\n const [pathOnly] = String(input || "/").split(/[?#]/);\n return pathOnly || "/";\n }\n })();\n const dataScript = document.getElementById(HYDRATION_DATA_ELEMENT_ID);\n if (!dataScript) {\n logError("Hydration data not found");\n return;\n }\n let data = {};\n try {\n data = JSON.parse(dataScript.textContent || "{}");\n } catch (parseError) {\n logError("Failed to parse hydration data:", parseError);\n return;\n }\n log("Hydration data:", data);\n if (data.studioEmbed && window.__veryfrontSetStudioEmbed) {\n window.__veryfrontSetStudioEmbed(true);\n }\n if (window.__veryfrontSetReleaseId) {\n window.__veryfrontSetReleaseId(data.releaseId || null);\n }\n if (data.releaseAssetModules && window.__veryfrontSetReleaseAssetModules) {\n window.__veryfrontSetReleaseAssetModules(data.releaseAssetModules);\n }\n try {\n let pageModule;\n const pagePath = typeof data.pagePath === "string" ? data.pagePath : "";\n const normalizedPagePath = pagePath.replace(/^\\/+/, "");\n const normalizedAppRouterRoot = typeof data.appRouterRoot === "string" && data.appRouterRoot.replace(/^\\/+|\\/+$/g, "") ? data.appRouterRoot.replace(/^\\/+|\\/+$/g, "") : "app";\n const hasReleaseAssetModules = data.releaseAssetModules && Object.keys(data.releaseAssetModules).length > 0;\n const shouldRenderRscClientPage = data.clientModuleStrategy === "rsc-module" && !hasReleaseAssetModules && isAppRouterPath(normalizedPagePath, normalizedAppRouterRoot);\n const isolatedClientPage = data.isolatedClientPage === true;\n const loadHydrationComponent = async (path, preferRscModule) => {\n const normalizedPath = typeof path === "string" ? path.replace(/^\\/+/, "") : "";\n if (preferRscModule && isAppRouterPath(normalizedPath, normalizedAppRouterRoot)) {\n const moduleUrl = buildPinnedRscModuleUrl(path, data);\n log("Loading App Router component from RSC module:", moduleUrl);\n const module = await importSnapshotBoundModule(moduleUrl);\n return module.default || module;\n }\n return loadComponent(path, data);\n };\n let pageModuleError = null;\n if (data.pagePath) {\n const moduleUrl = shouldRenderRscClientPage ? buildPinnedRscModuleUrl(data.pagePath, data) : pathToModuleUrl(data.pagePath, data.studioEmbed, data);\n log("Loading page from hydration data:", moduleUrl);\n try {\n pageModule = await importSnapshotBoundModule(moduleUrl);\n } catch (error) {\n pageModuleError = error;\n logError("Failed to load page from hydration data:", error);\n }\n }\n if (!pageModule) {\n const pageSlug = resolvedPathname === "/" ? "index" : resolvedPathname.slice(1);\n log("Falling back to Pages Router pattern:", pageSlug);\n const prefix = pageSlug.startsWith("@/") ? "" : "/pages";\n const basePath = moduleServerUrl2 + prefix + "/" + pageSlug;\n pageModule = await loadPageModuleWithIndexFallback(\n basePath,\n pageSlug,\n pageModuleError,\n (moduleUrl) => importSnapshotBoundModule(appendDependencyPinningVersion(moduleUrl, data))\n );\n }\n if (!pageModule) {\n logError("Page module failed to load");\n return;\n }\n const PageComponent = pageModule.default || pageModule;\n if (!PageComponent) {\n logError("Page component not found");\n return;\n }\n const normalizedParams = flattenRouteParams(data.params);\n const pageProps = { ...data.props || {}, params: normalizedParams };\n let tree = React2.createElement(PageComponent, pageProps);\n const layouts = data.layouts;\n if (layouts?.length) {\n for (let i = layouts.length - 1; i >= 0; i--) {\n const layout = layouts[i];\n if (!layout) continue;\n const LayoutComponent = await loadHydrationComponent(\n layout.path,\n shouldRenderRscClientPage\n );\n if (LayoutComponent) {\n const WrappedLayoutComponent = shouldRenderRscClientPage && isRootAppLayoutPath(layout.path, normalizedAppRouterRoot) ? unwrapAppRouterDocumentLayout(LayoutComponent, React2) : LayoutComponent;\n const layoutProps = data.layoutProps?.[layout.path] || {};\n tree = React2.createElement(\n WrappedLayoutComponent,\n { ...layoutProps, children: tree }\n );\n }\n }\n }\n if (data.appPath && !isolatedClientPage) {\n const AppComponent = await loadHydrationComponent(data.appPath, shouldRenderRscClientPage);\n if (AppComponent) {\n tree = React2.createElement(AppComponent, { children: tree });\n }\n }\n if (data.errorPath) {\n const ErrorComponent = await loadHydrationComponent(\n data.errorPath,\n shouldRenderRscClientPage\n );\n if (ErrorComponent) {\n class AppRouterErrorBoundary extends React2.Component {\n constructor(props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n static getDerivedStateFromError(error) {\n return { hasError: true, error };\n }\n render() {\n if (this.state.hasError) {\n return React2.createElement(ErrorComponent, {\n error: this.state.error,\n reset: () => this.setState({ hasError: false, error: null })\n });\n }\n return this.props.children;\n }\n }\n tree = React2.createElement(AppRouterErrorBoundary, null, tree);\n }\n }\n const headings = data.headings || [];\n const pageContext = {\n slug: data.slug || "",\n path: data.pagePath || resolvedPathname,\n params: normalizedParams,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n frontmatter: data.frontmatter || {},\n data: data.props || {},\n headings,\n mdxHeadings: headings\n // Alias for backwards compatibility\n };\n tree = React2.createElement(PageContextProvider2, { pageContext, children: tree });\n tree = React2.createElement(RouterProvider2, { router: deps.router, children: tree });\n const container = isolatedClientPage ? document.getElementById("veryfront-page-island") : document.getElementById("root");\n if (!container) {\n if (isolatedClientPage) {\n throw new Error("Isolated client page root not found");\n }\n return;\n }\n if (container.__reactRoot) {\n container.__reactRoot.render(tree);\n log("Page re-rendered");\n return;\n }\n if (shouldRenderRscClientPage) {\n container.__reactRoot = env2.createRoot(container);\n container.__reactRoot.render(tree);\n log("Client-side React app rendered successfully");\n } else {\n const { hydrateRoot } = await import("react-dom/client");\n const options = {\n identifierPrefix: "vf",\n onRecoverableError: (error) => {\n if (data.dev && DEBUG) {\n log("Hydration mismatch (suppressed):", error.message);\n }\n }\n };\n container.__reactRoot = hydrateRoot(container, tree, options);\n log("Client-side React app hydrated successfully");\n }\n if (window.__veryfrontHydrationComplete) {\n window.__veryfrontHydrationComplete();\n }\n } catch (error) {\n logError("Client initialization error:", error);\n if (window.__veryfrontHydrationFailed) {\n window.__veryfrontHydrationFailed(error);\n }\n }\n }\n function start() {\n window.__veryfrontRenderPage = renderPage;\n void renderPage(window.location.pathname);\n const initialDataScript = document.getElementById(HYDRATION_DATA_ELEMENT_ID);\n if (initialDataScript) {\n try {\n const pageData = JSON.parse(initialDataScript.textContent || "{}");\n if (pageData.pagePath) {\n window.history.replaceState({ pageData, scrollY: 0 }, "", window.location.href);\n log("Stored initial page data in history state");\n }\n } catch (_) {\n }\n }\n }\n return { renderPage, start };\n}\n\n// src/html/hydration-script-builder/runtime/navigation-store.ts\nvar NAVIGATION_STORE_REGISTRY_KEY = "veryfront.navigation.store.v1";\nfunction resolveNavigationStore(RouterRuntime2) {\n const usesRegistryFallback2 = typeof RouterRuntime2.getNavigationStore !== "function";\n if (!usesRegistryFallback2) {\n return {\n usesRegistryFallback: usesRegistryFallback2,\n getNavigationStore: RouterRuntime2.getNavigationStore\n };\n }\n return {\n usesRegistryFallback: usesRegistryFallback2,\n getNavigationStore: () => {\n const storeKey = Symbol.for(NAVIGATION_STORE_REGISTRY_KEY);\n const registry = globalThis;\n const existing = registry[storeKey];\n if (existing) return existing;\n const listeners = /* @__PURE__ */ new Set();\n let navigator = null;\n const store = {\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n getHref() {\n const loc = globalThis.location;\n return loc ? loc.pathname + loc.search + loc.hash : "/";\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch {\n }\n }\n },\n navigate(href, options) {\n if (navigator) return navigator(href, options);\n globalThis.location?.assign(href);\n return Promise.resolve();\n },\n setNavigator(next) {\n navigator = next;\n }\n };\n registry[storeKey] = store;\n return store;\n }\n };\n}\n\n// src/html/hydration-script-builder/runtime/main.ts\nvar runtimeWindow = globalThis;\nvar runtimeDocument = globalThis.document;\nvar env = {\n window: runtimeWindow,\n document: runtimeDocument,\n fetch: (url, init) => fetch(url, init),\n React,\n RouterProvider,\n PageContextProvider,\n createRoot: (container) => createRoot(container),\n importModule: (moduleUrl) => import(moduleUrl),\n useRouterFromModule,\n setTimeout: (handler, timeout) => setTimeout(handler, timeout),\n clearTimeout: (id) => clearTimeout(id)\n};\nvar logging = createLogging(runtimeWindow);\nvar initialHydrationData = readInitialHydrationData(runtimeDocument);\nvar documentDependencyPinningCacheKey = readDocumentDependencyPinningCacheKey(\n initialHydrationData\n);\nvar routeTiming = createRouteTimingRecorder(runtimeWindow, logging);\nvar snapshotModules = createSnapshotModuleImporter({\n importModule: env.importModule,\n fetchModule: env.fetch,\n reloadDocument: () => runtimeWindow.location.reload(),\n recoveryState: runtimeWindow\n});\nvar componentLoader = createComponentLoader({\n window: runtimeWindow,\n logging,\n moduleServerUrl: moduleServerUrl(runtimeWindow),\n snapshotModules\n});\nruntimeWindow.__veryfrontClearComponentCache = componentLoader.clearComponentCache;\nruntimeWindow.__veryfrontSetStudioEmbed = componentLoader.setStudioEmbed;\nruntimeWindow.__veryfrontSetReleaseId = componentLoader.setReleaseId;\nruntimeWindow.__veryfrontSetReleaseAssetModules = componentLoader.setReleaseAssetModules;\nruntimeWindow.__veryfrontSetHMRRefreshTimestamp = componentLoader.setHMRRefreshTimestamp;\nvar { usesRegistryFallback, getNavigationStore } = resolveNavigationStore(RouterRuntime);\nvar routerRuntime = createRouterRuntime({\n env,\n logging,\n routeTiming,\n componentLoader,\n snapshotModules,\n initialHydrationData,\n documentDependencyPinningCacheKey,\n getNavigationStore,\n navigationStoreUsesRegistryFallback: usesRegistryFallback\n});\ncreateHydrationRenderer({\n env,\n logging,\n componentLoader,\n snapshotModules,\n moduleServerUrl: moduleServerUrl(runtimeWindow),\n router: routerRuntime.router\n}).start();\n';
|
|
9
|
+
export const HYDRATION_RUNTIME_BUNDLE = '// src/html/hydration-script-builder/runtime/main.ts\nimport * as React from "react";\nimport { createRoot } from "react-dom/client";\nimport { RouterProvider, useRouter as useRouterFromModule } from "veryfront/router";\nimport * as RouterRuntime from "veryfront/router";\nimport { PageContextProvider } from "veryfront/context";\n\n// src/routing/flatten-route-params.ts\nfunction flattenRouteParams(params) {\n if (!params) return {};\n const flat = {};\n for (const [key, value] of Object.entries(params)) {\n if (value === void 0) continue;\n flat[key] = Array.isArray(value) ? value.join("/") : value;\n }\n return flat;\n}\n\n// src/html/hydration-script-builder/runtime/shared.ts\nfunction moduleServerUrl(window) {\n return window.location.origin + "/_vf_modules";\n}\nfunction createLogging(window) {\n const DEBUG = Boolean(\n window.__VERYFRONT_DEBUG__ || new URLSearchParams(window.location.search).has("vf_debug")\n );\n const log = DEBUG ? console.log.bind(console, "[Veryfront]") : () => {\n };\n const logError = console.error.bind(console, "[Veryfront]");\n function logBackgroundFetchFailure(reason, path, error) {\n const message = error?.message ?? String(error);\n log(reason + " failed:", path, message);\n }\n const perfTimers = /* @__PURE__ */ new Map();\n const perfStart = DEBUG ? (label) => {\n perfTimers.set(label, performance.now());\n } : () => {\n };\n const perfEnd = DEBUG ? (label) => {\n const start = perfTimers.get(label);\n if (start === void 0) return 0;\n const duration = performance.now() - start;\n perfTimers.delete(label);\n console.log(\n "[Veryfront Perf] %c" + label + ": %c" + duration.toFixed(2) + "ms",\n "color: #888",\n duration > 100 ? "color: #f00; font-weight: bold" : "color: #0a0"\n );\n return duration;\n } : () => 0;\n return { DEBUG, log, logError, logBackgroundFetchFailure, perfStart, perfEnd };\n}\nfunction isAbortError(error) {\n return error?.name === "AbortError";\n}\nfunction resolveDocumentNavigationUrl(target, origin) {\n try {\n const url = new URL(target, origin);\n if (url.protocol === "http:" || url.protocol === "https:") return url.href;\n } catch (_) {\n }\n return null;\n}\nfunction getDocumentNonce(document) {\n const element = document.querySelector("script[nonce], style[nonce], link[nonce]");\n if (!element) return void 0;\n return element.nonce || element.getAttribute("nonce") || void 0;\n}\n\n// src/html/hydration-script-builder/runtime/hydration-data.ts\nvar HYDRATION_DATA_ELEMENT_ID = "veryfront-hydration-data";\nfunction readInitialHydrationData(document) {\n try {\n const element = document.getElementById(HYDRATION_DATA_ELEMENT_ID);\n return JSON.parse(element && element.textContent ? element.textContent : "{}") || {};\n } catch (_) {\n return {};\n }\n}\nfunction readDocumentDependencyPinningCacheKey(initialHydrationData2) {\n return typeof initialHydrationData2.dependencyPinningCacheKey === "string" && initialHydrationData2.dependencyPinningCacheKey.startsWith("on:") ? initialHydrationData2.dependencyPinningCacheKey : null;\n}\n\n// src/html/hydration-script-builder/runtime/snapshot-modules.ts\nvar RECOVERY_STATE_KEY = "__VF_DEPENDENCY_SNAPSHOT_RECOVERY_STARTED__";\nasync function isDependencySnapshotConflictResponse(response) {\n if (!response || response.status !== 409) return false;\n try {\n const clone = response.clone?.() ?? response;\n const body = (await clone.text?.() ?? "").trim();\n return body === "Unknown dependency snapshot" || body === "export default null; // Unknown dependency snapshot";\n } catch (_) {\n return false;\n }\n}\nfunction createSnapshotModuleImporter(deps) {\n async function recoverFromSnapshotBoundModuleFailure(moduleUrl, allowDocumentReload = true) {\n try {\n const parsedUrl = new URL(moduleUrl, "http://veryfront.local");\n const snapshotKeys = parsedUrl.searchParams.getAll("pins");\n const pathMatch = parsedUrl.pathname.match(\n /^\\/_vf_modules\\/_pins\\/([^/]+)(?:\\/|$)/\n );\n if (pathMatch) {\n try {\n snapshotKeys.push(decodeURIComponent(pathMatch[1]));\n } catch (_) {\n return false;\n }\n }\n if (snapshotKeys.length !== 1 || !/^on:[A-Za-z0-9._-]+$/.test(snapshotKeys[0])) return false;\n const response = await deps.fetchModule(moduleUrl, { cache: "no-store" });\n if (!await isDependencySnapshotConflictResponse(response)) return false;\n if (!allowDocumentReload) return true;\n if (deps.recoveryState[RECOVERY_STATE_KEY] === true) return true;\n deps.recoveryState[RECOVERY_STATE_KEY] = true;\n try {\n deps.reloadDocument();\n } catch (_) {\n delete deps.recoveryState[RECOVERY_STATE_KEY];\n return false;\n }\n return true;\n } catch (_) {\n return false;\n }\n }\n async function importSnapshotBoundModule(moduleUrl, allowDocumentReload = true) {\n try {\n return await deps.importModule(moduleUrl);\n } catch (error) {\n const snapshotConflict = await recoverFromSnapshotBoundModuleFailure(\n moduleUrl,\n allowDocumentReload\n );\n if (snapshotConflict && !allowDocumentReload) {\n const conflictError = new Error(\n "Dependency snapshot is unavailable during speculative module prefetch"\n );\n conflictError.name = "DependencySnapshotConflictError";\n conflictError.dependencySnapshotConflict = true;\n conflictError.cause = error;\n throw conflictError;\n }\n throw error;\n }\n }\n return { importSnapshotBoundModule, recoverFromSnapshotBoundModuleFailure };\n}\nfunction isDependencySnapshotConflict(error) {\n return Boolean(error?.dependencySnapshotConflict);\n}\n\n// src/utils/version-constant.ts\nvar VERSION = "0.1.1182";\n\n// src/html/hydration-script-builder/runtime/module-urls.ts\nfunction appendQueryParam(url, key, value) {\n return url + (url.includes("?") ? "&" : "?") + key + "=" + value;\n}\nfunction appendDependencyPinningVersion(url, moduleData) {\n const pinKey = moduleData && moduleData.dependencyPinningCacheKey;\n if (typeof pinKey !== "string" || !pinKey.startsWith("on:")) return url;\n const hashIndex = url.indexOf("#");\n const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";\n const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;\n const queryIndex = withoutHash.indexOf("?");\n const base = queryIndex >= 0 ? withoutHash.slice(0, queryIndex) : withoutHash;\n const params = new URLSearchParams(queryIndex >= 0 ? withoutHash.slice(queryIndex + 1) : "");\n const modulePrefix = "/_vf_modules/";\n const prefixIndex = base.indexOf(modulePrefix);\n const origin = prefixIndex >= 0 ? base.slice(0, prefixIndex) : "";\n if (prefixIndex >= 0 && (origin === "" || /^https?:\\/\\/[^/]+$/i.test(origin))) {\n const pathStart = prefixIndex + modulePrefix.length;\n let modulePath = base.slice(pathStart);\n if (modulePath.startsWith("_pins/")) {\n const existingKeyEnd = modulePath.indexOf("/", "_pins/".length);\n const encodedExistingKey = existingKeyEnd < 0 ? modulePath.slice("_pins/".length) : modulePath.slice("_pins/".length, existingKeyEnd);\n let existingKey;\n try {\n existingKey = decodeURIComponent(encodedExistingKey);\n } catch {\n existingKey = void 0;\n }\n if (existingKey && /^on:[A-Za-z0-9._-]+$/.test(existingKey)) {\n if (existingKeyEnd < 0) return url;\n modulePath = modulePath.slice(existingKeyEnd + 1);\n }\n }\n params.delete("pins");\n const query = params.toString();\n return base.slice(0, pathStart) + "_pins/" + encodeURIComponent(pinKey) + "/" + modulePath + (query ? "?" + query : "") + hash;\n }\n params.set("pins", pinKey);\n return base + "?" + params.toString() + hash;\n}\nfunction componentCacheKey(path, moduleData) {\n const pinKey = moduleData && moduleData.dependencyPinningCacheKey;\n return typeof pinKey === "string" && pinKey.startsWith("on:") ? path + "|vf_pins|" + pinKey : path;\n}\nfunction normalizeReleaseAssetModulePath(path) {\n return String(path || "").replace(/^\\/?_vf_modules\\//, "").replace(/^\\/+/, "").replace(/[?#].*$/, "");\n}\nfunction buildPinnedRscModuleUrl(path, moduleData) {\n let moduleUrl = "/_veryfront/rsc/module?rel=" + encodeURIComponent(path);\n const pinKey = moduleData && moduleData.dependencyPinningCacheKey;\n if (typeof pinKey === "string" && pinKey.startsWith("on:")) {\n moduleUrl += "&pins=" + encodeURIComponent(pinKey);\n }\n return moduleUrl;\n}\nfunction buildPageDataEndpoint(path, origin) {\n const targetUrl = new URL(path, origin);\n const normalizedPath = targetUrl.pathname === "/" ? "" : targetUrl.pathname.replace(/^\\//, "");\n const endpointUrl = new URL(\n "/_veryfront/page-data/" + normalizedPath + ".json",\n origin\n );\n endpointUrl.search = targetUrl.search;\n return endpointUrl.pathname + endpointUrl.search;\n}\nfunction pageDataCacheIdentity(path, documentDependencyPinningCacheKey2) {\n return documentDependencyPinningCacheKey2 ? documentDependencyPinningCacheKey2 + "|path:" + path : path;\n}\nfunction assertPageDataMatchesDocumentSnapshot(path, data, documentDependencyPinningCacheKey2) {\n if (!documentDependencyPinningCacheKey2) return data;\n if (data && data.dependencyPinningCacheKey === documentDependencyPinningCacheKey2) {\n return data;\n }\n const error = new Error("Page data dependency snapshot does not match the document");\n error.status = 409;\n error.dependencySnapshotMismatch = true;\n error.path = path;\n throw error;\n}\n\n// src/html/hydration-script-builder/runtime/component-loader.ts\nvar VERYFRONT_RUNTIME_VERSION = VERSION;\nfunction createComponentLoader(deps) {\n const { window, moduleServerUrl: moduleServerUrl2 } = deps;\n const { DEBUG, log, logError } = deps.logging;\n const componentCache = /* @__PURE__ */ new Map();\n const loadingPromises = /* @__PURE__ */ new Map();\n let releaseId = null;\n let releaseAssetModules = null;\n let studioEmbed = false;\n let hmrRefreshTimestamp = null;\n function clearComponentCache(path) {\n if (!path) {\n componentCache.clear();\n loadingPromises.clear();\n log("Cleared all component caches");\n return;\n }\n for (const key of componentCache.keys()) {\n if (key === path || key.startsWith(path + "|vf_pins|")) {\n componentCache.delete(key);\n }\n }\n for (const key of loadingPromises.keys()) {\n if (key === path || key.startsWith(path + "|vf_pins|")) {\n loadingPromises.delete(key);\n }\n }\n log("Cleared component cache for:", path);\n }\n function setReleaseId(value) {\n releaseId = typeof value === "string" && value ? value : null;\n window.__veryfrontReleaseId = releaseId;\n }\n function appendReleaseModuleVersion(url) {\n if (!releaseId || url.includes("vf_release=")) return url;\n let versionedUrl = appendQueryParam(url, "vf_release", encodeURIComponent(releaseId));\n versionedUrl = appendQueryParam(\n versionedUrl,\n "vf_runtime",\n encodeURIComponent(VERYFRONT_RUNTIME_VERSION)\n );\n return versionedUrl;\n }\n function setReleaseAssetModules(value) {\n releaseAssetModules = value && typeof value === "object" && !Array.isArray(value) ? value : null;\n window.__veryfrontReleaseAssetModules = releaseAssetModules;\n }\n function resolveReleaseAssetModuleUrl(path) {\n if (!releaseAssetModules || studioEmbed || hmrRefreshTimestamp) return null;\n const key = normalizeReleaseAssetModulePath(path);\n if (releaseAssetModules[key]) return releaseAssetModules[key];\n const withoutExt = key.replace(/\\.(tsx|ts|jsx|mdx|js|mjs)$/, "");\n const extensions = [".tsx", ".ts", ".jsx", ".mdx", ".js"];\n for (const ext of extensions) {\n const candidate = withoutExt + ext;\n if (releaseAssetModules[candidate]) return releaseAssetModules[candidate];\n }\n return null;\n }\n function pathToModuleUrl(path, embedInStudio, moduleData) {\n const releaseAssetUrl = resolveReleaseAssetModuleUrl(path);\n if (releaseAssetUrl) return releaseAssetUrl;\n const pattern = /(pages|components|app|lib|layouts|shared|features)\\/(.+)\\.(tsx|ts|jsx|mdx)$/;\n const match = path.match(new RegExp("/" + pattern.source)) || path.match(new RegExp("^" + pattern.source));\n let url;\n if (match) {\n url = moduleServerUrl2 + "/" + match[1] + "/" + match[2] + ".js";\n } else {\n const hasKnownExt = /\\.(tsx|ts|jsx|mdx|js|mjs)$/.test(path);\n url = moduleServerUrl2 + "/" + (hasKnownExt ? path.replace(/\\.(tsx|ts|jsx|mdx)$/, ".js") : path + ".js");\n }\n if (embedInStudio) url = appendQueryParam(url, "studio_embed", "true");\n if (hmrRefreshTimestamp) url = appendQueryParam(url, "t", hmrRefreshTimestamp);\n if (!embedInStudio && !hmrRefreshTimestamp) url = appendReleaseModuleVersion(url);\n url = appendDependencyPinningVersion(url, moduleData);\n return url;\n }\n function setStudioEmbed(value) {\n studioEmbed = value;\n window.__veryfrontStudioEmbed = value;\n }\n function setHMRRefreshTimestamp(timestamp) {\n hmrRefreshTimestamp = timestamp;\n window.__veryfrontHMRRefreshTimestamp = timestamp;\n }\n async function loadComponent(path, moduleData, options = {}) {\n if (!path) return null;\n const cacheKey = componentCacheKey(path, moduleData);\n if (componentCache.has(cacheKey)) {\n log("Component cached:", path);\n return componentCache.get(cacheKey);\n }\n const existingPromise = loadingPromises.get(cacheKey);\n if (existingPromise) return existingPromise;\n const loadPromise = (async () => {\n try {\n const moduleUrl = pathToModuleUrl(path, studioEmbed, moduleData);\n const start = DEBUG ? performance.now() : 0;\n log("Loading component:", moduleUrl);\n const module = await deps.snapshotModules.importSnapshotBoundModule(\n moduleUrl,\n options.allowDocumentReload !== false\n );\n const component = module.MDXLayout || module.MainLayout || module.default || module;\n if (DEBUG) {\n const duration = performance.now() - start;\n console.log(\n "[Veryfront Perf] %cimport:" + path.split("/").pop() + ": %c" + duration.toFixed(2) + "ms",\n "color: #888",\n duration > 50 ? "color: #f00; font-weight: bold" : "color: #0a0"\n );\n }\n componentCache.set(cacheKey, component);\n return component;\n } catch (error) {\n if (isDependencySnapshotConflict(error)) throw error;\n logError("Failed to load component:", path, error);\n return null;\n } finally {\n loadingPromises.delete(cacheKey);\n }\n })();\n loadingPromises.set(cacheKey, loadPromise);\n return loadPromise;\n }\n return {\n loadComponent,\n pathToModuleUrl,\n clearComponentCache,\n setStudioEmbed,\n setReleaseId,\n setReleaseAssetModules,\n setHMRRefreshTimestamp\n };\n}\n\n// src/html/hydration-script-builder/runtime/route-timing.ts\nvar MAX_ROUTE_TIMINGS = 100;\nvar MAX_SERVER_TIMING_LENGTH = 1024;\nfunction routeTimingNow() {\n return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();\n}\nfunction sanitizeServerTimingMetricName(name) {\n return String(name || "").trim().replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 128);\n}\nfunction sanitizeServerTimingHeader(value) {\n if (!value) return null;\n const metrics = [];\n const printable = String(value).replace(/[^\\x20-\\x7E]/g, " ").trim();\n if (!printable) return null;\n for (const item of printable.split(",")) {\n const segments = item.split(";").map((segment) => segment.trim()).filter(Boolean);\n const name = sanitizeServerTimingMetricName(segments[0]);\n if (!name) continue;\n for (const segment of segments.slice(1)) {\n const [key, rawValue = ""] = segment.split("=");\n if ((key ?? "").trim().toLowerCase() !== "dur") continue;\n const duration = Number(rawValue.trim().replace(/^"|"$/g, ""));\n if (!Number.isFinite(duration) || duration < 0) continue;\n metrics.push(name + ";dur=" + (Math.round(duration * 100) / 100).toFixed(2));\n break;\n }\n }\n const sanitized = metrics.join(", ");\n return sanitized ? sanitized.slice(0, MAX_SERVER_TIMING_LENGTH) : null;\n}\nfunction parseServerTimingMetrics(value) {\n const header = sanitizeServerTimingHeader(value);\n if (!header) return null;\n const metrics = {};\n for (const item of header.split(",")) {\n const segments = item.split(";").map((segment) => segment.trim()).filter(Boolean);\n const name = sanitizeServerTimingMetricName(segments[0]);\n if (!name) continue;\n for (const segment of segments.slice(1)) {\n const [key, rawValue = ""] = segment.split("=");\n if ((key ?? "").trim().toLowerCase() !== "dur") continue;\n const duration = Number(rawValue.trim().replace(/^"|"$/g, ""));\n if (Number.isFinite(duration) && duration >= 0) {\n metrics[name] = Math.round(duration * 100) / 100;\n }\n }\n }\n return Object.keys(metrics).length ? metrics : null;\n}\nfunction readResponseServerTiming(response) {\n try {\n return sanitizeServerTimingHeader(response.headers?.get("server-timing"));\n } catch (_) {\n return null;\n }\n}\nfunction roundRouteTimingValue(value) {\n return Math.round(value * 100) / 100;\n}\nfunction extractResourceTiming(entry) {\n const fields = [\n "startTime",\n "requestStart",\n "responseStart",\n "responseEnd",\n "duration",\n "transferSize",\n "encodedBodySize",\n "decodedBodySize"\n ];\n const timing = {};\n for (const field of fields) {\n const value = entry?.[field];\n if (typeof value === "number" && Number.isFinite(value) && value >= 0) {\n timing[field] = roundRouteTimingValue(value);\n }\n }\n return Object.keys(timing).length ? timing : null;\n}\nfunction createRouteTimingRecorder(window, logging2) {\n const { log } = logging2;\n function emitRouteTiming(phase, path, startedAt, detail = {}) {\n const entry = {\n phase,\n path,\n duration: Math.max(0, routeTimingNow() - startedAt),\n timestamp: Date.now(),\n ...detail\n };\n const timings = Array.isArray(window.__veryfrontRouteTimings) ? window.__veryfrontRouteTimings : [];\n timings.push(entry);\n if (timings.length > MAX_ROUTE_TIMINGS) {\n timings.splice(0, timings.length - MAX_ROUTE_TIMINGS);\n }\n window.__veryfrontRouteTimings = timings;\n try {\n window.dispatchEvent(new CustomEvent("veryfront:route-timing", { detail: entry }));\n } catch (_) {\n }\n log("Route timing:", entry);\n return entry;\n }\n function getPageDataResourceTiming(endpoint, fetchStartedAt) {\n try {\n if (typeof performance === "undefined" || typeof performance.getEntriesByName !== "function") {\n return null;\n }\n const href = new URL(endpoint, window.location.href).href;\n const entries = performance.getEntriesByName(href, "resource");\n if (!entries.length) return null;\n for (let index = entries.length - 1; index >= 0; index--) {\n const entry = entries[index];\n const responseEnd = entry?.responseEnd;\n if (typeof responseEnd === "number" && Number.isFinite(responseEnd) && responseEnd + 1 >= fetchStartedAt) {\n return extractResourceTiming(entry);\n }\n }\n return null;\n } catch (_) {\n return null;\n }\n }\n function buildPageDataTimingDetail(response, endpoint, fetchStartedAt, source) {\n const detail = { source, status: response.status };\n const serverTiming = readResponseServerTiming(response);\n if (serverTiming) {\n detail.serverTiming = serverTiming;\n const serverTimingMetrics = parseServerTimingMetrics(serverTiming);\n if (serverTimingMetrics) detail.serverTimingMetrics = serverTimingMetrics;\n }\n const resourceTiming = getPageDataResourceTiming(response.url || endpoint, fetchStartedAt);\n if (resourceTiming) detail.resourceTiming = resourceTiming;\n return detail;\n }\n return { emitRouteTiming, buildPageDataTimingDetail };\n}\n\n// src/html/hydration-script-builder/runtime/router.ts\nvar FETCH_TIMEOUT_MS = 1e4;\nvar MAX_RETRIES = 2;\nvar MAX_CACHE_SIZE = 50;\nvar CACHE_TTL_MS = 5 * 60 * 1e3;\nvar BACKGROUND_REFRESH_INTERVAL_MS = 30 * 1e3;\nvar PREFETCH_DELAY_MS = 100;\nvar MAX_PREFETCH_PATHS = 100;\nvar IDLE_PREFETCH_DELAY_MS = 1200;\nvar IDLE_PREFETCH_MAX_LINKS = 4;\nvar VIEWPORT_PREFETCH_MAX_LINKS = 8;\nvar PAGE_DATA_PREFETCH_CONCURRENCY = 2;\nvar VIEWPORT_PREFETCH_ROOT_MARGIN = "200px";\nvar MAX_SCROLL_POSITIONS = 100;\nfunction createRouterRuntime(deps) {\n const { env: env2, logging: logging2, routeTiming: routeTiming2, componentLoader: componentLoader2, snapshotModules: snapshotModules2 } = deps;\n const { window, document, React: React2, RouterProvider: RouterProvider2, PageContextProvider: PageContextProvider2 } = env2;\n const { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = env2;\n const { log, logError, logBackgroundFetchFailure, perfStart, perfEnd } = logging2;\n const { emitRouteTiming, buildPageDataTimingDetail } = routeTiming2;\n const { loadComponent } = componentLoader2;\n const documentPinKey = deps.documentDependencyPinningCacheKey;\n let hydrationResolve;\n let hydrationReject;\n const hydrationPromise = new Promise((resolve, reject) => {\n hydrationResolve = resolve;\n hydrationReject = reject;\n });\n let hydrationCompleted = false;\n let hydrationFailed = false;\n function signalHydrationComplete() {\n hydrationCompleted = true;\n hydrationResolve();\n log("Hydration complete signal received");\n }\n function signalHydrationFailed(error) {\n hydrationFailed = true;\n hydrationReject(error);\n logError("Hydration failed signal received:", error);\n }\n window.__veryfrontHydrationComplete = signalHydrationComplete;\n window.__veryfrontHydrationFailed = signalHydrationFailed;\n function pageDataCacheIdentity2(path) {\n return pageDataCacheIdentity(path, documentPinKey);\n }\n function navigateDocument(target) {\n const safeUrl = resolveDocumentNavigationUrl(target, window.location.origin);\n if (safeUrl) {\n window.location.href = safeUrl;\n return;\n }\n logError("Refusing an unsafe document navigation:", target);\n window.location.reload();\n }\n let clientBuildVersion = null;\n function checkVersionMismatch(newVersion) {\n if (!clientBuildVersion) {\n clientBuildVersion = newVersion;\n log("Build version initialized:", newVersion);\n return false;\n }\n if (newVersion.serverStart !== clientBuildVersion.serverStart) {\n log("Server restarted, reloading...", {\n old: clientBuildVersion.serverStart,\n new: newVersion.serverStart\n });\n return true;\n }\n if (newVersion.framework !== clientBuildVersion.framework) {\n log("Framework version changed, reloading...", {\n old: clientBuildVersion.framework,\n new: newVersion.framework\n });\n return true;\n }\n if (newVersion.projectUpdated && clientBuildVersion.projectUpdated && newVersion.projectUpdated !== clientBuildVersion.projectUpdated) {\n log("Project content updated, reloading...", {\n old: clientBuildVersion.projectUpdated,\n new: newVersion.projectUpdated\n });\n return true;\n }\n return false;\n }\n const pageDataCache = /* @__PURE__ */ new Map();\n const pendingPageDataFetches = /* @__PURE__ */ new Map();\n const backgroundRefreshTimestamps = /* @__PURE__ */ new Map();\n function getCachedPageData(path) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n const entry = pageDataCache.get(cacheIdentity);\n if (!entry) return null;\n if (Date.now() - entry.timestamp < CACHE_TTL_MS) return entry.data;\n pageDataCache.delete(cacheIdentity);\n backgroundRefreshTimestamps.delete(cacheIdentity);\n return null;\n }\n function setCachedPageData(path, data) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n if (pageDataCache.size >= MAX_CACHE_SIZE) {\n const oldest = pageDataCache.keys().next().value;\n if (oldest) {\n pageDataCache.delete(oldest);\n backgroundRefreshTimestamps.delete(oldest);\n }\n }\n pageDataCache.set(cacheIdentity, { data, timestamp: Date.now() });\n }\n const scrollPositions = /* @__PURE__ */ new Map();\n function saveScrollPosition(path) {\n if (scrollPositions.size >= MAX_SCROLL_POSITIONS) {\n const oldest = scrollPositions.keys().next().value;\n if (oldest) scrollPositions.delete(oldest);\n }\n scrollPositions.set(path, window.scrollY);\n }\n function restoreScrollPosition(path) {\n const savedY = scrollPositions.get(path);\n if (savedY === void 0) return false;\n requestAnimationFrame(() => window.scrollTo(0, savedY));\n return true;\n }\n let progressBar = null;\n let progressTimeout = null;\n function showNavigationProgress() {\n if (!progressBar) {\n progressBar = document.createElement("div");\n progressBar.id = "vf-nav-progress";\n progressBar.style.cssText = "position:fixed;top:0;left:0;height:3px;width:0;background:linear-gradient(90deg,#0066ff,#00aaff);z-index:99999;transition:width 0.3s ease-out,opacity 0.2s;opacity:1;";\n document.body.prepend(progressBar);\n }\n progressBar.style.opacity = "1";\n progressBar.style.width = "30%";\n progressTimeout = setTimeout2(() => {\n if (progressBar?.style) progressBar.style.width = "70%";\n }, 300);\n document.body.setAttribute("aria-busy", "true");\n }\n function hideNavigationProgress() {\n if (progressTimeout) {\n clearTimeout2(progressTimeout);\n progressTimeout = null;\n }\n if (progressBar) {\n progressBar.style.width = "100%";\n setTimeout2(() => {\n if (!progressBar) return;\n progressBar.style.opacity = "0";\n setTimeout2(() => {\n if (progressBar) progressBar.style.width = "0";\n }, 200);\n }, 150);\n }\n document.body.removeAttribute("aria-busy");\n }\n let currentAbortController = null;\n function sleep(ms) {\n return new Promise((resolve) => setTimeout2(resolve, ms));\n }\n async function fetchWithRetry(url, options, maxRetries = MAX_RETRIES) {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const controller = new AbortController();\n const callerSignal = options.signal;\n const abortFromCaller = () => controller.abort();\n if (callerSignal?.aborted) controller.abort();\n callerSignal?.addEventListener("abort", abortFromCaller, { once: true });\n const timeout = setTimeout2(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const response = await env2.fetch(url, { ...options, signal: controller.signal });\n clearTimeout2(timeout);\n callerSignal?.removeEventListener("abort", abortFromCaller);\n if (response.ok) return response;\n if (response.status >= 500 && attempt < maxRetries) {\n log("Server error, retrying...", response.status);\n await sleep(Math.pow(2, attempt) * 500);\n continue;\n }\n return response;\n } catch (error) {\n clearTimeout2(timeout);\n callerSignal?.removeEventListener("abort", abortFromCaller);\n if (error.name === "AbortError" && callerSignal?.aborted) throw error;\n if (attempt === maxRetries) throw error;\n log("Fetch failed, retrying...", error.message);\n await sleep(Math.pow(2, attempt) * 500);\n }\n }\n throw new Error("Failed to fetch page data");\n }\n async function fetchPageDataFresh(path, signal, options = {}) {\n const {\n triggerReloadOnVersionMismatch = false,\n recordRouteTiming = false,\n timingSource = "network"\n } = options;\n const endpoint = buildPageDataEndpoint(path, window.location.origin);\n const startedAt = recordRouteTiming ? routeTimingNow() : 0;\n log("Fetching page data:", path);\n perfStart("fetch:" + path);\n const headers = options.prefetch ? { "X-Veryfront-Prefetch": "1" } : { "X-Veryfront-Navigation": "spa" };\n if (documentPinKey) {\n headers["X-Veryfront-Dependency-Pins"] = documentPinKey;\n }\n const response = await fetchWithRetry(endpoint, {\n headers,\n signal\n }, options.prefetch ? 0 : MAX_RETRIES);\n if (!response.ok) {\n perfEnd("fetch:" + path);\n if (recordRouteTiming) {\n emitRouteTiming(\n "page-data",\n path,\n startedAt,\n buildPageDataTimingDetail(response, endpoint, startedAt, timingSource)\n );\n }\n const error = new Error("Failed to fetch page data: " + response.status);\n error.status = response.status;\n throw error;\n }\n perfStart("parse:" + path);\n const data = assertPageDataMatchesDocumentSnapshot(\n path,\n await response.json(),\n documentPinKey\n );\n perfEnd("parse:" + path);\n perfEnd("fetch:" + path);\n if (recordRouteTiming) {\n emitRouteTiming(\n "page-data",\n path,\n startedAt,\n buildPageDataTimingDetail(response, endpoint, startedAt, timingSource)\n );\n }\n if (triggerReloadOnVersionMismatch) {\n const checkedData = handlePageDataVersionMismatch(path, data);\n if (checkedData !== data) return checkedData;\n }\n setCachedPageData(path, data);\n return data;\n }\n function handlePageDataVersionMismatch(path, data) {\n if (data.buildVersion && checkVersionMismatch(data.buildVersion)) {\n log("Version mismatch detected, performing full page reload to:", path);\n navigateDocument(path);\n return new Promise(() => {\n });\n }\n return data;\n }\n function startPageDataFetch(path, signal, options = {}) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n const request = fetchPageDataFresh(path, signal, options).finally(() => {\n if (options.trackPending !== false && pendingPageDataFetches.get(cacheIdentity) === request) {\n pendingPageDataFetches.delete(cacheIdentity);\n }\n });\n if (options.trackPending !== false) {\n pendingPageDataFetches.set(cacheIdentity, request);\n }\n return request;\n }\n function fetchPageDataDeduped(path) {\n const pending = pendingPageDataFetches.get(pageDataCacheIdentity2(path));\n if (pending) return pending;\n return startPageDataFetch(path, null);\n }\n function refreshPageDataInBackground(path) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n const lastRefreshAt = backgroundRefreshTimestamps.get(cacheIdentity) || 0;\n const now = Date.now();\n if (now - lastRefreshAt < BACKGROUND_REFRESH_INTERVAL_MS) return;\n backgroundRefreshTimestamps.set(cacheIdentity, now);\n fetchPageDataDeduped(path).catch((error) => {\n logBackgroundFetchFailure("Stale page data refresh", path, error);\n });\n }\n async function fetchPageDataForNavigation(path, signal) {\n const startedAt = routeTimingNow();\n const cached = getCachedPageData(path);\n if (cached) {\n log("Using cached page data:", path);\n refreshPageDataInBackground(path);\n emitRouteTiming("page-data", path, startedAt, { source: "cache" });\n return cached;\n }\n const pending = pendingPageDataFetches.get(pageDataCacheIdentity2(path));\n if (pending) {\n log("Reusing pending page data fetch for navigation:", path);\n const data = await pending;\n emitRouteTiming("page-data", path, startedAt, { source: "deduped" });\n return handlePageDataVersionMismatch(path, data);\n }\n return startPageDataFetch(path, signal, {\n triggerReloadOnVersionMismatch: true,\n recordRouteTiming: true,\n timingSource: "network"\n });\n }\n function fetchPageDataForPrefetch(path, signal) {\n if (getCachedPageData(path)) return Promise.resolve();\n return startPageDataFetch(path, signal, { prefetch: true, trackPending: false }).then((data) => preloadModulesForPageData(data, path)).catch((error) => {\n if (!isAbortError(error)) {\n logBackgroundFetchFailure("Page data prefetch", path, error);\n }\n throw error;\n });\n }\n let currentPath = window.location.pathname;\n let isNavigating = false;\n async function navigateSPA(href, historyMode = "push", restoreScroll = false) {\n currentAbortController?.abort();\n if (isNavigating) return;\n isNavigating = true;\n const [navigationPath] = href.split("#");\n removeQueuedPrefetch(navigationPath || href);\n abortActiveSpeculativePrefetches();\n currentAbortController = new AbortController();\n const signal = currentAbortController.signal;\n const navigationStartedAt = routeTimingNow();\n showNavigationProgress();\n perfStart("nav:total:" + href);\n try {\n log("SPA navigating to:", href);\n saveScrollPosition(currentPath);\n const [path, hash] = href.split("#");\n const targetPath = path || currentPath;\n perfStart("nav:fetchData:" + href);\n const pageData = await fetchPageDataForNavigation(targetPath, signal);\n perfEnd("nav:fetchData:" + href);\n if (signal.aborted) return;\n if (pageData && pageData.redirect && typeof pageData.redirect.destination === "string") {\n const redirectUrl = resolveDocumentNavigationUrl(\n pageData.redirect.destination,\n window.location.origin\n );\n if (redirectUrl) {\n log("SPA navigation redirect -> " + redirectUrl);\n window.location.href = redirectUrl;\n return;\n }\n }\n if (historyMode === "push") {\n window.history.pushState({ pageData, scrollY: 0 }, "", href);\n } else if (historyMode === "replace") {\n window.history.replaceState({ pageData, scrollY: 0 }, "", href);\n }\n currentPath = targetPath;\n router.pathname = targetPath;\n router.query = Object.fromEntries(new URLSearchParams(window.location.search));\n router.params = flattenRouteParams(pageData.params);\n perfStart("nav:render:" + href);\n await renderPageFromData(pageData, targetPath);\n perfEnd("nav:render:" + href);\n if (restoreScroll) {\n restoreScrollPosition(targetPath);\n } else if (hash) {\n requestAnimationFrame(() => {\n const target = document.getElementById(hash);\n if (target) {\n target.scrollIntoView({ behavior: "smooth" });\n return;\n }\n window.scrollTo(0, 0);\n });\n } else {\n window.scrollTo(0, 0);\n }\n hideNavigationProgress();\n perfEnd("nav:total:" + href);\n emitRouteTiming("total", targetPath, navigationStartedAt, {\n href,\n historyMode,\n restoreScroll\n });\n log("SPA navigation complete");\n } catch (error) {\n hideNavigationProgress();\n if (error.name === "AbortError") {\n log("Navigation aborted");\n return;\n }\n logError("SPA navigation failed:", error.message);\n if (error.status === 404) {\n logError("Page not found:", href);\n }\n navigateDocument(href);\n } finally {\n isNavigating = false;\n currentAbortController = null;\n processPageDataPrefetchQueue();\n }\n }\n async function loadPageDataComponent(pageData, path, options = {}) {\n if (!pageData.isolatedClientPage) return loadComponent(path, pageData, options);\n const moduleUrl = buildPinnedRscModuleUrl(path, pageData);\n const module = await snapshotModules2.importSnapshotBoundModule(\n moduleUrl,\n options.allowDocumentReload !== false\n );\n return module.MDXLayout || module.MainLayout || module.default || module;\n }\n async function renderPageFromData(pageData, targetPath) {\n if (pageData.requiresFullDocumentNavigation) {\n throw new Error("Server layout requires full document navigation");\n }\n if (window.__veryfrontSetReleaseId) {\n window.__veryfrontSetReleaseId(pageData.releaseId || null);\n }\n if (window.__veryfrontSetReleaseAssetModules) {\n window.__veryfrontSetReleaseAssetModules(pageData.releaseAssetModules || null);\n }\n perfStart("render:loadAll");\n const allPaths = getPageDataModulePaths(pageData);\n const modulesStartedAt = routeTimingNow();\n const components = await Promise.all(\n allPaths.map((path) => loadPageDataComponent(pageData, path))\n );\n emitRouteTiming("modules", targetPath, modulesStartedAt, { count: allPaths.length });\n perfEnd("render:loadAll");\n const [PageComponent, ...rest] = components;\n const ErrorComponent = pageData.errorPath ? rest.pop() : null;\n const AppComponent = pageData.appPath ? rest.pop() : null;\n const LayoutComponents = rest;\n if (!PageComponent) {\n throw new Error("Failed to load page component: " + pageData.pagePath);\n }\n if (pageData.frontmatter?.title) {\n document.title = pageData.frontmatter.title;\n }\n if (pageData.frontmatter?.description) {\n const metaDesc = document.querySelector(\'meta[name="description"]\');\n metaDesc?.setAttribute("content", pageData.frontmatter.description);\n }\n if (pageData.css) {\n const existingStyle = document.getElementById("veryfront-spa-css");\n if (existingStyle) {\n existingStyle.textContent = pageData.css;\n } else {\n const styleEl = document.createElement("style");\n const nonce = getDocumentNonce(document);\n if (nonce) styleEl.setAttribute("nonce", nonce);\n styleEl.id = "veryfront-spa-css";\n styleEl.textContent = pageData.css;\n document.head.appendChild(styleEl);\n }\n log("Injected CSS for SPA navigation", { cssLength: pageData.css.length });\n } else if (pageData.cssAction === "clear") {\n const existingStyle = document.getElementById("veryfront-spa-css");\n if (existingStyle) {\n existingStyle.remove();\n log("Cleared SPA CSS for release stylesheet navigation");\n }\n }\n const normalizedParams = flattenRouteParams(pageData.params);\n let tree = React2.createElement(PageComponent, {\n ...pageData.props,\n params: normalizedParams\n });\n if (pageData.layouts?.length) {\n for (let i = pageData.layouts.length - 1; i >= 0; i--) {\n const layout = pageData.layouts[i];\n const LayoutComponent = LayoutComponents[i];\n if (!LayoutComponent || !layout) continue;\n const layoutProps = pageData.layoutProps?.[layout.path] || {};\n tree = React2.createElement(LayoutComponent, { ...layoutProps, children: tree });\n }\n }\n if (AppComponent) {\n tree = React2.createElement(AppComponent, { children: tree });\n log("Wrapped with App component for SPA navigation");\n }\n if (ErrorComponent) {\n class AppRouterErrorBoundary extends React2.Component {\n constructor(props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n static getDerivedStateFromError(error) {\n return { hasError: true, error };\n }\n render() {\n if (this.state.hasError) {\n return React2.createElement(ErrorComponent, {\n error: this.state.error,\n reset: () => this.setState({ hasError: false, error: null })\n });\n }\n return this.props.children;\n }\n }\n tree = React2.createElement(AppRouterErrorBoundary, null, tree);\n }\n const headingsArray = pageData.headings || [];\n const pageContext = {\n slug: pageData.slug || "",\n path: pageData.pagePath || targetPath,\n params: normalizedParams,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n frontmatter: pageData.frontmatter || {},\n data: pageData.props || {},\n headings: headingsArray,\n mdxHeadings: headingsArray\n };\n tree = React2.createElement(PageContextProvider2, { pageContext, children: tree });\n tree = React2.createElement(RouterProvider2, { router, children: tree });\n const container = pageData.isolatedClientPage ? document.getElementById("veryfront-page-island") : document.getElementById("root");\n if (!hydrationCompleted && !hydrationFailed) {\n log("Waiting for hydration to complete before SPA render...");\n try {\n await Promise.race([\n hydrationPromise,\n new Promise(\n (_, reject) => setTimeout2(() => reject(new Error("Hydration timeout")), 1e4)\n )\n ]);\n } catch (waitError) {\n log("Hydration wait failed:", waitError.message);\n }\n }\n if (container?.__reactRoot) {\n perfStart("render:reactRender");\n container.__reactRoot.render(tree);\n perfEnd("render:reactRender");\n log("Page re-rendered via SPA");\n scheduleRoutePrefetchRefresh();\n return;\n }\n if (hydrationFailed) {\n throw new Error(\n "React root not found - hydration failed, falling back to full page navigation"\n );\n }\n throw new Error("React root not found");\n }\n let prefetchTimeout = null;\n let currentHoverLink = null;\n let routePrefetchRefreshPending = false;\n let viewportPrefetchObserver = null;\n const observedPrefetchLinks = /* @__PURE__ */ new WeakSet();\n const prefetchedPaths = /* @__PURE__ */ new Set();\n const inFlightPrefetches = /* @__PURE__ */ new Set();\n const queuedPrefetchPaths = /* @__PURE__ */ new Set();\n const pageDataPrefetchQueue = [];\n const activePageDataPrefetchControllers = /* @__PURE__ */ new Map();\n function cancelScheduledPrefetch() {\n if (prefetchTimeout) {\n clearTimeout2(prefetchTimeout);\n prefetchTimeout = null;\n }\n currentHoverLink = null;\n }\n function getPageDataModulePaths(pageData) {\n const layoutPaths = (pageData.layouts || []).map((l) => l.path).filter(Boolean);\n const allPaths = [pageData.pagePath, ...layoutPaths].filter(Boolean);\n if (pageData.appPath) allPaths.push(pageData.appPath);\n if (pageData.errorPath) allPaths.push(pageData.errorPath);\n return allPaths;\n }\n function getCurrentRouteHref() {\n return window.location.pathname + window.location.search;\n }\n function getInternalRouteHrefFromLink(link) {\n if (!link || link.target === "_blank" || link.hasAttribute("download") || link.getAttribute("data-prefetch") === "false") {\n return null;\n }\n const href = link.getAttribute("href");\n if (!href || href.startsWith("#") || href.startsWith("//") || !href.startsWith("/")) {\n return null;\n }\n try {\n const url = new URL(href, window.location.origin);\n if (url.origin !== window.location.origin) return null;\n const routeHref = url.pathname + url.search;\n return routeHref === getCurrentRouteHref() ? null : routeHref;\n } catch (_) {\n return null;\n }\n }\n function getEligiblePrefetchLinks(limit) {\n const links = [];\n const seenHrefs = /* @__PURE__ */ new Set();\n for (const link of document.querySelectorAll("a[href]")) {\n const href = getInternalRouteHrefFromLink(link);\n if (!href || seenHrefs.has(href)) continue;\n seenHrefs.add(href);\n links.push({ link, href });\n if (links.length >= limit) break;\n }\n return links;\n }\n async function preloadModulesForPageData(pageData, path) {\n if (!pageData || pageData.requiresFullDocumentNavigation) return;\n if (pageData.releaseId && window.__veryfrontSetReleaseId) {\n window.__veryfrontSetReleaseId(pageData.releaseId);\n }\n if (pageData.releaseAssetModules && window.__veryfrontSetReleaseAssetModules) {\n window.__veryfrontSetReleaseAssetModules(pageData.releaseAssetModules);\n }\n const modulePaths = getPageDataModulePaths(pageData);\n if (modulePaths.length === 0) return;\n try {\n await Promise.all(\n modulePaths.map(\n (modulePath) => loadPageDataComponent(pageData, modulePath, { allowDocumentReload: false })\n )\n );\n } catch (error) {\n if (isDependencySnapshotConflict(error)) {\n const cacheIdentity = pageDataCacheIdentity2(path);\n pageDataCache.delete(cacheIdentity);\n backgroundRefreshTimestamps.delete(cacheIdentity);\n prefetchedPaths.delete(path);\n throw error;\n }\n logBackgroundFetchFailure("Module prefetch", path, error);\n }\n }\n function removeQueuedPrefetch(path) {\n queuedPrefetchPaths.delete(path);\n for (let i = pageDataPrefetchQueue.length - 1; i >= 0; i--) {\n if (pageDataPrefetchQueue[i] === path) pageDataPrefetchQueue.splice(i, 1);\n }\n }\n function abortActiveSpeculativePrefetches() {\n for (const controller of activePageDataPrefetchControllers.values()) {\n controller.abort();\n }\n }\n function processPageDataPrefetchQueue() {\n if (isNavigating) return;\n while (activePageDataPrefetchControllers.size < PAGE_DATA_PREFETCH_CONCURRENCY && pageDataPrefetchQueue.length > 0) {\n const href = pageDataPrefetchQueue.shift();\n queuedPrefetchPaths.delete(href);\n if (prefetchedPaths.has(href) || inFlightPrefetches.has(href) || getCachedPageData(href)) {\n continue;\n }\n if (prefetchedPaths.size >= MAX_PREFETCH_PATHS) {\n const oldest = prefetchedPaths.values().next().value;\n if (oldest) prefetchedPaths.delete(oldest);\n }\n const controller = new AbortController();\n prefetchedPaths.add(href);\n inFlightPrefetches.add(href);\n activePageDataPrefetchControllers.set(href, controller);\n fetchPageDataForPrefetch(href, controller.signal).catch((error) => {\n prefetchedPaths.delete(href);\n if (isDependencySnapshotConflict(error)) {\n logBackgroundFetchFailure("Module prefetch", href, error);\n }\n }).finally(() => {\n inFlightPrefetches.delete(href);\n activePageDataPrefetchControllers.delete(href);\n processPageDataPrefetchQueue();\n });\n }\n }\n function prefetchPage(href) {\n if (isNavigating) return;\n if (prefetchedPaths.has(href) || inFlightPrefetches.has(href) || queuedPrefetchPaths.has(href)) return;\n const cachedPageData = getCachedPageData(href);\n if (cachedPageData) {\n preloadModulesForPageData(cachedPageData, href).catch((error) => {\n logBackgroundFetchFailure("Module prefetch", href, error);\n });\n return;\n }\n queuedPrefetchPaths.add(href);\n pageDataPrefetchQueue.push(href);\n processPageDataPrefetchQueue();\n }\n function prefetchEligibleRouteLinks(limit) {\n for (const { href } of getEligiblePrefetchLinks(limit)) {\n prefetchPage(href);\n }\n }\n function ensureViewportPrefetchObserver() {\n if (viewportPrefetchObserver || typeof IntersectionObserver !== "function") {\n return viewportPrefetchObserver;\n }\n viewportPrefetchObserver = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n if (!entry.isIntersecting) continue;\n viewportPrefetchObserver?.unobserve(entry.target);\n const href = getInternalRouteHrefFromLink(\n entry.target\n );\n if (href) prefetchPage(href);\n }\n }, { rootMargin: VIEWPORT_PREFETCH_ROOT_MARGIN });\n return viewportPrefetchObserver;\n }\n function observeViewportPrefetchLinks() {\n const observer = ensureViewportPrefetchObserver();\n if (!observer) return;\n for (const { link } of getEligiblePrefetchLinks(VIEWPORT_PREFETCH_MAX_LINKS)) {\n if (observedPrefetchLinks.has(link)) continue;\n observedPrefetchLinks.add(link);\n observer.observe(link);\n }\n }\n function runRoutePrefetchRefresh() {\n routePrefetchRefreshPending = false;\n prefetchEligibleRouteLinks(IDLE_PREFETCH_MAX_LINKS);\n observeViewportPrefetchLinks();\n }\n function scheduleRoutePrefetchRefresh() {\n if (routePrefetchRefreshPending) return;\n routePrefetchRefreshPending = true;\n setTimeout2(() => {\n if (typeof requestIdleCallback === "function") {\n requestIdleCallback(runRoutePrefetchRefresh, { timeout: IDLE_PREFETCH_DELAY_MS });\n return;\n }\n runRoutePrefetchRefresh();\n }, IDLE_PREFETCH_DELAY_MS);\n }\n const router = {\n domain: window.location.origin,\n path: window.location.pathname,\n push: (path) => {\n void navigateSPA(path, "push");\n },\n replace: (path) => {\n void navigateSPA(path, "replace");\n },\n back: () => {\n window.history.back();\n },\n forward: () => {\n window.history.forward();\n },\n prefetch: (path) => {\n prefetchPage(path);\n },\n pathname: window.location.pathname,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n // Seed route params from the hydration data (issue #2741). Catch-all\n // segments arrive as arrays and are joined so no path info is lost.\n params: flattenRouteParams(deps.initialHydrationData.params || {}),\n isPreview: false,\n isMounted: true,\n navigate: (path) => navigateSPA(path, "push"),\n reload: () => window.location.reload()\n };\n window.__veryfrontRouter = router;\n if (deps.navigationStoreUsesRegistryFallback) {\n log("Router runtime does not export getNavigationStore; using shared v1 registry fallback");\n }\n if (typeof deps.getNavigationStore === "function") {\n deps.getNavigationStore().setNavigator((href, options) => {\n const mode = options && options.history;\n const historyMode = mode === "replace" ? "replace" : mode === "none" ? "none" : "push";\n return navigateSPA(href, historyMode);\n });\n }\n window.addEventListener("popstate", async (e) => {\n const path = window.location.pathname;\n log("Popstate:", path);\n saveScrollPosition(currentPath);\n if (!e.state?.pageData) {\n await navigateSPA(path, "none", true);\n return;\n }\n showNavigationProgress();\n try {\n currentPath = path;\n router.pathname = path;\n router.query = Object.fromEntries(new URLSearchParams(window.location.search));\n router.params = flattenRouteParams(e.state.pageData.params);\n await renderPageFromData(e.state.pageData, path);\n restoreScrollPosition(path);\n hideNavigationProgress();\n } catch (error) {\n hideNavigationProgress();\n logError("Popstate render failed:", error.message);\n window.location.reload();\n }\n });\n document.addEventListener("click", (e) => {\n const link = e.target?.closest("a[href]");\n if (!link) return;\n const href = link.getAttribute("href");\n if (!href) return;\n if (href.startsWith("#")) {\n const target = document.getElementById(href.slice(1));\n if (!target) return;\n e.preventDefault();\n target.scrollIntoView({ behavior: "smooth" });\n window.history.pushState(null, "", href);\n return;\n }\n if (link.target === "_blank" || link.hasAttribute("download") || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || !href.startsWith("/") || href.startsWith("//")) {\n return;\n }\n e.preventDefault();\n cancelScheduledPrefetch();\n void navigateSPA(href, "push");\n });\n document.addEventListener(\n "mouseenter",\n (e) => {\n if (!e.target || typeof e.target.closest !== "function") return;\n const link = e.target.closest("a[href]");\n if (!link) return;\n const href = getInternalRouteHrefFromLink(link);\n if (!href) return;\n if (currentHoverLink === link) return;\n if (prefetchTimeout) {\n clearTimeout2(prefetchTimeout);\n prefetchTimeout = null;\n }\n currentHoverLink = link;\n prefetchTimeout = setTimeout2(() => {\n prefetchPage(href);\n prefetchTimeout = null;\n }, PREFETCH_DELAY_MS);\n },\n true\n );\n document.addEventListener(\n "mouseleave",\n (e) => {\n if (!e.target || typeof e.target.closest !== "function") return;\n const relatedTarget = e.relatedTarget;\n if (currentHoverLink && relatedTarget && currentHoverLink.contains(relatedTarget)) return;\n cancelScheduledPrefetch();\n },\n true\n );\n if (document.readyState === "loading") {\n document.addEventListener("DOMContentLoaded", scheduleRoutePrefetchRefresh, { once: true });\n } else {\n scheduleRoutePrefetchRefresh();\n }\n window.useRouter = () => {\n try {\n return env2.useRouterFromModule();\n } catch (_) {\n return window.__veryfrontRouter;\n }\n };\n return {\n router,\n navigateSPA,\n renderPageFromData,\n prefetchPage,\n signalHydrationComplete,\n signalHydrationFailed\n };\n}\n\n// src/html/hydration-script-builder/runtime/renderer.ts\nfunction isModuleNotFoundError(error) {\n if (!error) return false;\n if (error instanceof SyntaxError) return false;\n const message = String(error.message || error);\n return /(?:dynamically imported module|Importing a module script failed|Failed to load module script)/i.test(message);\n}\nfunction preferReachedModuleError(earlier, later) {\n if (!earlier) return later;\n if (!later) return earlier;\n if (isModuleNotFoundError(earlier) && !isModuleNotFoundError(later)) return later;\n return earlier;\n}\nasync function loadPageModuleWithIndexFallback(basePath, pageSlug, pageModuleError, importModule) {\n try {\n return await importModule(basePath + ".js");\n } catch (error) {\n const routeError = preferReachedModuleError(pageModuleError, error);\n if (pageSlug === "index" || pageSlug.endsWith("/index")) throw routeError;\n try {\n return await importModule(basePath + "/index.js");\n } catch (indexError) {\n throw preferReachedModuleError(routeError, indexError);\n }\n }\n}\nfunction isAppRouterPath(path, appRouterRoot) {\n const normalizedPath = typeof path === "string" ? path.replace(/^\\/+/, "") : "";\n return normalizedPath === appRouterRoot || normalizedPath.startsWith(appRouterRoot + "/");\n}\nfunction isRootAppLayoutPath(path, appRouterRoot) {\n const normalizedPath = typeof path === "string" ? path.replace(/^\\/+/, "") : "";\n const pathWithoutExtension = normalizedPath.replace(/\\.(?:tsx|jsx|ts|js)$/, "");\n return pathWithoutExtension === appRouterRoot + "/layout";\n}\nfunction unwrapAppRouterDocumentLayout(LayoutComponent, React2) {\n return function AppRouterDocumentLayout(props) {\n const element = LayoutComponent(props);\n const asElement = element;\n if (!React2.isValidElement(element) || asElement.type !== "html") {\n return element;\n }\n const body = React2.Children.toArray(asElement.props?.children).find(\n (child) => React2.isValidElement(child) && child.type === "body"\n );\n return body?.props?.children ?? props.children;\n };\n}\nfunction createHydrationRenderer(deps) {\n const { env: env2, logging: logging2, componentLoader: componentLoader2, snapshotModules: snapshotModules2, moduleServerUrl: moduleServerUrl2 } = deps;\n const { window, document, React: React2, RouterProvider: RouterProvider2, PageContextProvider: PageContextProvider2 } = env2;\n const { DEBUG, log, logError } = logging2;\n const { loadComponent, pathToModuleUrl } = componentLoader2;\n const { importSnapshotBoundModule } = snapshotModules2;\n async function renderPage(pathname) {\n const resolvedPathname = (() => {\n const input = typeof pathname === "string" ? pathname : window.location.pathname;\n try {\n return new URL(input, window.location.origin).pathname || "/";\n } catch (_) {\n const [pathOnly] = String(input || "/").split(/[?#]/);\n return pathOnly || "/";\n }\n })();\n const dataScript = document.getElementById(HYDRATION_DATA_ELEMENT_ID);\n if (!dataScript) {\n logError("Hydration data not found");\n return;\n }\n let data = {};\n try {\n data = JSON.parse(dataScript.textContent || "{}");\n } catch (parseError) {\n logError("Failed to parse hydration data:", parseError);\n return;\n }\n log("Hydration data:", data);\n if (data.studioEmbed && window.__veryfrontSetStudioEmbed) {\n window.__veryfrontSetStudioEmbed(true);\n }\n if (window.__veryfrontSetReleaseId) {\n window.__veryfrontSetReleaseId(data.releaseId || null);\n }\n if (data.releaseAssetModules && window.__veryfrontSetReleaseAssetModules) {\n window.__veryfrontSetReleaseAssetModules(data.releaseAssetModules);\n }\n try {\n let pageModule;\n const pagePath = typeof data.pagePath === "string" ? data.pagePath : "";\n const normalizedPagePath = pagePath.replace(/^\\/+/, "");\n const normalizedAppRouterRoot = typeof data.appRouterRoot === "string" && data.appRouterRoot.replace(/^\\/+|\\/+$/g, "") ? data.appRouterRoot.replace(/^\\/+|\\/+$/g, "") : "app";\n const hasReleaseAssetModules = data.releaseAssetModules && Object.keys(data.releaseAssetModules).length > 0;\n const shouldRenderRscClientPage = data.clientModuleStrategy === "rsc-module" && !hasReleaseAssetModules && isAppRouterPath(normalizedPagePath, normalizedAppRouterRoot);\n const isolatedClientPage = data.isolatedClientPage === true;\n const loadHydrationComponent = async (path, preferRscModule) => {\n const normalizedPath = typeof path === "string" ? path.replace(/^\\/+/, "") : "";\n if (preferRscModule && isAppRouterPath(normalizedPath, normalizedAppRouterRoot)) {\n const moduleUrl = buildPinnedRscModuleUrl(path, data);\n log("Loading App Router component from RSC module:", moduleUrl);\n const module = await importSnapshotBoundModule(moduleUrl);\n return module.default || module;\n }\n return loadComponent(path, data);\n };\n let pageModuleError = null;\n if (data.pagePath) {\n const moduleUrl = shouldRenderRscClientPage ? buildPinnedRscModuleUrl(data.pagePath, data) : pathToModuleUrl(data.pagePath, data.studioEmbed, data);\n log("Loading page from hydration data:", moduleUrl);\n try {\n pageModule = await importSnapshotBoundModule(moduleUrl);\n } catch (error) {\n pageModuleError = error;\n logError("Failed to load page from hydration data:", error);\n }\n }\n if (!pageModule) {\n const pageSlug = resolvedPathname === "/" ? "index" : resolvedPathname.slice(1);\n log("Falling back to Pages Router pattern:", pageSlug);\n const prefix = pageSlug.startsWith("@/") ? "" : "/pages";\n const basePath = moduleServerUrl2 + prefix + "/" + pageSlug;\n pageModule = await loadPageModuleWithIndexFallback(\n basePath,\n pageSlug,\n pageModuleError,\n (moduleUrl) => importSnapshotBoundModule(appendDependencyPinningVersion(moduleUrl, data))\n );\n }\n if (!pageModule) {\n logError("Page module failed to load");\n return;\n }\n const PageComponent = pageModule.default || pageModule;\n if (!PageComponent) {\n logError("Page component not found");\n return;\n }\n const normalizedParams = flattenRouteParams(data.params);\n const pageProps = { ...data.props || {}, params: normalizedParams };\n let tree = React2.createElement(PageComponent, pageProps);\n const layouts = data.layouts;\n if (layouts?.length) {\n for (let i = layouts.length - 1; i >= 0; i--) {\n const layout = layouts[i];\n if (!layout) continue;\n const LayoutComponent = await loadHydrationComponent(\n layout.path,\n shouldRenderRscClientPage\n );\n if (LayoutComponent) {\n const WrappedLayoutComponent = shouldRenderRscClientPage && isRootAppLayoutPath(layout.path, normalizedAppRouterRoot) ? unwrapAppRouterDocumentLayout(LayoutComponent, React2) : LayoutComponent;\n const layoutProps = data.layoutProps?.[layout.path] || {};\n tree = React2.createElement(\n WrappedLayoutComponent,\n { ...layoutProps, children: tree }\n );\n }\n }\n }\n if (data.appPath && !isolatedClientPage) {\n const AppComponent = await loadHydrationComponent(data.appPath, shouldRenderRscClientPage);\n if (AppComponent) {\n tree = React2.createElement(AppComponent, { children: tree });\n }\n }\n if (data.errorPath) {\n const ErrorComponent = await loadHydrationComponent(\n data.errorPath,\n shouldRenderRscClientPage\n );\n if (ErrorComponent) {\n class AppRouterErrorBoundary extends React2.Component {\n constructor(props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n static getDerivedStateFromError(error) {\n return { hasError: true, error };\n }\n render() {\n if (this.state.hasError) {\n return React2.createElement(ErrorComponent, {\n error: this.state.error,\n reset: () => this.setState({ hasError: false, error: null })\n });\n }\n return this.props.children;\n }\n }\n tree = React2.createElement(AppRouterErrorBoundary, null, tree);\n }\n }\n const headings = data.headings || [];\n const pageContext = {\n slug: data.slug || "",\n path: data.pagePath || resolvedPathname,\n params: normalizedParams,\n query: Object.fromEntries(new URLSearchParams(window.location.search)),\n frontmatter: data.frontmatter || {},\n data: data.props || {},\n headings,\n mdxHeadings: headings\n // Alias for backwards compatibility\n };\n tree = React2.createElement(PageContextProvider2, { pageContext, children: tree });\n tree = React2.createElement(RouterProvider2, { router: deps.router, children: tree });\n const container = isolatedClientPage ? document.getElementById("veryfront-page-island") : document.getElementById("root");\n if (!container) {\n if (isolatedClientPage) {\n throw new Error("Isolated client page root not found");\n }\n return;\n }\n if (container.__reactRoot) {\n container.__reactRoot.render(tree);\n log("Page re-rendered");\n return;\n }\n if (shouldRenderRscClientPage) {\n container.__reactRoot = env2.createRoot(container);\n container.__reactRoot.render(tree);\n log("Client-side React app rendered successfully");\n } else {\n const { hydrateRoot } = await import("react-dom/client");\n const options = {\n identifierPrefix: "vf",\n onRecoverableError: (error) => {\n if (data.dev && DEBUG) {\n log("Hydration mismatch (suppressed):", error.message);\n }\n }\n };\n container.__reactRoot = hydrateRoot(container, tree, options);\n log("Client-side React app hydrated successfully");\n }\n if (window.__veryfrontHydrationComplete) {\n window.__veryfrontHydrationComplete();\n }\n } catch (error) {\n logError("Client initialization error:", error);\n if (window.__veryfrontHydrationFailed) {\n window.__veryfrontHydrationFailed(error);\n }\n }\n }\n function start() {\n window.__veryfrontRenderPage = renderPage;\n void renderPage(window.location.pathname);\n const initialDataScript = document.getElementById(HYDRATION_DATA_ELEMENT_ID);\n if (initialDataScript) {\n try {\n const pageData = JSON.parse(initialDataScript.textContent || "{}");\n if (pageData.pagePath) {\n window.history.replaceState({ pageData, scrollY: 0 }, "", window.location.href);\n log("Stored initial page data in history state");\n }\n } catch (_) {\n }\n }\n }\n return { renderPage, start };\n}\n\n// src/html/hydration-script-builder/runtime/navigation-store.ts\nvar NAVIGATION_STORE_REGISTRY_KEY = "veryfront.navigation.store.v1";\nfunction resolveNavigationStore(RouterRuntime2) {\n const usesRegistryFallback2 = typeof RouterRuntime2.getNavigationStore !== "function";\n if (!usesRegistryFallback2) {\n return {\n usesRegistryFallback: usesRegistryFallback2,\n getNavigationStore: RouterRuntime2.getNavigationStore\n };\n }\n return {\n usesRegistryFallback: usesRegistryFallback2,\n getNavigationStore: () => {\n const storeKey = Symbol.for(NAVIGATION_STORE_REGISTRY_KEY);\n const registry = globalThis;\n const existing = registry[storeKey];\n if (existing) return existing;\n const listeners = /* @__PURE__ */ new Set();\n let navigator = null;\n const store = {\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n getHref() {\n const loc = globalThis.location;\n return loc ? loc.pathname + loc.search + loc.hash : "/";\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch {\n }\n }\n },\n navigate(href, options) {\n if (navigator) return navigator(href, options);\n globalThis.location?.assign(href);\n return Promise.resolve();\n },\n setNavigator(next) {\n navigator = next;\n }\n };\n registry[storeKey] = store;\n return store;\n }\n };\n}\n\n// src/html/hydration-script-builder/runtime/main.ts\nvar runtimeWindow = globalThis;\nvar runtimeDocument = globalThis.document;\nvar env = {\n window: runtimeWindow,\n document: runtimeDocument,\n fetch: (url, init) => fetch(url, init),\n React,\n RouterProvider,\n PageContextProvider,\n createRoot: (container) => createRoot(container),\n importModule: (moduleUrl) => import(moduleUrl),\n useRouterFromModule,\n setTimeout: (handler, timeout) => setTimeout(handler, timeout),\n clearTimeout: (id) => clearTimeout(id)\n};\nvar logging = createLogging(runtimeWindow);\nvar initialHydrationData = readInitialHydrationData(runtimeDocument);\nvar documentDependencyPinningCacheKey = readDocumentDependencyPinningCacheKey(\n initialHydrationData\n);\nvar routeTiming = createRouteTimingRecorder(runtimeWindow, logging);\nvar snapshotModules = createSnapshotModuleImporter({\n importModule: env.importModule,\n fetchModule: env.fetch,\n reloadDocument: () => runtimeWindow.location.reload(),\n recoveryState: runtimeWindow\n});\nvar componentLoader = createComponentLoader({\n window: runtimeWindow,\n logging,\n moduleServerUrl: moduleServerUrl(runtimeWindow),\n snapshotModules\n});\nruntimeWindow.__veryfrontClearComponentCache = componentLoader.clearComponentCache;\nruntimeWindow.__veryfrontSetStudioEmbed = componentLoader.setStudioEmbed;\nruntimeWindow.__veryfrontSetReleaseId = componentLoader.setReleaseId;\nruntimeWindow.__veryfrontSetReleaseAssetModules = componentLoader.setReleaseAssetModules;\nruntimeWindow.__veryfrontSetHMRRefreshTimestamp = componentLoader.setHMRRefreshTimestamp;\nvar { usesRegistryFallback, getNavigationStore } = resolveNavigationStore(RouterRuntime);\nvar routerRuntime = createRouterRuntime({\n env,\n logging,\n routeTiming,\n componentLoader,\n snapshotModules,\n initialHydrationData,\n documentDependencyPinningCacheKey,\n getNavigationStore,\n navigationStoreUsesRegistryFallback: usesRegistryFallback\n});\ncreateHydrationRenderer({\n env,\n logging,\n componentLoader,\n snapshotModules,\n moduleServerUrl: moduleServerUrl(runtimeWindow),\n router: routerRuntime.router\n}).start();\n';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-bundle-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/http-bundle-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"http-bundle-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/src/modules/react-loader/ssr-module-loader/http-bundle-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAkCzD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC7E,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;;GAGG;AACH,wBAAsB,kCAAkC,CACtD,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAyBhD;AAED,6EAA6E;AAC7E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA4B1F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB1D;AAED;;;GAGG;AACH,wBAAsB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBlF;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,wBAElC,CAAC"}
|
|
@@ -7,9 +7,18 @@
|
|
|
7
7
|
* @module module-system/react-loader/ssr-module-loader/http-bundle-helpers
|
|
8
8
|
*/
|
|
9
9
|
import { createFileSystem, exists } from "../../../platform/compat/fs.js";
|
|
10
|
+
import { fromFileUrl } from "../../../platform/compat/path/index.js";
|
|
10
11
|
import { LRUCache } from "../../../utils/lru-wrapper.js";
|
|
11
12
|
/** Max entries in the verified HTTP bundle paths LRU cache */
|
|
12
13
|
const VERIFIED_BUNDLE_CACHE_MAX_ENTRIES = 2_000;
|
|
14
|
+
function decodeFileUrlPath(path) {
|
|
15
|
+
try {
|
|
16
|
+
return fromFileUrl(`file://${path}`);
|
|
17
|
+
}
|
|
18
|
+
catch (_) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
13
22
|
/**
|
|
14
23
|
* Extract VF module paths (veryfront-mdx-esm/*.mjs) from code.
|
|
15
24
|
* These are user project modules that may import HTTP bundles.
|
|
@@ -21,12 +30,12 @@ function extractVfModulePaths(code) {
|
|
|
21
30
|
const seen = new Set();
|
|
22
31
|
let match;
|
|
23
32
|
while ((match = vfModulePattern.exec(code)) !== null) {
|
|
24
|
-
const path = match[1];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (!seen.has(
|
|
28
|
-
seen.add(
|
|
29
|
-
paths.push(
|
|
33
|
+
const path = decodeFileUrlPath(match[1]);
|
|
34
|
+
if (!path)
|
|
35
|
+
continue;
|
|
36
|
+
if (!seen.has(path)) {
|
|
37
|
+
seen.add(path);
|
|
38
|
+
paths.push(path);
|
|
30
39
|
}
|
|
31
40
|
}
|
|
32
41
|
return paths;
|
|
@@ -96,7 +105,7 @@ export function extractHttpBundlePaths(code) {
|
|
|
96
105
|
const absolutePattern = /file:\/\/([^"'\s]+veryfront-http-bundle\/http-([a-f0-9]+)\.mjs)/gi;
|
|
97
106
|
let match;
|
|
98
107
|
while ((match = absolutePattern.exec(code)) !== null) {
|
|
99
|
-
const path = match[1];
|
|
108
|
+
const path = match[1] ? decodeFileUrlPath(match[1]) : null;
|
|
100
109
|
const hash = match[2];
|
|
101
110
|
if (!path || !hash || seen.has(hash))
|
|
102
111
|
continue;
|
|
@@ -130,7 +139,7 @@ export function extractAllFilePaths(code) {
|
|
|
130
139
|
const seen = new Set();
|
|
131
140
|
let match;
|
|
132
141
|
while ((match = allFilePathsPattern.exec(code)) !== null) {
|
|
133
|
-
const path = match[1]
|
|
142
|
+
const path = match[1] ? decodeFileUrlPath(match[1]) : null;
|
|
134
143
|
if (!path || !supportedPathPattern.test(path) || seen.has(path))
|
|
135
144
|
continue;
|
|
136
145
|
seen.add(path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-conversion.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/compat/path/url-conversion.ts"],"names":[],"mappings":"AA6BA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"url-conversion.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/compat/path/url-conversion.ts"],"names":[],"mappings":"AA6BA,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,MAAM,CAwBrD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAS3C"}
|
|
@@ -21,25 +21,33 @@ function getFileURLToPath() {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
export function fromFileUrl(url) {
|
|
24
|
+
const parsedUrl = typeof url === "string" ? new URL(url) : url;
|
|
25
|
+
if (parsedUrl.protocol !== "file:") {
|
|
26
|
+
throw new TypeError("Must be a file URL");
|
|
27
|
+
}
|
|
24
28
|
const fileURLToPath = getFileURLToPath();
|
|
25
29
|
if (fileURLToPath)
|
|
26
|
-
return fileURLToPath(
|
|
27
|
-
const urlString = typeof url === "string" ? url : url.toString();
|
|
30
|
+
return fileURLToPath(parsedUrl);
|
|
28
31
|
if (isDeno) {
|
|
29
32
|
const g = dntShim.dntGlobalThis;
|
|
30
33
|
const hasCwd = Boolean(g.Deno?.cwd);
|
|
31
34
|
const isWindows = g.Deno?.build?.os === "windows";
|
|
32
35
|
if (hasCwd && isWindows) {
|
|
33
|
-
return decodeURIComponent(
|
|
36
|
+
return decodeURIComponent(parsedUrl.pathname)
|
|
37
|
+
.replace(/^\/([A-Za-z]:)/, "$1")
|
|
38
|
+
.replace(/\//g, "\\");
|
|
34
39
|
}
|
|
35
|
-
return decodeURIComponent(
|
|
36
|
-
}
|
|
37
|
-
if (!urlString.startsWith("file://")) {
|
|
38
|
-
throw new TypeError("Must be a file URL");
|
|
40
|
+
return decodeURIComponent(parsedUrl.pathname);
|
|
39
41
|
}
|
|
40
|
-
return decodeURIComponent(
|
|
42
|
+
return decodeURIComponent(parsedUrl.pathname);
|
|
41
43
|
}
|
|
42
44
|
export function toFileUrl(path) {
|
|
43
45
|
const absolute = hasNodePath ? path : isAbsolute(path) ? path : resolve(path);
|
|
44
|
-
|
|
46
|
+
// Preserve filesystem characters that URL parsing would otherwise decode or
|
|
47
|
+
// interpret as fragment/query delimiters.
|
|
48
|
+
const encodedPath = absolute
|
|
49
|
+
.replaceAll("%", "%25")
|
|
50
|
+
.replaceAll("#", "%23")
|
|
51
|
+
.replaceAll("?", "%3F");
|
|
52
|
+
return new URL(`file://${encodedPath}`);
|
|
45
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/dependency-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA4BzE,sEAAsE;AACtE,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,GAAG;IACnE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,sEAAsE;AACtE,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;CACzB;AA4GD,yEAAyE;AACzE,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAuBrC;AAED,2EAA2E;AAC3E,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,2BAA2B,EAAE,GAC7C,MAAM,
|
|
1
|
+
{"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/dependency-resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AA4BzE,sEAAsE;AACtE,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,6EAA6E;IAC7E,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,2BAA2B,GAAG,wBAAwB,GAAG;IACnE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,sEAAsE;AACtE,MAAM,WAAW,8BAA8B;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;CACzB;AA4GD,yEAAyE;AACzE,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAuBrC;AAED,2EAA2E;AAC3E,wBAAgB,gCAAgC,CAC9C,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,2BAA2B,EAAE,GAC7C,MAAM,CAaR"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { dirname, join, normalize } from "../../../platform/compat/path/index.js";
|
|
1
|
+
import { dirname, join, normalize, toFileUrl } from "../../../platform/compat/path/index.js";
|
|
2
2
|
import { parallelMap, rendererLogger } from "../../../utils/index.js";
|
|
3
3
|
import { findDynamicImportSpans, findStaticImportFromSpans, replaceSourceSpans, } from "../../../transforms/mdx/esm-module-loader/utils/source-spans.js";
|
|
4
4
|
import { findSourceFile } from "../file-resolver/index.js";
|
|
@@ -89,13 +89,16 @@ export async function resolveModuleDependencies(input) {
|
|
|
89
89
|
}
|
|
90
90
|
/** Rewrites resolved local imports to their transformed temp file URLs. */
|
|
91
91
|
export function rewriteResolvedDependencyImports(fileContent, transformedDeps) {
|
|
92
|
-
const replacements = transformedDeps.map((dep) =>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
const replacements = transformedDeps.map((dep) => {
|
|
93
|
+
const moduleUrl = toFileUrl(dep.depTempPath).href;
|
|
94
|
+
return {
|
|
95
|
+
start: dep.start,
|
|
96
|
+
end: dep.end,
|
|
97
|
+
expected: dep.full,
|
|
98
|
+
// A dynamic span covers only the quoted specifier; a static one covers the
|
|
99
|
+
// whole `from "…"` clause.
|
|
100
|
+
replacement: dep.isDynamic ? `"${moduleUrl}"` : `from "${moduleUrl}"`,
|
|
101
|
+
};
|
|
102
|
+
});
|
|
100
103
|
return replaceSourceSpans(fileContent, replacements);
|
|
101
104
|
}
|
|
@@ -10,7 +10,7 @@ import { rendererLogger } from "../../../utils/index.js";
|
|
|
10
10
|
import { getLocalAdapter } from "../../../platform/adapters/registry.js";
|
|
11
11
|
import { getProjectTmpDir } from "../../../modules/react-loader/index.js";
|
|
12
12
|
import { getHttpBundleCacheDir, getMdxEsmCacheDir } from "../../../utils/cache-dir.js";
|
|
13
|
-
import { join } from "../../../platform/compat/path/index.js";
|
|
13
|
+
import { join, toFileUrl } from "../../../platform/compat/path/index.js";
|
|
14
14
|
import { invalidateMdxEsmModule } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
|
|
15
15
|
import { resolveModuleDependencies, rewriteResolvedDependencyImports, } from "./dependency-resolver.js";
|
|
16
16
|
import { persistTransformedModule } from "./module-persistence.js";
|
|
@@ -235,7 +235,7 @@ export async function loadModule(filePath, config) {
|
|
|
235
235
|
catch (error) {
|
|
236
236
|
throw markBuildFailure(error);
|
|
237
237
|
}
|
|
238
|
-
const moduleUrl =
|
|
238
|
+
const moduleUrl = toFileUrl(tempFilePath).href;
|
|
239
239
|
markModuleLoadProgress(config, "module:import-start", filePath);
|
|
240
240
|
try {
|
|
241
241
|
const mod = await import(moduleUrl);
|
|
@@ -261,7 +261,7 @@ export async function loadModule(filePath, config) {
|
|
|
261
261
|
const recovered = await recoverHttpBundleByHash(hash, cacheDir);
|
|
262
262
|
if (recovered) {
|
|
263
263
|
logger.info("HTTP bundle recovered, retrying import", { hash });
|
|
264
|
-
return await import(
|
|
264
|
+
return await import(`${toFileUrl(tempFilePath).href}?t=${Date.now()}&retry=1`);
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
// Self-heal: the cached module artifact resolved to a path that no longer
|
|
@@ -287,7 +287,7 @@ export async function loadModule(filePath, config) {
|
|
|
287
287
|
catch (rebuildError) {
|
|
288
288
|
throw markBuildFailure(rebuildError);
|
|
289
289
|
}
|
|
290
|
-
return await import(
|
|
290
|
+
return await import(`${toFileUrl(rebuiltPath).href}?t=${Date.now()}&rebuilt=1`);
|
|
291
291
|
}
|
|
292
292
|
logger.error("Failed to import module:", {
|
|
293
293
|
filePath,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/renderer.ts"],"names":[],"mappings":"AAkDA,OAAO,EACL,mBAAmB,EACnB,+BAA+B,EAC/B,KAAK,0BAA0B,EAC/B,KAAK,aAAa,EACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,iCAAiC,CAAC;AAgBzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC7F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAmDxD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,oBAAoB;IACpB,KAAK,CAAC,EAAE,wBAAwB,CAAC;CAClC;AA4FD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,oBAAoB,CAAgC;IAC5D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,qBAAqB,CAA8B;IAE3D;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAAwC;IAC5D,yFAAyF;IACzF,OAAO,CAAC,sBAAsB,CAAsC;IACpE,OAAO,CAAC,yBAAyB,CAAoC;gBAEzD,OAAO,GAAE,eAAoB;IAInC,UAAU,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBhE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAI5F,OAAO,CAAC,uBAAuB;
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/src/rendering/renderer.ts"],"names":[],"mappings":"AAkDA,OAAO,EACL,mBAAmB,EACnB,+BAA+B,EAC/B,KAAK,0BAA0B,EAC/B,KAAK,aAAa,EACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,iCAAiC,CAAC;AAgBzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC7F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAmDxD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,oBAAoB;IACpB,KAAK,CAAC,EAAE,wBAAwB,CAAC;CAClC;AA4FD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,oBAAoB,CAAgC;IAC5D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,qBAAqB,CAA8B;IAE3D;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAAwC;IAC5D,yFAAyF;IACzF,OAAO,CAAC,sBAAsB,CAAsC;IACpE,OAAO,CAAC,yBAAyB,CAAoC;gBAEzD,OAAO,GAAE,eAAoB;IAInC,UAAU,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBhE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAI5F,OAAO,CAAC,uBAAuB;YA+FjB,2BAA2B;IAWzC,OAAO,CAAC,uBAAuB;IAiB/B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;;;;;;;;OASG;IACH,OAAO,CAAC,aAAa;IAyCrB,OAAO,CAAC,6BAA6B;IAcrC,OAAO,CAAC,+BAA+B;IAoCvC,OAAO,CAAC,+BAA+B;IASvC,OAAO,CAAC,oCAAoC;IAa5C,OAAO,CAAC,uBAAuB;IAU/B,OAAO,CAAC,yBAAyB;IASjC,OAAO,CAAC,4BAA4B;IAuBpC,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,wBAAwB;IAehC,OAAO,CAAC,+BAA+B;YAyDzB,0BAA0B;YAoE1B,YAAY;YAoGZ,qBAAqB;IAwHnC,eAAe,CACb,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,aAAa,EAClB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,gBAAgB,CAAC;IAuD5B,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAU5C,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;YAUtD,4BAA4B;IA4BpC,UAAU,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5D,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B,OAAO,CAAC,wBAAwB;CAwGjC;AAED,OAAO,EACL,mBAAmB,EACnB,+BAA+B,EAC/B,KAAK,0BAA0B,EAC/B,KAAK,aAAa,GACnB,CAAC;AAMF,wBAAgB,WAAW,IAAI,QAAQ,CAOtC;AAED,wBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsBrF;AAED,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAQrD;AAED,wBAAsB,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnF;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,cAAc,EAC1B,OAAO,CAAC,EAAE,aAAa,EACvB,cAAc,CAAC,EAAE,0BAA0B,GAC1C,OAAO,CAAC,YAAY,CAAC,CAIvB"}
|
|
@@ -213,6 +213,7 @@ export class Renderer {
|
|
|
213
213
|
releaseId: effectiveCtx.releaseId,
|
|
214
214
|
branch: effectiveCtx.branch,
|
|
215
215
|
config: effectiveCtx.config,
|
|
216
|
+
dependencyWritebackToken: effectiveCtx.proxyToken,
|
|
216
217
|
dependencyWritebackTarget: resolveDependencyWritebackTarget({
|
|
217
218
|
environment: effectiveCtx.environment,
|
|
218
219
|
isLocalProject: effectiveCtx.isLocalProject,
|
|
@@ -694,6 +695,7 @@ export class Renderer {
|
|
|
694
695
|
releaseId: effectiveCtx.releaseId,
|
|
695
696
|
branch: effectiveCtx.branch,
|
|
696
697
|
config: effectiveCtx.config,
|
|
698
|
+
dependencyWritebackToken: effectiveCtx.proxyToken,
|
|
697
699
|
dependencyWritebackTarget: resolveDependencyWritebackTarget({
|
|
698
700
|
environment: effectiveCtx.environment,
|
|
699
701
|
isLocalProject: effectiveCtx.isLocalProject,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-pinning-source.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/utils/dependency-pinning-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAEL,KAAK,uBAAuB,EAE7B,MAAM,6CAA6C,CAAC;AAErD,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CACjD,GAAG,EAAE,cAAc,GAClB,gCAAgC,CAYlC;AAED,wBAAgB,oCAAoC,CAClD,GAAG,EAAE,cAAc,GAClB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"dependency-pinning-source.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/utils/dependency-pinning-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAEL,KAAK,uBAAuB,EAE7B,MAAM,6CAA6C,CAAC;AAErD,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CACjD,GAAG,EAAE,cAAc,GAClB,gCAAgC,CAYlC;AAED,wBAAgB,oCAAoC,CAClD,GAAG,EAAE,cAAc,GAClB,uBAAuB,CAmBzB"}
|
|
@@ -10,11 +10,12 @@ import type { DependencyWritebackTarget } from "./package-registry.js";
|
|
|
10
10
|
export type DependencyResolutionEligibility = () => boolean;
|
|
11
11
|
export interface DependencyResolutionScheduleOptions {
|
|
12
12
|
target: DependencyWritebackTarget;
|
|
13
|
+
authToken?: string;
|
|
13
14
|
isEligible?: DependencyResolutionEligibility;
|
|
14
15
|
}
|
|
15
16
|
export declare const PLATFORM_RESOLUTION_MAX_PENDING = 4096;
|
|
16
17
|
export declare const PLATFORM_RESOLUTION_MAX_CONCURRENCY = 4;
|
|
17
|
-
type DependencyResolutionPoster = (projectId: string, specifiers: string[], target: DependencyWritebackTarget, expectedDeclarations: Readonly<Record<string, string | null
|
|
18
|
+
type DependencyResolutionPoster = (projectId: string, specifiers: string[], target: DependencyWritebackTarget, expectedDeclarations: Readonly<Record<string, string | null>>, authToken?: string) => Promise<void>;
|
|
18
19
|
/** Override the clock used by retry deduplication. For tests only. */
|
|
19
20
|
export declare function _setClockForTest(fn: () => number): void;
|
|
20
21
|
/** True when the string is a bare three-part semver version (no range prefix). */
|
|
@@ -41,17 +42,19 @@ export declare function _setDependencyResolutionPosterForTest(poster?: Dependenc
|
|
|
41
42
|
* Fire-and-forget POST to the platform API to resolve and persist dependency
|
|
42
43
|
* declarations.
|
|
43
44
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* (endpoint may not exist yet while the API track is built in parallel).
|
|
45
|
+
* Uses the request-scoped bearer token when provided, with the runtime
|
|
46
|
+
* environment token as a fallback. Silently ignores all failures including
|
|
47
|
+
* 404 (endpoint may not exist yet while the API track is built in parallel).
|
|
47
48
|
*
|
|
48
49
|
* @param projectId - project identifier from the render context
|
|
49
50
|
* @param specifiers - raw bare names or package declarations such as
|
|
50
51
|
* "pkg", "pkg@^1", "pkg@next", or "pkg@1.2.3"
|
|
52
|
+
* @param target - canonical main or branch package.json write-back target
|
|
51
53
|
* @param expectedDeclarations - package declarations observed in the immutable
|
|
52
54
|
* caller snapshot; null means the package was absent
|
|
55
|
+
* @param authToken - request-scoped bearer token; the runtime token remains the fallback
|
|
53
56
|
*/
|
|
54
|
-
export declare function postDependencyResolution(projectId: string, specifiers: string[], target: DependencyWritebackTarget, expectedDeclarations: Readonly<Record<string, string | null
|
|
57
|
+
export declare function postDependencyResolution(projectId: string, specifiers: string[], target: DependencyWritebackTarget, expectedDeclarations: Readonly<Record<string, string | null>>, authToken?: string): Promise<void>;
|
|
55
58
|
/**
|
|
56
59
|
* Clear resolved versions. For use in tests only.
|
|
57
60
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npm-registry-client.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/npm-registry-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAmBvE,MAAM,MAAM,+BAA+B,GAAG,MAAM,OAAO,CAAC;AAC5D,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,yBAAyB,CAAC;IAClC,UAAU,CAAC,EAAE,+BAA+B,CAAC;CAC9C;
|
|
1
|
+
{"version":3,"file":"npm-registry-client.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/npm-registry-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAmBvE,MAAM,MAAM,+BAA+B,GAAG,MAAM,OAAO,CAAC;AAC5D,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,yBAAyB,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,+BAA+B,CAAC;CAC9C;AAkBD,eAAO,MAAM,+BAA+B,OAAmC,CAAC;AAEhF,eAAO,MAAM,mCAAmC,IAAI,CAAC;AACrD,KAAK,0BAA0B,GAAG,CAChC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAAE,EACpB,MAAM,EAAE,yBAAyB,EACjC,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,EAC7D,SAAS,CAAC,EAAE,MAAM,KACf,OAAO,CAAC,IAAI,CAAC,CAAC;AA6DnB,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,MAAM,GAAG,IAAI,CAEvD;AA4CD,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,oCAAoC,CAClD,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,mCAAmC,GAC5C,IAAI,CA0EN;AAED;;;;GAIG;AACH,wBAAgB,sCAAsC,CACpD,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,mCAAmC,GAC5C,IAAI,CAON;AA+ED,kEAAkE;AAClE,wBAAgB,qCAAqC,CACnD,MAAM,CAAC,EAAE,0BAA0B,GAClC,IAAI,CAEN;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAAE,EACpB,MAAM,EAAE,yBAAyB,EACjC,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,EAC7D,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAyDf;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAM5C;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAYzD"}
|
|
@@ -174,10 +174,14 @@ export function schedulePlatformDependencyResolution(projectId, packageName, ran
|
|
|
174
174
|
queuedBatch = {
|
|
175
175
|
projectId,
|
|
176
176
|
target,
|
|
177
|
+
authToken: options.authToken,
|
|
177
178
|
resolutions: new Map(),
|
|
178
179
|
};
|
|
179
180
|
queuedPlatformResolutions.set(queueKey, queuedBatch);
|
|
180
181
|
}
|
|
182
|
+
else if (options.authToken) {
|
|
183
|
+
queuedBatch.authToken = options.authToken;
|
|
184
|
+
}
|
|
181
185
|
queuedBatch.resolutions.set(packageName, {
|
|
182
186
|
packageName,
|
|
183
187
|
rawSpecifier,
|
|
@@ -227,7 +231,7 @@ function schedulePlatformResolutionFlush(queueKey) {
|
|
|
227
231
|
return postDependencyResolutionImpl(queued.projectId, eligibleResolutions.map((resolution) => resolution.rawSpecifier), queued.target, Object.fromEntries(eligibleResolutions.map((resolution) => [
|
|
228
232
|
resolution.packageName,
|
|
229
233
|
resolution.expectedDeclaration,
|
|
230
|
-
])));
|
|
234
|
+
])), queued.authToken);
|
|
231
235
|
});
|
|
232
236
|
}
|
|
233
237
|
catch (error) {
|
|
@@ -263,23 +267,25 @@ export function _setDependencyResolutionPosterForTest(poster) {
|
|
|
263
267
|
* Fire-and-forget POST to the platform API to resolve and persist dependency
|
|
264
268
|
* declarations.
|
|
265
269
|
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* (endpoint may not exist yet while the API track is built in parallel).
|
|
270
|
+
* Uses the request-scoped bearer token when provided, with the runtime
|
|
271
|
+
* environment token as a fallback. Silently ignores all failures including
|
|
272
|
+
* 404 (endpoint may not exist yet while the API track is built in parallel).
|
|
269
273
|
*
|
|
270
274
|
* @param projectId - project identifier from the render context
|
|
271
275
|
* @param specifiers - raw bare names or package declarations such as
|
|
272
276
|
* "pkg", "pkg@^1", "pkg@next", or "pkg@1.2.3"
|
|
277
|
+
* @param target - canonical main or branch package.json write-back target
|
|
273
278
|
* @param expectedDeclarations - package declarations observed in the immutable
|
|
274
279
|
* caller snapshot; null means the package was absent
|
|
280
|
+
* @param authToken - request-scoped bearer token; the runtime token remains the fallback
|
|
275
281
|
*/
|
|
276
|
-
export async function postDependencyResolution(projectId, specifiers, target, expectedDeclarations) {
|
|
282
|
+
export async function postDependencyResolution(projectId, specifiers, target, expectedDeclarations, authToken) {
|
|
277
283
|
if (!isCanonicalDependencyWritebackTarget(target))
|
|
278
284
|
return;
|
|
279
285
|
const { getEnvironmentConfig } = await import("../../config/environment-config.js");
|
|
280
286
|
const config = getEnvironmentConfig();
|
|
281
287
|
const apiBaseUrl = config.apiBaseUrl;
|
|
282
|
-
const apiToken = config.apiToken;
|
|
288
|
+
const apiToken = authToken || config.apiToken;
|
|
283
289
|
if (!apiBaseUrl || !apiToken) {
|
|
284
290
|
logger.debug("Skipping dependency resolution write-back: no API config", { projectId });
|
|
285
291
|
return;
|
|
@@ -59,6 +59,8 @@ export interface DependencyPinningSource {
|
|
|
59
59
|
readonly branch?: string | null;
|
|
60
60
|
/** Explicit writable platform target; absent for release/production sources. */
|
|
61
61
|
readonly dependencyWritebackTarget?: DependencyWritebackTarget;
|
|
62
|
+
/** Request-scoped bearer token used only by the platform write-back transport. */
|
|
63
|
+
readonly dependencyWritebackToken?: string;
|
|
62
64
|
}
|
|
63
65
|
export type DependencyPinningSourceInput = string | null | undefined | DependencyPinningSource;
|
|
64
66
|
export interface CreateDependencyPinningSourceOptions {
|
|
@@ -72,6 +74,7 @@ export interface CreateDependencyPinningSourceOptions {
|
|
|
72
74
|
isLocalProject?: boolean;
|
|
73
75
|
config?: VeryfrontConfig | null;
|
|
74
76
|
dependencyWritebackTarget?: DependencyWritebackTarget;
|
|
77
|
+
dependencyWritebackToken?: string;
|
|
75
78
|
}
|
|
76
79
|
/**
|
|
77
80
|
* Build a request-scoped package source. Local callers retain the host-filesystem
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-registry.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/package-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAEV,iBAAiB,EACjB,cAAc,EACf,MAAM,iCAAiC,CAAC;AAIzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAwB7D,KAAK,wBAAwB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;CACrD,CAAC;AAqEF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC;QACrC,KAAK,CAAC,EAAE,QAAQ,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC7D,SAAS,CAAC,EAAE,QAAQ,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAClE,CAAC,CAAC;CACJ;AAED,MAAM,MAAM,yBAAyB,GACjC,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1B,QAAQ,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjD,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,gCAAgC,GACxC,yBAAyB,GAAG,SAAS,CAavC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,MAAM,CAAC,CAAC;IAC3D,oFAAoF;IACpF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,yEAAyE;IACzE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gFAAgF;IAChF,QAAQ,CAAC,yBAAyB,CAAC,EAAE,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"package-registry.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/package-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAEV,iBAAiB,EACjB,cAAc,EACf,MAAM,iCAAiC,CAAC;AAIzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAwB7D,KAAK,wBAAwB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;CACrD,CAAC;AAqEF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC;QACrC,KAAK,CAAC,EAAE,QAAQ,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC7D,SAAS,CAAC,EAAE,QAAQ,CAAC;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAClE,CAAC,CAAC;CACJ;AAED,MAAM,MAAM,yBAAyB,GACjC,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1B,QAAQ,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjD,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IAChD,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,gCAAgC,GACxC,yBAAyB,GAAG,SAAS,CAavC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,MAAM,CAAC,CAAC;IAC3D,oFAAoF;IACpF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,yEAAyE;IACzE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gFAAgF;IAChF,QAAQ,CAAC,yBAAyB,CAAC,EAAE,yBAAyB,CAAC;IAC/D,kFAAkF;IAClF,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;CAC5C;AAED,MAAM,MAAM,4BAA4B,GACpC,MAAM,GACN,IAAI,GACJ,SAAS,GACT,uBAAuB,CAAC;AAE5B,MAAM,WAAW,oCAAoC;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,yBAAyB,CAAC,EAAE,yBAAyB,CAAC;IACtD,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,oCAAoC,GAC5C,uBAAuB,CAkCzB;AAOD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAI7C;AAED,2EAA2E;AAC3E,wBAAgB,0CAA0C,IAAI,MAAM,CAEnE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,IAAI,CAON;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,4BAA4B,EACpC,gBAAgB,CAAC,EAAE,MAAM,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CASpC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,IAAI,CAAC,CAEf;AAgID;;;;GAIG;AACH,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,4BAA4B,EACpC,QAAQ,EAAE,MAAM,GACf,OAAO,CAYT;AAED;;;;;;GAMG;AACH,wBAAsB,yCAAyC,CAC7D,MAAM,EAAE,4BAA4B,EACpC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,GAChC,OAAO,CAAC,yBAAyB,GAAG,SAAS,CAAC,CAgBhD;AAED;;;GAGG;AACH,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,4BAA4B,EACpC,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAC9C,OAAO,CAAC,yBAAyB,CAAC,CAuDpC;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,yBAAyB,CAAC,CAgCpC;AAqCD,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,wBAAwB,CAAC,CAoBnC;AA6GD,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uBAAuB,CAAC,EAAE,4BAA4B,CAAC;IACvD,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,6BAA6B,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmFD;;;;;GAKG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,8BAA8B,CAAC,CA8BzC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,MAAM,CAAC,CAkCjB"}
|
|
@@ -119,6 +119,7 @@ export function createDependencyPinningSource(options) {
|
|
|
119
119
|
dependencyWritebackTarget: options.dependencyWritebackTarget
|
|
120
120
|
? Object.freeze({ ...options.dependencyWritebackTarget })
|
|
121
121
|
: undefined,
|
|
122
|
+
dependencyWritebackToken: options.dependencyWritebackToken,
|
|
122
123
|
...(adapterFs
|
|
123
124
|
? {
|
|
124
125
|
fs: adapterFs,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-resolution.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/import-rewriter/dependency-resolution.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,4BAA4B,EAGlC,MAAM,4BAA4B,CAAC;AAQpC,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,wCAAwC,CACtD,KAAK,EAAE,OAAO,EACd,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAC9C,SAAS,+BAA+B,EAAE,GAAG,IAAI,CAmCnD;AAED,MAAM,WAAW,iCAAiC;IAChD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,uBAAuB,CAAC,EAAE,4BAA4B,CAAC;IACvD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,6BAA6B,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE;;;;OAIG;IACH,8BAA8B,CAAC,EAAE,CAC/B,WAAW,EAAE,+BAA+B,KACzC,IAAI,CAAC;IACV,sEAAsE;IACtE,mCAAmC,CAAC,EAAE,OAAO,CAAC;CAC/C;AAWD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,iCAAiC,GACrC,MAAM,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"dependency-resolution.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/import-rewriter/dependency-resolution.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,4BAA4B,EAGlC,MAAM,4BAA4B,CAAC;AAQpC,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,wCAAwC,CACtD,KAAK,EAAE,OAAO,EACd,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAC9C,SAAS,+BAA+B,EAAE,GAAG,IAAI,CAmCnD;AAED,MAAM,WAAW,iCAAiC;IAChD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,uBAAuB,CAAC,EAAE,4BAA4B,CAAC;IACvD,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,6BAA6B,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE;;;;OAIG;IACH,8BAA8B,CAAC,EAAE,CAC/B,WAAW,EAAE,+BAA+B,KACzC,IAAI,CAAC;IACV,sEAAsE;IACtE,mCAAmC,CAAC,EAAE,OAAO,CAAC;CAC/C;AAWD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,iCAAiC,GACrC,MAAM,GAAG,SAAS,CAiEpB"}
|
|
@@ -80,12 +80,17 @@ export function resolveDependencyPinForImport(packageName, ctx) {
|
|
|
80
80
|
writebackSource !== null
|
|
81
81
|
? writebackSource.dependencyWritebackTarget
|
|
82
82
|
: undefined;
|
|
83
|
+
const writebackToken = typeof writebackSource === "object" &&
|
|
84
|
+
writebackSource !== null
|
|
85
|
+
? writebackSource.dependencyWritebackToken
|
|
86
|
+
: undefined;
|
|
83
87
|
const writebackAuthorization = writebackSource &&
|
|
84
88
|
writebackTarget &&
|
|
85
89
|
cacheKey?.startsWith("on:") &&
|
|
86
90
|
cacheKey !== "on:unknown"
|
|
87
91
|
? {
|
|
88
92
|
target: writebackTarget,
|
|
93
|
+
authToken: writebackToken,
|
|
89
94
|
isEligible: () => isCurrentDependencyPinningSnapshot(writebackSource, cacheKey),
|
|
90
95
|
}
|
|
91
96
|
: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAW5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9D,eAAO,MAAM,kBAAkB,wBAE7B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAW5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9D,eAAO,MAAM,kBAAkB,wBAE7B,CAAC;AAgIH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAOvF;AAUD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAM1F;AAqBD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBvF;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAezE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAQD,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAuBD,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CA0ElE;AA+ED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,SAAwB,EACpC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAaT;AAED,wBAAsB,mCAAmC,CACvD,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,SAAwB,EACpC,SAAS,GAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAiD,EAChF,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAOD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAevD;AAED,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAkEf;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAc1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAoBD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EAMnB,YAAY,CAAC,EAAE,MAAM,EACrB,eAAe,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,EAChE,YAAY,SAAwB,EACpC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,iBAAiB,CAAC,CA+J5B"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module build/transforms/mdx/esm-module-loader/cache
|
|
7
7
|
*/
|
|
8
|
-
import { join } from "../../../../platform/compat/path/index.js";
|
|
8
|
+
import { fromFileUrl, join } from "../../../../platform/compat/path/index.js";
|
|
9
9
|
import { rendererLogger as logger } from "../../../../utils/index.js";
|
|
10
10
|
import { getCacheBaseDir, getHttpBundleCacheDir, getMdxEsmCacheDir, } from "../../../../utils/cache-dir.js";
|
|
11
11
|
import { REACT_DEFAULT_VERSION } from "../../../../utils/constants/cdn.js";
|
|
@@ -26,6 +26,14 @@ const MAX_MODULE_PATH_CACHE_ENTRIES = 500;
|
|
|
26
26
|
export const verifiedModuleDeps = new LRUCache({
|
|
27
27
|
maxEntries: MAX_VERIFIED_MODULE_DEPS,
|
|
28
28
|
});
|
|
29
|
+
function decodeFileUrlPath(path) {
|
|
30
|
+
try {
|
|
31
|
+
return fromFileUrl(`file://${path}`);
|
|
32
|
+
}
|
|
33
|
+
catch (_) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
29
37
|
class BoundedModulePathCache extends Map {
|
|
30
38
|
maxEntries;
|
|
31
39
|
constructor(maxEntries) {
|
|
@@ -53,9 +61,12 @@ function hasIncompatibleCachePaths(code) {
|
|
|
53
61
|
const pattern = new RegExp(MDX_ESM_ALL_FILE_URL_PATTERN_SOURCE, "gi");
|
|
54
62
|
let match;
|
|
55
63
|
while ((match = pattern.exec(code)) !== null) {
|
|
56
|
-
const
|
|
57
|
-
if (!
|
|
64
|
+
const encodedPath = match[1];
|
|
65
|
+
if (!encodedPath)
|
|
58
66
|
continue;
|
|
67
|
+
const path = decodeFileUrlPath(encodedPath);
|
|
68
|
+
if (!path)
|
|
69
|
+
return true;
|
|
59
70
|
// Check HTTP bundle paths
|
|
60
71
|
if (path.includes("veryfront-http-bundle") && !path.startsWith(localHttpCacheDir)) {
|
|
61
72
|
logger.debug(`${LOG_PREFIX_MDX_LOADER} Cached module has incompatible HTTP bundle path`, {
|
|
@@ -93,9 +104,12 @@ async function findMissingFileDependencies(code) {
|
|
|
93
104
|
const missing = [];
|
|
94
105
|
let match;
|
|
95
106
|
while ((match = pattern.exec(code)) !== null) {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
107
|
+
const encodedPath = match[1];
|
|
108
|
+
const cleanPath = decodeFileUrlPath(encodedPath);
|
|
109
|
+
if (!cleanPath) {
|
|
110
|
+
missing.push(encodedPath.replace(/[?#].*$/, ""));
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
99
113
|
try {
|
|
100
114
|
const stat = await localFs.stat(cleanPath);
|
|
101
115
|
if (!stat?.isFile) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1182",
|
|
4
4
|
"description": "The simplest way to build AI-powered apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -344,10 +344,10 @@
|
|
|
344
344
|
"@types/react": "19.2.14",
|
|
345
345
|
"@types/react-dom": "19.2.3",
|
|
346
346
|
"ws": "8.21.0",
|
|
347
|
-
"@veryfront/ext-bundler-esbuild": "0.1.
|
|
348
|
-
"@veryfront/ext-content-mdx": "0.1.
|
|
349
|
-
"@veryfront/ext-css-tailwind": "0.1.
|
|
350
|
-
"@veryfront/ext-parser-babel": "0.1.
|
|
347
|
+
"@veryfront/ext-bundler-esbuild": "0.1.1182",
|
|
348
|
+
"@veryfront/ext-content-mdx": "0.1.1182",
|
|
349
|
+
"@veryfront/ext-css-tailwind": "0.1.1182",
|
|
350
|
+
"@veryfront/ext-parser-babel": "0.1.1182"
|
|
351
351
|
},
|
|
352
352
|
"devDependencies": {
|
|
353
353
|
"@types/node": "20.9.0"
|