vike 0.4.267-commit-b005535 → 0.4.267-commit-5676e14

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 (139) 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/renderPageClient.d.ts +472 -9
  6. package/dist/client/runtime-client-routing/renderPageClient.js +11 -5
  7. package/dist/client/runtime-client-routing/streamedValues.d.ts +5 -0
  8. package/dist/client/runtime-client-routing/streamedValues.js +23 -0
  9. package/dist/client/runtime-server-routing/createPageContextClient.d.ts +4 -0
  10. package/dist/client/runtime-server-routing/entry.js +1 -1
  11. package/dist/client/runtime-server-routing/getGlobalContextClientInternal.d.ts +4 -0
  12. package/dist/client/shared/getGlobalContextClientInternalShared.d.ts +4 -0
  13. package/dist/client/shared/getJsonSerializedInHtml.d.ts +2 -2
  14. package/dist/client/shared/getJsonSerializedInHtml.js +9 -6
  15. package/dist/client/shared/streamedValues/asyncIterable.d.ts +4 -0
  16. package/dist/client/shared/streamedValues/asyncIterable.js +26 -0
  17. package/dist/client/shared/streamedValues/lines.d.ts +11 -0
  18. package/dist/client/shared/streamedValues/lines.js +19 -0
  19. package/dist/client/shared/streamedValues/promise.d.ts +4 -0
  20. package/dist/client/shared/streamedValues/promise.js +19 -0
  21. package/dist/client/shared/streamedValues/readableStream.d.ts +4 -0
  22. package/dist/client/shared/streamedValues/readableStream.js +44 -0
  23. package/dist/client/shared/streamedValues/registry.d.ts +21 -0
  24. package/dist/client/shared/streamedValues/registry.js +40 -0
  25. package/dist/client/shared/streamedValues.d.ts +7 -0
  26. package/dist/client/shared/streamedValues.js +82 -0
  27. package/dist/node/api/resolveViteConfigUser.js +2 -2
  28. package/dist/node/prerender/runPrerender.d.ts +12 -4
  29. package/dist/node/prerender/runPrerender.js +60 -15
  30. package/dist/node/vite/assertEnvVite.js +1 -1
  31. package/dist/node/vite/index.js +2 -0
  32. package/dist/node/vite/plugins/build/handleAssetsManifest.js +6 -2
  33. package/dist/node/vite/plugins/build/pluginBuildApp.js +25 -26
  34. package/dist/node/vite/plugins/build/pluginBuildConfig.d.ts +2 -2
  35. package/dist/node/vite/plugins/build/pluginBuildConfig.js +24 -16
  36. package/dist/node/vite/plugins/build/pluginDistFileNames.js +70 -50
  37. package/dist/node/vite/plugins/build/pluginEnvironmentEntries.d.ts +6 -0
  38. package/dist/node/vite/plugins/build/pluginEnvironmentEntries.js +71 -0
  39. package/dist/node/vite/plugins/build/pluginSuppressRollupWarning.js +19 -17
  40. package/dist/node/vite/plugins/pluginCommon.js +9 -6
  41. package/dist/node/vite/plugins/pluginDev/optimizeDeps.js +1 -1
  42. package/dist/node/vite/plugins/pluginReplaceConstantsGlobalThis.js +6 -4
  43. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntry.d.ts +2 -1
  44. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntry.js +29 -12
  45. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntryWithOldDesign.js +3 -2
  46. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFilePageEntry.js +7 -7
  47. package/dist/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.d.ts +7 -5
  48. package/dist/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js +4 -10
  49. package/dist/node/vite/plugins/pluginVirtualFiles.js +20 -0
  50. package/dist/node/vite/shared/addSsrMiddleware.js +13 -1
  51. package/dist/node/vite/shared/getAssetsDir.d.ts +3 -2
  52. package/dist/node/vite/shared/getAssetsDir.js +3 -3
  53. package/dist/node/vite/shared/isViteCli.d.ts +3 -3
  54. package/dist/node/vite/shared/isViteCli.js +80 -84
  55. package/dist/node/vite/shared/isViteServerSide.js +2 -7
  56. package/dist/node/vite/shared/resolveVikeConfigInternal/metaBuiltIn.d.ts +1 -1
  57. package/dist/node/vite/shared/resolveVikeConfigInternal/metaBuiltIn.js +8 -6
  58. package/dist/node/vite/shared/resolveVikeConfigInternal.d.ts +4 -1
  59. package/dist/node/vite/shared/resolveVikeConfigInternal.js +82 -11
  60. package/dist/server/runtime/globalContext.d.ts +20 -0
  61. package/dist/server/runtime/renderPageServer/analyzePage.js +3 -3
  62. package/dist/server/runtime/renderPageServer/createHttpResponse.d.ts +20 -7
  63. package/dist/server/runtime/renderPageServer/createHttpResponse.js +34 -15
  64. package/dist/server/runtime/renderPageServer/createPageContextServer.d.ts +4 -0
  65. package/dist/server/runtime/renderPageServer/execHookOnError.js +1 -1
  66. package/dist/server/runtime/renderPageServer/execHookOnRenderHtml.d.ts +9 -0
  67. package/dist/server/runtime/renderPageServer/execHookOnRenderHtml.js +17 -5
  68. package/dist/server/runtime/renderPageServer/getHttpResponseBody.d.ts +2 -2
  69. package/dist/server/runtime/renderPageServer/getHttpResponseBody.js +17 -2
  70. package/dist/server/runtime/renderPageServer/getPageContextJson.d.ts +8 -0
  71. package/dist/server/runtime/renderPageServer/getPageContextJson.js +47 -0
  72. package/dist/server/runtime/renderPageServer/handleErrorWithoutErrorPage.d.ts +2 -0
  73. package/dist/server/runtime/renderPageServer/handleErrorWithoutErrorPage.js +1 -1
  74. package/dist/server/runtime/renderPageServer/headersResponse.d.ts +11 -2
  75. package/dist/server/runtime/renderPageServer/headersResponse.js +20 -1
  76. package/dist/server/runtime/renderPageServer/html/injectAssets/getHtmlTags.js +5 -4
  77. package/dist/server/runtime/renderPageServer/html/injectAssets.d.ts +3 -2
  78. package/dist/server/runtime/renderPageServer/html/injectAssets.js +7 -1
  79. package/dist/server/runtime/renderPageServer/html/renderHtml.js +4 -2
  80. package/dist/server/runtime/renderPageServer/html/serializeContext.d.ts +5 -1
  81. package/dist/server/runtime/renderPageServer/html/serializeContext.js +12 -9
  82. package/dist/server/runtime/renderPageServer/html/stream.d.ts +13 -6
  83. package/dist/server/runtime/renderPageServer/html/stream.js +121 -31
  84. package/dist/server/runtime/renderPageServer/html/streamedValuesHtml.d.ts +30 -0
  85. package/dist/server/runtime/renderPageServer/html/streamedValuesHtml.js +92 -0
  86. package/dist/server/runtime/renderPageServer/loadPageConfigsLazyServerSide.d.ts +4 -0
  87. package/dist/server/runtime/renderPageServer/loadPageConfigsLazyServerSide.js +5 -1
  88. package/dist/server/runtime/renderPageServer/loadPageContextEnvironments.d.ts +15 -0
  89. package/dist/server/runtime/renderPageServer/loadPageContextEnvironments.js +61 -0
  90. package/dist/server/runtime/renderPageServer/renderPageServerAfterRoute.d.ts +314 -1
  91. package/dist/server/runtime/renderPageServer/renderPageServerAfterRoute.js +21 -12
  92. package/dist/server/runtime/renderPageServer/streamedValues/asyncIterable.d.ts +4 -0
  93. package/dist/server/runtime/renderPageServer/streamedValues/asyncIterable.js +12 -0
  94. package/dist/server/runtime/renderPageServer/streamedValues/lines.d.ts +10 -0
  95. package/dist/server/runtime/renderPageServer/streamedValues/lines.js +49 -0
  96. package/dist/server/runtime/renderPageServer/streamedValues/promise.d.ts +4 -0
  97. package/dist/server/runtime/renderPageServer/streamedValues/promise.js +14 -0
  98. package/dist/server/runtime/renderPageServer/streamedValues/pump.d.ts +10 -0
  99. package/dist/server/runtime/renderPageServer/streamedValues/pump.js +67 -0
  100. package/dist/server/runtime/renderPageServer/streamedValues/readableStream.d.ts +4 -0
  101. package/dist/server/runtime/renderPageServer/streamedValues/readableStream.js +12 -0
  102. package/dist/server/runtime/renderPageServer/streamedValues/registry.d.ts +28 -0
  103. package/dist/server/runtime/renderPageServer/streamedValues/registry.js +33 -0
  104. package/dist/server/runtime/renderPageServer.d.ts +4 -0
  105. package/dist/server/runtime/renderPageServer.js +18 -8
  106. package/dist/shared-server-client/createGlobalContextShared.d.ts +8 -0
  107. package/dist/shared-server-client/createGlobalContextShared.js +2 -1
  108. package/dist/shared-server-client/getPageContextPublicShared.js +0 -2
  109. package/dist/shared-server-client/getPageFiles/parseVirtualFileExportsGlobalEntry.d.ts +8 -0
  110. package/dist/shared-server-client/getPageFiles/parseVirtualFileExportsGlobalEntry.js +17 -7
  111. package/dist/shared-server-client/hooks/execHook.d.ts +1 -1
  112. package/dist/shared-server-client/hooks/execHook.js +2 -2
  113. package/dist/shared-server-client/route/abort.d.ts +1 -1
  114. package/dist/shared-server-client/route/abort.js +4 -2
  115. package/dist/shared-server-client/streamedValues.d.ts +22 -0
  116. package/dist/shared-server-client/streamedValues.js +24 -0
  117. package/dist/shared-server-node/vike-environments.d.ts +4 -0
  118. package/dist/shared-server-node/vike-environments.js +10 -0
  119. package/dist/shared-server-node/virtualFileId.d.ts +7 -5
  120. package/dist/shared-server-node/virtualFileId.js +42 -42
  121. package/dist/types/Config.d.ts +1 -1
  122. package/dist/types/PageConfig.d.ts +13 -5
  123. package/dist/types/PageContext.d.ts +18 -1
  124. package/dist/utils/PROJECT_VERSION.d.ts +1 -1
  125. package/dist/utils/PROJECT_VERSION.js +1 -1
  126. package/dist/utils/assertViteVersion.d.ts +1 -3
  127. package/dist/utils/assertViteVersion.js +6 -9
  128. package/dist/utils/catchInfiniteLoop.js +33 -11
  129. package/dist/utils/deepEqual.d.ts +2 -1
  130. package/dist/utils/deepEqual.js +21 -6
  131. package/dist/utils/getContentTypeFromUrl.d.ts +2 -0
  132. package/dist/utils/getContentTypeFromUrl.js +39 -0
  133. package/dist/utils/injectRollupInputs.d.ts +2 -2
  134. package/dist/utils/injectRollupInputs.js +2 -2
  135. package/dist/utils/isDev.js +2 -7
  136. package/dist/utils/parseUrl-extras.js +4 -0
  137. package/package.json +7 -7
  138. package/dist/shared-server-client/addIs404ToPageProps.d.ts +0 -2
  139. package/dist/shared-server-client/addIs404ToPageProps.js +0 -17
