vike 0.4.179 → 0.4.180

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 (52) hide show
  1. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +3 -0
  2. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +46 -15
  3. package/dist/cjs/node/runtime/html/injectAssets/injectHtmlTags.js +3 -2
  4. package/dist/cjs/node/runtime/html/injectAssets.js +18 -3
  5. package/dist/cjs/node/runtime/html/renderHtml.js +12 -11
  6. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +14 -4
  7. package/dist/cjs/node/runtime/html/stream.js +12 -5
  8. package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -1
  9. package/dist/cjs/node/runtime/renderPage.js +14 -13
  10. package/dist/cjs/node/runtime/utils.js +1 -0
  11. package/dist/cjs/shared/page-configs/serialize/serializeConfigValues.js +4 -0
  12. package/dist/cjs/shared/route/index.js +4 -6
  13. package/dist/cjs/utils/augmentType.js +10 -0
  14. package/dist/cjs/utils/getPropAccessNotation.js +4 -1
  15. package/dist/cjs/utils/objectAssign.js +2 -0
  16. package/dist/cjs/utils/projectInfo.js +1 -1
  17. package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +1 -0
  18. package/dist/esm/client/client-routing-runtime/createPageContext.js +2 -1
  19. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +5 -3
  20. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +22 -27
  21. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +6 -12
  22. package/dist/esm/client/client-routing-runtime/utils.d.ts +1 -0
  23. package/dist/esm/client/client-routing-runtime/utils.js +1 -0
  24. package/dist/esm/client/shared/getPageContextProxyForUser.js +1 -1
  25. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +3 -0
  26. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.d.ts +3 -2
  27. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +46 -15
  28. package/dist/esm/node/runtime/html/injectAssets/injectHtmlTags.d.ts +3 -1
  29. package/dist/esm/node/runtime/html/injectAssets/injectHtmlTags.js +2 -1
  30. package/dist/esm/node/runtime/html/injectAssets.d.ts +1 -0
  31. package/dist/esm/node/runtime/html/injectAssets.js +19 -4
  32. package/dist/esm/node/runtime/html/renderHtml.js +12 -11
  33. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +15 -5
  34. package/dist/esm/node/runtime/html/stream.d.ts +2 -1
  35. package/dist/esm/node/runtime/html/stream.js +12 -5
  36. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -1
  37. package/dist/esm/node/runtime/renderPage.js +14 -13
  38. package/dist/esm/node/runtime/utils.d.ts +1 -0
  39. package/dist/esm/node/runtime/utils.js +1 -0
  40. package/dist/esm/shared/page-configs/Config.d.ts +5 -0
  41. package/dist/esm/shared/page-configs/serialize/serializeConfigValues.js +4 -0
  42. package/dist/esm/shared/route/index.d.ts +1 -1
  43. package/dist/esm/shared/route/index.js +4 -6
  44. package/dist/esm/shared/types.d.ts +1 -1
  45. package/dist/esm/utils/augmentType.d.ts +3 -0
  46. package/dist/esm/utils/augmentType.js +7 -0
  47. package/dist/esm/utils/getPropAccessNotation.js +4 -1
  48. package/dist/esm/utils/objectAssign.d.ts +1 -1
  49. package/dist/esm/utils/objectAssign.js +2 -0
  50. package/dist/esm/utils/projectInfo.d.ts +2 -2
  51. package/dist/esm/utils/projectInfo.js +1 -1
  52. package/package.json +4 -4
