vike 0.4.266 → 0.4.267-commit-7884d91

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.
Files changed (159) hide show
  1. package/dist/client/runtime-client-routing/createPageContextClient.d.ts +4 -0
  2. package/dist/client/runtime-client-routing/getGlobalContextClientInternal.d.ts +4 -0
  3. package/dist/client/runtime-client-routing/getPageContextFromHooks.d.ts +22 -2
  4. package/dist/client/runtime-client-routing/getPageContextFromHooks.js +4 -5
  5. package/dist/client/runtime-client-routing/history.d.ts +19 -19
  6. package/dist/client/runtime-client-routing/history.js +89 -83
  7. package/dist/client/runtime-client-routing/renderPageClient.d.ts +472 -9
  8. package/dist/client/runtime-client-routing/renderPageClient.js +12 -11
  9. package/dist/client/runtime-client-routing/setScrollPosition.js +6 -5
  10. package/dist/client/runtime-client-routing/streamedValues.d.ts +5 -0
  11. package/dist/client/runtime-client-routing/streamedValues.js +23 -0
  12. package/dist/client/runtime-server-routing/createPageContextClient.d.ts +4 -0
  13. package/dist/client/runtime-server-routing/entry.js +1 -1
  14. package/dist/client/runtime-server-routing/getGlobalContextClientInternal.d.ts +4 -0
  15. package/dist/client/shared/getGlobalContextClientInternalShared.d.ts +4 -0
  16. package/dist/client/shared/getJsonSerializedInHtml.d.ts +2 -2
  17. package/dist/client/shared/getJsonSerializedInHtml.js +9 -6
  18. package/dist/client/shared/streamedValues/asyncIterable.d.ts +4 -0
  19. package/dist/client/shared/streamedValues/asyncIterable.js +26 -0
  20. package/dist/client/shared/streamedValues/lines.d.ts +11 -0
  21. package/dist/client/shared/streamedValues/lines.js +19 -0
  22. package/dist/client/shared/streamedValues/promise.d.ts +4 -0
  23. package/dist/client/shared/streamedValues/promise.js +19 -0
  24. package/dist/client/shared/streamedValues/readableStream.d.ts +4 -0
  25. package/dist/client/shared/streamedValues/readableStream.js +44 -0
  26. package/dist/client/shared/streamedValues/registry.d.ts +21 -0
  27. package/dist/client/shared/streamedValues/registry.js +40 -0
  28. package/dist/client/shared/streamedValues.d.ts +7 -0
  29. package/dist/client/shared/streamedValues.js +82 -0
  30. package/dist/node/api/resolveViteConfigUser.js +2 -2
  31. package/dist/node/prerender/runPrerender.d.ts +12 -4
  32. package/dist/node/prerender/runPrerender.js +71 -15
  33. package/dist/node/vite/assertEnvVite.js +2 -2
  34. package/dist/node/vite/index.js +2 -0
  35. package/dist/node/vite/plugins/build/handleAssetsManifest.js +8 -3
  36. package/dist/node/vite/plugins/build/pluginBuildApp.js +25 -26
  37. package/dist/node/vite/plugins/build/pluginBuildConfig.d.ts +2 -2
  38. package/dist/node/vite/plugins/build/pluginBuildConfig.js +24 -16
  39. package/dist/node/vite/plugins/build/pluginDistFileNames.js +70 -50
  40. package/dist/node/vite/plugins/build/pluginEnvironmentEntries.d.ts +6 -0
  41. package/dist/node/vite/plugins/build/pluginEnvironmentEntries.js +71 -0
  42. package/dist/node/vite/plugins/build/pluginSuppressRollupWarning.js +19 -17
  43. package/dist/node/vite/plugins/pluginCommon.js +9 -6
  44. package/dist/node/vite/plugins/pluginDev/logSkillHint.js +6 -4
  45. package/dist/node/vite/plugins/pluginDev/optimizeDeps.js +1 -1
  46. package/dist/node/vite/plugins/pluginReplaceConstantsGlobalThis.js +6 -4
  47. package/dist/node/vite/plugins/pluginUniversalDeploy.js +3 -2
  48. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntry.d.ts +2 -1
  49. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntry.js +29 -12
  50. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntryWithOldDesign.js +3 -2
  51. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFilePageEntry.js +7 -7
  52. package/dist/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.d.ts +7 -5
  53. package/dist/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js +4 -10
  54. package/dist/node/vite/plugins/pluginVirtualFiles.js +20 -0
  55. package/dist/node/vite/shared/addSsrMiddleware.js +13 -1
  56. package/dist/node/vite/shared/getAssetsDir.d.ts +3 -2
  57. package/dist/node/vite/shared/getAssetsDir.js +3 -3
  58. package/dist/node/vite/shared/isViteCli.d.ts +3 -3
  59. package/dist/node/vite/shared/isViteCli.js +80 -84
  60. package/dist/node/vite/shared/isViteServerSide.js +2 -7
  61. package/dist/node/vite/shared/resolveVikeConfigInternal/getPlusFiles.d.ts +2 -2
  62. package/dist/node/vite/shared/resolveVikeConfigInternal/getPlusFiles.js +3 -3
  63. package/dist/node/vite/shared/resolveVikeConfigInternal/loadFileAtConfigTime.d.ts +4 -4
  64. package/dist/node/vite/shared/resolveVikeConfigInternal/loadFileAtConfigTime.js +9 -9
  65. package/dist/node/vite/shared/resolveVikeConfigInternal/metaBuiltIn.d.ts +1 -1
  66. package/dist/node/vite/shared/resolveVikeConfigInternal/metaBuiltIn.js +12 -6
  67. package/dist/node/vite/shared/resolveVikeConfigInternal/pointerImports.d.ts +3 -1
  68. package/dist/node/vite/shared/resolveVikeConfigInternal/pointerImports.js +18 -46
  69. package/dist/node/vite/shared/resolveVikeConfigInternal/transpileAndExecuteFile.d.ts +3 -3
  70. package/dist/node/vite/shared/resolveVikeConfigInternal/transpileAndExecuteFile.js +333 -212
  71. package/dist/node/vite/shared/resolveVikeConfigInternal.d.ts +4 -1
  72. package/dist/node/vite/shared/resolveVikeConfigInternal.js +97 -26
  73. package/dist/server/runtime/globalContext.d.ts +20 -0
  74. package/dist/server/runtime/renderPageServer/analyzePage.js +3 -3
  75. package/dist/server/runtime/renderPageServer/createHttpResponse.d.ts +20 -7
  76. package/dist/server/runtime/renderPageServer/createHttpResponse.js +34 -15
  77. package/dist/server/runtime/renderPageServer/createPageContextServer.d.ts +4 -0
  78. package/dist/server/runtime/renderPageServer/csp.d.ts +2 -1
  79. package/dist/server/runtime/renderPageServer/csp.js +2 -1
  80. package/dist/server/runtime/renderPageServer/execHookOnError.js +1 -1
  81. package/dist/server/runtime/renderPageServer/execHookOnRenderHtml.d.ts +9 -0
  82. package/dist/server/runtime/renderPageServer/execHookOnRenderHtml.js +17 -5
  83. package/dist/server/runtime/renderPageServer/getHttpResponseBody.d.ts +2 -2
  84. package/dist/server/runtime/renderPageServer/getHttpResponseBody.js +17 -2
  85. package/dist/server/runtime/renderPageServer/getPageContextJson.d.ts +8 -0
  86. package/dist/server/runtime/renderPageServer/getPageContextJson.js +47 -0
  87. package/dist/server/runtime/renderPageServer/handleErrorWithoutErrorPage.d.ts +2 -0
  88. package/dist/server/runtime/renderPageServer/handleErrorWithoutErrorPage.js +1 -1
  89. package/dist/server/runtime/renderPageServer/headersResponse.d.ts +11 -2
  90. package/dist/server/runtime/renderPageServer/headersResponse.js +22 -2
  91. package/dist/server/runtime/renderPageServer/html/injectAssets/getHtmlTags.js +5 -4
  92. package/dist/server/runtime/renderPageServer/html/injectAssets.d.ts +3 -2
  93. package/dist/server/runtime/renderPageServer/html/injectAssets.js +7 -1
  94. package/dist/server/runtime/renderPageServer/html/renderHtml.js +4 -2
  95. package/dist/server/runtime/renderPageServer/html/serializeContext.d.ts +5 -1
  96. package/dist/server/runtime/renderPageServer/html/serializeContext.js +12 -9
  97. package/dist/server/runtime/renderPageServer/html/stream.d.ts +13 -6
  98. package/dist/server/runtime/renderPageServer/html/stream.js +121 -31
  99. package/dist/server/runtime/renderPageServer/html/streamedValuesHtml.d.ts +30 -0
  100. package/dist/server/runtime/renderPageServer/html/streamedValuesHtml.js +92 -0
  101. package/dist/server/runtime/renderPageServer/loadPageConfigsLazyServerSide.d.ts +4 -0
  102. package/dist/server/runtime/renderPageServer/loadPageConfigsLazyServerSide.js +5 -1
  103. package/dist/server/runtime/renderPageServer/loadPageContextEnvironments.d.ts +15 -0
  104. package/dist/server/runtime/renderPageServer/loadPageContextEnvironments.js +61 -0
  105. package/dist/server/runtime/renderPageServer/renderPageServerAfterRoute.d.ts +314 -1
  106. package/dist/server/runtime/renderPageServer/renderPageServerAfterRoute.js +21 -12
  107. package/dist/server/runtime/renderPageServer/streamedValues/asyncIterable.d.ts +4 -0
  108. package/dist/server/runtime/renderPageServer/streamedValues/asyncIterable.js +12 -0
  109. package/dist/server/runtime/renderPageServer/streamedValues/lines.d.ts +10 -0
  110. package/dist/server/runtime/renderPageServer/streamedValues/lines.js +49 -0
  111. package/dist/server/runtime/renderPageServer/streamedValues/promise.d.ts +4 -0
  112. package/dist/server/runtime/renderPageServer/streamedValues/promise.js +14 -0
  113. package/dist/server/runtime/renderPageServer/streamedValues/pump.d.ts +10 -0
  114. package/dist/server/runtime/renderPageServer/streamedValues/pump.js +67 -0
  115. package/dist/server/runtime/renderPageServer/streamedValues/readableStream.d.ts +4 -0
  116. package/dist/server/runtime/renderPageServer/streamedValues/readableStream.js +12 -0
  117. package/dist/server/runtime/renderPageServer/streamedValues/registry.d.ts +28 -0
  118. package/dist/server/runtime/renderPageServer/streamedValues/registry.js +33 -0
  119. package/dist/server/runtime/renderPageServer.d.ts +4 -0
  120. package/dist/server/runtime/renderPageServer.js +17 -8
  121. package/dist/shared-server-client/createGlobalContextShared.d.ts +8 -0
  122. package/dist/shared-server-client/createGlobalContextShared.js +2 -1
  123. package/dist/shared-server-client/getPageContextPublicShared.js +0 -2
  124. package/dist/shared-server-client/getPageFiles/parseVirtualFileExportsGlobalEntry.d.ts +8 -0
  125. package/dist/shared-server-client/getPageFiles/parseVirtualFileExportsGlobalEntry.js +17 -7
  126. package/dist/shared-server-client/hooks/execHook.d.ts +1 -1
  127. package/dist/shared-server-client/hooks/execHook.js +2 -2
  128. package/dist/shared-server-client/route/abort.d.ts +1 -1
  129. package/dist/shared-server-client/route/abort.js +4 -2
  130. package/dist/shared-server-client/streamedValues.d.ts +22 -0
  131. package/dist/shared-server-client/streamedValues.js +24 -0
  132. package/dist/shared-server-node/vike-environments.d.ts +4 -0
  133. package/dist/shared-server-node/vike-environments.js +10 -0
  134. package/dist/shared-server-node/virtualFileId.d.ts +7 -5
  135. package/dist/shared-server-node/virtualFileId.js +42 -42
  136. package/dist/types/Config.d.ts +9 -1
  137. package/dist/types/PageConfig.d.ts +13 -5
  138. package/dist/types/PageContext.d.ts +18 -1
  139. package/dist/utils/PROJECT_VERSION.d.ts +1 -1
  140. package/dist/utils/PROJECT_VERSION.js +1 -1
  141. package/dist/utils/assertNodeVersion.d.ts +2 -0
  142. package/dist/utils/assertNodeVersion.js +4 -1
  143. package/dist/utils/assertViteVersion.d.ts +1 -3
  144. package/dist/utils/assertViteVersion.js +6 -9
  145. package/dist/utils/debug.d.ts +1 -1
  146. package/dist/utils/debug.js +1 -1
  147. package/dist/utils/deepEqual.d.ts +2 -1
  148. package/dist/utils/deepEqual.js +21 -6
  149. package/dist/utils/getContentTypeFromUrl.d.ts +2 -0
  150. package/dist/utils/getContentTypeFromUrl.js +39 -0
  151. package/dist/utils/injectRollupInputs.d.ts +2 -2
  152. package/dist/utils/injectRollupInputs.js +2 -2
  153. package/dist/utils/isDev.js +2 -7
  154. package/dist/utils/parseUrl-extras.js +4 -0
  155. package/dist/utils/requireResolve.d.ts +0 -6
  156. package/dist/utils/requireResolve.js +0 -8
  157. package/package.json +9 -10
  158. package/dist/shared-server-client/addIs404ToPageProps.d.ts +0 -2
  159. package/dist/shared-server-client/addIs404ToPageProps.js +0 -17