@@ -4,6 +4,7 @@ export { getVikeConfig };
4
4
  export { getVikeConfigInternal };
5
5
  export { getVikeConfigInternalOptional };
6
6
  export { setVikeConfigContext };
7
+ export { setViteEnvironmentNames };
7
8
  export { isVikeConfigContextSet };
8
9
  export { reloadVikeConfig };
9
10
  export { isV1Design };
@@ -12,7 +13,6 @@ export { getConfigDefinitionOptional };
12
13
  export { getVikeConfigFromCliOrEnv };
13
14
  export { EARLY_SETTINGS };
14
15
  import { deepEqual } from '../../../utils/deepEqual.js';
15
- import { assertKeys } from '../../../utils/assertKeys.js';
16
16
  import { assertIsNotProductionRuntime } from '../../../utils/assertSetup.js';
17
17
  import { getMostSimilar } from '../../../utils/getMostSimilar.js';
18
18
  import { objectEntries } from '../../../utils/objectEntries.js';
@@ -23,6 +23,7 @@ import { checkType } from '../../../utils/checkType.js';
23
23
  import { genPromise } from '../../../utils/genPromise.js';
24
24
  import { getGlobalObject } from '../../../utils/getGlobalObject.js';
25
25
  import { hasProp } from '../../../utils/hasProp.js';