@@ -105,6 +105,9 @@ const configDefinitionsBuiltIn = {
105
105
  cacheControl: {
106
106
  env: { server: true }
107
107
  },
108
+ injectScriptsAt: {
109
+ env: { server: true }
110
+ },
108
111
  name: {
109
112
  env: { config: true }
110
113
  },
@@ -9,13 +9,17 @@ const serializePageContextClientSide_js_1 = require("../serializePageContextClie
9
9
  const sanitizeJson_js_1 = require("./sanitizeJson.js");
10
10
  const inferHtmlTags_js_1 = require("./inferHtmlTags.js");
11
11
  const mergeScriptTags_js_1 = require("./mergeScriptTags.js");
12
+ const helpers_js_1 = require("../../../../shared/page-configs/helpers.js");
13
+ const getConfigValue_js_1 = require("../../../../shared/page-configs/getConfigValue.js");
12
14
  const globalContext_js_1 = require("../../globalContext.js");
13
15
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
16
+ const getConfigDefinedAt_js_1 = require("../../../../shared/page-configs/getConfigDefinedAt.js");
14
17
  const stamp = '__injectFilterEntry';
15
- function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectFilter, pageAssets, viteDevScript) {
18
+ function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectFilter, pageAssets, viteDevScript, isStream) {
16
19
  (0, utils_js_1.assert)([true, false].includes(pageContext._isHtmlOnly));
17
20
  const isHtmlOnly = pageContext._isHtmlOnly;
18
21
  const { isProduction } = (0, globalContext_js_1.getGlobalContext)();
22
+ const injectScriptsAt = getInjectScriptsAt(pageContext._pageId, pageContext._pageConfigs);
19
23
  const injectFilterEntries = pageAssets
20
24
  .filter((asset) => {
21
25
  if (asset.isEntry && asset.assetType === 'script') {
@@ -78,28 +82,39 @@ function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectFilter,
78
82
  // ==========
79
83
  // JavaScript
80
84
  // ==========
81
- // In order to avoid the race-condition depicted in https://github.com/vikejs/vike/issues/567
82
- // 1. <script id="vike_pageContext" type="application/json"> must appear before the entry <script> (which loads Vike's client runtime).
83
- // 2. <script id="vike_pageContext" type="application/json"> can't be async nor defer.
84
- // Additionally:
85
- // 3. the entry <script> can't be defer, otherwise progressive hydration while SSR streaming won't work.
86
- // 4. the entry <script> should be towards the end of the HTML as performance-wise it's more interesting to parse
87
- // <div id="page-view"> before running the entry <script> which initiates the hydration.
88
- // See https://github.com/vikejs/vike/pull/1271
85
+ // - The pageContext JSON should be fully sent before Vike's client runtime starts executing.
86
+ // - Otherwise, race condition "SyntaxError: Unterminated string in JSON": https://github.com/vikejs/vike/issues/567
87
+ // - <script id="vike_pageContext" type="application/json"> must appear before the entry <script> (which loads Vike's client runtime).
88
+ // - <script id="vike_pageContext" type="application/json"> can't be async nor defer.
89
+ // - The entry <script> can't be defer, otherwise progressive hydration while SSR streaming won't work.
90
+ // - The entry <script> should be towards the end of the HTML as performance-wise it's more interesting to parse <div id="page-view"> before running the entry <script> which initiates the hydration.
91
+ // - But with HTML streaming, in order to support [Progressive Rendering](https://vike.dev/streaming#progressive-rendering), the entry <script> should be injected early instead.
89
92
  const positionJavaScriptEntry = (() => {
93
+ if (injectScriptsAt !== null) {
94
+ if (pageContext._pageContextPromise) {
95
+ (0, utils_js_1.assertWarning)(injectScriptsAt === 'HTML_END' || !isStream, `You're setting injectScriptsAt to ${picocolors_1.default.code(JSON.stringify(injectScriptsAt))} while using HTML streaming with a pageContext promise (https://vike.dev/streaming#initial-data-after-stream-end) which is contradictory: the pageContext promise is skipped.`, { onlyOnce: true });
96
+ }
97
+ return injectScriptsAt;
98
+ }
90
99
  if (pageContext._pageContextPromise) {
91
- (0, utils_js_1.assertWarning)(!streamFromReactStreamingPackage, "[getHtmlTags()] We recommend against using streaming and a pageContext promise at the same time, because progressive hydration won't work.", { onlyOnce: true });
92
- // If there is a pageContext._pageContextPromise (which is resolved after the stream has ended) then the pageContext JSON data needs to await for it: https://vike.dev/streaming#initial-data-after-stream-end
100
+ // - If there is a pageContext._pageContextPromise then <script id="vike_pageContext" type="application/json"> needs to await for it.
101
+ // - pageContext._pageContextPromise is typically resolved only after the page's components are rendered and the stream ended.
102
+ // - https://vike.dev/streaming#initial-data-after-stream-end
93
103
  return 'HTML_END';
94
104
  }
95
105
  if (streamFromReactStreamingPackage && !streamFromReactStreamingPackage.hasStreamEnded()) {
96
- // If there is a stream then, in order to support progressive hydration, inject the JavaScript during the stream after React(/Vue/Solid/...) resolved the first suspense boundary
106
+ // If there is a stream then, in order to support progressive hydration, inject the JavaScript during the stream after React(/Vue/Solid/...) resolved the first suspense boundary.
97
107
  return 'STREAM';
98
108
  }
99
- else {
100
- return 'HTML_END';
101
- }
109
+ return 'HTML_END';
102
110
  })();
111
+ if (pageContext._pageContextPromise && streamFromReactStreamingPackage) {
112
+ // - Should we show this warning for Solid as well? Solid seems to also support progressive rendering.
113
+ // - https://github.com/vikejs/vike-solid/issues/95
114
+ // - Vue doesn't seem to support progressive rendering yet.
115
+ // - https://github.com/vikejs/vike-vue/issues/85
116
+ (0, utils_js_1.assertWarning)(false, "We recommend against using HTML streaming and a pageContext promise (https://vike.dev/streaming#initial-data-after-stream-end) at the same time, because progressive hydration (https://vike.dev/streaming#progressive-rendering) won't work.", { onlyOnce: true });
117
+ }
103
118
  // <script id="vike_pageContext" type="application/json">
104
119
  if (!isHtmlOnly) {
105
120
  htmlTags.push({
@@ -195,3 +210,19 @@ function checkForWarnings(injectFilterEntries) {
195
210
  }
196
211
  });
197
212
  }
213
+ function getInjectScriptsAt(pageId, pageConfigs) {
214
+ if (pageConfigs.length === 0)
215
+ return null; // only support V1 design
216
+ const pageConfig = (0, helpers_js_1.getPageConfig)(pageId, pageConfigs);
217
+ const configValue = (0, getConfigValue_js_1.getConfigValueRuntime)(pageConfig, 'injectScriptsAt');
218
+ if (!configValue)
219
+ return null;
220
+ const injectScriptsAt = configValue.value;
221
+ (0, utils_js_1.assert)(configValue.definedAtData);
222
+ const configDefinedAt = (0, getConfigDefinedAt_js_1.getConfigDefinedAt)('Config', 'injectScriptsAt', configValue.definedAtData);
223
+ (0, utils_js_1.assertUsage)(injectScriptsAt === null ||
224
+ injectScriptsAt === 'HTML_BEGIN' ||
225
+ injectScriptsAt === 'HTML_END' ||
226
+ injectScriptsAt === 'STREAM', `${configDefinedAt} has an invalid value`);
227
+ return injectScriptsAt;
228
+ }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  // Unit tests at ./injectHtmlTags.spec.ts
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.injectAtClosingTag = exports.injectAtOpeningTag = exports.createHtmlHeadIfMissing = exports.injectHtmlTagsUsingStream = exports.injectHtmlTags = void 0;
4
+ exports.injectAtClosingTag = exports.injectAtOpeningTag = exports.joinHtmlTags = exports.createHtmlHeadIfMissing = exports.injectHtmlTagsUsingStream = exports.injectHtmlTags = void 0;
5
5
  const utils_js_1 = require("../../utils.js");
6
6
  function injectHtmlTags(htmlString, htmlTags, position) {
7
7
  const htmlFragment = joinHtmlTags(htmlTags.filter((h) => h.position === position));
@@ -11,10 +11,10 @@ function injectHtmlTags(htmlString, htmlTags, position) {
11
11
  return htmlString;
12
12
  }
13
13
  exports.injectHtmlTags = injectHtmlTags;
14
+ // Is it worth it? Should we remove this? https://github.com/vikejs/vike/pull/1740#issuecomment-2230540892
14
15
  function injectHtmlTagsUsingStream(htmlTags, streamFromReactStreamingPackage) {
15
16
  const htmlFragment = joinHtmlTags(htmlTags.filter((h) => h.position === 'STREAM'));
16
17
  if (htmlFragment) {
17
- (0, utils_js_1.assert)(streamFromReactStreamingPackage);
18
18
  (0, utils_js_1.assert)(!streamFromReactStreamingPackage.hasStreamEnded());
19
19
  streamFromReactStreamingPackage.injectToStream(htmlFragment, { flush: true });
20
20
  }
@@ -24,6 +24,7 @@ function joinHtmlTags(htmlTags) {
24
24
  const htmlFragment = htmlTags.map((h) => resolveHtmlTag(h.htmlTag)).join('');
25
25
  return htmlFragment;
26
26
  }
27
+ exports.joinHtmlTags = joinHtmlTags;
27
28
  function injectHtmlFragment(position, htmlFragment, htmlString) {
28
29
  if (position === 'HTML_BEGIN') {
29
30
  {
@@ -9,7 +9,7 @@ const getViteDevScript_js_1 = require("./injectAssets/getViteDevScript.js");
9
9
  async function injectHtmlTagsToString(htmlParts, pageContext, injectFilter) {
10
10
  const pageAssets = await pageContext.__getPageAssets();
11
11
  const viteDevScript = await (0, getViteDevScript_js_1.getViteDevScript)();
12
- const htmlTags = (0, getHtmlTags_js_1.getHtmlTags)(pageContext, null, injectFilter, pageAssets, viteDevScript);
12
+ const htmlTags = (0, getHtmlTags_js_1.getHtmlTags)(pageContext, null, injectFilter, pageAssets, viteDevScript, false);
13
13
  let htmlString = htmlPartsToString(htmlParts, pageAssets);
14
14
  htmlString = injectToHtmlBegin(htmlString, htmlTags);
15
15
  htmlString = injectToHtmlEnd(htmlString, htmlTags);
@@ -21,17 +21,32 @@ function injectHtmlTagsToStream(pageContext, streamFromReactStreamingPackage, in
21
21
  let htmlTags;
22
22
  return {
23
23
  injectAtStreamBegin,
24
+ injectAtStreamAfterFirstChunk,
24
25
  injectAtStreamEnd
25
26
  };
26
27
  async function injectAtStreamBegin(htmlPartsBegin) {
27
28
  const pageAssets = await pageContext.__getPageAssets();
28
29
  const viteDevScript = await (0, getViteDevScript_js_1.getViteDevScript)();
29
- htmlTags = (0, getHtmlTags_js_1.getHtmlTags)(pageContext, streamFromReactStreamingPackage, injectFilter, pageAssets, viteDevScript);
30
+ htmlTags = (0, getHtmlTags_js_1.getHtmlTags)(pageContext, streamFromReactStreamingPackage, injectFilter, pageAssets, viteDevScript, true);
30
31
  let htmlBegin = htmlPartsToString(htmlPartsBegin, pageAssets);
31
32
  htmlBegin = injectToHtmlBegin(htmlBegin, htmlTags);
32
- (0, injectHtmlTags_js_1.injectHtmlTagsUsingStream)(htmlTags, streamFromReactStreamingPackage);
33
+ if (streamFromReactStreamingPackage) {
34
+ (0, injectHtmlTags_js_1.injectHtmlTagsUsingStream)(htmlTags, streamFromReactStreamingPackage);
35
+ }
33
36
  return htmlBegin;
34
37
  }
38
+ // Is it worth it? Should we remove this? https://github.com/vikejs/vike/pull/1740#issuecomment-2230540892
39
+ function injectAtStreamAfterFirstChunk() {
40
+ // React has its own stream injection mechanism, see injectHtmlTagsUsingStream()
41
+ if (streamFromReactStreamingPackage)
42
+ return null;
43
+ (0, utils_js_1.assert)(htmlTags);
44
+ const tags = htmlTags.filter((h) => h.position === 'STREAM');
45
+ if (tags.length === 0)
46
+ return null;
47
+ const htmlFragment = (0, injectHtmlTags_js_1.joinHtmlTags)(tags);
48
+ return htmlFragment;
49
+ }
35
50
  async function injectAtStreamEnd(htmlPartsEnd) {
36
51
  (0, utils_js_1.assert)(htmlTags);
37
52
  await resolvePageContextPromise(pageContext);
@@ -55,7 +55,7 @@ async function renderDocumentHtml(documentHtml, pageContext, onErrorWhileStreami
55
55
  }
56
56
  exports.renderDocumentHtml = renderDocumentHtml;
57
57
  async function renderHtmlStream(streamOriginal, injectString, pageContext, onErrorWhileStreaming, injectFilter) {
58
- const opts = {
58
+ const processStreamOptions = {
59
59
  onErrorWhileStreaming,
60
60
  enableEagerStreaming: pageContext.enableEagerStreaming
61
61
  };
@@ -64,17 +64,18 @@ async function renderHtmlStream(streamOriginal, injectString, pageContext, onErr
64
64
  if ((0, react_streaming_js_1.isStreamFromReactStreamingPackage)(streamOriginal) && !streamOriginal.disabled) {
65
65
  streamFromReactStreamingPackage = streamOriginal;
66
66
  }
67
- const { injectAtStreamBegin, injectAtStreamEnd } = (0, injectAssets_js_1.injectHtmlTagsToStream)(pageContext, streamFromReactStreamingPackage, injectFilter);
68
- (0, utils_js_1.objectAssign)(opts, {
69
- injectStringAtBegin: async () => {
70
- return await injectAtStreamBegin(injectString.htmlPartsBegin);
71
- },
72
- injectStringAtEnd: async () => {
73
- return await injectAtStreamEnd(injectString.htmlPartsEnd);
74
- }
75
- });
67
+ const { injectAtStreamBegin, injectAtStreamAfterFirstChunk, injectAtStreamEnd } = (0, injectAssets_js_1.injectHtmlTagsToStream)(pageContext, streamFromReactStreamingPackage, injectFilter);
68
+ processStreamOptions.injectStringAtBegin = async () => {
69
+ return await injectAtStreamBegin(injectString.htmlPartsBegin);
70
+ };
71
+ processStreamOptions.injectStringAtEnd = async () => {
72
+ return await injectAtStreamEnd(injectString.htmlPartsEnd);
73
+ };
74
+ processStreamOptions.injectStringAfterFirstChunk = () => {
75
+ return injectAtStreamAfterFirstChunk();
76
+ };
76
77
  }
77
- const streamWrapper = await (0, stream_js_1.processStream)(streamOriginal, opts);
78
+ const streamWrapper = await (0, stream_js_1.processStream)(streamOriginal, processStreamOptions);
78
79
  return streamWrapper;
79
80
  }
80
81
  function isTemplateWrapped(something) {
@@ -46,17 +46,27 @@ function serializePageContextClientSide(pageContext) {
46
46
  let hasWarned = false;
47
47
  const propsNonSerializable = [];
48
48
  passToClient.forEach((prop) => {
49
- const propName = JSON.stringify(prop);
50
- const varName = h(`pageContext[${propName}]`);
49
+ const propName1 = (0, utils_js_1.getPropAccessNotation)(prop);
50
+ const propName2 = JSON.stringify(prop);
51
+ const varName = `pageContext${propName1}`;
51
52
  try {
52
53
  serialize(pageContext[prop], varName);
53
54
  }
54
55
  catch (err) {
55
56
  hasWarned = true;
56
57
  propsNonSerializable.push(prop);
58
+ // useConfig() wrong usage
59
+ if (prop === '_configFromHook') {
60
+ let pathString = '';
61
+ if ((0, stringify_1.isJsonSerializerError)(err)) {
62
+ pathString = err.pathString;
63
+ }
64
+ (0, utils_js_1.assertUsage)(false, `Cannot serialize config ${h(pathString)} set by useConfig(), see https://vike.dev/useConfig#serialization-error`);
65
+ }
66
+ // Non-serializable pageContext set by the user
57
67
  let msg = [
58
- `${varName} cannot be serialized and, therefore, cannot be passed to the client.`,
59
- `Make sure that ${varName} is serializable, or remove ${h(propName)} from ${h('passToClient')}.`
68
+ `${h(varName)} can't be serialized and, therefore, can't be passed to the client side.`,
69
+ `Make sure ${h(varName)} is serializable, or remove ${h(propName2)} from ${h('passToClient')}.`
60
70
  ].join(' ');
61
71
  if ((0, stringify_1.isJsonSerializerError)(err)) {
62
72
  msg = `${msg} Serialization error: ${err.messageCore}.`;
@@ -198,7 +198,7 @@ function pipeToStreamWritableNode(htmlRender, writable) {
198
198
  (0, utils_js_1.assert)(false);
199
199
  }
200
200
  exports.pipeToStreamWritableNode = pipeToStreamWritableNode;
201
- async function processStream(streamOriginal, { injectStringAtBegin, injectStringAtEnd, onErrorWhileStreaming, enableEagerStreaming }) {
201
+ async function processStream(streamOriginal, { injectStringAtBegin, injectStringAfterFirstChunk, injectStringAtEnd, onErrorWhileStreaming, enableEagerStreaming }) {
202
202
  const buffer = [];
203
203
  let streamOriginalHasStartedEmitting = false;
204
204
  let streamOriginalEnded = false;
@@ -210,6 +210,7 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
210
210
  let resolve;
211
211
  let reject;
212
212
  let promiseHasResolved = false;
213
+ let injectStringAfterFirstChunk_done = false;
213
214
  const streamWrapperPromise = new Promise((resolve_, reject_) => {
214
215
  resolve = (streamWrapper) => {
215
216
  promiseHasResolved = true;
@@ -223,8 +224,8 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
223
224
  let resolveReadyToWrite;
224
225
  const promiseReadyToWrite = new Promise((r) => (resolveReadyToWrite = r));
225
226
  if (injectStringAtBegin) {
226
- const injectionBegin = await injectStringAtBegin();
227
- writeStream(injectionBegin); // Adds injectionBegin to buffer
227
+ const injectedChunk = await injectStringAtBegin();
228
+ writeStream(injectedChunk); // Adds injectedChunk to buffer
228
229
  flushStream(); // Sets shouldFlushStream to true
229
230
  }
230
231
  // We call onStreamEvent() also when the stream ends in order to properly handle the situation when the stream didn't emit any data
@@ -254,6 +255,12 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
254
255
  onData(chunk) {
255
256
  onStreamDataOrEnd(() => {
256
257
  writeStream(chunk);
258
+ if (injectStringAfterFirstChunk && !injectStringAfterFirstChunk_done) {
259
+ const injectedChunk = injectStringAfterFirstChunk();
260
+ if (injectedChunk !== null)
261
+ writeStream(injectedChunk);
262
+ injectStringAfterFirstChunk_done = true;
263
+ }
257
264
  });
258
265
  },
259
266
  async onEnd(
@@ -268,8 +275,8 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
268
275
  streamOriginalEnded = true;
269
276
  });
270
277
  if (injectStringAtEnd) {
271
- const injectEnd = await injectStringAtEnd();
272
- writeStream(injectEnd);
278
+ const injectedChunk = await injectStringAtEnd();
279
+ writeStream(injectedChunk);
273
280
  }
274
281
  await promiseReadyToWrite; // E.g. if the user calls the pipe wrapper after the original writable has ended
275
282
  (0, utils_js_1.assert)(isReady());
@@ -28,7 +28,7 @@ async function executeOnRenderHtmlHook(pageContext) {
28
28
  const onErrorWhileStreaming = (err) => {
29
29
  // Should the stream inject the following?
30
30
  // ```
31
- // <script>console.error("An error occurred on the server while streaming the app to HTML. Check the server logs for more information.")</script>
31
+ // <script>console.error("An error occurred on the server side while streaming the page to HTML, see server logs.")</script>
32
32
  // ```
33
33
  (0, loggerRuntime_js_1.logRuntimeError)(err, pageContext._httpRequestId);
34
34
  if (!pageContext.errorWhileRendering) {
@@ -247,8 +247,7 @@ function logHttpResponse(urlOriginal, httpRequestId, pageContextReturn) {
247
247
  (0, loggerRuntime_js_1.logRuntimeInfo)?.(msg, httpRequestId, isNominal ? 'info' : 'error');
248
248
  }
249
249
  function getPageContextHttpResponseNullWithError(err, pageContextInit) {
250
- const pageContextHttpResponseNull = {};
251
- (0, utils_js_1.objectAssign)(pageContextHttpResponseNull, pageContextInit);
250
+ const pageContextHttpResponseNull = createPageContext(pageContextInit);
252
251
  (0, utils_js_1.objectAssign)(pageContextHttpResponseNull, {
253
252
  httpResponse: null,
254
253
  errorWhileRendering: err
@@ -256,14 +255,20 @@ function getPageContextHttpResponseNullWithError(err, pageContextInit) {
256
255
  return pageContextHttpResponseNull;
257
256
  }
258
257
  function getPageContextHttpResponseNull(pageContextInit) {
259
- const pageContextHttpResponseNull = {};
260
- (0, utils_js_1.objectAssign)(pageContextHttpResponseNull, pageContextInit);
258
+ const pageContextHttpResponseNull = createPageContext(pageContextInit);
261
259
  (0, utils_js_1.objectAssign)(pageContextHttpResponseNull, {
262
260
  httpResponse: null,
263
261
  errorWhileRendering: null
264
262
  });
265
263
  return pageContextHttpResponseNull;
266
264
  }
265
+ function createPageContext(pageContextInit) {
266
+ const pageContext = {
267
+ _isPageContextObject: true
268
+ };
269
+ Object.assign(pageContext, pageContextInit);
270
+ return pageContext;
271
+ }
267
272
  async function renderPageNominal(pageContext) {
268
273
  (0, utils_js_1.objectAssign)(pageContext, { errorWhileRendering: null });
269
274
  // Route
@@ -347,8 +352,7 @@ function normalizeUrl(pageContextInit, httpRequestId) {
347
352
  return null;
348
353
  (0, loggerRuntime_js_1.logRuntimeInfo)?.(`URL normalized from ${picocolors_1.default.cyan(urlOriginal)} to ${picocolors_1.default.cyan(urlNormalized)} (https://vike.dev/url-normalization)`, httpRequestId, 'info');
349
354
  const httpResponse = (0, createHttpResponseObject_js_1.createHttpResponseObjectRedirect)({ url: urlNormalized, statusCode: 301 }, pageContextInit.urlOriginal);
350
- const pageContextHttpResponse = {};
351
- (0, utils_js_1.objectAssign)(pageContextHttpResponse, pageContextInit);
355
+ const pageContextHttpResponse = createPageContext(pageContextInit);
352
356
  (0, utils_js_1.objectAssign)(pageContextHttpResponse, { httpResponse });
353
357
  return pageContextHttpResponse;
354
358
  }
@@ -384,8 +388,7 @@ function getPermanentRedirect(pageContextInit, httpRequestId) {
384
388
  }
385
389
  (0, loggerRuntime_js_1.logRuntimeInfo)?.(`Permanent redirect defined by your config.redirects (https://vike.dev/redirects)`, httpRequestId, 'info');
386
390
  const httpResponse = (0, createHttpResponseObject_js_1.createHttpResponseObjectRedirect)({ url: urlTarget, statusCode: 301 }, urlWithoutBase);
387
- const pageContextHttpResponse = {};
388
- (0, utils_js_1.objectAssign)(pageContextHttpResponse, pageContextInit);
391
+ const pageContextHttpResponse = createPageContext(pageContextInit);
389
392
  (0, utils_js_1.objectAssign)(pageContextHttpResponse, { httpResponse });
390
393
  return pageContextHttpResponse;
391
394
  }
@@ -401,9 +404,8 @@ pageContextNominalPageInit, httpRequestId, renderContext, pageContextErrorPageIn
401
404
  const abortCall = pageContextAbort._abortCall;
402
405
  (0, utils_js_1.assert)(abortCall);
403
406
  (0, utils_js_1.assertUsage)(errorPageId, `You called ${picocolors_1.default.cyan(abortCall)} but you didn't define an error page, make sure to define one https://vike.dev/error-page`);
404
- const pageContext = {
405
- _pageId: errorPageId
406
- };
407
+ const pageContext = createPageContext({});
408
+ (0, utils_js_1.objectAssign)(pageContext, { _pageId: errorPageId });
407
409
  (0, utils_js_1.objectAssign)(pageContext, pageContextAbort);
408
410
  (0, utils_js_1.objectAssign)(pageContext, pageContextErrorPageInit);
409
411
  (0, utils_js_1.objectAssign)(pageContext, renderContext);
@@ -427,8 +429,7 @@ pageContextNominalPageInit, httpRequestId, renderContext, pageContextErrorPageIn
427
429
  return { pageContextReturn };
428
430
  }
429
431
  if (pageContextAbort._urlRedirect) {
430
- const pageContextReturn = {};
431
- (0, utils_js_1.objectAssign)(pageContextReturn, pageContextInit);
432
+ const pageContextReturn = createPageContext(pageContextInit);
432
433
  (0, utils_js_1.objectAssign)(pageContextReturn, pageContextAbort);
433
434
  const httpResponse = (0, createHttpResponseObject_js_1.createHttpResponseObjectRedirect)(pageContextAbort._urlRedirect, (() => {
434
435
  const { pathname, searchOriginal } = pageContextNominalPageInit.urlParsed;
@@ -71,3 +71,4 @@ __exportStar(require("../../utils/isArrayOfStrings.js"), exports);
71
71
  __exportStar(require("../../utils/escapeHtml.js"), exports);
72
72
  __exportStar(require("../../utils/normalizeHeaders.js"), exports);
73
73
  __exportStar(require("../../utils/isVikeReactApp.js"), exports);
74
+ __exportStar(require("../../utils/getPropAccessNotation.js"), exports);
@@ -157,6 +157,10 @@ function valueToJson(value, configName, definedAtData, importStatements) {
157
157
  configValueSerialized = (0, stringify_1.stringify)(value, {
158
158
  valueName,
159
159
  forbidReactElements: true,
160
+ // Replace import strings with import variables.
161
+ // - We don't need this anymore and could remove it.
162
+ // - We temporarily needed it for nested document configs (`config.document.{title,description,favicon}`), but we finally decided to go for flat document configs instead (`config.{title,description,favicon}`).
163
+ // - https://github.com/vikejs/vike-react/pull/113
160
164
  replacer(_, value) {
161
165
  if (typeof value === 'string') {
162
166
  const importData = (0, transformFileImports_js_1.parsePointerImportData)(value);
@@ -18,12 +18,12 @@ const resolveRouteFunction_js_1 = require("./resolveRouteFunction.js");
18
18
  const executeOnBeforeRouteHook_js_1 = require("./executeOnBeforeRouteHook.js");
19
19
  const debug_js_1 = require("./debug.js");
20
20
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
21
- async function route(pageContextForRoute) {
22
- (0, debug_js_1.debug)('Pages routes:', pageContextForRoute._pageRoutes);
23
- (0, getPageContextUrlComputed_js_1.assertPageContextUrl)(pageContextForRoute);
21
+ async function route(pageContext) {
22
+ (0, debug_js_1.debug)('Pages routes:', pageContext._pageRoutes);
23
+ (0, getPageContextUrlComputed_js_1.assertPageContextUrl)(pageContext);
24
24
  const pageContextFromRoute = {};
25
25
  // onBeforeRoute()
26
- const pageContextFromOnBeforeRouteHook = await (0, executeOnBeforeRouteHook_js_1.executeOnBeforeRouteHook)(pageContextForRoute);
26
+ const pageContextFromOnBeforeRouteHook = await (0, executeOnBeforeRouteHook_js_1.executeOnBeforeRouteHook)(pageContext);
27
27
  if (pageContextFromOnBeforeRouteHook) {
28
28
  if (pageContextFromOnBeforeRouteHook._routingProvidedByOnBeforeRouteHook) {
29
29
  (0, utils_js_1.assert)(pageContextFromOnBeforeRouteHook._pageId);
@@ -34,8 +34,6 @@ async function route(pageContextForRoute) {
34
34
  }
35
35
  }
36
36
  // We take into account pageContext.urlLogical set by onBeforeRoute()
37
- const pageContext = {};
38
- (0, utils_js_1.objectAssign)(pageContext, pageContextForRoute);
39
37
  (0, utils_js_1.objectAssign)(pageContext, pageContextFromOnBeforeRouteHook);
40
38
  // Vike's routing
41
39
  const allPageIds = pageContext._allPageIds;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.augmentType = void 0;
4
+ const assert_js_1 = require("./assert.js");
5
+ /** Help TypeScript augment the type of objects. */
6
+ function augmentType(thing, clone) {
7
+ // @ts-ignore
8
+ (0, assert_js_1.assert)(thing === clone);
9
+ }
10
+ exports.augmentType = augmentType;
@@ -2,6 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPropAccessNotation = void 0;
4
4
  function getPropAccessNotation(key) {
5
- return typeof key === 'string' && /^[a-z0-9\$_]+$/i.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
5
+ return typeof key === 'string' && isKeyDotNotationCompatible(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
6
6
  }
7
7
  exports.getPropAccessNotation = getPropAccessNotation;
8
+ function isKeyDotNotationCompatible(key) {
9
+ return /^[a-z0-9\$_]+$/i.test(key);
10
+ }
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.objectAssign = void 0;
4
+ const assert_js_1 = require("./assert.js");
4
5
  // Same as Object.assign() but:
5
6
  // - With type inference
6
7
  // - Preserves property descriptors, which we need for preserving the getters added by getPageContextUrlComputed()
7
8
  function objectAssign(obj, objAddendum) {
8
9
  if (objAddendum) {
10
+ (0, assert_js_1.assert)(!('_isPageContextObject' in objAddendum));
9
11
  Object.defineProperties(obj, Object.getOwnPropertyDescriptors(objAddendum));
10
12
  }
11
13
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PROJECT_VERSION = exports.projectInfo = void 0;
4
- const PROJECT_VERSION = '0.4.179';
4
+ const PROJECT_VERSION = '0.4.180';
5
5
  exports.PROJECT_VERSION = PROJECT_VERSION;
6
6
  const projectInfo = {
7
7
  projectName: 'Vike',
@@ -11,6 +11,7 @@ declare function createPageContext(urlOriginal: string): Promise<{
11
11
  _allPageIds: string[];
12
12
  _pageRoutes: import("../../shared/route/loadPageRoutes.js").PageRoutes;
13
13
  _onBeforeRouteHook: import("../../shared/hooks/getHook.js").Hook | null;
14
+ _isPageContextObject: boolean;
14
15
  } & {
15
16
  urlParsed: import("../../shared/getPageContextUrlComputed.js").Url;
16
17
  urlPathname: string;
@@ -24,7 +24,8 @@ async function createPageContext(urlOriginal) {
24
24
  _pageConfigGlobal: pageConfigGlobal,
25
25
  _allPageIds: allPageIds,
26
26
  _pageRoutes: pageRoutes,
27
- _onBeforeRouteHook: onBeforeRouteHook
27
+ _onBeforeRouteHook: onBeforeRouteHook,
28
+ _isPageContextObject: true
28
29
  };
29
30
  const pageContextUrlComputed = getPageContextUrlComputed(pageContext);
30
31
  objectAssign(pageContext, pageContextUrlComputed);
@@ -16,7 +16,7 @@ type PageContextSerialized = {
16
16
  declare function getPageContextFromHooks_serialized(): PageContextSerialized & {
17
17
  routeParams: Record<string, string>;
18
18
  };
19
- declare function getPageContextFromHooks_isHydration(pageContext: PageContextSerialized & PageContext & PageContextExports): Promise<{
19
+ declare function getPageContextFromHooks_isHydration(pageContext: PageContextSerialized & PageContext & PageContextExports): Promise<PageContextSerialized & PageContext & PageContextExports & {
20
20
  isHydration: true;
21
21
  _hasPageContextFromClient: false;
22
22
  _hasPageContextFromServer: true;
@@ -25,9 +25,11 @@ declare function getPageContextFromHooks_isNotHydration(pageContext: {
25
25
  _pageId: string;
26
26
  } & PageContext & PageContextExports, isErrorPage: boolean): Promise<{
27
27
  is404ServerSideRouted: boolean;
28
- pageContextFromHooks?: undefined;
28
+ pageContextAugmented?: undefined;
29
29
  } | {
30
- pageContextFromHooks: {
30
+ pageContextAugmented: {
31
+ _pageId: string;
32
+ } & PageContext & PageContextExports & {
31
33
  isHydration: false;
32
34
  _hasPageContextFromClient: boolean;
33
35
  } & {