@rsc-kit/core 0.22.4 → 0.22.6
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/dist/host.js +22 -2
- package/dist/host.js.map +1 -1
- package/dist/js/SegmentBoundary.js +21 -2
- package/dist/js/SegmentBoundary.js.map +1 -1
- package/dist/js/createViteRscApp.js +2 -2
- package/dist/js/createViteRscApp.js.map +1 -1
- package/dist/js/navigate.d.ts +1 -1
- package/dist/js/navigate.js +9 -1
- package/dist/js/navigate.js.map +1 -1
- package/dist/js/segmentStore.d.ts +15 -2
- package/dist/js/segmentStore.js +23 -7
- package/dist/js/segmentStore.js.map +1 -1
- package/dist/request.d.ts +12 -0
- package/dist/request.js +17 -0
- package/dist/request.js.map +1 -1
- package/dist/vite.js +41 -8
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segmentStore.js","sourceRoot":"","sources":["../../src/js/segmentStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What each segment boundary is showing, and what it is keeping alive behind it.\n *\n * A navigation replaces one segment. Keeping the previous one mounted — hidden,\n * not unmounted — is what lets going back restore it with its client state:\n * the half-typed form, the open disclosure, the scrolled list. Unmounting\n * throws all of that away, which is what replacing the root used to do.\n *\n * Entries are keyed by page (the URL, or its intercept variant), so a boundary\n * can hold several and reveal one. Empty is meaningful: a boundary with nothing\n * stored renders the children the server gave it.\n *\n * A store rather than state, and not a preference — three things rule state out.\n * A boundary is inserted between every layout level, so there are several and a\n * navigation targets one by depth; they are separated by server components, so\n * no setter can be threaded down to them, because a function does not cross\n * that boundary; and navigate.ts is a plain module with no component instance\n * to call one on. Addressing a component you hold no reference to is what an\n * external store is for.\n *\n * Underneath it is the wire protocol. A partial navigation sends only the\n * segment that changed — see the X-RSC-Segments headers — so there is nothing\n * for a root to re-render with even if it held the state. Next.js keeps its\n * router in useState and derives every segment from it; that is the same trade\n * in the other direction.\n *\n * What it costs: React pins an external store's updates to synchronous\n * priority, because a store cannot be safely time-sliced. Synchronous is never\n * a transition, and anything that only runs for one — React's <ViewTransition>\n * among them — never ran for a navigation.\n *\n * Which is why SegmentBoundary does not read this with useSyncExternalStore\n * any more. The store still does the addressing, which is the part only it can\n * do; the boundary copies into state, so the render is a transition. See the\n * view transitions guide.\n */\n\ntype Tree = unknown;\ntype Listener = () => void;\n\ninterface Entry {\n key: string;\n tree: Tree;\n /**\n * When this tree arrived, so a link can decide whether it is still worth\n * revealing. The back button never asks — it means \"the page I was on\",\n * however long ago that was.\n */\n at: number;\n /**\n * Its place in the order things happened, for the question \"was this\n * here before the mutation?\" - which a clock answers wrongly for a seed\n * and a write in the same millisecond, and a test hit exactly that.\n */\n seq: number;\n /**\n * Rendered before the click, hidden, on the strength of a touch or a\n * settled hover - see prerenderSegment. Outside the retention window: it\n * is a guess, and a guess must not evict a page the visitor was on. One\n * per depth; the next guess replaces it, and a navigation to anything\n * else drops it.\n */\n speculative?: boolean;\n}\n\n/**\n * Immutable: useSyncExternalStore compares snapshots by identity, so a new\n * object per read reads as \"changed every render\" and loops forever. Every\n * mutation replaces this wholesale; nothing edits one in place.\n */\ninterface DepthState {\n readonly entries: readonly Entry[];\n readonly activeKey: string;\n /** Most recently shown last; eviction takes from the front. */\n readonly order: readonly string[];\n}\n\n/** Pages kept alive per boundary. Four covers ordinary back-and-forth. */\nexport const RETENTION = 4;\n\nconst depths = new Map<number, DepthState>();\n/** A counter every entry takes a number from, in order. */\nlet tick = 0;\n/** The number the last mutation took: everything held before it is wrong. */\nlet invalidatedAt = 0;\nconst listeners = new Map<number, Set<Listener>>();\n\nfunction notify(depth: number): void {\n for (const listener of listeners.get(depth) ?? []) listener();\n}\n\nexport function subscribeToSegment(\n depth: number,\n listener: Listener,\n): () => void {\n let set = listeners.get(depth);\n\n if (!set) {\n set = new Set();\n listeners.set(depth, set);\n }\n\n set.add(listener);\n\n return () => {\n set!.delete(listener);\n if (set!.size === 0) listeners.delete(depth);\n };\n}\n\n/** Everything a boundary at this depth needs to render, or null for \"use children\". */\nexport function getSegmentState(depth: number): DepthState | null {\n return depths.get(depth) ?? null;\n}\n\n/** Apply the retention window to a candidate state. */\nfunction retain(\n entries: readonly Entry[],\n order: readonly string[],\n activeKey: string,\n): DepthState {\n const kept = order.slice(-RETENTION);\n\n return {\n entries: entries.filter((entry) => kept.includes(entry.key) || entry.speculative),\n order: kept,\n activeKey,\n };\n}\n\nfunction put(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n const entries = [\n ...(state?.entries ?? []).filter((entry) => entry.key !== key),\n { key, tree, at: Date.now(), seq: ++tick },\n ];\n const order = [...(state?.order ?? []).filter((k) => k !== key), key];\n\n depths.set(depth, retain(entries, order, key));\n}\n\n/**\n * Show `tree` at `depth` for `key`, retaining what was there.\n *\n * Deeper segments belonged to the page being replaced; leaving them would\n * render the previous page inside the new one.\n */\nexport function setSegment(depth: number, key: string, tree: Tree): void {\n // A guess about another page was wrong; the one about this page, if there\n // was one, is replaced by put() below - with the same tree, when the\n // prerender and the navigation read the same decoded payload, which is\n // what makes the update a reveal rather than a render.\n dropSpeculative(depth, key);\n put(depth, key, tree);\n\n const stale = [...depths.keys()].filter((d) => d > depth);\n for (const d of stale) depths.delete(d);\n\n notify(depth);\n for (const d of stale) notify(d);\n}\n\nfunction dropSpeculative(depth: number, except?: string): void {\n const state = depths.get(depth);\n\n if (!state?.entries.some((entry) => entry.speculative && entry.key !== except)) return;\n\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => !entry.speculative || entry.key === except),\n });\n}\n\n/**\n * Render a page hidden at `depth`, before any navigation to it.\n *\n * The click then finds the work done: setSegment with the same tree is a\n * bail-out for React - same element, same props - and the Activity flips\n * from hidden to visible. What was 87 ms of rendering on a phone, after\n * the tap, is paid before the finger lifts, at idle priority, yielding to\n * the scroll. Never changes what is showing, never counts against\n * retention, and a page already held needs nothing.\n */\nexport function prerenderSegment(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n\n // Nothing at this depth yet: the boundary is still showing the server's\n // children, and it has no page key to keep them under. A guess would take\n // the store over with no active entry to show. seedSegment runs on mount,\n // so this is the gap between hydration and that effect; the click will\n // render.\n if (!state) return;\n\n if (state.entries.some((entry) => entry.key === key)) return;\n\n depths.set(depth, {\n ...state,\n entries: [\n ...state.entries.filter((entry) => !entry.speculative),\n { key, tree, at: Date.now(), seq: ++tick, speculative: true },\n ],\n });\n\n notify(depth);\n}\n\n/** Whether a page is rendered hidden at `depth`, ahead of a navigation to it. */\nexport function isPrerendered(depth: number, key: string): boolean {\n return depths.get(depth)?.entries.some((entry) => entry.key === key && entry.speculative) ?? false;\n}\n\n/**\n * Give the page on screen at `depth` a new tree, under the key it has.\n *\n * For revalidate(\"all\"): the whole document rendered again, in place. The\n * root hands its layout the new tree, the layout hands its boundary new\n * children, and a boundary that holds state would otherwise keep showing\n * the store's tree and drop the new one on the floor - or, cleared first,\n * re-key its Activity to the current url and remount everything under it.\n * Neither. The entry that is showing takes the new tree and keeps its key,\n * so React reconciles the page in place, and the boundary below gets its\n * new children the same way.\n */\nexport function replaceActive(depth: number, tree: Tree): void {\n const state = depths.get(depth);\n\n if (!state) return;\n\n const active = state.entries.find((entry) => entry.key === state.activeKey);\n\n if (!active || active.tree === tree) return;\n\n // The tree changes; when the entry arrived does not. A layout's entry is\n // keyed by the page it was seeded with - \"/\" for a document loaded at\n // home - and stays active through every navigation below it. Stamped\n // with the re-render's time it read as held since the mutation, and a\n // tap on the brand link after \"Add to cart\" revealed it: the url went\n // to \"/\" and the product stayed, because the tree under that key was\n // now the product's document. See dropHidden and isHeld.\n depths.set(depth, {\n ...state,\n entries: state.entries.map((entry) => (entry === active ? { ...entry, tree } : entry)),\n });\n notify(depth);\n}\n\n/**\n * Record the children the server rendered, so the page you arrived on can be\n * returned to later. Never changes what is showing.\n */\nexport function seedSegment(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n\n if (state?.entries.some((entry) => entry.key === key)) return;\n\n if (!state) {\n put(depth, key, tree);\n notify(depth);\n\n return;\n }\n\n // Older than whatever is showing, so it goes to the front of the eviction\n // order — and crucially does not become the active page.\n depths.set(\n depth,\n retain(\n [...state.entries, { key, tree, at: Date.now(), seq: ++tick }],\n [key, ...state.order.filter((k) => k !== key)],\n state.activeKey,\n ),\n );\n\n notify(depth);\n}\n\n/**\n * Reveal a page the boundaries are still holding, without asking the server.\n *\n * Restoring is anchored on the deepest boundary that can show the page. Deeper\n * ones than that belonged to the page being left — a section with its own\n * layout adds a boundary the page you are going back to never had — so they\n * are dropped, exactly as setSegment drops them. Requiring every boundary to\n * hold the key instead made any such page refuse to restore.\n *\n * Shallower boundaries need no key of their own: their trees contain the\n * deeper boundary, so they delegate to whatever it is showing. One that does\n * hold the key is switched to it, since that is a real change at its level.\n */\n/**\n * Whether a link to `key` would be answered by revealing a held page.\n *\n * The question restoreSegments answers, asked without acting on it: a\n * prefetch of a page the boundaries still hold is a request for nothing -\n * a navigation would reveal it. The page just left is the usual case, one\n * wasted payload per navigation.\n */\nexport function isHeld(key: string, maxAge?: number): boolean {\n const ages = [...depths.values()].flatMap((state) =>\n state.entries.filter((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt).map((entry) => entry.at),\n );\n\n if (ages.length === 0) return false;\n if (maxAge === undefined) return true;\n\n return Date.now() - Math.min(...ages) < maxAge;\n}\n\n/**\n * Drop every page held behind the one on screen.\n *\n * After a mutation: a page kept for the back button holds the data from\n * before it, and revealing it would show a row that is gone, a name that\n * changed. The page on screen stays - it was re-rendered by the action, or\n * is about to be.\n */\nexport function dropHidden(): void {\n // And the ones that stay - the active entry at each depth - are from\n // before it too. A layout's entry is keyed by the page it was seeded\n // with, and revealing that key later shows the page inside it as it was\n // then. Nothing seeded before this moment is revealed again.\n invalidatedAt = ++tick;\n\n for (const [depth, state] of depths) {\n if (state.entries.length <= 1 && !state.entries.some((entry) => entry.speculative)) continue;\n\n depths.set(depth, {\n entries: state.entries.filter((entry) => entry.key === state.activeKey),\n order: state.order.filter((key) => key === state.activeKey),\n activeKey: state.activeKey,\n });\n notify(depth);\n }\n}\n\n/**\n * Reveal a page still being held, if it is worth revealing.\n *\n * `maxAge` is what a link passes and the back button does not. Going back is\n * unambiguous — it names a moment, and the page from that moment is the right\n * answer however old. A link says \"go here\", and answering it with a tree from\n * twenty minutes ago is stale data presented as fresh, which is the objection\n * this design started with. Recent enough, and it is the same page you were\n * just on, with the form you were filling in still filled in.\n */\nexport function restoreSegments(key: string, maxAge?: number): boolean {\n // A guess is not a held page: revealing it would be showing prefetched\n // data as the page the visitor was on. The navigation takes the\n // prerendered tree through setSegment instead, where it is a reveal too.\n // Nor is a page from before a mutation - see dropHidden.\n const holding = [...depths.keys()].filter((d) =>\n depths.get(d)!.entries.some((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt),\n );\n\n if (holding.length === 0) return false;\n\n if (maxAge !== undefined) {\n const ages = holding.flatMap((d) =>\n depths\n .get(d)!\n .entries.filter((entry) => entry.key === key)\n .map((entry) => entry.at),\n );\n\n // The oldest layer decides: revealing a fresh page under a stale layout\n // would be a chain nobody rendered together.\n // >= rather than >, so a window of 0 means never rather than \"only within\n // the same millisecond\".\n if (Date.now() - Math.min(...ages) >= maxAge) return false;\n }\n\n const anchor = Math.max(...holding);\n\n for (const d of [...depths.keys()].filter((d) => d > anchor)) {\n depths.delete(d);\n notify(d);\n }\n\n for (const d of holding) {\n dropSpeculative(d);\n\n const state = depths.get(d)!;\n\n depths.set(\n d,\n retain(\n state.entries,\n [...state.order.filter((k) => k !== key), key],\n key,\n ),\n );\n notify(d);\n }\n\n return true;\n}\n\n/**\n * Drop everything, so boundaries fall back to their server-given children.\n *\n * A deployment invalidates them all: a segment from the previous build has no\n * claim on being correct for this one.\n */\nexport function clearSegments(): void {\n const all = [...depths.keys()];\n depths.clear();\n for (const depth of all) notify(depth);\n}\n\n/**\n * Whether a navigation has happened in this document.\n *\n * The first commit after hydration is the boundary taking over its\n * server-rendered children - the same page, re-keyed for retention. A view\n * transition for that commit fades the page into itself: the blank-then-\n * content a first load or a reload showed. Inertia transitions on visits and\n * never on load; so does this. The router notes the first navigation before\n * it updates a segment, and the boundary animates from then on.\n */\nlet navigated = false;\n\nexport function noteNavigation(): void {\n navigated = true;\n}\n\nexport function navigatedOnce(): boolean {\n return navigated;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"segmentStore.js","sourceRoot":"","sources":["../../src/js/segmentStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What each segment boundary is showing, and what it is keeping alive behind it.\n *\n * A navigation replaces one segment. Keeping the previous one mounted — hidden,\n * not unmounted — is what lets going back restore it with its client state:\n * the half-typed form, the open disclosure, the scrolled list. Unmounting\n * throws all of that away, which is what replacing the root used to do.\n *\n * Entries are keyed by page (the URL, or its intercept variant), so a boundary\n * can hold several and reveal one. Empty is meaningful: a boundary with nothing\n * stored renders the children the server gave it.\n *\n * A store rather than state, and not a preference — three things rule state out.\n * A boundary is inserted between every layout level, so there are several and a\n * navigation targets one by depth; they are separated by server components, so\n * no setter can be threaded down to them, because a function does not cross\n * that boundary; and navigate.ts is a plain module with no component instance\n * to call one on. Addressing a component you hold no reference to is what an\n * external store is for.\n *\n * Underneath it is the wire protocol. A partial navigation sends only the\n * segment that changed — see the X-RSC-Segments headers — so there is nothing\n * for a root to re-render with even if it held the state. Next.js keeps its\n * router in useState and derives every segment from it; that is the same trade\n * in the other direction.\n *\n * What it costs: React pins an external store's updates to synchronous\n * priority, because a store cannot be safely time-sliced. Synchronous is never\n * a transition, and anything that only runs for one — React's <ViewTransition>\n * among them — never ran for a navigation.\n *\n * Which is why SegmentBoundary does not read this with useSyncExternalStore\n * any more. The store still does the addressing, which is the part only it can\n * do; the boundary copies into state, so the render is a transition. See the\n * view transitions guide.\n */\n\ntype Tree = unknown;\ntype Listener = () => void;\n\ninterface Entry {\n key: string;\n /**\n * The key React mounts this page under, when it is not `key`.\n *\n * `key` is what a navigation files the page under - its path and query, so\n * Back to ?q=a restores that page and not ?q=b. The identity is what keeps\n * it mounted, and it has to survive two things that are not a new page: a\n * page loaded with a query, which the server rendered under its pathname\n * alone (the shell was frozen that way), and a replace to the same path with\n * a new query - the first message of a chat - which leaves nothing to go\n * back to. A new identity is a remount, and a remount shows every Suspense\n * fallback in the page: a skeleton over the chat, on every reply.\n */\n identity?: string;\n tree: Tree;\n /**\n * When this tree arrived, so a link can decide whether it is still worth\n * revealing. The back button never asks — it means \"the page I was on\",\n * however long ago that was.\n */\n at: number;\n /**\n * Its place in the order things happened, for the question \"was this\n * here before the mutation?\" - which a clock answers wrongly for a seed\n * and a write in the same millisecond, and a test hit exactly that.\n */\n seq: number;\n /**\n * Rendered before the click, hidden, on the strength of a touch or a\n * settled hover - see prerenderSegment. Outside the retention window: it\n * is a guess, and a guess must not evict a page the visitor was on. One\n * per depth; the next guess replaces it, and a navigation to anything\n * else drops it.\n */\n speculative?: boolean;\n}\n\n/**\n * Immutable: useSyncExternalStore compares snapshots by identity, so a new\n * object per read reads as \"changed every render\" and loops forever. Every\n * mutation replaces this wholesale; nothing edits one in place.\n */\ninterface DepthState {\n readonly entries: readonly Entry[];\n readonly activeKey: string;\n /** Most recently shown last; eviction takes from the front. */\n readonly order: readonly string[];\n}\n\n/** Pages kept alive per boundary. Four covers ordinary back-and-forth. */\nexport const RETENTION = 4;\n\nconst depths = new Map<number, DepthState>();\n/** A counter every entry takes a number from, in order. */\nlet tick = 0;\n/** The number the last mutation took: everything held before it is wrong. */\nlet invalidatedAt = 0;\nconst listeners = new Map<number, Set<Listener>>();\n\nfunction notify(depth: number): void {\n for (const listener of listeners.get(depth) ?? []) listener();\n}\n\nexport function subscribeToSegment(\n depth: number,\n listener: Listener,\n): () => void {\n let set = listeners.get(depth);\n\n if (!set) {\n set = new Set();\n listeners.set(depth, set);\n }\n\n set.add(listener);\n\n return () => {\n set!.delete(listener);\n if (set!.size === 0) listeners.delete(depth);\n };\n}\n\n/** Everything a boundary at this depth needs to render, or null for \"use children\". */\nexport function getSegmentState(depth: number): DepthState | null {\n return depths.get(depth) ?? null;\n}\n\n/** Apply the retention window to a candidate state. */\nfunction retain(\n entries: readonly Entry[],\n order: readonly string[],\n activeKey: string,\n): DepthState {\n const kept = order.slice(-RETENTION);\n\n return {\n entries: entries.filter((entry) => kept.includes(entry.key) || entry.speculative),\n order: kept,\n activeKey,\n };\n}\n\nfunction put(depth: number, key: string, tree: Tree, identity?: string): void {\n const state = depths.get(depth);\n // The same page again keeps the identity it is mounted under.\n const kept = identity ?? state?.entries.find((entry) => entry.key === key)?.identity;\n const entries = [\n ...(state?.entries ?? []).filter((entry) => entry.key !== key),\n { key, tree, at: Date.now(), seq: ++tick, ...(kept !== undefined && kept !== key ? { identity: kept } : {}) },\n ];\n const order = [...(state?.order ?? []).filter((k) => k !== key), key];\n\n depths.set(depth, retain(entries, order, key));\n}\n\n/**\n * Show `tree` at `depth` for `key`, retaining what was there.\n *\n * Deeper segments belonged to the page being replaced; leaving them would\n * render the previous page inside the new one.\n */\nexport function setSegment(depth: number, key: string, tree: Tree, inPlaceOf?: string | null): void {\n // A guess about another page was wrong; the one about this page, if there\n // was one, is replaced by put() below - with the same tree, when the\n // prerender and the navigation read the same decoded payload, which is\n // what makes the update a reveal rather than a render.\n dropSpeculative(depth, key);\n\n // A replace to the same path with a new query: the page it replaces is gone\n // from history, so this is that page, moved - not a new one to mount beside\n // it. It takes the old entry's identity, and the old entry goes.\n const state = depths.get(depth);\n const replaced =\n inPlaceOf && inPlaceOf !== key && !state?.entries.some((entry) => entry.key === key)\n ? state?.entries.find((entry) => entry.key === inPlaceOf)\n : undefined;\n\n if (replaced && state) {\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => entry !== replaced),\n order: state.order.filter((k) => k !== replaced.key),\n });\n }\n\n put(depth, key, tree, replaced ? (replaced.identity ?? replaced.key) : undefined);\n\n const stale = [...depths.keys()].filter((d) => d > depth);\n for (const d of stale) depths.delete(d);\n\n notify(depth);\n for (const d of stale) notify(d);\n}\n\nfunction dropSpeculative(depth: number, except?: string): void {\n const state = depths.get(depth);\n\n if (!state?.entries.some((entry) => entry.speculative && entry.key !== except)) return;\n\n depths.set(depth, {\n ...state,\n entries: state.entries.filter((entry) => !entry.speculative || entry.key === except),\n });\n}\n\n/**\n * Render a page hidden at `depth`, before any navigation to it.\n *\n * The click then finds the work done: setSegment with the same tree is a\n * bail-out for React - same element, same props - and the Activity flips\n * from hidden to visible. What was 87 ms of rendering on a phone, after\n * the tap, is paid before the finger lifts, at idle priority, yielding to\n * the scroll. Never changes what is showing, never counts against\n * retention, and a page already held needs nothing.\n */\nexport function prerenderSegment(depth: number, key: string, tree: Tree): void {\n const state = depths.get(depth);\n\n // Nothing at this depth yet: the boundary is still showing the server's\n // children, and it has no page key to keep them under. A guess would take\n // the store over with no active entry to show. seedSegment runs on mount,\n // so this is the gap between hydration and that effect; the click will\n // render.\n if (!state) return;\n\n if (state.entries.some((entry) => entry.key === key)) return;\n\n depths.set(depth, {\n ...state,\n entries: [\n ...state.entries.filter((entry) => !entry.speculative),\n { key, tree, at: Date.now(), seq: ++tick, speculative: true },\n ],\n });\n\n notify(depth);\n}\n\n/** Whether a page is rendered hidden at `depth`, ahead of a navigation to it. */\nexport function isPrerendered(depth: number, key: string): boolean {\n return depths.get(depth)?.entries.some((entry) => entry.key === key && entry.speculative) ?? false;\n}\n\n/**\n * Give the page on screen at `depth` a new tree, under the key it has.\n *\n * For revalidate(\"all\"): the whole document rendered again, in place. The\n * root hands its layout the new tree, the layout hands its boundary new\n * children, and a boundary that holds state would otherwise keep showing\n * the store's tree and drop the new one on the floor - or, cleared first,\n * re-key its Activity to the current url and remount everything under it.\n * Neither. The entry that is showing takes the new tree and keeps its key,\n * so React reconciles the page in place, and the boundary below gets its\n * new children the same way.\n */\nexport function replaceActive(depth: number, tree: Tree): void {\n const state = depths.get(depth);\n\n if (!state) return;\n\n const active = state.entries.find((entry) => entry.key === state.activeKey);\n\n if (!active || active.tree === tree) return;\n\n // The tree changes; when the entry arrived does not. A layout's entry is\n // keyed by the page it was seeded with - \"/\" for a document loaded at\n // home - and stays active through every navigation below it. Stamped\n // with the re-render's time it read as held since the mutation, and a\n // tap on the brand link after \"Add to cart\" revealed it: the url went\n // to \"/\" and the product stayed, because the tree under that key was\n // now the product's document. See dropHidden and isHeld.\n depths.set(depth, {\n ...state,\n entries: state.entries.map((entry) => (entry === active ? { ...entry, tree } : entry)),\n });\n notify(depth);\n}\n\n/**\n * Record the children the server rendered, so the page you arrived on can be\n * returned to later. Never changes what is showing.\n */\nexport function seedSegment(depth: number, key: string, tree: Tree, identity?: string): void {\n const state = depths.get(depth);\n\n if (state?.entries.some((entry) => entry.key === key)) return;\n\n if (!state) {\n put(depth, key, tree, identity);\n notify(depth);\n\n return;\n }\n\n // Older than whatever is showing, so it goes to the front of the eviction\n // order — and crucially does not become the active page.\n depths.set(\n depth,\n retain(\n [...state.entries, { key, tree, at: Date.now(), seq: ++tick, ...(identity !== undefined && identity !== key ? { identity } : {}) }],\n [key, ...state.order.filter((k) => k !== key)],\n state.activeKey,\n ),\n );\n\n notify(depth);\n}\n\n/**\n * Reveal a page the boundaries are still holding, without asking the server.\n *\n * Restoring is anchored on the deepest boundary that can show the page. Deeper\n * ones than that belonged to the page being left — a section with its own\n * layout adds a boundary the page you are going back to never had — so they\n * are dropped, exactly as setSegment drops them. Requiring every boundary to\n * hold the key instead made any such page refuse to restore.\n *\n * Shallower boundaries need no key of their own: their trees contain the\n * deeper boundary, so they delegate to whatever it is showing. One that does\n * hold the key is switched to it, since that is a real change at its level.\n */\n/**\n * Whether a link to `key` would be answered by revealing a held page.\n *\n * The question restoreSegments answers, asked without acting on it: a\n * prefetch of a page the boundaries still hold is a request for nothing -\n * a navigation would reveal it. The page just left is the usual case, one\n * wasted payload per navigation.\n */\nexport function isHeld(key: string, maxAge?: number): boolean {\n const ages = [...depths.values()].flatMap((state) =>\n state.entries.filter((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt).map((entry) => entry.at),\n );\n\n if (ages.length === 0) return false;\n if (maxAge === undefined) return true;\n\n return Date.now() - Math.min(...ages) < maxAge;\n}\n\n/**\n * Drop every page held behind the one on screen.\n *\n * After a mutation: a page kept for the back button holds the data from\n * before it, and revealing it would show a row that is gone, a name that\n * changed. The page on screen stays - it was re-rendered by the action, or\n * is about to be.\n */\nexport function dropHidden(): void {\n // And the ones that stay - the active entry at each depth - are from\n // before it too. A layout's entry is keyed by the page it was seeded\n // with, and revealing that key later shows the page inside it as it was\n // then. Nothing seeded before this moment is revealed again.\n invalidatedAt = ++tick;\n\n for (const [depth, state] of depths) {\n if (state.entries.length <= 1 && !state.entries.some((entry) => entry.speculative)) continue;\n\n depths.set(depth, {\n entries: state.entries.filter((entry) => entry.key === state.activeKey),\n order: state.order.filter((key) => key === state.activeKey),\n activeKey: state.activeKey,\n });\n notify(depth);\n }\n}\n\n/**\n * Reveal a page still being held, if it is worth revealing.\n *\n * `maxAge` is what a link passes and the back button does not. Going back is\n * unambiguous — it names a moment, and the page from that moment is the right\n * answer however old. A link says \"go here\", and answering it with a tree from\n * twenty minutes ago is stale data presented as fresh, which is the objection\n * this design started with. Recent enough, and it is the same page you were\n * just on, with the form you were filling in still filled in.\n */\nexport function restoreSegments(key: string, maxAge?: number): boolean {\n // A guess is not a held page: revealing it would be showing prefetched\n // data as the page the visitor was on. The navigation takes the\n // prerendered tree through setSegment instead, where it is a reveal too.\n // Nor is a page from before a mutation - see dropHidden.\n const holding = [...depths.keys()].filter((d) =>\n depths.get(d)!.entries.some((entry) => entry.key === key && !entry.speculative && entry.seq > invalidatedAt),\n );\n\n if (holding.length === 0) return false;\n\n if (maxAge !== undefined) {\n const ages = holding.flatMap((d) =>\n depths\n .get(d)!\n .entries.filter((entry) => entry.key === key)\n .map((entry) => entry.at),\n );\n\n // The oldest layer decides: revealing a fresh page under a stale layout\n // would be a chain nobody rendered together.\n // >= rather than >, so a window of 0 means never rather than \"only within\n // the same millisecond\".\n if (Date.now() - Math.min(...ages) >= maxAge) return false;\n }\n\n const anchor = Math.max(...holding);\n\n for (const d of [...depths.keys()].filter((d) => d > anchor)) {\n depths.delete(d);\n notify(d);\n }\n\n for (const d of holding) {\n dropSpeculative(d);\n\n const state = depths.get(d)!;\n\n depths.set(\n d,\n retain(\n state.entries,\n [...state.order.filter((k) => k !== key), key],\n key,\n ),\n );\n notify(d);\n }\n\n return true;\n}\n\n/**\n * Drop everything, so boundaries fall back to their server-given children.\n *\n * A deployment invalidates them all: a segment from the previous build has no\n * claim on being correct for this one.\n */\nexport function clearSegments(): void {\n const all = [...depths.keys()];\n depths.clear();\n for (const depth of all) notify(depth);\n}\n\n/**\n * Whether a navigation has happened in this document.\n *\n * The first commit after hydration is the boundary taking over its\n * server-rendered children - the same page, re-keyed for retention. A view\n * transition for that commit fades the page into itself: the blank-then-\n * content a first load or a reload showed. Inertia transitions on visits and\n * never on load; so does this. The router notes the first navigation before\n * it updates a segment, and the boundary animates from then on.\n */\nlet navigated = false;\n\nexport function noteNavigation(): void {\n navigated = true;\n}\n\nexport function navigatedOnce(): boolean {\n return navigated;\n}\n"]}
|
package/dist/request.d.ts
CHANGED
|
@@ -126,6 +126,18 @@ export declare function url(): Promise<string | null>;
|
|
|
126
126
|
* it happened to send.
|
|
127
127
|
*/
|
|
128
128
|
export declare function withRequest<T>(from: RequestLike, run: () => Promise<T>): Promise<T>;
|
|
129
|
+
/**
|
|
130
|
+
* Run a render with a different url, the request otherwise unchanged.
|
|
131
|
+
*
|
|
132
|
+
* An action's response renders what it revalidated for the page it was called
|
|
133
|
+
* from. The request is the action's POST, whose url is the endpoint's; the
|
|
134
|
+
* page's query string lives in the page's url. A slot on /agent/test?c=25
|
|
135
|
+
* re-rendered after a message was sent read the POST's empty query - through
|
|
136
|
+
* searchParams() and through the page's own searchParams prop, which is built
|
|
137
|
+
* on it - and came back as a new chat. Headers and cookies stay the request's:
|
|
138
|
+
* it is the same visitor, asking about a different url.
|
|
139
|
+
*/
|
|
140
|
+
export declare function withUrl<T>(href: string, run: () => Promise<T>): Promise<T>;
|
|
129
141
|
/**
|
|
130
142
|
* A promise that never settles, so the caller suspends.
|
|
131
143
|
*
|
package/dist/request.js
CHANGED
|
@@ -462,6 +462,23 @@ export async function withRequest(from, run) {
|
|
|
462
462
|
};
|
|
463
463
|
return await scope().run(store, run);
|
|
464
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* Run a render with a different url, the request otherwise unchanged.
|
|
467
|
+
*
|
|
468
|
+
* An action's response renders what it revalidated for the page it was called
|
|
469
|
+
* from. The request is the action's POST, whose url is the endpoint's; the
|
|
470
|
+
* page's query string lives in the page's url. A slot on /agent/test?c=25
|
|
471
|
+
* re-rendered after a message was sent read the POST's empty query - through
|
|
472
|
+
* searchParams() and through the page's own searchParams prop, which is built
|
|
473
|
+
* on it - and came back as a new chat. Headers and cookies stay the request's:
|
|
474
|
+
* it is the same visitor, asking about a different url.
|
|
475
|
+
*/
|
|
476
|
+
export async function withUrl(href, run) {
|
|
477
|
+
const store = slot();
|
|
478
|
+
if (!store.request)
|
|
479
|
+
return await run();
|
|
480
|
+
return await scope().run({ ...store, url: href }, run);
|
|
481
|
+
}
|
|
465
482
|
/**
|
|
466
483
|
* A promise that never settles, so the caller suspends.
|
|
467
484
|
*
|
package/dist/request.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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","sourcesContent":["// Reading the request from inside a render.\n//\n// import { headers, cookies } from '@rsc-kit/core/request'\n//\n// export default async function middleware() {\n// const locale = cookies().get('locale')?.value ?? negotiate(headers().get('accept-language'))\n// if (!locale) redirect('/en')\n// }\n//\n// Server components have no arguments beyond their props, and middleware has\n// none at all, so without this an app on a JavaScript host cannot see a header\n// — no locale negotiation, no subdomain, no cookie. The Laravel host escaped\n// that through rpc(), because PHP has the request; this is the same thing for\n// everyone else.\n//\n// Read-only on purpose. Setting a cookie means writing a response header, and\n// by the time a component renders the shell may already have been flushed — an\n// API that appears to set one and silently does not is worse than not having\n// it. Set them in the host, which owns the response.\n//\n// Asynchronous on purpose too, and not for ergonomics. A build has no request,\n// so a read there suspends and never settles — which is the same thing the\n// prerender probe does to a host call. Anything still waiting when the probe's\n// budget expires becomes a fallback in the frozen shell, so a read inside a\n// Suspense boundary leaves the shell frozen and makes only that boundary\n// dynamic. Reading synchronously could only mark the whole route dynamic,\n// because there would be nothing to suspend on.\n//\n// Scoped to the request, on the same store cache() uses. Two requests in\n// flight cannot see each other's headers.\n\nimport { resolveScope } from \"./revalidate.js\";\n\n/** What a host can supply: a real Request, or the parts of one. */\nexport type RequestLike =\n Request | { url: string; headers: Record<string, string> } | null;\n\ninterface Slot {\n /** False during a build: there is nothing to answer with. */\n request: boolean;\n url: string | null;\n /**\n * Held as Headers rather than as a Request.\n *\n * `new Request(url, { headers })` drops Cookie: a spec-compliant Headers\n * built with the \"request\" guard refuses the forbidden header names, and\n * Cookie is one of them. `new Headers()` has no guard and keeps it. Bun\n * happens to allow both, which is why rebuilding a Request looked fine until\n * it ran anywhere stricter — and what it loses is every cookie, silently.\n */\n headers: Headers;\n original: Request | null;\n /**\n * Whether anything asked. Only for the build's report — the classification\n * comes from the suspension, not from this.\n */\n read: boolean;\n /**\n * What read it, in the order they did.\n *\n * Only the name of the accessor — `cookies()`, `headers()` — which is enough\n * for the build to say why a page could not be frozen. Without it the answer\n * is \"something in this page reached for the request\", and finding which is\n * the part that takes an afternoon.\n */\n readBy: string[];\n /**\n * The same reads with the component that made each one - `cookies() in\n * RootLayout` - taken from the stack at the moment of the read, which is\n * still the component's own call: an accessor runs synchronously up to\n * the point it suspends. Only the build reads this. \"Reads the request\" is\n * a category; this is the line to open.\n */\n readWhere: string[];\n /**\n * Reads the server could not answer and React caught at a boundary - the\n * fallback is what got stored - with the component that made each:\n * `useSearchParams() in Query`. Noted by the SSR entry, read by the build,\n * which attaches them to the route so a page stored as its own loading\n * screen says why.\n */\n fallbacks: string[];\n /**\n * For a read made inside a cache()-wrapped helper: the components that\n * awaited that helper, first caller included. The helper runs once, so\n * the stack at the read names only whoever got there first; every later\n * awaiter is a cache hit that never reaches the accessor. The one above\n * every boundary is usually one of the later ones.\n */\n awaiters: Map<unknown, string[]>;\n /** The cache()-wrapped helper whose body is running, while it runs. */\n inHelper: unknown;\n /** readWhere entry -> the helper it was read inside. */\n readVia: Map<string, unknown>;\n /** Work to run once the answer is on its way - see after(). */\n after: (() => unknown)[];\n}\n\nconst SCOPE = Symbol.for(\"@rsc-kit/core.request-scope\");\n\n/**\n * The accessors themselves and the plumbing under them: frames to walk past\n * on the way to the component that called.\n */\nconst NOT_A_CALLER = new Set([\n \"never\",\n \"cache\",\n \"noteAwaiter\",\n \"withHelper\",\n \"noteRequestRead\",\n \"recordRead\",\n \"caller\",\n \"slot\",\n \"cookies\",\n \"headers\",\n \"connection\",\n \"searchParams\",\n \"request\",\n \"url\",\n \"parseParams\",\n \"parseSearchParams\",\n \"parseBody\",\n \"get\",\n \"set\",\n \"has\",\n]);\n\n/** The accessors a component calls by name. One calling another is plumbing, not a second read. */\nconst ACCESSORS = new Set([\n \"cookies\",\n \"headers\",\n \"connection\",\n \"searchParams\",\n \"request\",\n \"url\",\n]);\n\n/**\n * The nearest named function above the accessor on the stack, and whether\n * another accessor sits between: `cookies()` reads through `headers()`, and\n * that inner read is not a second thing the component did.\n *\n * Read from a thrown-away Error: the one thing a build cannot otherwise learn\n * is which component reached for the request, and the stack knows. Function\n * names survive a server bundle, which is not minified, so this is\n * `RootLayout` and not a line number in a chunk. Internal names are walked\n * past; an anonymous frame is skipped rather than reported as `<anonymous>`.\n */\nfunction caller(own: string): { name: string | null; nested: boolean } {\n const stack = new Error().stack ?? \"\";\n let accessors = 0;\n let helper: string | null = null;\n\n for (const line of stack.split(\"\\n\")) {\n const match = /^\\s*at (?:async )?([^\\s(]+)/.exec(line);\n\n if (!match) continue;\n\n const name = match[1]!.split(\".\").pop()!;\n\n // A frame with no function name prints its location instead - `js:6054:8`\n // - which is not a name to report.\n if (!/^[\\w$]+$/.test(name)) continue;\n\n if (ACCESSORS.has(name)) accessors++;\n if (\n NOT_A_CALLER.has(name) ||\n name === \"<anonymous>\" ||\n name === \"Object\" ||\n name === \"Promise\"\n )\n continue;\n\n const nested = accessors > (ACCESSORS.has(own) ? 1 : 0);\n\n // A function that is not a component - getCurrentUser, wrapped in\n // cache() - is the shared helper the read lives in. Named, because with\n // cache() the read runs once, on whichever component called first, and\n // every other caller of the helper is invisible to the stack. The helper\n // is what they have in common.\n if (/^[a-z_$]/.test(name) && !/^use[A-Z]/.test(name)) {\n helper ??= name;\n\n continue;\n }\n\n return {\n name: helper && helper !== name ? `${helper} (from ${name})` : name,\n nested,\n };\n }\n\n return { name: helper, nested: accessors > (ACCESSORS.has(own) ? 1 : 0) };\n}\n\nfunction recordRead(store: Slot, by: string): void {\n if (!store.readBy.includes(by)) store.readBy.push(by);\n\n // Older stores, written by a bundle built before this field existed.\n store.readWhere ??= [];\n\n const { name, nested } = caller(by.replace(/\\(.*$/, \"\"));\n\n if (nested) return;\n\n const entry = name ? `${by} in ${name}` : by;\n\n if (!store.readWhere.includes(entry)) store.readWhere.push(entry);\n if (store.inHelper) (store.readVia ??= new Map()).set(entry, store.inHelper);\n}\n\nconst globals = globalThis as Record<symbol | string, unknown>;\n\nlet ready: Promise<void> | null = null;\n\ninterface Scope {\n getStore(): Slot | undefined;\n run<T>(store: Slot, fn: () => T): T;\n}\n\nfunction scope(): Scope | null {\n return (globals[SCOPE] as Scope | undefined) ?? null;\n}\n\nfunction slot(): Slot {\n const store = scope()?.getStore();\n\n if (!store) {\n throw new Error(\n \"No request in scope. headers() and cookies() are for a render — middleware, a layout, \" +\n \"a page — and there is nothing to read outside one.\",\n );\n }\n\n store.read = true;\n\n return store;\n}\n\n/**\n * The request's headers.\n *\n * Empty during a build, where there is no request: the page is marked as\n * needing one instead, and rendered on demand rather than frozen.\n */\nexport async function headers(): Promise<Headers> {\n const store = slot();\n\n return store.request ? store.headers : never(\"headers()\");\n}\n\n/** How a cookie should be written. The names browsers use. */\nexport interface CookieOptions {\n path?: string;\n domain?: string;\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n partitioned?: boolean;\n}\n\n/** One cookie as the request carried it: the shape Next's `cookies().get()` returns. */\nexport interface RequestCookie {\n name: string;\n value: string;\n}\n\n/**\n * The cookie jar, in the shape Next's `cookies()` has.\n *\n * `get()` returns `{ name, value }` rather than the string, because the guide\n * says \"the same names from `@rsc-kit/core/request`\" and a name that is the\n * same with a different return shape is the worst of both: ported code\n * reading `?.value` off a string got `undefined`, silently. `getAll()` is a\n * list for the same reason, and because a list composes where a record does\n * not.\n */\nexport interface Cookies {\n get(name: string): RequestCookie | undefined;\n has(name: string): boolean;\n getAll(): RequestCookie[];\n /**\n * Write one on the response.\n *\n * Only from a server action, which has a response of its own that has not\n * been sent. A render has already flushed its headers by the time a\n * component runs — that is what makes the first paint fast — so this throws\n * there rather than appearing to work.\n *\n * Either call shape Next takes: `set(name, value, options)` or\n * `set({ name, value, ...options })`.\n */\n set(name: string, value: string, options?: CookieOptions): void;\n set(cookie: RequestCookie & CookieOptions): void;\n /** Write one that expires immediately. Same rule about where. */\n delete(name: string, options?: CookieOptions): void;\n}\n\n/** Kept for the name it had when it could only read. */\nexport type ReadonlyCookies = Cookies;\n\n/**\n * The response being built, while it can still be changed.\n *\n * Open from the moment a request is picked up until the host constructs its\n * Response, and sealed the instant it does. Middleware runs inside that window\n * — before any rendering starts — so a header set there is on the answer. A\n * component runs after it, during streaming, where the status line and headers\n * are already on the wire; setting one there is refused rather than dropped.\n */\ninterface Draft {\n headers: Headers;\n sealed: boolean;\n /**\n * What this request wrote to the jar, over what it arrived with: a value,\n * or null for a deletion. Read back by `cookies()` for the rest of the\n * request, so a render that follows the write - the sections an action\n * revalidates travel back with its answer, rendered in the same request -\n * sees what the browser is about to hold. Next has the same rule, which\n * is why `set` then `revalidate` is what every port writes; without it\n * the sidebar re-rendered with the cookie the request arrived with, and\n * showed the old choice until a reload.\n */\n cookies: Map<string, string | null>;\n}\n\nconst DRAFT = Symbol.for(\"@rsc-kit/core.response-draft\");\n\nlet draftReady: Promise<void> | null = null;\n\ninterface DraftScope {\n getStore(): Draft | undefined;\n run<T>(store: Draft, fn: () => T): T;\n}\n\nfunction draft(): DraftScope | null {\n return (globals[DRAFT] as DraftScope | undefined) ?? null;\n}\n\n/** The open draft, or an explanation of why there is not one. */\nfunction writable(what: string): Draft {\n const open = draft()?.getStore();\n\n if (!open) {\n throw new Error(\n `${what} needs a response that has not been sent. Middleware and server actions have one; ` +\n \"a script outside a request does not.\",\n );\n }\n\n if (open.sealed) {\n throw new Error(\n `${what} was called after the response had been sent. Headers go out before the render ` +\n \"starts — that is what makes the first paint fast — so set them in middleware, which \" +\n \"runs before it.\",\n );\n }\n\n return open;\n}\n\n/**\n * Headers to put on the answer.\n *\n * Mutate it as you would any Headers. `append` is the one to reach for when a\n * header may legitimately appear twice; `set` replaces.\n */\n/**\n * The draft's headers, refusing writes once the response has gone.\n *\n * A proxy rather than the Headers itself: returning the live object means code\n * that captured it before the response was built can go on mutating a thing\n * nobody will read. Nothing in this package does that — the host copies the\n * headers onto the response the instant it seals — but \"safe because of the\n * order two other functions happen to run in\" is not a property, and an app\n * holding the object across an await would find writes silently doing nothing.\n */\nfunction sealable(draft: Draft): Headers {\n const guard =\n (method: \"set\" | \"append\" | \"delete\") =>\n (...args: [string, string]) => {\n writable(\"responseHeaders()\");\n\n return (draft.headers[method] as (...a: string[]) => void)(...args);\n };\n\n const proxy: Headers = new Proxy(draft.headers, {\n get(target, property, receiver) {\n if (\n property === \"set\" ||\n property === \"append\" ||\n property === \"delete\"\n ) {\n return guard(property);\n }\n\n // A maplike forEach passes the object it was called on as the third\n // callback argument, and binding to the target makes that the raw\n // Headers — a live, unguarded reference handed out by the very method\n // meant to be read-only. Substituted for the proxy so there is no way\n // through.\n if (property === \"forEach\") {\n return (\n fn: (value: string, key: string, parent: Headers) => void,\n thisArg?: unknown,\n ) =>\n target.forEach((value, key) => fn.call(thisArg, value, key, proxy));\n }\n\n const value = Reflect.get(target, property, receiver);\n\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n });\n\n return proxy;\n}\n\nexport function responseHeaders(): Headers {\n return sealable(writable(\"responseHeaders()\"));\n}\n\n/**\n * Run a request with a response that can still be changed, and take what was\n * put on it.\n *\n * `seal()` is called by the host the moment it builds the Response, so\n * anything set afterwards is refused instead of silently going nowhere.\n */\nexport async function withResponseDraft<T>(\n run: (draft: { taken: () => Headers; seal: () => void }) => Promise<T>,\n): Promise<T> {\n if (!globals[DRAFT]) {\n draftReady ??= resolveScope().then((resolved) => {\n globals[DRAFT] ??= resolved as unknown as DraftScope;\n });\n\n await draftReady;\n }\n\n const open: Draft = { headers: new Headers(), sealed: false, cookies: new Map() };\n\n return await draft()!.run(open, () =>\n run({\n taken: () => open.headers,\n seal: () => {\n open.sealed = true;\n },\n }),\n );\n}\n\n/**\n * A cookie name, as RFC 6265 defines one: a token, so no separators at all.\n *\n * Checked rather than escaped because there is no escaping — a name is not a\n * quoted string. An app that derives one from user input (`pref_${key}`) would\n * otherwise let that input close the pair and open another: a name of\n * `session=attacker; Path=/; HttpOnly; x` serializes to a header whose *first*\n * pair is a session cookie the caller chose, and the browser reads the first.\n */\nconst COOKIE_NAME = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n\n/** No separator may appear in an attribute either, for the same reason. */\nconst COOKIE_ATTRIBUTE = /[;,\\r\\n]/;\n\n/** `name=value; Path=/; HttpOnly` — the header a browser expects. */\nexport function serializeCookie(cookie: {\n name: string;\n value: string;\n options: CookieOptions;\n}): string {\n if (!COOKIE_NAME.test(cookie.name)) {\n throw new Error(\n `Not a usable cookie name: ${JSON.stringify(cookie.name)}. ` +\n \"A name is a token — letters, digits and !#$%&'*+-.^_`|~ — with no spaces, \" +\n \"semicolons or equals signs. Nothing escapes them, so one cannot be encoded around.\",\n );\n }\n\n if (cookie.options.sameSite !== undefined) {\n const value = String(cookie.options.sameSite).toLowerCase();\n\n if (value !== \"strict\" && value !== \"lax\" && value !== \"none\") {\n throw new Error(\n `Not a SameSite value: ${JSON.stringify(cookie.options.sameSite)}. ` +\n \"It is written into the header as given, so anything else becomes further attributes.\",\n );\n }\n }\n\n for (const [attribute, value] of [\n [\"path\", cookie.options.path],\n [\"domain\", cookie.options.domain],\n ] as const) {\n if (typeof value === \"string\" && COOKIE_ATTRIBUTE.test(value)) {\n throw new Error(\n `The cookie ${attribute} ${JSON.stringify(value)} contains a separator. ` +\n \"It would be read as further attributes rather than as part of this one.\",\n );\n }\n }\n\n // Typed as a Date, but a cast reaches this and the result lands in the\n // header verbatim. Checked apart from the others because a date has commas\n // in it by definition - \"Sun, 20 Sep 2026 14:49:56 GMT\" - and the general\n // check refused every Expires ever written.\n const expires = cookie.options.expires?.toUTCString();\n\n if (typeof expires === \"string\" && /[;\\r\\n]/.test(expires)) {\n throw new Error(\n `The cookie expires ${JSON.stringify(expires)} contains a separator. ` +\n \"It would be read as further attributes rather than as part of this one.\",\n );\n }\n\n const parts = [`${cookie.name}=${encodeURIComponent(cookie.value)}`];\n const o = cookie.options;\n\n if (o.maxAge !== undefined) parts.push(`Max-Age=${Math.floor(o.maxAge)}`);\n if (o.expires) parts.push(`Expires=${o.expires.toUTCString()}`);\n // Defaulted, because a cookie without one is scoped to the path that set it\n // — a session written by POST /_rsc/action would not be sent for any page.\n parts.push(`Path=${o.path ?? \"/\"}`);\n if (o.domain) parts.push(`Domain=${o.domain}`);\n if (o.sameSite)\n parts.push(`SameSite=${o.sameSite[0].toUpperCase()}${o.sameSite.slice(1)}`);\n if (o.secure) parts.push(\"Secure\");\n if (o.httpOnly) parts.push(\"HttpOnly\");\n if (o.partitioned) parts.push(\"Partitioned\");\n\n return parts.join(\"; \");\n}\n\nexport async function cookies(): Promise<Cookies> {\n // Named before the await, because `headers()` never settles during a build —\n // nothing after this line runs there, and the reason would be recorded as\n // headers() for a call nobody wrote.\n const store = slot();\n\n if (!store.request) recordRead(store, \"cookies()\");\n\n const parsed = parseCookies((await headers()).get(\"cookie\") ?? \"\");\n\n // What arrived, then what this request wrote over it. Read at each call\n // rather than once: a write between two reads is the case that matters.\n const jar = (): Record<string, string> => {\n const written = draft()?.getStore()?.cookies;\n\n if (!written?.size) return parsed;\n\n const merged = { ...parsed };\n\n for (const [name, value] of written) {\n if (value === null) delete merged[name];\n else merged[name] = value;\n }\n\n return merged;\n };\n\n const write = (\n name: string,\n value: string,\n options: CookieOptions = {},\n ): void => {\n const open = writable(\"cookies().set()\");\n\n // Appended, never set: several cookies on one response are several\n // Set-Cookie headers, and replacing would leave only the last.\n open.headers.append(\"Set-Cookie\", serializeCookie({ name, value, options }));\n\n // A cookie told to expire is one the browser will not send back.\n const gone =\n options.maxAge !== undefined ? options.maxAge <= 0 : options.expires !== undefined && options.expires.getTime() <= Date.now();\n\n open.cookies.set(name, gone ? null : value);\n };\n\n return {\n get: (name) => {\n const current = jar();\n\n // Own keys only: `in` found \"constructor\" in any jar.\n return Object.hasOwn(current, name) ? { name, value: current[name] } : undefined;\n },\n has: (name) => Object.hasOwn(jar(), name),\n getAll: () => Object.entries(jar()).map(([name, value]) => ({ name, value })),\n set: (nameOrCookie: string | (RequestCookie & CookieOptions), value?: string, options?: CookieOptions) => {\n if (typeof nameOrCookie === \"string\") return write(nameOrCookie, value ?? \"\", options);\n\n const { name, value: v, ...rest } = nameOrCookie;\n\n return write(name, v, rest);\n },\n // Expired rather than removed: a browser drops a cookie when it is told\n // one has already passed, and there is no other way to say it.\n delete: (name, options = {}) => write(name, \"\", { ...options, maxAge: 0 }),\n };\n}\n\n/**\n * The whole request, for a host-specific need the accessors do not cover.\n *\n * Null on a host that forwards only the parts — the worker behind Laravel has\n * a socket, not a request. Use headers() and cookies(), which work everywhere.\n */\nexport async function request(): Promise<Request | null> {\n const store = slot();\n\n return store.request ? store.original : never(\"request()\");\n}\n\n/**\n * Mark everything below as belonging to the request, not to the build.\n *\n * export default async function Orders() {\n * await connection()\n *\n * const rows = await db.query('select * from orders')\n *\n * return <ul>{rows.map(...)}</ul>\n * }\n *\n * At build time this never resolves, so nothing after it runs: the query is not\n * made, the boundary above becomes a hole, and the rest of the page still\n * freezes. At request time it resolves immediately and the component runs\n * normally.\n *\n * **Once is enough.** It is a barrier, not a wrapper — everything after it in\n * this component belongs to the request, however many calls that is. Repeating\n * it before each query does nothing.\n *\n * It needs a boundary above it. With a <Suspense> or a loading.tsx there is a\n * fallback to store and the page becomes a shell; with neither, nothing can\n * paint and the build refuses the route rather than storing a blank.\n *\n * Reach for it when the build should not run something — a database the build\n * machine cannot see, or a value that must differ per visitor. A query the\n * build CAN run, whose answer is the same for everyone, wants none of this: it\n * should be frozen.\n *\n * The same name and behaviour as Next's `connection()`.\n */\nexport async function connection(): Promise<void> {\n const store = slot();\n\n // No request means a build. Suspend rather than continue, the same way\n // headers() and cookies() do.\n if (!store.request) return never(\"connection()\");\n}\n\n/** The url this request was made to, whichever way the host supplied it. */\nexport async function url(): Promise<string | null> {\n const store = slot();\n\n return store.request ? store.url : never(\"url()\");\n}\n\nfunction parseCookies(header: string): Record<string, string> {\n const out: Record<string, string> = {};\n\n for (const part of header.split(\";\")) {\n const eq = part.indexOf(\"=\");\n\n if (eq === -1) continue;\n\n const name = part.slice(0, eq).trim();\n\n if (!name) continue;\n\n // Decoded because that is how they were written. A malformed escape is\n // left as it arrived rather than throwing the render away.\n const raw = part.slice(eq + 1).trim();\n\n try {\n out[name] = decodeURIComponent(raw);\n } catch {\n out[name] = raw;\n }\n }\n\n return out;\n}\n\n/**\n * Run one request with its headers readable.\n *\n * `null` is the build: a scope with nothing in it, so a page that reads is\n * caught rather than silently frozen holding whatever the machine that built\n * it happened to send.\n */\nexport async function withRequest<T>(\n from: RequestLike,\n run: () => Promise<T>,\n): Promise<T> {\n if (!globals[SCOPE]) {\n ready ??= resolveScope().then((resolved) => {\n globals[SCOPE] ??= resolved as unknown as Scope;\n });\n\n await ready;\n }\n\n const isRequest = from instanceof Request;\n const store: Slot = {\n request: from !== null,\n url: from ? (isRequest ? from.url : from.url) : null,\n headers: from\n ? isRequest\n ? from.headers\n : new Headers(from.headers)\n : new Headers(),\n original: isRequest ? from : null,\n read: false,\n readBy: [],\n readWhere: [],\n fallbacks: [],\n awaiters: new Map(),\n inHelper: null,\n readVia: new Map(),\n after: [],\n };\n\n return await scope()!.run(store, run);\n}\n\n/**\n * A promise that never settles, so the caller suspends.\n *\n * What a read does during a build. React treats it exactly as it treats a host\n * call that never answers: the component suspends, its Suspense fallback goes\n * into the shell, and the probe's budget decides the rest.\n */\n/**\n * The build's probe hands a route a Request that records what is read out of\n * it, and a read of `url` marks the route as depending on the caller — the\n * Next way to read a query is `new URL(request.url).searchParams`, which the\n * probe cannot otherwise see. The engine itself reads the url to resolve the\n * awaited `searchParams`, and that read is accounted for by `searchParams`,\n * not by `url`; this is the door it goes through. A probe answers the real\n * Request to this key; anything else answers nothing, and the request is its\n * own.\n */\nexport const UNPROBED = Symbol.for(\"rsc-kit.unprobed\");\n\n/** The request's url, read by the engine rather than the route. */\nexport function urlOf(request: Request): string {\n return ((request as unknown as Record<symbol, Request | undefined>)[UNPROBED] ?? request).url;\n}\n\n/**\n * Record a read without suspending on it.\n *\n * For a reader that CAN answer during a build but whose answer would be wrong\n * to store — an api route's query string, which exists and is empty, and which\n * the build has no business freezing an answer to. `never()` is for a reader\n * with nothing to return; this is for one that has something and should still\n * be noticed.\n *\n * A no-op outside a render scope, so a handler called at request time pays a\n * property read and nothing else.\n */\nexport function noteRequestRead(by: string): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n recordRead(store, by);\n}\n\nfunction never(by: string): Promise<never> {\n const store = slot();\n\n store.read = true;\n recordRead(store, by);\n\n return new Promise(() => {});\n}\n\n/**\n * Whether anything read the request during the scope that is open.\n *\n * For the prerenderer, which opens one with no request and asks afterwards.\n */\nexport function requestWasRead(): boolean {\n return scope()?.getStore()?.read ?? false;\n}\n\n/**\n * What reached for the request during the scope that is open.\n *\n * For the build, which asks afterwards so it can say why a page is rendered per\n * visitor rather than only that it is.\n */\nexport function requestReadBy(): string[] {\n return scope()?.getStore()?.readBy ?? [];\n}\n\n/** A read React caught at a boundary during SSR: `useSearchParams() in Query`. */\nexport function noteFallback(text: string): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n store.fallbacks ??= [];\n\n if (!store.fallbacks.includes(text)) store.fallbacks.push(text);\n}\n\n/**\n * Run something once the answer is on its way, without making it wait.\n *\n * Logging, an audit row, an email, a cache warm: work the visitor should not\n * pay for, and that must still finish. Next's `after()`, and needed for the\n * same reason on every host: on a long-lived process a detached promise\n * happens to run to completion, but a Worker tears the isolate down when the\n * response ends unless the work is registered with the platform's\n * `waitUntil` - so a fire-and-forget promise there dies silently, some of\n * the time. The host hands these to `waitUntil` where one exists and runs\n * them detached where a process will keep them.\n *\n * From a component, a middleware, a server action or an api route. A\n * rejection is reported and never reaches the response, which has already\n * gone. Outside a request - a build - the work runs at once.\n */\nexport function after(work: () => unknown): void {\n const store = scope()?.getStore();\n\n if (!store || !store.request) {\n void Promise.resolve().then(work).catch(reportAfter);\n\n return;\n }\n\n store.after.push(work);\n}\n\nfunction reportAfter(error: unknown): void {\n console.error(\"[rsc-kit] after() work failed:\", error);\n}\n\n/**\n * @internal For the host: the work `after()` collected for this request, as\n * one promise that never rejects. Taken once; a second call has nothing.\n */\nexport function takeAfterWork(): Promise<void> | null {\n const store = scope()?.getStore();\n\n if (!store || store.after.length === 0) return null;\n\n const work = store.after.splice(0);\n\n return Promise.allSettled(\n work.map((run) => Promise.resolve().then(run)),\n ).then((results) => {\n for (const result of results) {\n if (result.status === \"rejected\") reportAfter(result.reason);\n }\n });\n}\n\n/** The reads caught at a boundary during this render, with their components. */\nexport function requestFallbacks(): string[] {\n return scope()?.getStore()?.fallbacks ?? [];\n}\n\n/**\n * A component called a cache()-wrapped helper. Recorded on every call, hit\n * or miss, so a read the helper makes can name everyone who waited for it.\n */\nexport function noteAwaiter(helper: unknown): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n const { name } = caller(\"cache\");\n\n if (!name) return;\n\n store.awaiters ??= new Map();\n\n const list = store.awaiters.get(helper) ?? [];\n\n if (!list.includes(name)) list.push(name);\n\n store.awaiters.set(helper, list);\n}\n\n/** Run a cache()-wrapped helper's body, so a read inside it is filed under the helper. */\nexport function withHelper<T>(helper: unknown, run: () => T): T {\n const store = scope()?.getStore();\n\n if (!store) return run();\n\n const before = store.inHelper;\n\n store.inHelper = helper;\n\n try {\n return run();\n } finally {\n store.inHelper = before;\n }\n}\n\n/**\n * The same reads, each with the component that made it: `cookies() in\n * RootLayout`. A read inside a cached helper with more than one awaiter\n * names them all - `connection() awaited by AuthLinks, AuthDialogSlot` -\n * because the stack saw only the first, and the first is rarely the one\n * that blocks.\n */\nexport function requestReadWhere(): string[] {\n const store = scope()?.getStore();\n\n if (!store?.readWhere?.length) return store?.readBy ?? [];\n\n return store.readWhere.map((entry) => {\n const helper = store.readVia?.get(entry);\n const awaiters = helper ? store.awaiters?.get(helper) : undefined;\n\n if (!awaiters || awaiters.length < 2) return entry;\n\n const names =\n awaiters.length === 2\n ? awaiters.join(\" and \")\n : awaiters.slice(0, -1).join(\", \") + \" and \" + awaiters.at(-1);\n\n return `${entry.split(\" in \")[0]} awaited by ${names}`;\n });\n}\n\n/**\n * The query string, as a page receives it.\n *\n * Derived from the request rather than passed down the render, so no host has\n * to forward it separately — and so it suspends during a build for the same\n * reason every other read does. A frozen page cannot know the query it will be\n * asked for.\n */\nexport async function searchParams(): Promise<URLSearchParams> {\n // Named before the await, so the build reports the call someone wrote rather\n // than url(), which this happens to be built on.\n const store = slot();\n\n if (!store.request && !store.readBy.includes(\"searchParams()\")) {\n store.readBy.push(\"searchParams()\");\n }\n\n const from = await url();\n\n return from ? new URL(from).searchParams : new URLSearchParams();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,EAAE;AACF,6DAA6D;AAC7D,EAAE;AACF,iDAAiD;AACjD,mGAAmG;AACnG,mCAAmC;AACnC,MAAM;AACN,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,iBAAiB;AACjB,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,6EAA6E;AAC7E,qDAAqD;AACrD,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,+EAA+E;AAC/E,4EAA4E;AAC5E,yEAAyE;AACzE,0EAA0E;AAC1E,gDAAgD;AAChD,EAAE;AACF,yEAAyE;AACzE,0CAA0C;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmE/C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,OAAO;IACP,OAAO;IACP,aAAa;IACb,YAAY;IACZ,iBAAiB;IACjB,YAAY;IACZ,QAAQ;IACR,MAAM;IACN,SAAS;IACT,SAAS;IACT,YAAY;IACZ,cAAc;IACd,SAAS;IACT,KAAK;IACL,aAAa;IACb,mBAAmB;IACnB,WAAW;IACX,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC,CAAC;AAEH,mGAAmG;AACnG,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,SAAS;IACT,SAAS;IACT,YAAY;IACZ,cAAc;IACd,SAAS;IACT,KAAK;CACN,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,SAAS,MAAM,CAAC,GAAW;IACzB,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;IACtC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,MAAM,GAAkB,IAAI,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEvD,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,CAAC;QAEzC,0EAA0E;QAC1E,mCAAmC;QACnC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAErC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS,EAAE,CAAC;QACrC,IACE,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;YACtB,IAAI,KAAK,aAAa;YACtB,IAAI,KAAK,QAAQ;YACjB,IAAI,KAAK,SAAS;YAElB,SAAS;QAEX,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAExD,kEAAkE;QAClE,wEAAwE;QACxE,uEAAuE;QACvE,yEAAyE;QACzE,+BAA+B;QAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,MAAM,KAAK,IAAI,CAAC;YAEhB,SAAS;QACX,CAAC;QAED,OAAO;YACL,IAAI,EAAE,MAAM,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI;YACnE,MAAM;SACP,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,UAAU,CAAC,KAAW,EAAE,EAAU;IACzC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEtD,qEAAqE;IACrE,KAAK,CAAC,SAAS,KAAK,EAAE,CAAC;IAEvB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAEzD,IAAI,MAAM;QAAE,OAAO;IAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7C,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClE,IAAI,KAAK,CAAC,QAAQ;QAAE,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,OAAO,GAAG,UAA8C,CAAC;AAE/D,IAAI,KAAK,GAAyB,IAAI,CAAC;AAOvC,SAAS,KAAK;IACZ,OAAQ,OAAO,CAAC,KAAK,CAAuB,IAAI,IAAI,CAAC;AACvD,CAAC;AAED,SAAS,IAAI;IACX,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,wFAAwF;YACtF,oDAAoD,CACvD,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAElB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;IAErB,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AAC5D,CAAC;AA+ED,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;AAEzD,IAAI,UAAU,GAAyB,IAAI,CAAC;AAO5C,SAAS,KAAK;IACZ,OAAQ,OAAO,CAAC,KAAK,CAA4B,IAAI,IAAI,CAAC;AAC5D,CAAC;AAED,iEAAiE;AACjE,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,IAAI,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAEjC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,oFAAoF;YACzF,sCAAsC,CACzC,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,iFAAiF;YACtF,sFAAsF;YACtF,iBAAiB,CACpB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH;;;;;;;;;GASG;AACH,SAAS,QAAQ,CAAC,KAAY;IAC5B,MAAM,KAAK,GACT,CAAC,MAAmC,EAAE,EAAE,CACxC,CAAC,GAAG,IAAsB,EAAE,EAAE;QAC5B,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QAE9B,OAAQ,KAAK,CAAC,OAAO,CAAC,MAAM,CAA8B,CAAC,GAAG,IAAI,CAAC,CAAC;IACtE,CAAC,CAAC;IAEJ,MAAM,KAAK,GAAY,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE;QAC9C,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ;YAC5B,IACE,QAAQ,KAAK,KAAK;gBAClB,QAAQ,KAAK,QAAQ;gBACrB,QAAQ,KAAK,QAAQ,EACrB,CAAC;gBACD,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;YAED,oEAAoE;YACpE,kEAAkE;YAClE,sEAAsE;YACtE,sEAAsE;YACtE,WAAW;YACX,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO,CACL,EAAyD,EACzD,OAAiB,EACjB,EAAE,CACF,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;YACxE,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAEtD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAClE,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAsE;IAEtE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,UAAU,KAAK,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC9C,OAAO,CAAC,KAAK,CAAC,KAAK,QAAiC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAU,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IAElF,OAAO,MAAM,KAAK,EAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,CACnC,GAAG,CAAC;QACF,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO;QACzB,IAAI,EAAE,GAAG,EAAE;YACT,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,GAAG,gCAAgC,CAAC;AAErD,2EAA2E;AAC3E,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAEpC,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,MAI/B;IACC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,6BAA6B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;YAC1D,4EAA4E;YAC5E,oFAAoF,CACvF,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QAE5D,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAClE,sFAAsF,CACzF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI;QAC/B,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;QAC7B,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;KACzB,EAAE,CAAC;QACX,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CACb,cAAc,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,yBAAyB;gBACvE,yEAAyE,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,2EAA2E;IAC3E,0EAA0E;IAC1E,4CAA4C;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;IAEtD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,sBAAsB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,yBAAyB;YACpE,yEAAyE,CAC5E,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrE,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;IAEzB,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1E,IAAI,CAAC,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAChE,4EAA4E;IAC5E,2EAA2E;IAC3E,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,CAAC,QAAQ;QACZ,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9E,IAAI,CAAC,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvC,IAAI,CAAC,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE7C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,6EAA6E;IAC7E,0EAA0E;IAC1E,qCAAqC;IACrC,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;IAErB,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,UAAU,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAEnE,wEAAwE;IACxE,wEAAwE;IACxE,MAAM,GAAG,GAAG,GAA2B,EAAE;QACvC,MAAM,OAAO,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,CAAC;QAE7C,IAAI,CAAC,OAAO,EAAE,IAAI;YAAE,OAAO,MAAM,CAAC;QAElC,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;QAE7B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;YACpC,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;;gBACnC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC5B,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CACZ,IAAY,EACZ,KAAa,EACb,OAAO,GAAkB,EAAE,EACrB,EAAE;QACR,MAAM,IAAI,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC;QAEzC,mEAAmE;QACnE,+DAA+D;QAC/D,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAE7E,iEAAiE;QACjE,MAAM,IAAI,GACR,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QAEhI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC,CAAC;IAEF,OAAO;QACL,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;YAEtB,sDAAsD;YACtD,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACnF,CAAC;QACD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC;QACzC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7E,GAAG,EAAE,CAAC,YAAsD,EAAE,KAAc,EAAE,OAAuB,EAAE,EAAE;YACvG,IAAI,OAAO,YAAY,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;YAEvF,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,YAAY,CAAC;YAEjD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC;QACD,wEAAwE;QACxE,+DAA+D;QAC/D,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;KAC3E,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;IAErB,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;IAErB,uEAAuE;IACvE,8BAA8B;IAC9B,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC,cAAc,CAAC,CAAC;AACnD,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;IAErB,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,GAAG,GAA2B,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,SAAS;QAExB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAEtC,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,uEAAuE;QACvE,2DAA2D;QAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEtC,IAAI,CAAC;YACH,GAAG,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAiB,EACjB,GAAqB;IAErB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,KAAK,KAAK,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YACzC,OAAO,CAAC,KAAK,CAAC,KAAK,QAA4B,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,YAAY,OAAO,CAAC;IAC1C,MAAM,KAAK,GAAS;QAClB,OAAO,EAAE,IAAI,KAAK,IAAI;QACtB,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;QACpD,OAAO,EAAE,IAAI;YACX,CAAC,CAAC,SAAS;gBACT,CAAC,CAAC,IAAI,CAAC,OAAO;gBACd,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAC7B,CAAC,CAAC,IAAI,OAAO,EAAE;QACjB,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QACjC,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,EAAE;QACb,SAAS,EAAE,EAAE;QACb,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,KAAK,EAAE,EAAE;KACV,CAAC;IAEF,OAAO,MAAM,KAAK,EAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAI,IAAY,EAAE,GAAqB;IAClE,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;IAErB,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO,MAAM,GAAG,EAAE,CAAC;IAEvC,OAAO,MAAM,KAAK,EAAG,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAEvD,mEAAmE;AACnE,MAAM,UAAU,KAAK,CAAC,OAAgB;IACpC,OAAO,CAAE,OAA0D,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC;AAChG,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;IAErB,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtB,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,IAAI,IAAI,KAAK,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,KAAK,CAAC,SAAS,KAAK,EAAE,CAAC;IAEvB,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,KAAK,CAAC,IAAmB;IACvC,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7B,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAErD,OAAO;IACT,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAEnC,OAAO,OAAO,CAAC,UAAU,CACvB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAC/C,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QACjB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU;gBAAE,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,SAAS,IAAI,EAAE,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAe;IACzC,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAEjC,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,KAAK,CAAC,QAAQ,KAAK,IAAI,GAAG,EAAE,CAAC;IAE7B,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAE9C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE1C,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,UAAU,CAAI,MAAe,EAAE,GAAY;IACzD,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,EAAE,CAAC;IAEzB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC;IAE9B,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC;IAExB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC;IACf,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,KAAK,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC;IAElC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM;QAAE,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC;IAE1D,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAElE,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAEnD,MAAM,KAAK,GACT,QAAQ,CAAC,MAAM,KAAK,CAAC;YACnB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;YACxB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAEnE,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe,KAAK,EAAE,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,6EAA6E;IAC7E,iDAAiD;IACjD,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;IAErB,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC/D,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,EAAE,CAAC;IAEzB,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC;AACnE,CAAC","sourcesContent":["// Reading the request from inside a render.\n//\n// import { headers, cookies } from '@rsc-kit/core/request'\n//\n// export default async function middleware() {\n// const locale = cookies().get('locale')?.value ?? negotiate(headers().get('accept-language'))\n// if (!locale) redirect('/en')\n// }\n//\n// Server components have no arguments beyond their props, and middleware has\n// none at all, so without this an app on a JavaScript host cannot see a header\n// — no locale negotiation, no subdomain, no cookie. The Laravel host escaped\n// that through rpc(), because PHP has the request; this is the same thing for\n// everyone else.\n//\n// Read-only on purpose. Setting a cookie means writing a response header, and\n// by the time a component renders the shell may already have been flushed — an\n// API that appears to set one and silently does not is worse than not having\n// it. Set them in the host, which owns the response.\n//\n// Asynchronous on purpose too, and not for ergonomics. A build has no request,\n// so a read there suspends and never settles — which is the same thing the\n// prerender probe does to a host call. Anything still waiting when the probe's\n// budget expires becomes a fallback in the frozen shell, so a read inside a\n// Suspense boundary leaves the shell frozen and makes only that boundary\n// dynamic. Reading synchronously could only mark the whole route dynamic,\n// because there would be nothing to suspend on.\n//\n// Scoped to the request, on the same store cache() uses. Two requests in\n// flight cannot see each other's headers.\n\nimport { resolveScope } from \"./revalidate.js\";\n\n/** What a host can supply: a real Request, or the parts of one. */\nexport type RequestLike =\n Request | { url: string; headers: Record<string, string> } | null;\n\ninterface Slot {\n /** False during a build: there is nothing to answer with. */\n request: boolean;\n url: string | null;\n /**\n * Held as Headers rather than as a Request.\n *\n * `new Request(url, { headers })` drops Cookie: a spec-compliant Headers\n * built with the \"request\" guard refuses the forbidden header names, and\n * Cookie is one of them. `new Headers()` has no guard and keeps it. Bun\n * happens to allow both, which is why rebuilding a Request looked fine until\n * it ran anywhere stricter — and what it loses is every cookie, silently.\n */\n headers: Headers;\n original: Request | null;\n /**\n * Whether anything asked. Only for the build's report — the classification\n * comes from the suspension, not from this.\n */\n read: boolean;\n /**\n * What read it, in the order they did.\n *\n * Only the name of the accessor — `cookies()`, `headers()` — which is enough\n * for the build to say why a page could not be frozen. Without it the answer\n * is \"something in this page reached for the request\", and finding which is\n * the part that takes an afternoon.\n */\n readBy: string[];\n /**\n * The same reads with the component that made each one - `cookies() in\n * RootLayout` - taken from the stack at the moment of the read, which is\n * still the component's own call: an accessor runs synchronously up to\n * the point it suspends. Only the build reads this. \"Reads the request\" is\n * a category; this is the line to open.\n */\n readWhere: string[];\n /**\n * Reads the server could not answer and React caught at a boundary - the\n * fallback is what got stored - with the component that made each:\n * `useSearchParams() in Query`. Noted by the SSR entry, read by the build,\n * which attaches them to the route so a page stored as its own loading\n * screen says why.\n */\n fallbacks: string[];\n /**\n * For a read made inside a cache()-wrapped helper: the components that\n * awaited that helper, first caller included. The helper runs once, so\n * the stack at the read names only whoever got there first; every later\n * awaiter is a cache hit that never reaches the accessor. The one above\n * every boundary is usually one of the later ones.\n */\n awaiters: Map<unknown, string[]>;\n /** The cache()-wrapped helper whose body is running, while it runs. */\n inHelper: unknown;\n /** readWhere entry -> the helper it was read inside. */\n readVia: Map<string, unknown>;\n /** Work to run once the answer is on its way - see after(). */\n after: (() => unknown)[];\n}\n\nconst SCOPE = Symbol.for(\"@rsc-kit/core.request-scope\");\n\n/**\n * The accessors themselves and the plumbing under them: frames to walk past\n * on the way to the component that called.\n */\nconst NOT_A_CALLER = new Set([\n \"never\",\n \"cache\",\n \"noteAwaiter\",\n \"withHelper\",\n \"noteRequestRead\",\n \"recordRead\",\n \"caller\",\n \"slot\",\n \"cookies\",\n \"headers\",\n \"connection\",\n \"searchParams\",\n \"request\",\n \"url\",\n \"parseParams\",\n \"parseSearchParams\",\n \"parseBody\",\n \"get\",\n \"set\",\n \"has\",\n]);\n\n/** The accessors a component calls by name. One calling another is plumbing, not a second read. */\nconst ACCESSORS = new Set([\n \"cookies\",\n \"headers\",\n \"connection\",\n \"searchParams\",\n \"request\",\n \"url\",\n]);\n\n/**\n * The nearest named function above the accessor on the stack, and whether\n * another accessor sits between: `cookies()` reads through `headers()`, and\n * that inner read is not a second thing the component did.\n *\n * Read from a thrown-away Error: the one thing a build cannot otherwise learn\n * is which component reached for the request, and the stack knows. Function\n * names survive a server bundle, which is not minified, so this is\n * `RootLayout` and not a line number in a chunk. Internal names are walked\n * past; an anonymous frame is skipped rather than reported as `<anonymous>`.\n */\nfunction caller(own: string): { name: string | null; nested: boolean } {\n const stack = new Error().stack ?? \"\";\n let accessors = 0;\n let helper: string | null = null;\n\n for (const line of stack.split(\"\\n\")) {\n const match = /^\\s*at (?:async )?([^\\s(]+)/.exec(line);\n\n if (!match) continue;\n\n const name = match[1]!.split(\".\").pop()!;\n\n // A frame with no function name prints its location instead - `js:6054:8`\n // - which is not a name to report.\n if (!/^[\\w$]+$/.test(name)) continue;\n\n if (ACCESSORS.has(name)) accessors++;\n if (\n NOT_A_CALLER.has(name) ||\n name === \"<anonymous>\" ||\n name === \"Object\" ||\n name === \"Promise\"\n )\n continue;\n\n const nested = accessors > (ACCESSORS.has(own) ? 1 : 0);\n\n // A function that is not a component - getCurrentUser, wrapped in\n // cache() - is the shared helper the read lives in. Named, because with\n // cache() the read runs once, on whichever component called first, and\n // every other caller of the helper is invisible to the stack. The helper\n // is what they have in common.\n if (/^[a-z_$]/.test(name) && !/^use[A-Z]/.test(name)) {\n helper ??= name;\n\n continue;\n }\n\n return {\n name: helper && helper !== name ? `${helper} (from ${name})` : name,\n nested,\n };\n }\n\n return { name: helper, nested: accessors > (ACCESSORS.has(own) ? 1 : 0) };\n}\n\nfunction recordRead(store: Slot, by: string): void {\n if (!store.readBy.includes(by)) store.readBy.push(by);\n\n // Older stores, written by a bundle built before this field existed.\n store.readWhere ??= [];\n\n const { name, nested } = caller(by.replace(/\\(.*$/, \"\"));\n\n if (nested) return;\n\n const entry = name ? `${by} in ${name}` : by;\n\n if (!store.readWhere.includes(entry)) store.readWhere.push(entry);\n if (store.inHelper) (store.readVia ??= new Map()).set(entry, store.inHelper);\n}\n\nconst globals = globalThis as Record<symbol | string, unknown>;\n\nlet ready: Promise<void> | null = null;\n\ninterface Scope {\n getStore(): Slot | undefined;\n run<T>(store: Slot, fn: () => T): T;\n}\n\nfunction scope(): Scope | null {\n return (globals[SCOPE] as Scope | undefined) ?? null;\n}\n\nfunction slot(): Slot {\n const store = scope()?.getStore();\n\n if (!store) {\n throw new Error(\n \"No request in scope. headers() and cookies() are for a render — middleware, a layout, \" +\n \"a page — and there is nothing to read outside one.\",\n );\n }\n\n store.read = true;\n\n return store;\n}\n\n/**\n * The request's headers.\n *\n * Empty during a build, where there is no request: the page is marked as\n * needing one instead, and rendered on demand rather than frozen.\n */\nexport async function headers(): Promise<Headers> {\n const store = slot();\n\n return store.request ? store.headers : never(\"headers()\");\n}\n\n/** How a cookie should be written. The names browsers use. */\nexport interface CookieOptions {\n path?: string;\n domain?: string;\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n partitioned?: boolean;\n}\n\n/** One cookie as the request carried it: the shape Next's `cookies().get()` returns. */\nexport interface RequestCookie {\n name: string;\n value: string;\n}\n\n/**\n * The cookie jar, in the shape Next's `cookies()` has.\n *\n * `get()` returns `{ name, value }` rather than the string, because the guide\n * says \"the same names from `@rsc-kit/core/request`\" and a name that is the\n * same with a different return shape is the worst of both: ported code\n * reading `?.value` off a string got `undefined`, silently. `getAll()` is a\n * list for the same reason, and because a list composes where a record does\n * not.\n */\nexport interface Cookies {\n get(name: string): RequestCookie | undefined;\n has(name: string): boolean;\n getAll(): RequestCookie[];\n /**\n * Write one on the response.\n *\n * Only from a server action, which has a response of its own that has not\n * been sent. A render has already flushed its headers by the time a\n * component runs — that is what makes the first paint fast — so this throws\n * there rather than appearing to work.\n *\n * Either call shape Next takes: `set(name, value, options)` or\n * `set({ name, value, ...options })`.\n */\n set(name: string, value: string, options?: CookieOptions): void;\n set(cookie: RequestCookie & CookieOptions): void;\n /** Write one that expires immediately. Same rule about where. */\n delete(name: string, options?: CookieOptions): void;\n}\n\n/** Kept for the name it had when it could only read. */\nexport type ReadonlyCookies = Cookies;\n\n/**\n * The response being built, while it can still be changed.\n *\n * Open from the moment a request is picked up until the host constructs its\n * Response, and sealed the instant it does. Middleware runs inside that window\n * — before any rendering starts — so a header set there is on the answer. A\n * component runs after it, during streaming, where the status line and headers\n * are already on the wire; setting one there is refused rather than dropped.\n */\ninterface Draft {\n headers: Headers;\n sealed: boolean;\n /**\n * What this request wrote to the jar, over what it arrived with: a value,\n * or null for a deletion. Read back by `cookies()` for the rest of the\n * request, so a render that follows the write - the sections an action\n * revalidates travel back with its answer, rendered in the same request -\n * sees what the browser is about to hold. Next has the same rule, which\n * is why `set` then `revalidate` is what every port writes; without it\n * the sidebar re-rendered with the cookie the request arrived with, and\n * showed the old choice until a reload.\n */\n cookies: Map<string, string | null>;\n}\n\nconst DRAFT = Symbol.for(\"@rsc-kit/core.response-draft\");\n\nlet draftReady: Promise<void> | null = null;\n\ninterface DraftScope {\n getStore(): Draft | undefined;\n run<T>(store: Draft, fn: () => T): T;\n}\n\nfunction draft(): DraftScope | null {\n return (globals[DRAFT] as DraftScope | undefined) ?? null;\n}\n\n/** The open draft, or an explanation of why there is not one. */\nfunction writable(what: string): Draft {\n const open = draft()?.getStore();\n\n if (!open) {\n throw new Error(\n `${what} needs a response that has not been sent. Middleware and server actions have one; ` +\n \"a script outside a request does not.\",\n );\n }\n\n if (open.sealed) {\n throw new Error(\n `${what} was called after the response had been sent. Headers go out before the render ` +\n \"starts — that is what makes the first paint fast — so set them in middleware, which \" +\n \"runs before it.\",\n );\n }\n\n return open;\n}\n\n/**\n * Headers to put on the answer.\n *\n * Mutate it as you would any Headers. `append` is the one to reach for when a\n * header may legitimately appear twice; `set` replaces.\n */\n/**\n * The draft's headers, refusing writes once the response has gone.\n *\n * A proxy rather than the Headers itself: returning the live object means code\n * that captured it before the response was built can go on mutating a thing\n * nobody will read. Nothing in this package does that — the host copies the\n * headers onto the response the instant it seals — but \"safe because of the\n * order two other functions happen to run in\" is not a property, and an app\n * holding the object across an await would find writes silently doing nothing.\n */\nfunction sealable(draft: Draft): Headers {\n const guard =\n (method: \"set\" | \"append\" | \"delete\") =>\n (...args: [string, string]) => {\n writable(\"responseHeaders()\");\n\n return (draft.headers[method] as (...a: string[]) => void)(...args);\n };\n\n const proxy: Headers = new Proxy(draft.headers, {\n get(target, property, receiver) {\n if (\n property === \"set\" ||\n property === \"append\" ||\n property === \"delete\"\n ) {\n return guard(property);\n }\n\n // A maplike forEach passes the object it was called on as the third\n // callback argument, and binding to the target makes that the raw\n // Headers — a live, unguarded reference handed out by the very method\n // meant to be read-only. Substituted for the proxy so there is no way\n // through.\n if (property === \"forEach\") {\n return (\n fn: (value: string, key: string, parent: Headers) => void,\n thisArg?: unknown,\n ) =>\n target.forEach((value, key) => fn.call(thisArg, value, key, proxy));\n }\n\n const value = Reflect.get(target, property, receiver);\n\n return typeof value === \"function\" ? value.bind(target) : value;\n },\n });\n\n return proxy;\n}\n\nexport function responseHeaders(): Headers {\n return sealable(writable(\"responseHeaders()\"));\n}\n\n/**\n * Run a request with a response that can still be changed, and take what was\n * put on it.\n *\n * `seal()` is called by the host the moment it builds the Response, so\n * anything set afterwards is refused instead of silently going nowhere.\n */\nexport async function withResponseDraft<T>(\n run: (draft: { taken: () => Headers; seal: () => void }) => Promise<T>,\n): Promise<T> {\n if (!globals[DRAFT]) {\n draftReady ??= resolveScope().then((resolved) => {\n globals[DRAFT] ??= resolved as unknown as DraftScope;\n });\n\n await draftReady;\n }\n\n const open: Draft = { headers: new Headers(), sealed: false, cookies: new Map() };\n\n return await draft()!.run(open, () =>\n run({\n taken: () => open.headers,\n seal: () => {\n open.sealed = true;\n },\n }),\n );\n}\n\n/**\n * A cookie name, as RFC 6265 defines one: a token, so no separators at all.\n *\n * Checked rather than escaped because there is no escaping — a name is not a\n * quoted string. An app that derives one from user input (`pref_${key}`) would\n * otherwise let that input close the pair and open another: a name of\n * `session=attacker; Path=/; HttpOnly; x` serializes to a header whose *first*\n * pair is a session cookie the caller chose, and the browser reads the first.\n */\nconst COOKIE_NAME = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n\n/** No separator may appear in an attribute either, for the same reason. */\nconst COOKIE_ATTRIBUTE = /[;,\\r\\n]/;\n\n/** `name=value; Path=/; HttpOnly` — the header a browser expects. */\nexport function serializeCookie(cookie: {\n name: string;\n value: string;\n options: CookieOptions;\n}): string {\n if (!COOKIE_NAME.test(cookie.name)) {\n throw new Error(\n `Not a usable cookie name: ${JSON.stringify(cookie.name)}. ` +\n \"A name is a token — letters, digits and !#$%&'*+-.^_`|~ — with no spaces, \" +\n \"semicolons or equals signs. Nothing escapes them, so one cannot be encoded around.\",\n );\n }\n\n if (cookie.options.sameSite !== undefined) {\n const value = String(cookie.options.sameSite).toLowerCase();\n\n if (value !== \"strict\" && value !== \"lax\" && value !== \"none\") {\n throw new Error(\n `Not a SameSite value: ${JSON.stringify(cookie.options.sameSite)}. ` +\n \"It is written into the header as given, so anything else becomes further attributes.\",\n );\n }\n }\n\n for (const [attribute, value] of [\n [\"path\", cookie.options.path],\n [\"domain\", cookie.options.domain],\n ] as const) {\n if (typeof value === \"string\" && COOKIE_ATTRIBUTE.test(value)) {\n throw new Error(\n `The cookie ${attribute} ${JSON.stringify(value)} contains a separator. ` +\n \"It would be read as further attributes rather than as part of this one.\",\n );\n }\n }\n\n // Typed as a Date, but a cast reaches this and the result lands in the\n // header verbatim. Checked apart from the others because a date has commas\n // in it by definition - \"Sun, 20 Sep 2026 14:49:56 GMT\" - and the general\n // check refused every Expires ever written.\n const expires = cookie.options.expires?.toUTCString();\n\n if (typeof expires === \"string\" && /[;\\r\\n]/.test(expires)) {\n throw new Error(\n `The cookie expires ${JSON.stringify(expires)} contains a separator. ` +\n \"It would be read as further attributes rather than as part of this one.\",\n );\n }\n\n const parts = [`${cookie.name}=${encodeURIComponent(cookie.value)}`];\n const o = cookie.options;\n\n if (o.maxAge !== undefined) parts.push(`Max-Age=${Math.floor(o.maxAge)}`);\n if (o.expires) parts.push(`Expires=${o.expires.toUTCString()}`);\n // Defaulted, because a cookie without one is scoped to the path that set it\n // — a session written by POST /_rsc/action would not be sent for any page.\n parts.push(`Path=${o.path ?? \"/\"}`);\n if (o.domain) parts.push(`Domain=${o.domain}`);\n if (o.sameSite)\n parts.push(`SameSite=${o.sameSite[0].toUpperCase()}${o.sameSite.slice(1)}`);\n if (o.secure) parts.push(\"Secure\");\n if (o.httpOnly) parts.push(\"HttpOnly\");\n if (o.partitioned) parts.push(\"Partitioned\");\n\n return parts.join(\"; \");\n}\n\nexport async function cookies(): Promise<Cookies> {\n // Named before the await, because `headers()` never settles during a build —\n // nothing after this line runs there, and the reason would be recorded as\n // headers() for a call nobody wrote.\n const store = slot();\n\n if (!store.request) recordRead(store, \"cookies()\");\n\n const parsed = parseCookies((await headers()).get(\"cookie\") ?? \"\");\n\n // What arrived, then what this request wrote over it. Read at each call\n // rather than once: a write between two reads is the case that matters.\n const jar = (): Record<string, string> => {\n const written = draft()?.getStore()?.cookies;\n\n if (!written?.size) return parsed;\n\n const merged = { ...parsed };\n\n for (const [name, value] of written) {\n if (value === null) delete merged[name];\n else merged[name] = value;\n }\n\n return merged;\n };\n\n const write = (\n name: string,\n value: string,\n options: CookieOptions = {},\n ): void => {\n const open = writable(\"cookies().set()\");\n\n // Appended, never set: several cookies on one response are several\n // Set-Cookie headers, and replacing would leave only the last.\n open.headers.append(\"Set-Cookie\", serializeCookie({ name, value, options }));\n\n // A cookie told to expire is one the browser will not send back.\n const gone =\n options.maxAge !== undefined ? options.maxAge <= 0 : options.expires !== undefined && options.expires.getTime() <= Date.now();\n\n open.cookies.set(name, gone ? null : value);\n };\n\n return {\n get: (name) => {\n const current = jar();\n\n // Own keys only: `in` found \"constructor\" in any jar.\n return Object.hasOwn(current, name) ? { name, value: current[name] } : undefined;\n },\n has: (name) => Object.hasOwn(jar(), name),\n getAll: () => Object.entries(jar()).map(([name, value]) => ({ name, value })),\n set: (nameOrCookie: string | (RequestCookie & CookieOptions), value?: string, options?: CookieOptions) => {\n if (typeof nameOrCookie === \"string\") return write(nameOrCookie, value ?? \"\", options);\n\n const { name, value: v, ...rest } = nameOrCookie;\n\n return write(name, v, rest);\n },\n // Expired rather than removed: a browser drops a cookie when it is told\n // one has already passed, and there is no other way to say it.\n delete: (name, options = {}) => write(name, \"\", { ...options, maxAge: 0 }),\n };\n}\n\n/**\n * The whole request, for a host-specific need the accessors do not cover.\n *\n * Null on a host that forwards only the parts — the worker behind Laravel has\n * a socket, not a request. Use headers() and cookies(), which work everywhere.\n */\nexport async function request(): Promise<Request | null> {\n const store = slot();\n\n return store.request ? store.original : never(\"request()\");\n}\n\n/**\n * Mark everything below as belonging to the request, not to the build.\n *\n * export default async function Orders() {\n * await connection()\n *\n * const rows = await db.query('select * from orders')\n *\n * return <ul>{rows.map(...)}</ul>\n * }\n *\n * At build time this never resolves, so nothing after it runs: the query is not\n * made, the boundary above becomes a hole, and the rest of the page still\n * freezes. At request time it resolves immediately and the component runs\n * normally.\n *\n * **Once is enough.** It is a barrier, not a wrapper — everything after it in\n * this component belongs to the request, however many calls that is. Repeating\n * it before each query does nothing.\n *\n * It needs a boundary above it. With a <Suspense> or a loading.tsx there is a\n * fallback to store and the page becomes a shell; with neither, nothing can\n * paint and the build refuses the route rather than storing a blank.\n *\n * Reach for it when the build should not run something — a database the build\n * machine cannot see, or a value that must differ per visitor. A query the\n * build CAN run, whose answer is the same for everyone, wants none of this: it\n * should be frozen.\n *\n * The same name and behaviour as Next's `connection()`.\n */\nexport async function connection(): Promise<void> {\n const store = slot();\n\n // No request means a build. Suspend rather than continue, the same way\n // headers() and cookies() do.\n if (!store.request) return never(\"connection()\");\n}\n\n/** The url this request was made to, whichever way the host supplied it. */\nexport async function url(): Promise<string | null> {\n const store = slot();\n\n return store.request ? store.url : never(\"url()\");\n}\n\nfunction parseCookies(header: string): Record<string, string> {\n const out: Record<string, string> = {};\n\n for (const part of header.split(\";\")) {\n const eq = part.indexOf(\"=\");\n\n if (eq === -1) continue;\n\n const name = part.slice(0, eq).trim();\n\n if (!name) continue;\n\n // Decoded because that is how they were written. A malformed escape is\n // left as it arrived rather than throwing the render away.\n const raw = part.slice(eq + 1).trim();\n\n try {\n out[name] = decodeURIComponent(raw);\n } catch {\n out[name] = raw;\n }\n }\n\n return out;\n}\n\n/**\n * Run one request with its headers readable.\n *\n * `null` is the build: a scope with nothing in it, so a page that reads is\n * caught rather than silently frozen holding whatever the machine that built\n * it happened to send.\n */\nexport async function withRequest<T>(\n from: RequestLike,\n run: () => Promise<T>,\n): Promise<T> {\n if (!globals[SCOPE]) {\n ready ??= resolveScope().then((resolved) => {\n globals[SCOPE] ??= resolved as unknown as Scope;\n });\n\n await ready;\n }\n\n const isRequest = from instanceof Request;\n const store: Slot = {\n request: from !== null,\n url: from ? (isRequest ? from.url : from.url) : null,\n headers: from\n ? isRequest\n ? from.headers\n : new Headers(from.headers)\n : new Headers(),\n original: isRequest ? from : null,\n read: false,\n readBy: [],\n readWhere: [],\n fallbacks: [],\n awaiters: new Map(),\n inHelper: null,\n readVia: new Map(),\n after: [],\n };\n\n return await scope()!.run(store, run);\n}\n\n/**\n * Run a render with a different url, the request otherwise unchanged.\n *\n * An action's response renders what it revalidated for the page it was called\n * from. The request is the action's POST, whose url is the endpoint's; the\n * page's query string lives in the page's url. A slot on /agent/test?c=25\n * re-rendered after a message was sent read the POST's empty query - through\n * searchParams() and through the page's own searchParams prop, which is built\n * on it - and came back as a new chat. Headers and cookies stay the request's:\n * it is the same visitor, asking about a different url.\n */\nexport async function withUrl<T>(href: string, run: () => Promise<T>): Promise<T> {\n const store = slot();\n\n if (!store.request) return await run();\n\n return await scope()!.run({ ...store, url: href }, run);\n}\n\n/**\n * A promise that never settles, so the caller suspends.\n *\n * What a read does during a build. React treats it exactly as it treats a host\n * call that never answers: the component suspends, its Suspense fallback goes\n * into the shell, and the probe's budget decides the rest.\n */\n/**\n * The build's probe hands a route a Request that records what is read out of\n * it, and a read of `url` marks the route as depending on the caller — the\n * Next way to read a query is `new URL(request.url).searchParams`, which the\n * probe cannot otherwise see. The engine itself reads the url to resolve the\n * awaited `searchParams`, and that read is accounted for by `searchParams`,\n * not by `url`; this is the door it goes through. A probe answers the real\n * Request to this key; anything else answers nothing, and the request is its\n * own.\n */\nexport const UNPROBED = Symbol.for(\"rsc-kit.unprobed\");\n\n/** The request's url, read by the engine rather than the route. */\nexport function urlOf(request: Request): string {\n return ((request as unknown as Record<symbol, Request | undefined>)[UNPROBED] ?? request).url;\n}\n\n/**\n * Record a read without suspending on it.\n *\n * For a reader that CAN answer during a build but whose answer would be wrong\n * to store — an api route's query string, which exists and is empty, and which\n * the build has no business freezing an answer to. `never()` is for a reader\n * with nothing to return; this is for one that has something and should still\n * be noticed.\n *\n * A no-op outside a render scope, so a handler called at request time pays a\n * property read and nothing else.\n */\nexport function noteRequestRead(by: string): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n recordRead(store, by);\n}\n\nfunction never(by: string): Promise<never> {\n const store = slot();\n\n store.read = true;\n recordRead(store, by);\n\n return new Promise(() => {});\n}\n\n/**\n * Whether anything read the request during the scope that is open.\n *\n * For the prerenderer, which opens one with no request and asks afterwards.\n */\nexport function requestWasRead(): boolean {\n return scope()?.getStore()?.read ?? false;\n}\n\n/**\n * What reached for the request during the scope that is open.\n *\n * For the build, which asks afterwards so it can say why a page is rendered per\n * visitor rather than only that it is.\n */\nexport function requestReadBy(): string[] {\n return scope()?.getStore()?.readBy ?? [];\n}\n\n/** A read React caught at a boundary during SSR: `useSearchParams() in Query`. */\nexport function noteFallback(text: string): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n store.fallbacks ??= [];\n\n if (!store.fallbacks.includes(text)) store.fallbacks.push(text);\n}\n\n/**\n * Run something once the answer is on its way, without making it wait.\n *\n * Logging, an audit row, an email, a cache warm: work the visitor should not\n * pay for, and that must still finish. Next's `after()`, and needed for the\n * same reason on every host: on a long-lived process a detached promise\n * happens to run to completion, but a Worker tears the isolate down when the\n * response ends unless the work is registered with the platform's\n * `waitUntil` - so a fire-and-forget promise there dies silently, some of\n * the time. The host hands these to `waitUntil` where one exists and runs\n * them detached where a process will keep them.\n *\n * From a component, a middleware, a server action or an api route. A\n * rejection is reported and never reaches the response, which has already\n * gone. Outside a request - a build - the work runs at once.\n */\nexport function after(work: () => unknown): void {\n const store = scope()?.getStore();\n\n if (!store || !store.request) {\n void Promise.resolve().then(work).catch(reportAfter);\n\n return;\n }\n\n store.after.push(work);\n}\n\nfunction reportAfter(error: unknown): void {\n console.error(\"[rsc-kit] after() work failed:\", error);\n}\n\n/**\n * @internal For the host: the work `after()` collected for this request, as\n * one promise that never rejects. Taken once; a second call has nothing.\n */\nexport function takeAfterWork(): Promise<void> | null {\n const store = scope()?.getStore();\n\n if (!store || store.after.length === 0) return null;\n\n const work = store.after.splice(0);\n\n return Promise.allSettled(\n work.map((run) => Promise.resolve().then(run)),\n ).then((results) => {\n for (const result of results) {\n if (result.status === \"rejected\") reportAfter(result.reason);\n }\n });\n}\n\n/** The reads caught at a boundary during this render, with their components. */\nexport function requestFallbacks(): string[] {\n return scope()?.getStore()?.fallbacks ?? [];\n}\n\n/**\n * A component called a cache()-wrapped helper. Recorded on every call, hit\n * or miss, so a read the helper makes can name everyone who waited for it.\n */\nexport function noteAwaiter(helper: unknown): void {\n const store = scope()?.getStore();\n\n if (!store) return;\n\n const { name } = caller(\"cache\");\n\n if (!name) return;\n\n store.awaiters ??= new Map();\n\n const list = store.awaiters.get(helper) ?? [];\n\n if (!list.includes(name)) list.push(name);\n\n store.awaiters.set(helper, list);\n}\n\n/** Run a cache()-wrapped helper's body, so a read inside it is filed under the helper. */\nexport function withHelper<T>(helper: unknown, run: () => T): T {\n const store = scope()?.getStore();\n\n if (!store) return run();\n\n const before = store.inHelper;\n\n store.inHelper = helper;\n\n try {\n return run();\n } finally {\n store.inHelper = before;\n }\n}\n\n/**\n * The same reads, each with the component that made it: `cookies() in\n * RootLayout`. A read inside a cached helper with more than one awaiter\n * names them all - `connection() awaited by AuthLinks, AuthDialogSlot` -\n * because the stack saw only the first, and the first is rarely the one\n * that blocks.\n */\nexport function requestReadWhere(): string[] {\n const store = scope()?.getStore();\n\n if (!store?.readWhere?.length) return store?.readBy ?? [];\n\n return store.readWhere.map((entry) => {\n const helper = store.readVia?.get(entry);\n const awaiters = helper ? store.awaiters?.get(helper) : undefined;\n\n if (!awaiters || awaiters.length < 2) return entry;\n\n const names =\n awaiters.length === 2\n ? awaiters.join(\" and \")\n : awaiters.slice(0, -1).join(\", \") + \" and \" + awaiters.at(-1);\n\n return `${entry.split(\" in \")[0]} awaited by ${names}`;\n });\n}\n\n/**\n * The query string, as a page receives it.\n *\n * Derived from the request rather than passed down the render, so no host has\n * to forward it separately — and so it suspends during a build for the same\n * reason every other read does. A frozen page cannot know the query it will be\n * asked for.\n */\nexport async function searchParams(): Promise<URLSearchParams> {\n // Named before the await, so the build reports the call someone wrote rather\n // than url(), which this happens to be built on.\n const store = slot();\n\n if (!store.request && !store.readBy.includes(\"searchParams()\")) {\n store.readBy.push(\"searchParams()\");\n }\n\n const from = await url();\n\n return from ? new URL(from).searchParams : new URLSearchParams();\n}\n"]}
|
package/dist/vite.js
CHANGED
|
@@ -31,7 +31,7 @@ import { serverImportsOfClientPackages } from "./clientImports.js";
|
|
|
31
31
|
import { automaticSitemap, METADATA_ROUTES, ROOT_FILES, rootFileType, } from "./metadataRoutes.js";
|
|
32
32
|
import { ownHosts } from "./hostRouting.js";
|
|
33
33
|
import { unrollBarrelImports } from "./barrelImports.js";
|
|
34
|
-
import { serverRendererMessage, SERVER_RENDERER, ssrProxyModule, UseSsrError, withoutSsrDirective } from "./useSsr.js";
|
|
34
|
+
import { hasUseSsr, serverRendererMessage, SERVER_RENDERER, ssrProxyModule, UseSsrError, withoutSsrDirective } from "./useSsr.js";
|
|
35
35
|
import { httpHostCalls } from "./hostCalls.js";
|
|
36
36
|
import { clientPackages, importsServerRenderer, packageDir as installedPackageDir, packageEntryInGraph, polyfillsToTrace, traceableByName } from "./clientPackages.js";
|
|
37
37
|
// Resolved once per rscKit() call. One build runs in one process, so these are
|
|
@@ -2585,7 +2585,7 @@ import __rsc_assets from 'virtual:vite-rsc/assets-manifest'
|
|
|
2585
2585
|
import { sectionComponent } from ${JSON.stringify(join(packageDir, "js/section"))}
|
|
2586
2586
|
import { PathnameProvider } from ${JSON.stringify(join(packageDir, "js/PathnameProvider"))}
|
|
2587
2587
|
import { DefaultRouteError } from ${JSON.stringify(join(packageDir, "js/DefaultRouteError"))}
|
|
2588
|
-
import { searchParams as requestSearchParams } from ${JSON.stringify(join(packageDir, "request"))}
|
|
2588
|
+
import { searchParams as requestSearchParams, withUrl } from ${JSON.stringify(join(packageDir, "request"))}
|
|
2589
2589
|
import { parseParams, parseSearchParams, parseBody, isSearchParamsError, isBodyError } from ${JSON.stringify(join(packageDir, "routeSchema"))}
|
|
2590
2590
|
import { notFoundDigest, isNotFoundSignal } from ${JSON.stringify(join(packageDir, "notFound"))}
|
|
2591
2591
|
import { noteRequestRead, urlOf } from ${JSON.stringify(join(packageDir, "request"))}
|
|
@@ -4091,6 +4091,8 @@ interface PageContext {
|
|
|
4091
4091
|
props: Record<string, unknown>
|
|
4092
4092
|
/** The page's url, as the host matched it: the key a navigation to it renders under. */
|
|
4093
4093
|
url?: string
|
|
4094
|
+
/** The page's whole url, query string included: what its re-render reads through searchParams(). */
|
|
4095
|
+
href?: string
|
|
4094
4096
|
layouts: LayoutEntry[]
|
|
4095
4097
|
loadings: string[]
|
|
4096
4098
|
parallelSlots: Record<string, string>
|
|
@@ -4347,15 +4349,24 @@ export async function handleAction(
|
|
|
4347
4349
|
// from those memos still showed the old name after a rename.
|
|
4348
4350
|
forgetCached()
|
|
4349
4351
|
|
|
4350
|
-
|
|
4352
|
+
// For the page's url, not the POST's: the page's query string is what its
|
|
4353
|
+
// searchParams prop and searchParams() read, and the POST has none. A slot
|
|
4354
|
+
// on ?c=25 re-rendered after a message came back as a new chat. The whole
|
|
4355
|
+
// render runs inside, because server components execute as the stream is
|
|
4356
|
+
// produced, not when the tree is built.
|
|
4357
|
+
const render = async () => {
|
|
4358
|
+
const revalidated: Record<string, unknown> = {}
|
|
4351
4359
|
|
|
4352
|
-
|
|
4353
|
-
|
|
4360
|
+
for (const target of targets) {
|
|
4361
|
+
revalidated[target] = await renderRevalidated(target, page)
|
|
4362
|
+
}
|
|
4363
|
+
|
|
4364
|
+
// Marked, so an action whose own result happens to be an object with a
|
|
4365
|
+
// 'result' key is not mistaken for this envelope.
|
|
4366
|
+
return { stream: renderToReadableStream({ __rscRevalidated: revalidated, result }) }
|
|
4354
4367
|
}
|
|
4355
4368
|
|
|
4356
|
-
|
|
4357
|
-
// 'result' key is not mistaken for this envelope.
|
|
4358
|
-
return { stream: renderToReadableStream({ __rscRevalidated: revalidated, result }) }
|
|
4369
|
+
return page.href ? await withUrl(page.href, render) : await render()
|
|
4359
4370
|
}
|
|
4360
4371
|
|
|
4361
4372
|
/**
|
|
@@ -5684,6 +5695,22 @@ export function serverRendererInRsc() {
|
|
|
5684
5695
|
};
|
|
5685
5696
|
// Per package, so a dependency imported from twenty files is read once.
|
|
5686
5697
|
const externalRenderers = new Map();
|
|
5698
|
+
// Per app file: whether it is a "use ssr" module, read once.
|
|
5699
|
+
const ssrModules = new Map();
|
|
5700
|
+
const isUseSsrModule = (importer) => {
|
|
5701
|
+
const file = importer.split("?")[0];
|
|
5702
|
+
let answer = ssrModules.get(file);
|
|
5703
|
+
if (answer === undefined) {
|
|
5704
|
+
try {
|
|
5705
|
+
answer = hasUseSsr(readFileSync(file, "utf-8"));
|
|
5706
|
+
}
|
|
5707
|
+
catch {
|
|
5708
|
+
answer = false;
|
|
5709
|
+
}
|
|
5710
|
+
ssrModules.set(file, answer);
|
|
5711
|
+
}
|
|
5712
|
+
return answer;
|
|
5713
|
+
};
|
|
5687
5714
|
// Packages already named by the warning above, so the stub's own warning
|
|
5688
5715
|
// - "imported by node_modules/<package>/dist/index.mjs" - stays quiet for
|
|
5689
5716
|
// them: one problem, one line.
|
|
@@ -5720,6 +5747,12 @@ export function serverRendererInRsc() {
|
|
|
5720
5747
|
const name = source.startsWith("@") ? source.split("/").slice(0, 2).join("/") : source.split("/")[0];
|
|
5721
5748
|
if (name === "react-dom" || name === "react" || name.startsWith("@rsc-kit/") || name.startsWith("@vitejs/"))
|
|
5722
5749
|
return;
|
|
5750
|
+
// A "use ssr" module is where this warning sends the rendering. This
|
|
5751
|
+
// environment gets a proxy in its place, but Vite's dependency scan
|
|
5752
|
+
// reads the source as written and resolves its imports here anyway:
|
|
5753
|
+
// a port that had followed the advice was given it on every dev start.
|
|
5754
|
+
if (isUseSsrModule(importer))
|
|
5755
|
+
return;
|
|
5723
5756
|
let imports = externalRenderers.get(name);
|
|
5724
5757
|
if (imports === undefined) {
|
|
5725
5758
|
// Vite answers a dependency either as external, by its bare name,
|