26
+ import { includes } from '../../../utils/includes.js';
26
27
  import { isCallable } from '../../../utils/isCallable.js';
27
28
  import { isObject } from '../../../utils/isObject.js';
28
29
  import { joinEnglish } from '../../../utils/joinEnglish.js';
@@ -42,6 +43,7 @@ import { loadPointerImport, loadValueFile } from './resolveVikeConfigInternal/lo
42
43
  import { resolvePointerImport } from './resolveVikeConfigInternal/resolvePointerImport.js';
43
44
  import { parsePointerImportData } from './resolveVikeConfigInternal/pointerImports.js';
44
45
  import { getFilePathResolved } from './getFilePath.js';
46
+ import { isEnvironmentBuiltIn, isEnvironmentNameValid } from '../../../shared-server-node/vike-environments.js';
45
47
  import { getConfigValueBuildTime } from '../../../shared-server-client/page-configs/getConfigValueBuildTime.js';
46
48
  import { resolveGlobalConfigPublic, } from '../../../shared-server-client/page-configs/resolveVikeConfigPublic.js';
47
49
  import { getConfigValuesBase, isJsonValue, } from '../../../shared-server-client/page-configs/serialize/serializeConfigValues.js';
@@ -65,12 +67,13 @@ const globalObject = getGlobalObject('vite/shared/resolveVikeConfigInternal.ts',
65
67
  vikeConfigSync: null,
66
68
  vikeConfigCtx: null, // Information provided by Vite's `config` and Vike's CLI. We could, if we want or need to, completely remove the dependency on Vite.
67
69
  prerenderContext: null,
70
+ viteEnvironmentNames: null,
68
71
  });
69
72
  function reloadVikeConfig() {
70
73
  assert(globalObject.vikeConfigCtx);
71
- const { userRootDir, vikeVitePluginOptions } = globalObject.vikeConfigCtx;
74
+ const { userRootDir, isDev, vikeVitePluginOptions } = globalObject.vikeConfigCtx;
72
75
  assert(vikeVitePluginOptions);
73
- resolveVikeConfigInternal_withErrorHandling(userRootDir, true, vikeVitePluginOptions);
76
+ resolveVikeConfigInternal_withErrorHandling(userRootDir, isDev, vikeVitePluginOptions);
74
77
  }
