rwsdk 1.0.0-beta.4 → 1.0.0-beta.41
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/lib/constants.d.mts +1 -0
- package/dist/lib/constants.mjs +7 -4
- package/dist/lib/e2e/browser.mjs +6 -2
- package/dist/lib/e2e/constants.d.mts +4 -0
- package/dist/lib/e2e/constants.mjs +49 -12
- package/dist/lib/e2e/dev.mjs +37 -49
- package/dist/lib/e2e/environment.d.mts +2 -0
- package/dist/lib/e2e/environment.mjs +201 -64
- package/dist/lib/e2e/index.d.mts +1 -0
- package/dist/lib/e2e/index.mjs +1 -0
- package/dist/lib/e2e/poll.d.mts +1 -1
- package/dist/lib/e2e/release.d.mts +1 -0
- package/dist/lib/e2e/release.mjs +16 -32
- package/dist/lib/e2e/tarball.mjs +2 -34
- package/dist/lib/e2e/testHarness.d.mts +34 -3
- package/dist/lib/e2e/testHarness.mjs +219 -90
- package/dist/lib/e2e/utils.d.mts +1 -0
- package/dist/lib/e2e/utils.mjs +15 -0
- package/dist/runtime/client/client.d.ts +35 -0
- package/dist/runtime/client/client.js +35 -0
- package/dist/runtime/client/navigation.d.ts +49 -0
- package/dist/runtime/client/navigation.js +80 -31
- package/dist/runtime/entries/clientSSR.d.ts +1 -0
- package/dist/runtime/entries/clientSSR.js +3 -0
- package/dist/runtime/entries/no-react-server-ssr-bridge.d.ts +0 -0
- package/dist/runtime/entries/no-react-server-ssr-bridge.js +2 -0
- package/dist/runtime/entries/router.d.ts +1 -0
- package/dist/runtime/entries/routerClient.d.ts +1 -0
- package/dist/runtime/entries/routerClient.js +1 -0
- package/dist/runtime/entries/worker.d.ts +2 -0
- package/dist/runtime/entries/worker.js +2 -0
- package/dist/runtime/imports/__mocks__/use-client-lookup.d.ts +6 -0
- package/dist/runtime/imports/__mocks__/use-client-lookup.js +6 -0
- package/dist/runtime/lib/db/SqliteDurableObject.d.ts +2 -2
- package/dist/runtime/lib/db/SqliteDurableObject.js +2 -2
- package/dist/runtime/lib/db/createDb.d.ts +1 -2
- package/dist/runtime/lib/db/createDb.js +4 -0
- package/dist/runtime/lib/db/typeInference/builders/alterTable.d.ts +13 -3
- package/dist/runtime/lib/db/typeInference/builders/columnDefinition.d.ts +35 -21
- package/dist/runtime/lib/db/typeInference/builders/createTable.d.ts +9 -2
- package/dist/runtime/lib/db/typeInference/database.d.ts +16 -2
- package/dist/runtime/lib/db/typeInference/typetests/alterTable.typetest.js +80 -5
- package/dist/runtime/lib/db/typeInference/typetests/createTable.typetest.js +104 -2
- package/dist/runtime/lib/db/typeInference/typetests/testUtils.d.ts +1 -0
- package/dist/runtime/lib/db/typeInference/utils.d.ts +59 -9
- package/dist/runtime/lib/links.d.ts +21 -7
- package/dist/runtime/lib/links.js +82 -24
- package/dist/runtime/lib/links.test.js +20 -0
- package/dist/runtime/lib/manifest.d.ts +1 -1
- package/dist/runtime/lib/manifest.js +7 -4
- package/dist/runtime/lib/realtime/client.js +8 -2
- package/dist/runtime/lib/realtime/worker.d.ts +1 -1
- package/dist/runtime/lib/router.d.ts +153 -36
- package/dist/runtime/lib/router.js +169 -20
- package/dist/runtime/lib/router.test.js +241 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +66 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.js +302 -35
- package/dist/runtime/lib/stitchDocumentAndAppStreams.test.d.ts +1 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.test.js +418 -0
- package/dist/runtime/lib/{rwContext.d.ts → types.d.ts} +1 -0
- package/dist/runtime/lib/types.js +1 -0
- package/dist/runtime/render/renderDocumentHtmlStream.d.ts +1 -1
- package/dist/runtime/render/renderToStream.d.ts +4 -2
- package/dist/runtime/render/renderToStream.js +53 -24
- package/dist/runtime/render/renderToString.d.ts +3 -6
- package/dist/runtime/requestInfo/types.d.ts +4 -1
- package/dist/runtime/requestInfo/utils.d.ts +9 -0
- package/dist/runtime/requestInfo/utils.js +44 -0
- package/dist/runtime/requestInfo/worker.d.ts +0 -1
- package/dist/runtime/requestInfo/worker.js +3 -10
- package/dist/runtime/script.d.ts +1 -3
- package/dist/runtime/script.js +1 -10
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +13 -0
- package/dist/runtime/worker.d.ts +3 -1
- package/dist/runtime/worker.js +32 -0
- package/dist/scripts/debug-sync.mjs +18 -20
- package/dist/scripts/worker-run.d.mts +1 -1
- package/dist/scripts/worker-run.mjs +59 -113
- package/dist/use-synced-state/SyncedStateServer.d.mts +21 -0
- package/dist/use-synced-state/SyncedStateServer.mjs +128 -0
- package/dist/use-synced-state/__tests__/SyncStateServer.test.d.mts +1 -0
- package/dist/use-synced-state/__tests__/SyncStateServer.test.mjs +109 -0
- package/dist/use-synced-state/__tests__/useSyncState.test.d.ts +1 -0
- package/dist/use-synced-state/__tests__/useSyncState.test.js +115 -0
- package/dist/use-synced-state/__tests__/useSyncedState.test.d.ts +1 -0
- package/dist/use-synced-state/__tests__/useSyncedState.test.js +115 -0
- package/dist/use-synced-state/__tests__/worker.test.d.mts +1 -0
- package/dist/use-synced-state/__tests__/worker.test.mjs +69 -0
- package/dist/use-synced-state/client-core.d.ts +26 -0
- package/dist/use-synced-state/client-core.js +39 -0
- package/dist/use-synced-state/client.d.ts +3 -0
- package/dist/use-synced-state/client.js +4 -0
- package/dist/use-synced-state/constants.d.mts +1 -0
- package/dist/use-synced-state/constants.mjs +1 -0
- package/dist/use-synced-state/useSyncedState.d.ts +20 -0
- package/dist/use-synced-state/useSyncedState.js +58 -0
- package/dist/use-synced-state/worker.d.mts +13 -0
- package/dist/use-synced-state/worker.mjs +69 -0
- package/dist/vite/buildApp.mjs +34 -2
- package/dist/vite/cloudflarePreInitPlugin.d.mts +11 -0
- package/dist/vite/cloudflarePreInitPlugin.mjs +40 -0
- package/dist/vite/configPlugin.mjs +9 -14
- package/dist/vite/constants.d.mts +1 -0
- package/dist/vite/constants.mjs +1 -0
- package/dist/vite/createDirectiveLookupPlugin.mjs +10 -7
- package/dist/vite/devServerTimingPlugin.mjs +4 -0
- package/dist/vite/diagnosticAssetGraphPlugin.d.mts +4 -0
- package/dist/vite/diagnosticAssetGraphPlugin.mjs +41 -0
- package/dist/vite/directiveModulesDevPlugin.mjs +9 -1
- package/dist/vite/directivesPlugin.mjs +4 -4
- package/dist/vite/envResolvers.d.mts +11 -0
- package/dist/vite/envResolvers.mjs +20 -0
- package/dist/vite/getViteEsbuild.mjs +2 -1
- package/dist/vite/hmrStabilityPlugin.d.mts +2 -0
- package/dist/vite/hmrStabilityPlugin.mjs +73 -0
- package/dist/vite/injectVitePreamblePlugin.mjs +0 -4
- package/dist/vite/knownDepsResolverPlugin.d.mts +0 -6
- package/dist/vite/knownDepsResolverPlugin.mjs +25 -17
- package/dist/vite/linkerPlugin.d.mts +2 -1
- package/dist/vite/linkerPlugin.mjs +11 -3
- package/dist/vite/linkerPlugin.test.mjs +15 -0
- package/dist/vite/miniflareHMRPlugin.mjs +6 -38
- package/dist/vite/moveStaticAssetsPlugin.mjs +35 -4
- package/dist/vite/redwoodPlugin.mjs +8 -10
- package/dist/vite/runDirectivesScan.mjs +72 -18
- package/dist/vite/ssrBridgePlugin.mjs +132 -40
- package/dist/vite/ssrBridgeWrapPlugin.d.mts +2 -0
- package/dist/vite/ssrBridgeWrapPlugin.mjs +85 -0
- package/dist/vite/staleDepRetryPlugin.d.mts +2 -0
- package/dist/vite/staleDepRetryPlugin.mjs +74 -0
- package/dist/vite/statePlugin.d.mts +4 -0
- package/dist/vite/statePlugin.mjs +62 -0
- package/dist/vite/transformJsxScriptTagsPlugin.mjs +0 -5
- package/dist/vite/virtualPlugin.mjs +6 -7
- package/package.json +27 -10
- package/dist/vite/manifestPlugin.d.mts +0 -4
- package/dist/vite/manifestPlugin.mjs +0 -63
- /package/dist/runtime/lib/{rwContext.js → links.test.d.ts} +0 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { stitchDocumentAndAppStreams } from "./stitchDocumentAndAppStreams.js";
|
|
3
|
+
function stringToStream(str) {
|
|
4
|
+
const encoder = new TextEncoder();
|
|
5
|
+
return new ReadableStream({
|
|
6
|
+
start(controller) {
|
|
7
|
+
controller.enqueue(encoder.encode(str));
|
|
8
|
+
controller.close();
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function streamToString(stream) {
|
|
13
|
+
const decoder = new TextDecoder();
|
|
14
|
+
const reader = stream.getReader();
|
|
15
|
+
let result = "";
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
function pump() {
|
|
18
|
+
return reader
|
|
19
|
+
.read()
|
|
20
|
+
.then(({ done, value }) => {
|
|
21
|
+
if (done) {
|
|
22
|
+
resolve(result);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
result += decoder.decode(value, { stream: true });
|
|
26
|
+
return pump();
|
|
27
|
+
})
|
|
28
|
+
.catch(reject);
|
|
29
|
+
}
|
|
30
|
+
return pump();
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function createChunkedStream(chunks) {
|
|
34
|
+
const encoder = new TextEncoder();
|
|
35
|
+
return new ReadableStream({
|
|
36
|
+
start(controller) {
|
|
37
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
38
|
+
controller.enqueue(encoder.encode(chunks[i]));
|
|
39
|
+
}
|
|
40
|
+
controller.close();
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
describe("stitchDocumentAndAppStreams", () => {
|
|
45
|
+
const startMarker = '<div id="rwsdk-app-start" />';
|
|
46
|
+
const endMarker = '<div id="rwsdk-app-end"></div>';
|
|
47
|
+
describe("meta tag hoisting", () => {
|
|
48
|
+
it("places hoisted tags inside head, after existing head content", async () => {
|
|
49
|
+
const outerHtml = `<!DOCTYPE html>
|
|
50
|
+
<html>
|
|
51
|
+
<head>
|
|
52
|
+
<meta charset="utf-8" />
|
|
53
|
+
</head>
|
|
54
|
+
<body>
|
|
55
|
+
${startMarker}
|
|
56
|
+
<script src="/client.js"></script>
|
|
57
|
+
</body>
|
|
58
|
+
</html>`;
|
|
59
|
+
const innerHtml = `<title>Page Title</title><div>App content</div>${endMarker}`;
|
|
60
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
61
|
+
expect(result).toContain(`<title>Page Title</title>`);
|
|
62
|
+
expect(result).toMatch(/<head>[\s\S]*<meta charset="utf-8" \/>[\s\S]*<title>Page Title<\/title>[\s\S]*<\/head>/);
|
|
63
|
+
expect(result).toContain(`<div>App content</div>`);
|
|
64
|
+
const doctypeIndex = result.indexOf(`<!DOCTYPE html>`);
|
|
65
|
+
const headIndex = result.indexOf(`<head>`);
|
|
66
|
+
const charsetIndex = result.indexOf(`<meta charset="utf-8" />`);
|
|
67
|
+
const titleIndex = result.indexOf(`<title>Page Title</title>`);
|
|
68
|
+
const headCloseIndex = result.indexOf(`</head>`);
|
|
69
|
+
expect(doctypeIndex).toBe(0);
|
|
70
|
+
expect(doctypeIndex).toBeLessThan(headIndex);
|
|
71
|
+
expect(charsetIndex).toBeLessThan(titleIndex);
|
|
72
|
+
expect(titleIndex).toBeLessThan(headCloseIndex);
|
|
73
|
+
});
|
|
74
|
+
it("places multiple hoisted tags inside head, after existing head content", async () => {
|
|
75
|
+
const outerHtml = `<!DOCTYPE html>
|
|
76
|
+
<html>
|
|
77
|
+
<head>
|
|
78
|
+
<meta charset="utf-8" />
|
|
79
|
+
</head>
|
|
80
|
+
<body>
|
|
81
|
+
${startMarker}
|
|
82
|
+
<script src="/client.js"></script>
|
|
83
|
+
</body>
|
|
84
|
+
</html>`;
|
|
85
|
+
const innerHtml = `<title>Page Title</title><meta name="description" content="Test" /><link rel="stylesheet" href="/styles.css" /><div>App content</div>${endMarker}`;
|
|
86
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
87
|
+
expect(result).toContain(`<title>Page Title</title>`);
|
|
88
|
+
expect(result).toContain(`<meta name="description" content="Test" />`);
|
|
89
|
+
expect(result).toContain(`<link rel="stylesheet" href="/styles.css" />`);
|
|
90
|
+
expect(result).toMatch(/<head>[\s\S]*<meta charset="utf-8" \/>[\s\S]*<title>Page Title<\/title>[\s\S]*<meta name="description" content="Test" \/>[\s\S]*<link rel="stylesheet" href="\/styles.css" \/>[\s\S]*<\/head>/);
|
|
91
|
+
const doctypeIndex = result.indexOf(`<!DOCTYPE html>`);
|
|
92
|
+
const charsetIndex = result.indexOf(`<meta charset="utf-8" />`);
|
|
93
|
+
const titleIndex = result.indexOf(`<title>Page Title</title>`);
|
|
94
|
+
const headCloseIndex = result.indexOf(`</head>`);
|
|
95
|
+
expect(doctypeIndex).toBe(0);
|
|
96
|
+
expect(charsetIndex).toBeLessThan(titleIndex);
|
|
97
|
+
expect(titleIndex).toBeLessThan(headCloseIndex);
|
|
98
|
+
});
|
|
99
|
+
it("handles app stream with no hoisted tags", async () => {
|
|
100
|
+
const outerHtml = `<!DOCTYPE html>
|
|
101
|
+
<html>
|
|
102
|
+
<head>
|
|
103
|
+
<meta charset="utf-8" />
|
|
104
|
+
</head>
|
|
105
|
+
<body>
|
|
106
|
+
${startMarker}
|
|
107
|
+
<script src="/client.js"></script>
|
|
108
|
+
</body>
|
|
109
|
+
</html>`;
|
|
110
|
+
const innerHtml = `<div>App content</div>${endMarker}`;
|
|
111
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
112
|
+
expect(result).toContain(`<div>App content</div>`);
|
|
113
|
+
expect(result).not.toContain(`<title>`);
|
|
114
|
+
});
|
|
115
|
+
it("handles hoisted tags split across chunks", async () => {
|
|
116
|
+
const outerHtml = `<!DOCTYPE html>
|
|
117
|
+
<html>
|
|
118
|
+
<head>
|
|
119
|
+
<meta charset="utf-8" />
|
|
120
|
+
</head>
|
|
121
|
+
<body>
|
|
122
|
+
${startMarker}
|
|
123
|
+
<script src="/client.js"></script>
|
|
124
|
+
</body>
|
|
125
|
+
</html>`;
|
|
126
|
+
const innerHtmlChunks = [
|
|
127
|
+
`<title>Page `,
|
|
128
|
+
`Title</title><meta name="description" `,
|
|
129
|
+
`content="Test" /><div>App content</div>${endMarker}`,
|
|
130
|
+
];
|
|
131
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), createChunkedStream(innerHtmlChunks), startMarker, endMarker));
|
|
132
|
+
expect(result).toContain(`<title>Page Title</title>`);
|
|
133
|
+
expect(result).toContain(`<meta name="description" content="Test" />`);
|
|
134
|
+
expect(result).toMatch(/<head>[\s\S]*<meta charset="utf-8" \/>[\s\S]*<title>Page Title<\/title>[\s\S]*<\/head>/);
|
|
135
|
+
const doctypeIndex = result.indexOf(`<!DOCTYPE html>`);
|
|
136
|
+
const charsetIndex = result.indexOf(`<meta charset="utf-8" />`);
|
|
137
|
+
const titleIndex = result.indexOf(`<title>Page Title</title>`);
|
|
138
|
+
const headCloseIndex = result.indexOf(`</head>`);
|
|
139
|
+
expect(doctypeIndex).toBe(0);
|
|
140
|
+
expect(charsetIndex).toBeLessThan(titleIndex);
|
|
141
|
+
expect(titleIndex).toBeLessThan(headCloseIndex);
|
|
142
|
+
});
|
|
143
|
+
it("ensures doctype is always first", async () => {
|
|
144
|
+
const outerHtml = `<!DOCTYPE html>
|
|
145
|
+
<html>
|
|
146
|
+
<head>
|
|
147
|
+
<meta charset="utf-8" />
|
|
148
|
+
</head>
|
|
149
|
+
<body>
|
|
150
|
+
${startMarker}
|
|
151
|
+
<script src="/client.js"></script>
|
|
152
|
+
</body>
|
|
153
|
+
</html>`;
|
|
154
|
+
const innerHtml = `<title>Page Title</title><div>App content</div>${endMarker}`;
|
|
155
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
156
|
+
expect(result.trim().startsWith(`<!DOCTYPE html>`)).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe("basic stitching flow", () => {
|
|
160
|
+
it("stitches document head, app shell, and document tail", async () => {
|
|
161
|
+
const outerHtml = `<!DOCTYPE html>
|
|
162
|
+
<html>
|
|
163
|
+
<head>
|
|
164
|
+
<meta charset="utf-8" />
|
|
165
|
+
</head>
|
|
166
|
+
<body>
|
|
167
|
+
${startMarker}
|
|
168
|
+
<script src="/client.js"></script>
|
|
169
|
+
</body>
|
|
170
|
+
</html>`;
|
|
171
|
+
const innerHtml = `<div>App content</div>${endMarker}`;
|
|
172
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
173
|
+
expect(result).toContain(`<!DOCTYPE html>`);
|
|
174
|
+
expect(result).toContain(`<head>`);
|
|
175
|
+
expect(result).toContain(`<meta charset="utf-8" />`);
|
|
176
|
+
expect(result).toContain(`<div>App content</div>`);
|
|
177
|
+
expect(result).toContain(`<script src="/client.js"></script>`);
|
|
178
|
+
expect(result).toContain(`</body>`);
|
|
179
|
+
expect(result).toContain(`</html>`);
|
|
180
|
+
const doctypeIndex = result.indexOf(`<!DOCTYPE html>`);
|
|
181
|
+
const appContentIndex = result.indexOf(`<div>App content</div>`);
|
|
182
|
+
const scriptIndex = result.indexOf(`<script src="/client.js"></script>`);
|
|
183
|
+
const bodyCloseIndex = result.indexOf(`</body>`);
|
|
184
|
+
expect(doctypeIndex).toBeLessThan(appContentIndex);
|
|
185
|
+
expect(appContentIndex).toBeLessThan(scriptIndex);
|
|
186
|
+
expect(scriptIndex).toBeLessThan(bodyCloseIndex);
|
|
187
|
+
});
|
|
188
|
+
it("removes start marker from output", async () => {
|
|
189
|
+
const outerHtml = `<!DOCTYPE html>
|
|
190
|
+
<html>
|
|
191
|
+
<body>
|
|
192
|
+
${startMarker}
|
|
193
|
+
<script src="/client.js"></script>
|
|
194
|
+
</body>
|
|
195
|
+
</html>`;
|
|
196
|
+
const innerHtml = `<div>App content</div>${endMarker}`;
|
|
197
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
198
|
+
expect(result).not.toContain(startMarker);
|
|
199
|
+
});
|
|
200
|
+
it("preserves end marker in output", async () => {
|
|
201
|
+
const outerHtml = `<!DOCTYPE html>
|
|
202
|
+
<html>
|
|
203
|
+
<body>
|
|
204
|
+
${startMarker}
|
|
205
|
+
<script src="/client.js"></script>
|
|
206
|
+
</body>
|
|
207
|
+
</html>`;
|
|
208
|
+
const innerHtml = `<div>App content</div>${endMarker}`;
|
|
209
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
210
|
+
expect(result).toContain(endMarker);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
describe("suspense boundaries (suspended content)", () => {
|
|
214
|
+
it("streams suspended content after script tag", async () => {
|
|
215
|
+
const outerHtml = `<!DOCTYPE html>
|
|
216
|
+
<html>
|
|
217
|
+
<head>
|
|
218
|
+
<meta charset="utf-8" />
|
|
219
|
+
</head>
|
|
220
|
+
<body>
|
|
221
|
+
${startMarker}
|
|
222
|
+
<script src="/client.js"></script>
|
|
223
|
+
</body>
|
|
224
|
+
</html>`;
|
|
225
|
+
const innerHtml = `<div>Initial content</div>${endMarker}<div>Suspended content</div>`;
|
|
226
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
227
|
+
expect(result).toContain(`<div>Initial content</div>`);
|
|
228
|
+
expect(result).toContain(`<script src="/client.js"></script>`);
|
|
229
|
+
expect(result).toContain(`<div>Suspended content</div>`);
|
|
230
|
+
const initialIndex = result.indexOf(`<div>Initial content</div>`);
|
|
231
|
+
const scriptIndex = result.indexOf(`<script src="/client.js"></script>`);
|
|
232
|
+
const suspendedIndex = result.indexOf(`<div>Suspended content</div>`);
|
|
233
|
+
const bodyCloseIndex = result.indexOf(`</body>`);
|
|
234
|
+
expect(initialIndex).toBeLessThan(scriptIndex);
|
|
235
|
+
expect(scriptIndex).toBeLessThan(suspendedIndex);
|
|
236
|
+
expect(suspendedIndex).toBeLessThan(bodyCloseIndex);
|
|
237
|
+
});
|
|
238
|
+
it("handles multiple suspended content chunks", async () => {
|
|
239
|
+
const outerHtml = `<!DOCTYPE html>
|
|
240
|
+
<html>
|
|
241
|
+
<body>
|
|
242
|
+
${startMarker}
|
|
243
|
+
<script src="/client.js"></script>
|
|
244
|
+
</body>
|
|
245
|
+
</html>`;
|
|
246
|
+
const innerHtml = `<div>Initial</div>${endMarker}<div>Suspended 1</div><div>Suspended 2</div>`;
|
|
247
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
248
|
+
expect(result).toContain(`<div>Initial</div>`);
|
|
249
|
+
expect(result).toContain(`<div>Suspended 1</div>`);
|
|
250
|
+
expect(result).toContain(`<div>Suspended 2</div>`);
|
|
251
|
+
const scriptIndex = result.indexOf(`<script src="/client.js"></script>`);
|
|
252
|
+
const suspended1Index = result.indexOf(`<div>Suspended 1</div>`);
|
|
253
|
+
const suspended2Index = result.indexOf(`<div>Suspended 2</div>`);
|
|
254
|
+
expect(scriptIndex).toBeLessThan(suspended1Index);
|
|
255
|
+
expect(suspended1Index).toBeLessThan(suspended2Index);
|
|
256
|
+
});
|
|
257
|
+
it("handles app stream with no suspended content", async () => {
|
|
258
|
+
const outerHtml = `<!DOCTYPE html>
|
|
259
|
+
<html>
|
|
260
|
+
<body>
|
|
261
|
+
${startMarker}
|
|
262
|
+
<script src="/client.js"></script>
|
|
263
|
+
</body>
|
|
264
|
+
</html>`;
|
|
265
|
+
const innerHtml = `<div>Initial content</div>${endMarker}`;
|
|
266
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
267
|
+
expect(result).toContain(`<div>Initial content</div>`);
|
|
268
|
+
expect(result).toContain(`<script src="/client.js"></script>`);
|
|
269
|
+
expect(result).not.toContain(`Suspended`);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
describe("chunked streams", () => {
|
|
273
|
+
it("handles document stream split across chunks", async () => {
|
|
274
|
+
const outerHtmlChunks = [
|
|
275
|
+
`<!DOCTYPE html>\n<html>\n<head>\n`,
|
|
276
|
+
` <meta charset="utf-8" />\n</head>\n<body>\n`,
|
|
277
|
+
` ${startMarker}\n <script src="/client.js"></script>\n</body>\n</html>`,
|
|
278
|
+
];
|
|
279
|
+
const innerHtml = `<div>App content</div>${endMarker}`;
|
|
280
|
+
const result = await streamToString(stitchDocumentAndAppStreams(createChunkedStream(outerHtmlChunks), stringToStream(innerHtml), startMarker, endMarker));
|
|
281
|
+
expect(result).toContain(`<!DOCTYPE html>`);
|
|
282
|
+
expect(result).toContain(`<div>App content</div>`);
|
|
283
|
+
expect(result).toContain(`<script src="/client.js"></script>`);
|
|
284
|
+
});
|
|
285
|
+
it("handles app stream split across chunks", async () => {
|
|
286
|
+
const outerHtml = `<!DOCTYPE html>
|
|
287
|
+
<html>
|
|
288
|
+
<body>
|
|
289
|
+
${startMarker}
|
|
290
|
+
<script src="/client.js"></script>
|
|
291
|
+
</body>
|
|
292
|
+
</html>`;
|
|
293
|
+
const innerHtmlChunks = [
|
|
294
|
+
`<div>Initial `,
|
|
295
|
+
`content</div>${endMarker}`,
|
|
296
|
+
`<div>Suspended content</div>`,
|
|
297
|
+
];
|
|
298
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), createChunkedStream(innerHtmlChunks), startMarker, endMarker));
|
|
299
|
+
expect(result).toContain(`<div>Initial content</div>`);
|
|
300
|
+
expect(result).toContain(`<div>Suspended content</div>`);
|
|
301
|
+
});
|
|
302
|
+
it("handles markers split across chunks", async () => {
|
|
303
|
+
const outerHtml = `<!DOCTYPE html>
|
|
304
|
+
<html>
|
|
305
|
+
<body>
|
|
306
|
+
${startMarker}
|
|
307
|
+
<script src="/client.js"></script>
|
|
308
|
+
</body>
|
|
309
|
+
</html>`;
|
|
310
|
+
const innerHtmlChunks = [
|
|
311
|
+
`<div>App content</div><div id="rwsdk-app-end`,
|
|
312
|
+
`"></div>`,
|
|
313
|
+
];
|
|
314
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), createChunkedStream(innerHtmlChunks), startMarker, endMarker));
|
|
315
|
+
expect(result).toContain(`<div>App content</div>`);
|
|
316
|
+
expect(result).toContain(endMarker);
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
describe("edge cases", () => {
|
|
320
|
+
it("handles empty app stream", async () => {
|
|
321
|
+
const outerHtml = `<!DOCTYPE html>
|
|
322
|
+
<html>
|
|
323
|
+
<body>
|
|
324
|
+
${startMarker}
|
|
325
|
+
<script src="/client.js"></script>
|
|
326
|
+
</body>
|
|
327
|
+
</html>`;
|
|
328
|
+
const innerHtml = ``;
|
|
329
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
330
|
+
expect(result).toContain(`<!DOCTYPE html>`);
|
|
331
|
+
expect(result).toContain(`<script src="/client.js"></script>`);
|
|
332
|
+
expect(result).toContain(`</body>`);
|
|
333
|
+
});
|
|
334
|
+
it("handles empty outer stream", async () => {
|
|
335
|
+
const outerHtml = ``;
|
|
336
|
+
const innerHtml = `<div>App content</div>${endMarker}`;
|
|
337
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
338
|
+
expect(result).toBe(`<div>App content</div>${endMarker}`);
|
|
339
|
+
});
|
|
340
|
+
it("handles app stream ending before end marker", async () => {
|
|
341
|
+
const outerHtml = `<!DOCTYPE html>
|
|
342
|
+
<html>
|
|
343
|
+
<body>
|
|
344
|
+
${startMarker}
|
|
345
|
+
<script src="/client.js"></script>
|
|
346
|
+
</body>
|
|
347
|
+
</html>`;
|
|
348
|
+
const innerHtml = `<div>App content</div>`;
|
|
349
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
350
|
+
expect(result).toContain(`<div>App content</div>`);
|
|
351
|
+
expect(result).toContain(`<script src="/client.js"></script>`);
|
|
352
|
+
});
|
|
353
|
+
it("handles outer stream ending before start marker", async () => {
|
|
354
|
+
const outerHtml = `<!DOCTYPE html>
|
|
355
|
+
<html>
|
|
356
|
+
<head>
|
|
357
|
+
<meta charset="utf-8" />
|
|
358
|
+
</head>`;
|
|
359
|
+
const innerHtml = `<div>App content</div>${endMarker}`;
|
|
360
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
361
|
+
expect(result).toContain(`<!DOCTYPE html>`);
|
|
362
|
+
expect(result).toContain(`<meta charset="utf-8" />`);
|
|
363
|
+
expect(result).toContain(`<div>App content</div>`);
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
describe("complete flow verification", () => {
|
|
367
|
+
it("correctly orders all phases: head -> shell -> script -> suspended -> close", async () => {
|
|
368
|
+
const outerHtml = `<!DOCTYPE html>
|
|
369
|
+
<html>
|
|
370
|
+
<head>
|
|
371
|
+
<meta charset="utf-8" />
|
|
372
|
+
<title>Test Page</title>
|
|
373
|
+
</head>
|
|
374
|
+
<body>
|
|
375
|
+
${startMarker}
|
|
376
|
+
<script src="/client.js"></script>
|
|
377
|
+
</body>
|
|
378
|
+
</html>`;
|
|
379
|
+
const innerHtml = `<div>Initial content</div>${endMarker}<div>Suspended content</div>`;
|
|
380
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
381
|
+
const doctypeIndex = result.indexOf(`<!DOCTYPE html>`);
|
|
382
|
+
const headIndex = result.indexOf(`<head>`);
|
|
383
|
+
const titleIndex = result.indexOf(`<title>Test Page</title>`);
|
|
384
|
+
const initialIndex = result.indexOf(`<div>Initial content</div>`);
|
|
385
|
+
const scriptIndex = result.indexOf(`<script src="/client.js"></script>`);
|
|
386
|
+
const suspendedIndex = result.indexOf(`<div>Suspended content</div>`);
|
|
387
|
+
const bodyCloseIndex = result.indexOf(`</body>`);
|
|
388
|
+
const htmlCloseIndex = result.indexOf(`</html>`);
|
|
389
|
+
expect(doctypeIndex).toBeLessThan(headIndex);
|
|
390
|
+
expect(headIndex).toBeLessThan(titleIndex);
|
|
391
|
+
expect(titleIndex).toBeLessThan(initialIndex);
|
|
392
|
+
expect(initialIndex).toBeLessThan(scriptIndex);
|
|
393
|
+
expect(scriptIndex).toBeLessThan(suspendedIndex);
|
|
394
|
+
expect(suspendedIndex).toBeLessThan(bodyCloseIndex);
|
|
395
|
+
expect(bodyCloseIndex).toBeLessThan(htmlCloseIndex);
|
|
396
|
+
});
|
|
397
|
+
it("preserves content structure and markers", async () => {
|
|
398
|
+
const outerHtml = `<!DOCTYPE html>
|
|
399
|
+
<html>
|
|
400
|
+
<body>
|
|
401
|
+
${startMarker}
|
|
402
|
+
<script src="/client.js"></script>
|
|
403
|
+
</body>
|
|
404
|
+
</html>`;
|
|
405
|
+
const innerHtml = `<div id="app">
|
|
406
|
+
<h1>Hello</h1>
|
|
407
|
+
<p>World</p>
|
|
408
|
+
</div>${endMarker}<div>More content</div>`;
|
|
409
|
+
const result = await streamToString(stitchDocumentAndAppStreams(stringToStream(outerHtml), stringToStream(innerHtml), startMarker, endMarker));
|
|
410
|
+
expect(result).toContain(`<div id="app">`);
|
|
411
|
+
expect(result).toContain(`<h1>Hello</h1>`);
|
|
412
|
+
expect(result).toContain(`<p>World</p>`);
|
|
413
|
+
expect(result).toContain(endMarker);
|
|
414
|
+
expect(result).toContain(`<div>More content</div>`);
|
|
415
|
+
expect(result).not.toContain(startMarker);
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DocumentProps } from "../lib/
|
|
1
|
+
import { type DocumentProps } from "../lib/types.js";
|
|
2
2
|
import { type RequestInfo } from "../requestInfo/types.js";
|
|
3
3
|
export declare const renderDocumentHtmlStream: ({ rscPayloadStream, Document, requestInfo, shouldSSR, onError, }: {
|
|
4
4
|
rscPayloadStream: ReadableStream;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { FC, ReactElement } from "react";
|
|
2
|
-
import { DocumentProps } from "../lib/
|
|
2
|
+
import { DocumentProps } from "../lib/types.js";
|
|
3
|
+
import { type PartialRequestInfo } from "../requestInfo/types";
|
|
3
4
|
export interface RenderToStreamOptions {
|
|
4
5
|
Document?: FC<DocumentProps>;
|
|
5
6
|
ssr?: boolean;
|
|
6
7
|
injectRSCPayload?: boolean;
|
|
7
8
|
onError?: (error: unknown) => void;
|
|
9
|
+
requestInfo?: PartialRequestInfo;
|
|
8
10
|
}
|
|
9
11
|
export declare const IdentityDocument: FC<DocumentProps>;
|
|
10
|
-
export declare const renderToStream: (element: ReactElement, { ssr: shouldSSR, Document, injectRSCPayload: shouldInjectRSCPayload, onError, }?: RenderToStreamOptions) => Promise<ReadableStream>;
|
|
12
|
+
export declare const renderToStream: (element: ReactElement, { ssr: shouldSSR, Document, injectRSCPayload: shouldInjectRSCPayload, requestInfo: givenRequestInfo, onError, }?: RenderToStreamOptions) => Promise<ReadableStream>;
|
|
@@ -1,34 +1,63 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { injectRSCPayload } from "rsc-html-stream/server";
|
|
3
|
-
import {
|
|
3
|
+
import { ssrWebpackRequire } from "../imports/worker.js";
|
|
4
|
+
import { constructWithDefaultRequestInfo } from "../requestInfo/utils";
|
|
5
|
+
import { getRequestInfo, runWithRequestInfo } from "../requestInfo/worker";
|
|
4
6
|
import { renderDocumentHtmlStream } from "./renderDocumentHtmlStream";
|
|
5
7
|
import { renderToRscStream } from "./renderToRscStream";
|
|
6
8
|
export const IdentityDocument = ({ children }) => (_jsx(_Fragment, { children: children }));
|
|
7
|
-
export const renderToStream = async (element, { ssr: shouldSSR = true, Document = IdentityDocument, injectRSCPayload: shouldInjectRSCPayload = true, onError = () => { }, } = {}) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export const renderToStream = async (element, { ssr: shouldSSR = true, Document = IdentityDocument, injectRSCPayload: shouldInjectRSCPayload = true, requestInfo: givenRequestInfo, onError = () => { }, } = {}) => {
|
|
10
|
+
if (!globalThis.__webpack_require__) {
|
|
11
|
+
globalThis.__webpack_require__ = ssrWebpackRequire;
|
|
12
|
+
}
|
|
13
|
+
// Try to get the context requestInfo from the async store.
|
|
14
|
+
let contextRequestInfo;
|
|
15
|
+
try {
|
|
16
|
+
contextRequestInfo = getRequestInfo();
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
// No requestInfo detected from store.
|
|
20
|
+
}
|
|
21
|
+
// Construct requestInfo with defaults where overrides take precedence.
|
|
22
|
+
// If provided, `givenRequestInfo` will override values from context requestInfo if it exists
|
|
23
|
+
const requestInfo = constructWithDefaultRequestInfo({
|
|
24
|
+
...contextRequestInfo,
|
|
25
|
+
...givenRequestInfo,
|
|
26
|
+
rw: {
|
|
27
|
+
...contextRequestInfo?.rw,
|
|
28
|
+
...givenRequestInfo?.rw,
|
|
12
29
|
},
|
|
13
|
-
onError,
|
|
14
30
|
});
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
// context(gching, 2025-10-29): We wrap the following with context to the requestInfo
|
|
32
|
+
// due to `ssrWebpackRequire` needing to reference the `requestInfo` in context.
|
|
33
|
+
// Therefore, we need to wrap + also pass in the requestInfo in their independent
|
|
34
|
+
// function calls
|
|
35
|
+
return runWithRequestInfo(requestInfo, async () => {
|
|
36
|
+
let rscStream = renderToRscStream({
|
|
37
|
+
input: {
|
|
38
|
+
node: element,
|
|
39
|
+
actionResult: undefined,
|
|
40
|
+
},
|
|
41
|
+
onError,
|
|
21
42
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
let injectRSCStream;
|
|
44
|
+
if (shouldInjectRSCPayload) {
|
|
45
|
+
const [rscPayloadStream1, rscPayloadStream2] = rscStream.tee();
|
|
46
|
+
rscStream = rscPayloadStream1;
|
|
47
|
+
injectRSCStream = injectRSCPayload(rscPayloadStream2, {
|
|
48
|
+
nonce: requestInfo.rw.nonce,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
let htmlStream = await renderDocumentHtmlStream({
|
|
52
|
+
rscPayloadStream: rscStream,
|
|
53
|
+
Document,
|
|
54
|
+
requestInfo,
|
|
55
|
+
shouldSSR,
|
|
56
|
+
onError,
|
|
57
|
+
});
|
|
58
|
+
if (injectRSCStream) {
|
|
59
|
+
htmlStream = htmlStream.pipeThrough(injectRSCStream);
|
|
60
|
+
}
|
|
61
|
+
return htmlStream;
|
|
29
62
|
});
|
|
30
|
-
if (injectRSCStream) {
|
|
31
|
-
htmlStream = htmlStream.pipeThrough(injectRSCStream);
|
|
32
|
-
}
|
|
33
|
-
return htmlStream;
|
|
34
63
|
};
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
export
|
|
4
|
-
Document?: FC<DocumentProps>;
|
|
5
|
-
injectRSCPayload?: boolean;
|
|
6
|
-
}
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { type RenderToStreamOptions } from "./renderToStream";
|
|
3
|
+
export type RenderToStringOptions = Omit<RenderToStreamOptions, "onError">;
|
|
7
4
|
export declare const renderToString: (element: ReactElement, options?: RenderToStringOptions) => Promise<string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RwContext } from "../lib/
|
|
1
|
+
import { RwContext } from "../lib/types.js";
|
|
2
2
|
export interface DefaultAppContext {
|
|
3
3
|
}
|
|
4
4
|
export interface RequestInfo<Params = any, AppContext = DefaultAppContext> {
|
|
@@ -12,3 +12,6 @@ export interface RequestInfo<Params = any, AppContext = DefaultAppContext> {
|
|
|
12
12
|
};
|
|
13
13
|
isAction: boolean;
|
|
14
14
|
}
|
|
15
|
+
export type PartialRequestInfo<Params = any, AppContext = DefaultAppContext> = Omit<Partial<RequestInfo<Params, AppContext>>, "rw"> & {
|
|
16
|
+
rw?: Partial<RwContext>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { type DocumentProps } from "../lib/types";
|
|
3
|
+
import { type PartialRequestInfo, type RequestInfo } from "./types";
|
|
4
|
+
export declare const DefaultRequestInfoDocument: FC<DocumentProps>;
|
|
5
|
+
/**
|
|
6
|
+
* Constructs a generic requestInfo that can be used as defaults.
|
|
7
|
+
* Allows for passing in overrides to initialize with defaults.
|
|
8
|
+
*/
|
|
9
|
+
export declare const constructWithDefaultRequestInfo: (overrides?: PartialRequestInfo) => RequestInfo;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { generateNonce } from "../lib/utils";
|
|
3
|
+
export const DefaultRequestInfoDocument = ({ children }) => (_jsx(_Fragment, { children: children }));
|
|
4
|
+
/**
|
|
5
|
+
* Constructs a generic requestInfo that can be used as defaults.
|
|
6
|
+
* Allows for passing in overrides to initialize with defaults.
|
|
7
|
+
*/
|
|
8
|
+
export const constructWithDefaultRequestInfo = (overrides = {}) => {
|
|
9
|
+
const { rw: rwOverrides, ...otherRequestInfoOverrides } = overrides;
|
|
10
|
+
const defaultRequestInfo = {
|
|
11
|
+
request: new Request("http://localhost/"),
|
|
12
|
+
params: {},
|
|
13
|
+
ctx: {},
|
|
14
|
+
cf: {
|
|
15
|
+
waitUntil: () => { },
|
|
16
|
+
passThroughOnException: () => { },
|
|
17
|
+
props: {},
|
|
18
|
+
},
|
|
19
|
+
response: {
|
|
20
|
+
status: 200,
|
|
21
|
+
headers: new Headers(),
|
|
22
|
+
},
|
|
23
|
+
isAction: false,
|
|
24
|
+
rw: {
|
|
25
|
+
Document: DefaultRequestInfoDocument,
|
|
26
|
+
nonce: generateNonce(),
|
|
27
|
+
rscPayload: true,
|
|
28
|
+
ssr: true,
|
|
29
|
+
databases: new Map(),
|
|
30
|
+
scriptsToBeLoaded: new Set(),
|
|
31
|
+
entryScripts: new Set(),
|
|
32
|
+
inlineScripts: new Set(),
|
|
33
|
+
pageRouteResolved: undefined,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
...defaultRequestInfo,
|
|
38
|
+
...otherRequestInfoOverrides,
|
|
39
|
+
rw: {
|
|
40
|
+
...defaultRequestInfo.rw,
|
|
41
|
+
...rwOverrides,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -2,7 +2,6 @@ import { DefaultAppContext, RequestInfo } from "./types";
|
|
|
2
2
|
type DefaultRequestInfo = RequestInfo<DefaultAppContext>;
|
|
3
3
|
export declare const requestInfo: DefaultRequestInfo;
|
|
4
4
|
export declare function getRequestInfo(): RequestInfo;
|
|
5
|
-
export declare function waitForRequestInfo(): Promise<DefaultRequestInfo>;
|
|
6
5
|
export declare function runWithRequestInfo<Result>(nextRequestInfo: DefaultRequestInfo, fn: () => Result): Result;
|
|
7
6
|
export declare function runWithRequestInfoOverrides<Result>(overrides: Partial<DefaultRequestInfo>, fn: () => Result): Result;
|
|
8
7
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "async_hooks";
|
|
2
|
-
|
|
3
|
-
const requestInfoStore = new AsyncLocalStorage();
|
|
2
|
+
import { defineRwState } from "rwsdk/__state";
|
|
3
|
+
const requestInfoStore = defineRwState("requestInfoStore", () => new AsyncLocalStorage());
|
|
4
4
|
const requestInfoBase = {};
|
|
5
5
|
const REQUEST_INFO_KEYS = ["request", "params", "ctx", "rw", "cf", "response"];
|
|
6
6
|
REQUEST_INFO_KEYS.forEach((key) => {
|
|
@@ -21,15 +21,8 @@ export function getRequestInfo() {
|
|
|
21
21
|
}
|
|
22
22
|
return store;
|
|
23
23
|
}
|
|
24
|
-
export function waitForRequestInfo() {
|
|
25
|
-
return requestInfoDeferred.promise;
|
|
26
|
-
}
|
|
27
24
|
export function runWithRequestInfo(nextRequestInfo, fn) {
|
|
28
|
-
|
|
29
|
-
requestInfoDeferred.resolve(nextRequestInfo);
|
|
30
|
-
return fn();
|
|
31
|
-
};
|
|
32
|
-
return requestInfoStore.run(nextRequestInfo, runWithRequestInfoFn);
|
|
25
|
+
return requestInfoStore.run(nextRequestInfo, fn);
|
|
33
26
|
}
|
|
34
27
|
export function runWithRequestInfoOverrides(overrides, fn) {
|
|
35
28
|
const requestInfo = requestInfoStore.getStore();
|
package/dist/runtime/script.d.ts
CHANGED