@@ -1,14 +1,17 @@
1
1
  export { execHookOnRenderHtml };
2
2
  export type { RenderHook };
3
+ export type { Content };
3
4
  import { type HtmlRender } from './html/renderHtml.js';
4
5
  import { type HookInternal } from '../../../shared-server-client/hooks/getHook.js';
5
6
  import type { PageAsset } from './getPageAssets.js';
7
+ import { type StreamReadableWeb } from './html/stream.js';
6
8
  import type { PageContextSerialization } from './html/serializeContext.js';
7
9
  import { type PageContextExecHook } from '../../../shared-server-client/hooks/execHook.js';
8
10
  import type { PageContextConfig } from '../../../shared-server-client/getPageFiles.js';
9
11
  import type { PageContextInternalServer } from '../../../types/PageContext.js';
10
12
  import '../../assertEnvServer.js';
11
13
  type GetPageAssets = () => Promise<PageAsset[]>;
14
+ type Content = string | Uint8Array | StreamReadableWeb;
12
15
  type RenderHook = HookInternal & {
13
16
  hookName: HookName;
14
17
  };
@@ -19,7 +22,13 @@ declare function execHookOnRenderHtml(pageContext: PageContextConfig & PageConte
19
22
  _isHtmlOnly: boolean;
20
23
  _baseServer: string;
21
24
  _requestId: number;
25
+ content?: unknown;
22
26
  }): Promise<{
23
27
  renderHook: RenderHook;
24
28
  htmlRender: HtmlRender;
29
+ content: null;
30
+ } | {
31
+ renderHook: RenderHook;
32
+ htmlRender: null;
33
+ content: Content;
25
34
  }>;