75
78
  async function getVikeConfigInternal(
76
79
  // I don't remember the logic behind it — neither why we restart Vite's dev server, nor why we sometimes don't.
@@ -110,6 +113,32 @@ function setVikeConfigContext(vikeConfigCtx_) {
110
113
  // If the user changes Vite's `config.root` => Vite completely reloads itself => setVikeConfigContext() is called again
111
114
  globalObject.vikeConfigCtx = vikeConfigCtx_;
112
115
  }
116
+ // Vike's config is resolved before Vite's environments are known (Vike's config can modify Vite's config)
117
+ async function setViteEnvironmentNames(viteEnvironmentNames) {
118
+ globalObject.viteEnvironmentNames = viteEnvironmentNames;
119
+ if (!globalObject.vikeConfigPromise)
120
+ return;
121
+ const vikeConfig = await globalObject.vikeConfigPromise;
122
+ // Resolve again: to report a missing environment like any other config error, or to recover from one (e.g. the user added the environment to Vite's config)
123
+ const isMissing = getAdditionalEnvironmentsMissing(vikeConfig._additionalEnvironmentNames).length > 0;
124
+ if (!isMissing && !globalObject.vikeConfigHasBuildError)
125
+ return;
126
+ reloadVikeConfig();
127
+ await globalObject.vikeConfigPromise;
128
+ }
129
+ function getAdditionalEnvironmentsMissing(additionalEnvironmentNames) {
130
+ const { viteEnvironmentNames } = globalObject;
131
+ if (!viteEnvironmentNames)
132
+ return [];
133
+ return additionalEnvironmentNames.filter((name) => !viteEnvironmentNames.includes(name));
134
+ }
135
+ function assertAdditionalEnvironmentsExist(additionalEnvironmentNames) {
136
+ const [name] = getAdditionalEnvironmentsMissing(additionalEnvironmentNames);
137
+ if (name === undefined)
138
+ return;
139
+ assert(globalObject.viteEnvironmentNames);
140
+ assertUsage(false, `The environment ${pc.cyan(JSON.stringify(name))} is used by ${pc.cyan('meta.env')} but it doesn't exist in Vite's ${pc.cyan('config.environments')} (${joinEnglish(globalObject.viteEnvironmentNames.map((n) => pc.cyan(n)), 'and')})`);
141
+ }
113
142
  function isVikeConfigContextSet() {
114
143
  return !!globalObject.vikeConfigCtx;
115
144
  }
@@ -219,6 +248,8 @@ async function resolveVikeConfigInternal(userRootDir, vikeVitePluginOptions, vik
219
248
  const plusFilesByLocationId = await getPlusFiles(userRootDir, vikeTranspileCache);
220
249
  const configDefinitionsResolved = await resolveConfigDefinitions(plusFilesByLocationId, userRootDir, vikeTranspileCache);
221
250
  const { pageConfigGlobal, pageConfigs } = getPageConfigsBuildTime(configDefinitionsResolved, plusFilesByLocationId, userRootDir);
251
+ const additionalEnvironmentNames = getAdditionalEnvironmentNames(getMetaEnvAll(configDefinitionsResolved, [pageConfigGlobal, ...pageConfigs]));
252
+ assertAdditionalEnvironmentsExist(additionalEnvironmentNames);
222
253
  if (!globalObject.isV1Design_)
223
254
  globalObject.isV1Design_ = pageConfigs.length > 0;
224
255
  // Backwards compatibility for vike(options) in vite.config.js
@@ -241,6 +272,7 @@ async function resolveVikeConfigInternal(userRootDir, vikeVitePluginOptions, vik
241
272
  _pageConfigGlobal: pageConfigGlobal,
242
273
  _vikeConfigDependencies: vikeTranspileCache.vikeConfigDependencies,
243
274
  _extensions,
275
+ _additionalEnvironmentNames: additionalEnvironmentNames,
244
276
  };
245
277
  globalObject.vikeConfigSync = vikeConfig;
246
278
  return vikeConfig;
@@ -330,6 +362,23 @@ function getPageConfigsBuildTime(configDefinitionsResolved, plusFilesByLocationI
330
362
  assertPageConfigs(pageConfigs);
331
363
  return { pageConfigs, pageConfigGlobal };
332
364
  }
365
+ // Get all the `meta.env` of all configs
366
+ function getMetaEnvAll(configDefinitionsResolved, pageConfigs) {
367
+ const configDefinitionsAll = [
368
+ configDefinitionsResolved.configDefinitionsGlobal,
369
+ ...Object.values(configDefinitionsResolved.configDefinitionsLocal).map(({ configDefinitions }) => configDefinitions),
370
+ ];
371
+ return [
372
+ ...configDefinitionsAll.flatMap((configDefinitions) => Object.values(configDefinitions).map(({ env }) => env)),
373
+ ...pageConfigs.flatMap(({ configValueSources }) => Object.values(configValueSources).flatMap((sources) => sources.map(({ configEnv }) => configEnv))),
374
+ ];
375
+ }
376
+ function getAdditionalEnvironmentNames(configEnvs) {
377
+ const names = configEnvs.flatMap((configEnv) => Object.entries(configEnv)
378
+ .filter(([, value]) => value)
379
+ .map(([name]) => name));
380
+ return unique(names.filter(isAdditionalEnvironmentName));
381
+ }
333
382
  function resolvePageConfigBuildTime(pageId, locationId, plusFilesRelevant, configDefinitionsLocal, plusFilesByLocationId, userRootDir) {
334
383
  const configValueSources = {};
335
384
  objectEntries(configDefinitionsLocal)
@@ -1091,11 +1140,13 @@ function applyEffectMetaEnv(configModFromEffect, configValueSources, configDefEf
1091
1140
  });
1092
1141
  }
1093
1142
  function getComputed(pageConfig) {
1143
+ assert(globalObject.vikeConfigCtx);
1144
+ const { isDev } = globalObject.vikeConfigCtx;
1094
1145
  const configValuesComputed = {};
1095
1146
  objectEntries(pageConfig.configDefinitions).forEach(([configName, configDef]) => {
1096
1147
  if (!configDef._computed)
1097
1148
  return;
1098
- const value = configDef._computed(pageConfig);
1149
+ const value = configDef._computed(pageConfig, isDev);
1099
1150
  if (value === undefined)
1100
1151
  return;
1101
1152
  configValuesComputed[configName] = {
@@ -1220,6 +1271,14 @@ function determineIsErrorPage(routeFilesystem) {
1220
1271
  assertPosixPath(routeFilesystem);
1221
1272
  return routeFilesystem.split('/').includes('_error');
1222
1273
  }
1274
+ // Keys of `meta.env` that only Vike sets
1275
+ const configEnvKeysInternal = ['clientRoutingOnly', 'eager'];
1276
+ // Keys of `meta.env` that can't be environment names
1277
+ // - Including file suffixes such as `.ssr.js`, `.shared.js`, `.clear.js`, `.default.js`
1278
+ const configEnvKeysReserved = ['ssr', 'shared', 'clear', 'default', ...configEnvKeysInternal];
1279
+ function isAdditionalEnvironmentName(configEnvKey) {
1280
+ return (!isEnvironmentBuiltIn(configEnvKey) && !['config', 'production', ...configEnvKeysInternal].includes(configEnvKey));
1281
+ }
1223
1282
  function getConfigEnvValue(val, errMsgIntro) {
1224
1283
  const errInvalidValue = `${errMsgIntro} an invalid value ${pc.cyan(JSON.stringify(val))}`;
1225
1284
  // Legacy outdated values
@@ -1235,22 +1294,23 @@ function getConfigEnvValue(val, errMsgIntro) {
1235
1294
  if (val === 'config-only')
1236
1295
  return { config: true };
1237
1296
  if (val === '_routing-lazy')
1238
- return { server: true, client: 'if-client-routing' };
1297
+ return { server: true, client: true, clientRoutingOnly: true };
1239
1298
  if (val === '_routing-eager')
1240
- return { server: true, client: 'if-client-routing', eager: true };
1299
+ return { server: true, client: true, clientRoutingOnly: true, eager: true };
1241
1300
  assertUsage(false, errInvalidValue);
1242
1301
  })();
1243
1302
  assertWarning(false, `${errMsgIntro} ${pc.cyan(val)} which is deprecated and will be removed in the next major release`, { onlyOnce: true });
1244
1303
  return valConverted;
1245
1304
  }
1246
1305
  assertUsage(isObject(val), `${errMsgIntro} an invalid type ${pc.cyan(typeof val)}`);
1247
- assertKeys(val, ['config', 'server', 'client'], `${errInvalidValue}:`);
1248
- assertUsage(hasProp(val, 'config', 'undefined') || hasProp(val, 'config', 'boolean'), errInvalidValue);
1249
- assertUsage(hasProp(val, 'server', 'undefined') || hasProp(val, 'server', 'boolean'), errInvalidValue);
1250
- assertUsage(hasProp(val, 'client', 'undefined') || hasProp(val, 'client', 'boolean'), errInvalidValue);
1306
+ Object.entries(val).forEach(([key, value]) => {
1307
+ assertUsage(!includes(configEnvKeysReserved, key), `${errInvalidValue}: ${pc.cyan(key)} can't be an environment name, because ${includes(configEnvKeysInternal, key) ? 'Vike uses it internally' : `it's a file suffix (${pc.cyan(`+Page.${key}.js`)})`}`);
1308
+ assertUsage(isEnvironmentNameValid(key), `${errInvalidValue}: ${pc.cyan(key)} isn't a valid environment name`);
1309
+ assertUsage(value === undefined || typeof value === 'boolean', errInvalidValue);
1310
+ });
1251
1311
  /* To allow users to set an eager config:
1252
1312
  * - Uncomment line below.
1253
- * - Add 'eager' to assertKeys() call above.
1313
+ * - Move 'eager' from configEnvKeysInternal to the keys that isAdditionalEnvironmentName() excludes.
1254
1314
  * - Add `eager: boolean` to ConfigEnv type.
1255
1315
  assertUsage(hasProp(val, 'eager', 'undefined') || hasProp(val, 'eager', 'boolean'), errInvalidValue)
1256
1316
  */
@@ -1279,11 +1339,21 @@ function resolveConfigEnv(configEnv, filePath) {
1279
1339
  else if (suffixes.includes('client')) {
1280
1340
  configEnvResolved.client = true;
1281
1341
  configEnvResolved.server = false;
1342
+ // Additional environments (e.g. `rsc`) are server-side
1343
+ Object.keys(configEnvResolved).forEach((key) => {
1344
+ if (isAdditionalEnvironmentName(key))
1345
+ delete configEnvResolved[key];
1346
+ });
1282
1347
  }
1283
1348
  else if (suffixes.includes('shared')) {
1284
1349
  configEnvResolved.server = true;
1285
1350
  configEnvResolved.client = true;
1286
1351
  }
1352
+ else {
1353
+ return configEnvResolved;
1354
+ }
1355
+ // The file suffix decides, regardless of Client Routing
1356
+ delete configEnvResolved.clientRoutingOnly;
1287
1357
  }
1288
1358
  return configEnvResolved;
1289
1359
  }
@@ -1347,6 +1417,7 @@ async function getVikeConfigDummy(vikeTranspileCache) {
1347
1417
  prerenderContext: prerenderContextDummy,
1348
1418
  _vikeConfigDependencies: vikeTranspileCache.vikeConfigDependencies,
1349
1419
  _extensions: [],
1420
+ _additionalEnvironmentNames: [],
1350
1421
  };
1351
1422
  globalObject.vikeConfigSync = vikeConfigDummy;
1352
1423
  globalObject.isV1Design_ = true;
@@ -54,6 +54,10 @@ declare function getGlobalContextServerInternal(): Promise<{
54
54
  _pageFilesAll: import("../__internal/index.js").PageFile[];
55
55
  _pageConfigs: import("../__internal/index.js").PageConfig[];
56
56
  _pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
57
+ _environmentEntries: Record<string, {
58
+ pageConfigs: import("../__internal/index.js").PageConfig[];
59
+ pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
60
+ } | null>;
57
61
  _allPageIds: string[];
58
62
  } & {
59
63
  isClientSide: false;
@@ -102,6 +106,10 @@ declare function getGlobalContextServerInternal(): Promise<{
102
106
  _pageFilesAll: import("../__internal/index.js").PageFile[];
103
107
  _pageConfigs: import("../__internal/index.js").PageConfig[];
104
108
  _pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
109
+ _environmentEntries: Record<string, {
110
+ pageConfigs: import("../__internal/index.js").PageConfig[];
111
+ pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
112
+ } | null>;
105
113
  _allPageIds: string[];
106
114
  } & {
107
115
  isClientSide: false;
@@ -151,6 +159,10 @@ declare function getGlobalContextServerInternal(): Promise<{
151
159
  _pageFilesAll: import("../__internal/index.js").PageFile[];
152
160
  _pageConfigs: import("../__internal/index.js").PageConfig[];
153
161
  _pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
162
+ _environmentEntries: Record<string, {
163
+ pageConfigs: import("../__internal/index.js").PageConfig[];
164
+ pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
165
+ } | null>;
154
166
  _allPageIds: string[];
155
167
  } & {
156
168
  isClientSide: false;
@@ -202,6 +214,10 @@ declare function getGlobalContextServerInternalOptional(): (Record<string, unkno
202
214
  _pageFilesAll: import("../__internal/index.js").PageFile[];
203
215
  _pageConfigs: import("../__internal/index.js").PageConfig[];
204
216
  _pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
217
+ _environmentEntries: Record<string, {
218
+ pageConfigs: import("../__internal/index.js").PageConfig[];
219
+ pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
220
+ } | null>;
205
221
  _allPageIds: string[];
206
222
  } & (({
207
223
  isClientSide: false;
@@ -309,6 +325,10 @@ declare function createGlobalContext(virtualFileExportsGlobalEntry: unknown): Pr
309
325
  _pageFilesAll: import("../__internal/index.js").PageFile[];
310
326
  _pageConfigs: import("../__internal/index.js").PageConfig[];
311
327
  _pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
328
+ _environmentEntries: Record<string, {
329
+ pageConfigs: import("../__internal/index.js").PageConfig[];
330
+ pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
331
+ } | null>;
312
332
  _allPageIds: string[];
313
333
  } & (({
314
334
  isClientSide: false;
@@ -18,14 +18,14 @@ function analyzePage(pageContext) {
18
18
  clientEntries.push(getVikeClientEntry(isClientRouting));
19
19
  const clientDependencies = [];
20
20
  clientDependencies.push({
21
- id: generateVirtualFileId({ type: 'page-entry', pageId: pageConfig.pageId, isForClientSide: true }),
21
+ id: generateVirtualFileId({ type: 'page-entry', pageId: pageConfig.pageId, environmentName: 'client' }),
22
22
  onlyAssets: isClientRuntimeLoaded ? false : true,
23
23
  eagerlyImported: false,
24
24
  });
25
25
  // In production we inject the import of the server virtual module with ?extractAssets inside the client virtual module
26
26
  if (!globalContext._isProduction) {
27
27
  clientDependencies.push({
28
- id: generateVirtualFileId({ type: 'page-entry', pageId: pageConfig.pageId, isForClientSide: false }),
28
+ id: generateVirtualFileId({ type: 'page-entry', pageId: pageConfig.pageId, environmentName: 'server' }),
29
29
  onlyAssets: true,
30
30
  eagerlyImported: false,
31
31
  });
@@ -36,7 +36,7 @@ function analyzePage(pageContext) {
36
36
  const { env } = configElement
37
37
  assert(env)
38
38
  const onlyAssets = env === { server: true }
39
- const eagerlyImported = env === { server: true, client: 'if-client-routing', eager: true }
39
+ const eagerlyImported = env === { server: true, client: true, clientRoutingOnly: true, eager: true }
40
40
  if (onlyAssets || eagerlyImported) {
41
41
  clientDependencies.push({
42
42
  id: configElement.importPath,
@@ -1,4 +1,5 @@
1
- export { createHttpResponsePage };
1
+ export { createHttpResponsePageHtml };
2
+ export { createHttpResponsePageContent };
2
3
  export { createHttpResponsePageJson };
3
4
  export { createHttpResponseErrorFallback };
4
5
  export { createHttpResponseErrorFallback_noGlobalContext };
@@ -10,8 +11,9 @@ export { createHttpResponseFromUniversalMiddleware };
10
11
  export type { HttpResponse };
11
12
  import type { GetPageAssets } from './getPageAssets.js';
12
13
  import type { HtmlRender } from './html/renderHtml.js';
13
- import type { RenderHook } from './execHookOnRenderHtml.js';
14
- import type { AbortStatusCode, UrlRedirect } from '../../../shared-server-client/route/abort.js';
14
+ import type { StreamReadableWeb } from './html/stream.js';
15
+ import type { Content, RenderHook } from './execHookOnRenderHtml.js';
16
+ import type { AbortStatusCode, UrlRedirect, PageContextAborted } from '../../../shared-server-client/route/abort.js';
15
17
  import { HttpResponseBody } from './getHttpResponseBody.js';
16
18
  import { type EarlyHint } from './getEarlyHints.js';
17
19
  import type { PageContextBegin } from '../renderPageServer.js';
@@ -24,7 +26,7 @@ type HttpResponse = {
24
26
  /** **Deprecated**: use `headers` instead, see https://vike.dev/migration/0.4.134 */
25
27
  contentType: string | undefined;
26
28
  } & HttpResponseBody;
27
- declare function createHttpResponsePage(htmlRender: HtmlRender, renderHook: null | RenderHook, pageContext: {
29
+ type PageContextHttpResponsePage = {
28
30
  pageId: null | string;
29
31
  is404: null | boolean;
30
32
  errorWhileRendering: null | Error;
@@ -32,14 +34,25 @@ declare function createHttpResponsePage(htmlRender: HtmlRender, renderHook: null
32
34
  _globalContext: GlobalContextServerInternal;
33
35
  abortStatusCode?: AbortStatusCode;
34
36
  headersResponse?: Headers;
35
- }): Promise<HttpResponse>;
37
+ pageContextsAborted: PageContextAborted[];
38
+ };
39
+ declare function createHttpResponsePageHtml(htmlRender: HtmlRender, renderHook: null | RenderHook, pageContext: PageContextHttpResponsePage): Promise<HttpResponse>;
40
+ declare function createHttpResponsePageContent(content: Content, renderHook: RenderHook, pageContext: PageContextHttpResponsePage & {
41
+ urlOriginal: string;
42
+ }): HttpResponse;
36
43
  declare function createHttpResponse404(errMsg404: string): HttpResponse;
37
44
  declare function createHttpResponseBaseIsMissing(urlOriginal: string, baseServer: string): HttpResponse;
38
45
  declare function createHttpResponseErrorFallback(pageContext: {
39
46
  _globalContext: GlobalContextServerInternal;
47
+ pageContextsAborted: PageContextAborted[];
40
48
  }): HttpResponse;
41
49
  declare function createHttpResponseErrorFallback_noGlobalContext(): HttpResponse;
42
- declare function createHttpResponseErrorFallbackJson(): HttpResponse;
43
- declare function createHttpResponsePageJson(pageContextSerialized: string): Promise<HttpResponse>;
50
+ declare function createHttpResponseErrorFallbackJson(pageContext: {
51
+ pageContextsAborted: PageContextAborted[];
52
+ }): HttpResponse;
53
+ declare function createHttpResponsePageJson(pageContextJson: string | StreamReadableWeb, pageContext: {
54
+ headersResponse?: Headers;
55
+ pageContextsAborted: PageContextAborted[];
56
+ }): Promise<HttpResponse>;
44
57
  declare function createHttpResponseRedirect({ url, statusCode }: UrlRedirect, pageContextInit: PageContextBegin): HttpResponse;
45
58
  declare function createHttpResponseFromUniversalMiddleware(response: Response, earlyHints?: EarlyHint[]): HttpResponse;
@@ -1,4 +1,5 @@
1
- export { createHttpResponsePage };
1
+ export { createHttpResponsePageHtml };
2
+ export { createHttpResponsePageContent };
2
3
  export { createHttpResponsePageJson };
3
4
  export { createHttpResponseErrorFallback };
4
5
  export { createHttpResponseErrorFallback_noGlobalContext };
@@ -10,16 +11,31 @@ export { createHttpResponseFromUniversalMiddleware };
10
11
  import { escapeHtml } from '../../../utils/escapeHtml.js';
11
12
  import { assert, assertWarning } from '../../../utils/assert.js';
12
13
  import { getErrorPageId, isErrorPage } from '../../../shared-server-client/error-page.js';
14
+ import { getContentTypeFromUrl } from '../../../utils/getContentTypeFromUrl.js';
13
15
  import { getHttpResponseBody, getHttpResponseBodyStreamHandlers } from './getHttpResponseBody.js';
14
16
  import { getEarlyHints } from './getEarlyHints.js';
15
17
  import { assertNoInfiniteHttpRedirect } from './createHttpResponse/assertNoInfiniteHttpRedirect.js';
16
- import { resolveHeadersResponseFinal } from './headersResponse.js';
18
+ import { getHeadersSetCookieAborted, resolveHeadersResponseFinal, resolveHeadersResponseSetCookie, } from './headersResponse.js';
17
19
  import { stringify } from '@brillout/json-serializer/stringify';
18
20
  import '../../assertEnvServer.js';
19
21
  const contentTypeJson = 'application/json';
20
22
  const contentTypeHtml = 'text/html;charset=utf-8';
21
23
  const htmlFallbackLog = 'This HTML was generated by Vike.';
22
- async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
24
+ async function createHttpResponsePageHtml(htmlRender, renderHook, pageContext) {
25
+ const statusCode = getStatusCode(pageContext);
26
+ const earlyHints = getEarlyHints(await pageContext.__getPageAssets());
27
+ const headers = resolveHeadersResponseFinal(pageContext, statusCode);
28
+ return createHttpResponse(statusCode, contentTypeHtml, headers, htmlRender, earlyHints, renderHook);
29
+ }
30
+ function createHttpResponsePageContent(content, renderHook, pageContext) {
31
+ const statusCode = getStatusCode(pageContext);
32
+ const headers = resolveHeadersResponseFinal(pageContext, statusCode);
33
+ if (!headers.some(([k]) => k.toLowerCase() === 'content-type')) {
34
+ headers.push(['Content-Type', getContentTypeFromUrl(pageContext.urlOriginal) ?? 'application/octet-stream']);
35
+ }
36
+ return createHttpResponseCommon(statusCode, headers, content, [], renderHook);
37
+ }
38
+ function getStatusCode(pageContext) {
23
39
  let statusCode = pageContext.abortStatusCode;
24
40
  if (!statusCode) {
25
41
  const isError = !pageContext.pageId || isErrorPage(pageContext.pageId, pageContext._globalContext._pageConfigs);
@@ -35,9 +51,7 @@ async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
35
51
  statusCode = pageContext.is404 ? 404 : 500;
36
52
  }
37
53
  }
38
- const earlyHints = getEarlyHints(await pageContext.__getPageAssets());
39
- const headers = resolveHeadersResponseFinal(pageContext, statusCode);
40
- return createHttpResponse(statusCode, contentTypeHtml, headers, htmlRender, earlyHints, renderHook);
54
+ return statusCode;
41
55
  }
42
56
  function createHttpResponse404(errMsg404) {
43
57
  const httpResponse = createHttpResponse(404, contentTypeHtml, [], getHtmlFallback(`<p>${errMsg404}.</p>`));
@@ -76,21 +90,26 @@ function createHttpResponseErrorFallback(pageContext) {
76
90
  return 'no error page (https://vike.dev/error-page) is defined, make sure to create one';
77
91
  }
78
92
  })();
79
- return createHttpResponseError_(reason);
93
+ // Cookies set before `throw redirect()` or `throw render()` are kept
94
+ return createHttpResponseError_(reason, getHeadersSetCookieAborted(pageContext));
80
95
  }
81
96
  function createHttpResponseErrorFallback_noGlobalContext() {
82
- return createHttpResponseError_('no error page (https://vike.dev/error-page) could be rendered');
97
+ return createHttpResponseError_('no error page (https://vike.dev/error-page) could be rendered', []);
83
98
  }
84
- function createHttpResponseError_(reason) {
85
- const httpResponse = createHttpResponse(500, contentTypeHtml, [], getHtmlFallback('<p>An error occurred.</p>', `${htmlFallbackLog} Vike returned this HTML because ${reason}.`));
99
+ function createHttpResponseError_(reason, headers) {
100
+ const httpResponse = createHttpResponse(500, contentTypeHtml, headers, getHtmlFallback('<p>An error occurred.</p>', `${htmlFallbackLog} Vike returned this HTML because ${reason}.`));
86
101
  return httpResponse;
87
102
  }
88
- function createHttpResponseErrorFallbackJson() {
89
- const httpResponse = createHttpResponse(500, contentTypeJson, [], stringify({ serverSideError: true }));
103
+ function createHttpResponseErrorFallbackJson(pageContext) {
104
+ const headers = getHeadersSetCookieAborted(pageContext);
105
+ const httpResponse = createHttpResponse(500, contentTypeJson, headers, stringify({ serverSideError: true }));
90
106
  return httpResponse;
91
107
  }
92
- async function createHttpResponsePageJson(pageContextSerialized) {
93
- const httpResponse = createHttpResponse(200, contentTypeJson, [], pageContextSerialized, [], null);
108
+ async function createHttpResponsePageJson(pageContextJson, pageContext) {
109
+ const headers = resolveHeadersResponseSetCookie(pageContext);
110
+ headers.push(['Content-Type', contentTypeJson]);
111
+ // A stream if there are streamed pageContext values, see https://vike.dev/passToClient#streaming
112
+ const httpResponse = createHttpResponseCommon(200, headers, pageContextJson);
94
113
  return httpResponse;
95
114
  }
96
115
  function createHttpResponseRedirect({ url, statusCode }, pageContextInit) {
@@ -98,7 +117,7 @@ function createHttpResponseRedirect({ url, statusCode }, pageContextInit) {
98
117
  assert(url);
99
118
  assert(statusCode);
100
119
  assert(300 <= statusCode && statusCode <= 399);
101
- const headers = [['Location', url]];
120
+ const headers = [['Location', url], ...resolveHeadersResponseSetCookie(pageContextInit)];
102
121
  return createHttpResponse(statusCode, contentTypeHtml, headers,
103
122
  // For bots / programmatic crawlig: show what's going on.
104
123
  // For users: showing a blank page is probably better than a flickering text.
@@ -53,6 +53,10 @@ declare function createPageContextServer(pageContextInit: PageContextInitInterna
53
53
  _pageFilesAll: import("../../__internal/index.js").PageFile[];
54
54
  _pageConfigs: import("../../__internal/index.js").PageConfig[];
55
55
  _pageConfigGlobal: import("../../../types/PageConfig.js").PageConfigGlobalRuntime;
56
+ _environmentEntries: Record<string, {
57
+ pageConfigs: import("../../__internal/index.js").PageConfig[];
58
+ pageConfigGlobal: import("../../../types/PageConfig.js").PageConfigGlobalRuntime;
59
+ } | null>;
56
60
  _allPageIds: string[];
57
61
  } & (({
58
62
  isClientSide: false;
@@ -23,7 +23,7 @@ function execHookOnError(err, pageContext) {
23
23
  const hooks = getHooksFromPageConfigGlobalCumulative(globalContext._pageConfigGlobal, 'onError');
24
24
  for (const hook of hooks) {
25
25
  try {
26
- execHookSingleSync(hook, globalContext, pageContext, getPageContextPublicServer, () => hook.hookFn(err, pageContext));
26
+ execHookSingleSync(hook, globalContext, pageContext, getPageContextPublicServer, (pageContextPublic) => hook.hookFn(err, pageContextPublic));
27
27
  }
28
28
  catch (hookErr) {
29
29
  console.error(hookErr);
@@ -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;