@@ -6,7 +6,7 @@ import { isCallable } from '../../../utils/isCallable.js';
6
6
  import { assert, assertUsage, assertWarning } from '../../../utils/assert.js';
7
7
  import { isObject } from '../../../utils/isObject.js';
8
8
  import { objectAssign } from '../../../utils/objectAssign.js';
9
- import { isStream } from './html/stream.js';
9
+ import { awaitFirstChunk, isStream, isStreamReadableWeb } from './html/stream.js';
10
10
  import { assertPageContextProvidedByUser } from '../../../shared-server-client/assertPageContextProvidedByUser.js';
11
11
  import { getPageContextPublicServer } from './getPageContextPublicServer.js';
12
12
  import { assertHookReturnedObject } from '../../../shared-server-client/assertHookReturnedObject.js';
@@ -18,9 +18,6 @@ async function execHookOnRenderHtml(pageContext) {
18
18
  const hook = getRenderHook(pageContext);
19
19
  objectAssign(pageContext, { _renderHook: hook });
20
20
  const { hookReturn } = await execHookSingleWithReturn(hook, pageContext, getPageContextPublicServer);
21
- const { documentHtml, pageContextProvidedByRenderHook, pageContextPromise, injectFilter } = processHookReturnValue(hookReturn, hook);
22
- Object.assign(pageContext, pageContextProvidedByRenderHook);
23
- objectAssign(pageContext, { _pageContextPromise: pageContextPromise });
24
21
  const onErrorWhileStreaming = (err) => {
25
22
  // Should the stream inject the following?
26
23
  // ```
@@ -31,9 +28,24 @@ async function execHookOnRenderHtml(pageContext) {
31
28
  pageContext.errorWhileRendering = err;
32
29
  }
33
30
  };
31
+ // The render hook sets `pageContext.content` instead of returning `documentHtml`
32
+ if (hookReturn === undefined && pageContext.content !== undefined) {
33
+ const content = await getContent(pageContext.content, onErrorWhileStreaming);
34
+ return { content, htmlRender: null, renderHook: hook };
35
+ }
36
+ const { documentHtml, pageContextProvidedByRenderHook, pageContextPromise, injectFilter } = processHookReturnValue(hookReturn, hook);
37
+ Object.assign(pageContext, pageContextProvidedByRenderHook);
38
+ objectAssign(pageContext, { _pageContextPromise: pageContextPromise });
34
39
  const htmlRender = await renderDocumentHtml(documentHtml, pageContext, onErrorWhileStreaming, injectFilter);
35
40
  assert(typeof htmlRender === 'string' || isStream(htmlRender));
36
- return { htmlRender, renderHook: hook };
41
+ return { htmlRender, content: null, renderHook: hook };
42
+ }
43
+ async function getContent(content, onErrorWhileStreaming) {
44
+ if (typeof content === 'string' || content instanceof Uint8Array)
45
+ return content;
46
+ assertUsage(isStreamReadableWeb(content), `${pc.code('pageContext.content')} is a value that isn't a string, a Uint8Array, nor a ReadableStream, see https://vike.dev/pageContext#content`);
47
+ // Errors before the first chunk => error page
48
+ return await awaitFirstChunk(content, onErrorWhileStreaming);
37
49
  }
38
50
  function getRenderHook(pageContext) {
39
51
  let hookFound;
@@ -20,8 +20,8 @@ type HttpResponseBody = {
20
20
  /** @deprecated */
21
21
  pipeToWebWritable: StreamPipeWeb;
22
22
  };
23
- declare function getHttpResponseBody(htmlRender: HtmlRender, renderHook: null | RenderHook): string;
24
- declare function getHttpResponseBodyStreamHandlers(htmlRender: HtmlRender, renderHook: null | RenderHook): {
23
+ declare function getHttpResponseBody(htmlRender: HtmlRender | Uint8Array, renderHook: null | RenderHook): string;
24
+ declare function getHttpResponseBodyStreamHandlers(htmlRender: HtmlRender | Uint8Array, renderHook: null | RenderHook): {
25
25
  pipe(writable: StreamWritableNode | StreamWritableWeb): void;
26
26
  getReadableWebStream(): StreamReadableWeb;
27
27
  getReadableNodeStream(): Promise<import("stream").Readable>;
@@ -53,7 +53,16 @@ function getHttpResponseBodyStreamHandlers(htmlRender, renderHook) {
53
53
  }
54
54
  return nodeStream;
55
55
  },
56
+ // Decodes the body as UTF-8 text
56
57
  async getBody() {
58
+ if (htmlRender instanceof Uint8Array) {
59
+ try {
60
+ return new TextDecoder('utf-8', { fatal: true }).decode(htmlRender);
61
+ }
62
+ catch {
63
+ assertUsage(false, getErrMsg(htmlRender, renderHook, 'getBody()', `The Uint8Array isn't UTF-8 text: use ${pc.cyan('pageContext.httpResponse.pipe()')} instead`));
64
+ }
65
+ }
57
66
  const body = await getHtmlString(htmlRender);
58
67
  return body;
59
68
  },
@@ -99,7 +108,8 @@ function getHttpResponseBodyStreamHandlers(htmlRender, renderHook) {
99
108
  function getFixMsg(kind, type) {
100
109
  const streamName = getStreamName(kind, type);
101
110
  assert(['a ', 'an ', 'the '].some((s) => streamName.startsWith(s)));
102
- assert(renderHook);
111
+ if (!renderHook)
112
+ return `Use ${pc.cyan('pageContext.httpResponse.pipe()')} instead`;
103
113
  const { hookFilePath, hookName } = renderHook;
104
114
  return `Make sure the ${hookName}() hook defined by ${hookFilePath} provides ${streamName} instead`;
105
115
  }
@@ -112,7 +122,9 @@ function getErrMsg(htmlRender, renderHook, method, msgAddendum) {
112
122
  .join('. ');
113
123
  }
114
124
  function getErrMsgBody(htmlRender, renderHook) {
115
- assert(renderHook);
125
+ // E.g. a pageContext.json response with streamed pageContext values
126
+ if (!renderHook)
127
+ return `HTTP response body is ${getHookReturnType(htmlRender)}`;
116
128
  const { hookFilePath, hookName } = renderHook;
117
129
  const hookReturnType = getHookReturnType(htmlRender);
118
130
  assert(['a ', 'an ', 'the '].some((s) => hookReturnType.startsWith(s)));
@@ -124,6 +136,9 @@ function getHookReturnType(htmlRender) {
124
136
  if (typeof htmlRender === 'string') {
125
137
  return 'an HTML string';
126
138
  }
139
+ else if (htmlRender instanceof Uint8Array) {
140
+ return 'a Uint8Array';
141
+ }
127
142
  else if (isStream(htmlRender)) {
128
143
  return inferStreamName(htmlRender);
129
144
  }
@@ -0,0 +1,8 @@
1
+ export { getPageContextJson };
2
+ export { getPageContextJsonFile };
3
+ import { type PageContextSerialization } from './html/serializeContext.js';
4
+ import type { PageContext_logRuntime } from '../loggerRuntime.js';
5
+ import '../../assertEnvServer.js';
6
+ type PageContextForJson = PageContextSerialization & NonNullable<PageContext_logRuntime>;
7
+ declare function getPageContextJson(pageContext: PageContextForJson): string | ReadableStream<Uint8Array>;
8
+ declare function getPageContextJsonFile(pageContext: PageContextSerialization, lines: null | string[]): string;
@@ -0,0 +1,47 @@
1
+ // The body of `.pageContext.json` requests (client-side navigation) and of pre-rendered `index.pageContext.json` files.
2
+ //
3
+ // - Without streamed pageContext values: the serialized pageContext, as is.
4
+ // - With streamed pageContext values (see shared-server-client/streamedValues.ts): a JSON array, written line by line
5
+ // so that the client can read it while it streams:
6
+ // [{"pageId":"/pages/index","data":"!VikePromise:0"}
7
+ // ,{"s":0,"v":{"title":"Hello"}}
8
+ // ]
9
+ export { getPageContextJson };
10
+ export { getPageContextJsonFile };
11
+ import { getPageContextClientSerialized } from './html/serializeContext.js';
12
+ import { pumpStreamedValues } from './streamedValues/pump.js';
13
+ import '../../assertEnvServer.js';
14
+ const textEncoder = new TextEncoder();
15
+ function getPageContextJson(pageContext) {
16
+ const { pageContextSerialized, streamedValues } = getPageContextClientSerialized(pageContext, false);
17
+ if (streamedValues.length === 0)
18
+ return pageContextSerialized;
19
+ let pump;
20
+ let isCancelled = false;
21
+ return new ReadableStream({
22
+ start(controller) {
23
+ const enqueue = (line) => controller.enqueue(textEncoder.encode(line + '\n'));
24
+ // Sent right away: the client runs its hooks while the values are still being produced
25
+ enqueue('[' + pageContextSerialized);
26
+ pump = pumpStreamedValues(pageContext, streamedValues, (line) => enqueue(',' + line), { failFast: false });
27
+ pump.done.then(() => {
28
+ if (isCancelled)
29
+ return;
30
+ enqueue(']');
31
+ controller.close();
32
+ });
33
+ },
34
+ // E.g. the user navigated away
35
+ cancel() {
36
+ isCancelled = true;
37
+ pump.cancel();
38
+ },
39
+ });
40
+ }
41
+ // Pre-rendering: the lines were collected while rendering the HTML (see html/streamedValuesHtml.ts)
42
+ function getPageContextJsonFile(pageContext, lines) {
43
+ const { pageContextSerialized } = getPageContextClientSerialized(pageContext, false);
44
+ if (!lines)
45
+ return pageContextSerialized;
46
+ return ['[' + pageContextSerialized, ...lines.map((line) => ',' + line), ']'].map((line) => line + '\n').join('');
47
+ }
@@ -1,6 +1,7 @@
1
1
  export { handleErrorWithoutErrorPage };
2
2
  import type { GlobalContextServerInternal } from '../globalContext.js';
3
3
  import type { PageContextCreatedServer } from './createPageContextServer.js';
4
+ import type { PageContextAborted } from '../../../shared-server-client/route/abort.js';
4
5
  import '../../assertEnvServer.js';
5
6
  declare function handleErrorWithoutErrorPage<PageContext extends PageContextCreatedServer & {
6
7
  errorWhileRendering: null | Error;
@@ -8,6 +9,7 @@ declare function handleErrorWithoutErrorPage<PageContext extends PageContextCrea
8
9
  pageId: null;
9
10
  _globalContext: GlobalContextServerInternal;
10
11
  urlOriginal: string;
12
+ pageContextsAborted: PageContextAborted[];
11
13
  }>(pageContext: PageContext): PageContext & {
12
14
  httpResponse: import("./createHttpResponse.js").HttpResponse;
13
15
  };
@@ -20,7 +20,7 @@ function handleErrorWithoutErrorPage(pageContext) {
20
20
  else {
21
21
  const __getPageAssets = async () => [];
22
22
  objectAssign(pageContext, { __getPageAssets });
23
- const httpResponse = createHttpResponseErrorFallbackJson();
23
+ const httpResponse = createHttpResponseErrorFallbackJson(pageContext);
24
24
  objectAssign(pageContext, { httpResponse });
25
25
  return pageContext;
26
26
  }
@@ -1,11 +1,20 @@
1
1
  export { resolveHeadersResponseEarly };
2
2
  export { resolveHeadersResponseFinal };
3
+ export { resolveHeadersResponseSetCookie };
4
+ export { getHeadersSetCookieAborted };
3
5
  import { PageContextCspNonce } from './csp.js';
4
6
  import type { PageContextAfterPageEntryLoaded } from './loadPageConfigsLazyServerSide.js';
7
+ import type { PageContextAborted } from '../../../shared-server-client/route/abort.js';
5
8
  import '../../assertEnvServer.js';
6
- declare function resolveHeadersResponseFinal(pageContext: {
9
+ type PageContextHeadersResponse = {
7
10
  headersResponse?: Headers;
8
- }, statusCode: number): [string, string][];
11
+ pageContextsAborted: PageContextAborted[];
12
+ };
13
+ declare function resolveHeadersResponseFinal(pageContext: PageContextHeadersResponse, statusCode: number): [string, string][];
14
+ declare function resolveHeadersResponseSetCookie(pageContext: PageContextHeadersResponse): [string, string][];
15
+ declare function getHeadersSetCookieAborted(pageContext: {
16
+ pageContextsAborted: PageContextAborted[];
17
+ }): [string, string][];
9
18
  declare function resolveHeadersResponseEarly(pageContext: PageContextAfterPageEntryLoaded & PageContextCspNonce): Promise<{
10
19
  headersResponse: Headers;
11
20
  }>;
@@ -1,21 +1,41 @@
1
1
  export { resolveHeadersResponseEarly };
2
2
  export { resolveHeadersResponseFinal };
3
+ export { resolveHeadersResponseSetCookie };
4
+ export { getHeadersSetCookieAborted };
3
5
  import { addCspResponseHeader } from './csp.js';
4
6
  import { isCallable } from '../../../utils/isCallable.js';
5
7
  import { cacheControlDisable, getCacheControl } from './getCacheControl.js';
8
+ import { getPageContextPublicServer } from './getPageContextPublicServer.js';
6
9
  import '../../assertEnvServer.js';
10
+ // Headers of HTML page responses
7
11
  function resolveHeadersResponseFinal(pageContext, statusCode) {
8
12
  const headersResponse = pageContext.headersResponse || new Headers();
9
13
  // 5xx error pages are temporary and shouldn't be cached.
10
14
  // This overrides any previously set Cache-Control value.
11
15
  if (statusCode >= 500)
12
16
  headersResponse.set('Cache-Control', cacheControlDisable);
13
- const headers = [];
17
+ const headers = getHeadersSetCookieAborted(pageContext);
14
18
  headersResponse.forEach((value, key) => {
15
19
  headers.push([key, value]);
16
20
  });
17
21
  return headers;
18
22
  }
23
+ // Headers of `pageContext.json` and redirect responses: only `Set-Cookie` applies to them, the other headers (e.g. `Cache-Control` and `Content-Security-Policy`) are about the HTML page.
24
+ function resolveHeadersResponseSetCookie(pageContext) {
25
+ const headersResponse = pageContext.headersResponse || new Headers();
26
+ const headers = getHeadersSetCookieAborted(pageContext);
27
+ headersResponse.getSetCookie().forEach((value) => {
28
+ headers.push(['set-cookie', value]);
29
+ });
30
+ return headers;
31
+ }
32
+ // Cookies set before `throw redirect()` or `throw render()` are kept. They're sent first, so that a cookie set again later wins.
33
+ function getHeadersSetCookieAborted(pageContext) {
34
+ return pageContext.pageContextsAborted.flatMap((pageContextAborted) => {
35
+ const { headersResponse } = pageContextAborted;
36
+ return (headersResponse?.getSetCookie() ?? []).map((value) => ['set-cookie', value]);
37
+ });
38
+ }
19
39
  async function resolveHeadersResponseEarly(pageContext) {
20
40
  const headersResponse = await resolveHeadersResponseConfig(pageContext);
21
41
  if (!headersResponse.get('Cache-Control')) {
@@ -34,7 +54,7 @@ async function resolveHeadersResponseConfig(pageContext) {
34
54
  await Promise.all((pageContext.config.headersResponse ?? []).map(async (headers) => {
35
55
  let headersInit;
36
56
  if (isCallable(headers)) {
37
- headersInit = await headers(pageContext);
57
+ headersInit = await headers(getPageContextPublicServer(pageContext));
38
58
  }
39
59
  else {
40
60
  headersInit = headers;
@@ -2,7 +2,7 @@ export { getHtmlTags };
2
2
  import { assert, assertWarning, assertUsage } from '../../../../../utils/assert.js';
3
3
  import { freezePartial } from '../../../../../utils/freezePartial.js';
4
4
  import { isObject } from '../../../../../utils/isObject.js';
5
- import { getGlobalContextClientSerialized, getPageContextClientSerialized, } from '../serializeContext.js';
5
+ import { getGlobalContextClientSerialized } from '../serializeContext.js';
6
6
  import { inferAssetTag, inferPreloadTag } from './inferHtmlTags.js';
7
7
  import { mergeScriptTags } from './mergeScriptTags.js';
8
8
  import { getPageConfig } from '../../../../../shared-server-client/page-configs/helpers.js';
@@ -12,6 +12,7 @@ import { getConfigDefinedAt } from '../../../../../shared-server-client/page-con
12
12
  import { htmlElementId_globalContext, htmlElementId_pageContext, } from '../../../../../shared-server-client/htmlElementIds.js';
13
13
  import { isFontFallback } from '../../isFontFallback.js';
14
14
  import { inferNonceAttr } from '../../csp.js';
15
+ import { serializePageContextHtml } from '../streamedValuesHtml.js';
15
16
  import '../../../../assertEnvServer.js';
16
17
  const stamp = '__injectFilterEntry';
17
18
  async function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectFilter, pageAssets, viteDevScript, isStream) {
@@ -128,7 +129,7 @@ async function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectF
128
129
  htmlTags.push({
129
130
  htmlTag: () =>
130
131
  // Needs to be called after resolvePageContextPromise()
131
- getPageContextJsonScriptTag(pageContext),
132
+ getPageContextJsonScriptTag(pageContext, streamFromReactStreamingPackage),
132
133
  position: positionJavaScriptEntry,
133
134
  });
134
135
  // <script id="vike_globalContext" type="application/json">
@@ -184,8 +185,8 @@ function mergeScriptEntries(pageAssets, viteDevScript, pageContext) {
184
185
  scriptEntry = mergeScriptTags(scriptEntry, pageContext);
185
186
  return scriptEntry;
186
187
  }
187
- function getPageContextJsonScriptTag(pageContext) {
188
- const pageContextClientSerialized = getPageContextClientSerialized(pageContext, true);
188
+ function getPageContextJsonScriptTag(pageContext, streamFromReactStreamingPackage) {
189
+ const pageContextClientSerialized = serializePageContextHtml(pageContext, streamFromReactStreamingPackage);
189
190
  const nonceAttr = inferNonceAttr(pageContext);
190
191
  const htmlTag = `<script id="${htmlElementId_pageContext}" type="application/json"${nonceAttr}>${pageContextClientSerialized}</script>`;
191
192
  // Used by contra.com https://github.com/gajus
@@ -7,6 +7,7 @@ import type { HtmlPart } from './renderHtml.js';
7
7
  import { type PreloadFilter } from './injectAssets/getHtmlTags.js';
8
8
  import type { StreamFromReactStreamingPackage } from './stream/react-streaming.js';
9
9
  import type { PageContextSerialization } from './serializeContext.js';
10
+ import { type PageContextStreamedValuesHtml } from './streamedValuesHtml.js';
10
11
  import type { GlobalContextServerInternal } from '../../globalContext.js';
11
12
  import '../../../assertEnvServer.js';
12
13
  type PageContextInjectAssets = {
@@ -22,7 +23,7 @@ type PageContextInjectAssets = {
22
23
  _baseServer: string;
23
24
  is404: null | boolean;
24
25
  _globalContext: GlobalContextServerInternal;
25
- } & PageContextSerialization;
26
+ } & PageContextSerialization & PageContextStreamedValuesHtml;
26
27
  declare function injectHtmlTagsToString(htmlParts: HtmlPart[], pageContext: PageContextInjectAssets & {
27
28
  _isStream: false;
28
29
  }, injectFilter: PreloadFilter): Promise<string>;
@@ -31,6 +32,6 @@ declare function injectHtmlTagsToStream(pageContext: PageContextInjectAssets & {
31
32
  }, streamFromReactStreamingPackage: null | StreamFromReactStreamingPackage, injectFilter: PreloadFilter): {
32
33
  injectAtStreamBegin: (htmlPartsBegin: HtmlPart[]) => Promise<string>;
33
34
  injectAtStreamAfterFirstChunk: () => null | string;
34
- injectAtStreamEnd: (htmlPartsEnd: HtmlPart[]) => Promise<string>;
35
+ injectAtStreamEnd: (htmlPartsEnd: HtmlPart[], writeHtml: (html: string) => void) => Promise<string>;
35
36
  };
36
37
  type PageContextPromise = null | Promise<unknown> | (() => void | Promise<unknown>);
@@ -6,6 +6,7 @@ import { assert } from '../../../../utils/assert.js';
6
6
  import { assertPageContextProvidedByUser } from '../../../../shared-server-client/assertPageContextProvidedByUser.js';
7
7
  import { joinHtmlTags, injectHtmlTags, createHtmlHeadIfMissing, injectHtmlTagsUsingStream, } from './injectAssets/injectHtmlTags.js';
8
8
  import { getHtmlTags } from './injectAssets/getHtmlTags.js';
9
+ import { getStreamedValuesHtml, writeStreamedValuesHtmlAtStreamEnd, } from './streamedValuesHtml.js';
9
10
  import { getViteDevScript } from './injectAssets/getViteDevScript.js';
10
11
  import '../../../assertEnvServer.js';
11
12
  async function injectHtmlTagsToString(htmlParts, pageContext, injectFilter) {
@@ -16,6 +17,10 @@ async function injectHtmlTagsToString(htmlParts, pageContext, injectFilter) {
16
17
  htmlString = injectToHtmlBegin(htmlString, htmlTags);
17
18
  htmlString = injectToHtmlEnd(htmlString, htmlTags);
18
19
  assert(htmlTags.filter((snippet) => snippet.position === 'HTML_STREAM').length === 0);
20
+ const streamedValuesHtml = await getStreamedValuesHtml(pageContext);
21
+ if (streamedValuesHtml !== null) {
22
+ htmlString = injectToHtmlEnd(htmlString, [{ htmlTag: streamedValuesHtml, position: 'HTML_END' }]);
23
+ }
19
24
  return htmlString;
20
25
  }
21
26
  function injectHtmlTagsToStream(pageContext, streamFromReactStreamingPackage, injectFilter) {
@@ -48,12 +53,13 @@ function injectHtmlTagsToStream(pageContext, streamFromReactStreamingPackage, in
48
53
  const htmlFragment = joinHtmlTags(tags);
49
54
  return htmlFragment;
50
55
  }
51
- async function injectAtStreamEnd(htmlPartsEnd) {
56
+ async function injectAtStreamEnd(htmlPartsEnd, writeHtml) {
52
57
  assert(htmlTags);
53
58
  await resolvePageContextPromise(pageContext);
54
59
  const pageAssets = await pageContext.__getPageAssets();
55
60
  let htmlEnd = htmlPartsToString(htmlPartsEnd, pageAssets);
56
61
  htmlEnd = injectToHtmlEnd(htmlEnd, htmlTags);
62
+ htmlEnd = await writeStreamedValuesHtmlAtStreamEnd(pageContext, htmlEnd, writeHtml);
57
63
  return htmlEnd;
58
64
  }
59
65
  }
@@ -13,6 +13,7 @@ import { objectAssign } from '../../../../utils/objectAssign.js';
13
13
  import { injectHtmlTagsToString, injectHtmlTagsToStream } from './injectAssets.js';
14
14
  import { processStream, isStream, streamToString, } from './stream.js';
15
15
  import { isStreamFromReactStreamingPackage } from './stream/react-streaming.js';
16
+ import { cancelStreamedValuesHtml } from './streamedValuesHtml.js';
16
17
  import pc from '@brillout/picocolors';
17
18
  import '../../../assertEnvServer.js';
18
19
  function isDocumentHtml(something) {
@@ -61,6 +62,7 @@ async function renderHtmlStream(streamOriginal, injectString, pageContext, onErr
61
62
  const processStreamOptions = {
62
63
  onErrorWhileStreaming,
63
64
  enableEagerStreaming: pageContext.enableEagerStreaming,
65
+ onCancel: () => cancelStreamedValuesHtml(pageContext),
64
66
  };
65
67
  if (injectString) {
66
68
  let streamFromReactStreamingPackage = null;
@@ -71,8 +73,8 @@ async function renderHtmlStream(streamOriginal, injectString, pageContext, onErr
71
73
  processStreamOptions.injectStringAtBegin = async () => {
72
74
  return await injectAtStreamBegin(injectString.htmlPartsBegin);
73
75
  };
74
- processStreamOptions.injectStringAtEnd = async () => {
75
- return await injectAtStreamEnd(injectString.htmlPartsEnd);
76
+ processStreamOptions.injectStringAtEnd = async (writeHtml) => {
77
+ return await injectAtStreamEnd(injectString.htmlPartsEnd, writeHtml);
76
78
  };
77
79
  processStreamOptions.injectStringAfterFirstChunk = () => {
78
80
  return injectAtStreamAfterFirstChunk();
@@ -9,6 +9,7 @@ import type { GlobalContextServerInternal } from '../../globalContext.js';
9
9
  import type { PageContextCreatedServer } from '../createPageContextServer.js';
10
10
  import type { PageContextBegin } from '../../renderPageServer.js';
11
11
  import type { PageContextCspNonce } from '../csp.js';
12
+ import { type StreamedValue } from '../streamedValues/registry.js';
12
13
  import '../../../assertEnvServer.js';
13
14
  type PageContextSerialization = PageContextCreatedServer & {
14
15
  pageId: string;
@@ -20,7 +21,10 @@ type PageContextSerialization = PageContextCreatedServer & {
20
21
  _globalContext: GlobalContextServerInternal;
21
22
  _isPageContextJsonRequest: null | PageContextBegin['_isPageContextJsonRequest'];
22
23
  } & PageContextCspNonce;
23
- declare function getPageContextClientSerialized(pageContext: PageContextSerialization, isHtmlJsonScript: boolean): string;
24
+ declare function getPageContextClientSerialized(pageContext: PageContextSerialization, isHtmlJsonScript: boolean): {
25
+ pageContextSerialized: string;
26
+ streamedValues: StreamedValue[];
27
+ };
24
28
  declare function getGlobalContextClientSerialized(pageContext: PageContextSerialization, isHtmlJsonScript: boolean): string;
25
29
  type PassToClient = string[];
26
30
  type PassToClientPublic = (string | {
@@ -7,12 +7,12 @@ import { getPropAccessNotation } from '../../../../utils/getPropAccessNotation.j
7
7
  import { assert, assertUsage, assertWarning } from '../../../../utils/assert.js';
8
8
  import { hasProp } from '../../../../utils/hasProp.js';
9
9
  import { isErrorPage } from '../../../../shared-server-client/error-page.js';
10
- import { addIs404ToPageProps } from '../../../../shared-server-client/addIs404ToPageProps.js';
11
10
  import pc from '@brillout/picocolors';
12
11
  import { NOT_SERIALIZABLE } from '../../../../shared-server-client/NOT_SERIALIZABLE.js';
13
12
  import { pageContextInitIsPassedToClient } from '../../../../shared-server-client/misc/pageContextInitIsPassedToClient.js';
14
13
  import { isServerSideError } from '../../../../shared-server-client/misc/isServerSideError.js';
15
14
  import { getPropKeys, getPropVal, setPropVal } from './propKeys.js';
15
+ import { getReplacer } from '../streamedValues/registry.js';
16
16
  import { assertRouteParams } from '../../../../shared-server-client/route/resolveRouteFunction.js';
17
17
  import '../../../assertEnvServer.js';
18
18
  const passToClientBuiltInPageContext = [
@@ -30,6 +30,8 @@ const passToClientBuiltInPageContext = [
30
30
  'data', // for data() hook
31
31
  ];
32
32
  const pageToClientBuiltInPageContextError = ['pageProps', 'is404', isServerSideError];
33
+ // Streamed pageContext values (see shared-server-client/streamedValues.ts) are serialized as placeholders and returned:
34
+ // the caller sends them after the serialized pageContext.
33
35
  function getPageContextClientSerialized(pageContext, isHtmlJsonScript) {
34
36
  const passToClientPageContext = getPassToClientPageContext(pageContext);
35
37
  const res = applyPassToClient(passToClientPageContext, pageContext);
@@ -38,8 +40,9 @@ function getPageContextClientSerialized(pageContext, isHtmlJsonScript) {
38
40
  if (pageContextClientProps.some((prop) => getPropVal(pageContext._pageContextInit, prop))) {
39
41
  pageContextClient[pageContextInitIsPassedToClient] = true;
40
42
  }
41
- const pageContextClientSerialized = serializeObject(pageContextClient, passToClientPageContext, 'pageContext', isHtmlJsonScript);
42
- return pageContextClientSerialized;
43
+ const { replacer, streamedValues } = getReplacer(pageContext);
44
+ const pageContextSerialized = serializeObject(pageContextClient, passToClientPageContext, 'pageContext', isHtmlJsonScript, replacer);
45
+ return { pageContextSerialized, streamedValues };
43
46
  }
44
47
  function getGlobalContextClientSerialized(pageContext, isHtmlJsonScript) {
45
48
  const passToClient = pageContext._passToClient;
@@ -49,10 +52,10 @@ function getGlobalContextClientSerialized(pageContext, isHtmlJsonScript) {
49
52
  const globalContextClientSerialized = serializeObject(globalContextClient, passToClient, 'globalContext', isHtmlJsonScript);
50
53
  return globalContextClientSerialized;
51
54
  }
52
- function serializeObject(obj, passToClient, objName, isHtmlJsonScript) {
55
+ function serializeObject(obj, passToClient, objName, isHtmlJsonScript, replacer) {
53
56
  let serialized;
54
57
  try {
55
- serialized = serializeValue(obj, isHtmlJsonScript);
58
+ serialized = serializeValue(obj, isHtmlJsonScript, undefined, replacer);
56
59
  }
57
60
  catch (err) {
58
61
  const h = (s) => pc.cyan(s);
@@ -65,7 +68,7 @@ function serializeObject(obj, passToClient, objName, isHtmlJsonScript) {
65
68
  const { value } = res;
66
69
  const varName = `${objName}${getPropKeys(prop).map(getPropAccessNotation).join('')}`;
67
70
  try {
68
- serializeValue(value, isHtmlJsonScript, varName);
71
+ serializeValue(value, isHtmlJsonScript, varName, replacer);
69
72
  }
70
73
  catch (err) {
71
74
  propsNonSerializable.push(prop);
@@ -103,7 +106,7 @@ function serializeObject(obj, passToClient, objName, isHtmlJsonScript) {
103
106
  obj[getPropKeys(prop)[0]] = NOT_SERIALIZABLE;
104
107
  });
105
108
  try {
106
- serialized = serializeValue(obj, isHtmlJsonScript);
109
+ serialized = serializeValue(obj, isHtmlJsonScript, undefined, replacer);
107
110
  }
108
111
  catch (err) {
109
112
  assert(false);
@@ -111,10 +114,11 @@ function serializeObject(obj, passToClient, objName, isHtmlJsonScript) {
111
114
  }
112
115
  return serialized;
113
116
  }
114
- function serializeValue(value, isHtmlJsonScript, varName) {
117
+ function serializeValue(value, isHtmlJsonScript, varName, replacer) {
115
118
  return stringify(value, {
116
119
  forbidReactElements: true,
117
120
  valueName: varName,
121
+ replacer,
118
122
  htmlScriptSafe: {
119
123
  // Could be set to `isHtmlJsonScript` but we always use `htmlScriptSafe.escapeScripts` to be extra safe
120
124
  escapeScripts: true,
@@ -127,7 +131,6 @@ function getPassToClientPageContext(pageContext) {
127
131
  let passToClient = [...pageContext._passToClient, ...passToClientBuiltInPageContext];
128
132
  if (isErrorPage(pageContext.pageId, pageContext._globalContext._pageConfigs)) {
129
133
  assert(hasProp(pageContext, 'is404', 'boolean'));
130
- addIs404ToPageProps(pageContext);
131
134
  passToClient.push(...pageToClientBuiltInPageContextError);
132
135
  }
133
136
  passToClient = unique(passToClient);
@@ -16,6 +16,8 @@ export { isStreamReadableNode };
16
16
  export { getStreamName };
17
17
  export { inferStreamName };
18
18
  export { streamReadableWebToString };
19
+ export { streamReadableWebToBytes };
20
+ export { awaitFirstChunk };
19
21
  export { streamPipeNodeToString };
20
22
  export { isStreamWritableWeb };
21
23
  export { isStreamWritableNode };
@@ -46,17 +48,22 @@ declare function isStreamWritableWeb(thing: unknown): thing is StreamWritableWeb
46
48
  declare function isStreamReadableNode(thing: unknown): thing is StreamReadableNode;
47
49
  declare function isStreamWritableNode(thing: unknown): thing is StreamWritableNode;
48
50
  declare function streamReadableWebToString(readableWeb: ReadableStream): Promise<string>;
51
+ declare function streamReadableWebToBytes(readableWeb: ReadableStream): Promise<Uint8Array>;
52
+ declare function awaitFirstChunk(stream: StreamReadableWeb, onErrorWhileStreaming: (err: unknown) => void): Promise<StreamReadableWeb>;
49
53
  declare function streamPipeNodeToString(streamPipeNode: StreamPipeNode): Promise<string>;
50
- declare function getStreamReadableNode(htmlRender: HtmlRender): Promise<null | StreamReadableNode>;
51
- declare function getStreamReadableWeb(htmlRender: HtmlRender): null | StreamReadableWeb;
52
- declare function pipeToStreamWritableWeb(htmlRender: HtmlRender, writable: StreamWritableWeb): boolean;
53
- declare function pipeToStreamWritableNode(htmlRender: HtmlRender, writable: StreamWritableNode): boolean;
54
- declare function processStream(streamOriginal: StreamProviderAny, { injectStringAtBegin, injectStringAfterFirstChunk, injectStringAtEnd, onErrorWhileStreaming, enableEagerStreaming, }: {
54
+ declare function getStreamReadableNode(htmlRender: HtmlRender | Uint8Array): Promise<null | StreamReadableNode>;
55
+ declare function getStreamReadableWeb(htmlRender: HtmlRender | Uint8Array): null | StreamReadableWeb;
56
+ declare function pipeToStreamWritableWeb(htmlRender: HtmlRender | Uint8Array, writable: StreamWritableWeb): boolean;
57
+ declare function pipeToStreamWritableNode(htmlRender: HtmlRender | Uint8Array, writable: StreamWritableNode): boolean;
58
+ declare function processStream(streamOriginal: StreamProviderAny, { injectStringAtBegin, injectStringAfterFirstChunk, injectStringAtEnd, onErrorWhileStreaming, enableEagerStreaming, onCancel, }: {
55
59
  injectStringAtBegin?: () => Promise<string>;
56
60
  injectStringAfterFirstChunk?: () => string | null;
57
- injectStringAtEnd?: () => Promise<string>;
61
+ /** `writeHtml()` writes HTML before the returned string (e.g. streamed pageContext values) */
62
+ injectStringAtEnd?: (writeHtml: (html: string) => void) => Promise<string>;
58
63
  onErrorWhileStreaming: (err: unknown) => void;
59
64
  enableEagerStreaming?: boolean;
65
+ /** The stream was cancelled (e.g. the user closed the tab) or failed */
66
+ onCancel: () => void;
60
67
  }): Promise<StreamProviderNormalized>;
61
68
  declare function isStream(something: unknown): something is StreamProviderAny;
62
69
  declare const __streamPipeWeb = "__streamPipeWeb";