vike 0.4.228-commit-d423e4f → 0.4.228-commit-ae4784f

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 (61) hide show
  1. package/dist/cjs/client/client-routing-runtime/globalContextClientSide.js +10 -0
  2. package/dist/cjs/client/client-routing-runtime/onLoad.js +10 -0
  3. package/dist/cjs/client/client-routing-runtime/utils.js +43 -0
  4. package/dist/cjs/client/server-routing-runtime/utils.js +0 -1
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +5 -0
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles/ignorePatternsBuiltIn.js +2 -0
  7. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +1 -1
  8. package/dist/cjs/node/prerender/runPrerender.js +8 -7
  9. package/dist/cjs/node/runtime/renderPage/createHttpResponse.js +8 -3
  10. package/dist/cjs/node/runtime/renderPage/createPageContextServerSide.js +73 -0
  11. package/dist/cjs/node/runtime/renderPage/executeHookGeneric.js +18 -0
  12. package/dist/cjs/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.js +2 -2
  13. package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +2 -2
  14. package/dist/cjs/node/runtime/renderPage/getPageAssets/retrieveAssetsDev.js +1 -17
  15. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +0 -65
  16. package/dist/cjs/node/runtime/renderPage.js +96 -75
  17. package/dist/cjs/shared/hooks/getHook.js +45 -27
  18. package/dist/cjs/shared/route/executeGuardHook.js +1 -1
  19. package/dist/cjs/shared/route/loadPageRoutes.js +1 -0
  20. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  21. package/dist/cjs/utils/objectAssign.js +2 -6
  22. package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +3 -0
  23. package/dist/esm/client/client-routing-runtime/createPageContext.js +2 -0
  24. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +4 -3
  25. package/dist/esm/client/client-routing-runtime/globalContextClientSide.d.ts +5 -0
  26. package/dist/esm/client/client-routing-runtime/globalContextClientSide.js +8 -0
  27. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +8 -6
  28. package/dist/esm/client/client-routing-runtime/utils.d.ts +0 -1
  29. package/dist/esm/client/client-routing-runtime/utils.js +0 -1
  30. package/dist/esm/client/server-routing-runtime/utils.d.ts +0 -1
  31. package/dist/esm/client/server-routing-runtime/utils.js +0 -1
  32. package/dist/esm/client/shared/executeOnRenderClientHook.js +5 -4
  33. package/dist/esm/client/shared/removeFoucBuster.js +1 -0
  34. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +5 -0
  35. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles/ignorePatternsBuiltIn.d.ts +1 -1
  36. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles/ignorePatternsBuiltIn.js +2 -0
  37. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +1 -1
  38. package/dist/esm/node/prerender/runPrerender.js +9 -8
  39. package/dist/esm/node/runtime/renderPage/createHttpResponse.d.ts +5 -4
  40. package/dist/esm/node/runtime/renderPage/createHttpResponse.js +8 -3
  41. package/dist/esm/node/runtime/renderPage/createPageContextServerSide.d.ts +85 -0
  42. package/dist/esm/node/runtime/renderPage/createPageContextServerSide.js +71 -0
  43. package/dist/esm/node/runtime/renderPage/executeHookGeneric.d.ts +9 -0
  44. package/dist/esm/node/runtime/renderPage/executeHookGeneric.js +16 -0
  45. package/dist/esm/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.js +3 -3
  46. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +3 -3
  47. package/dist/esm/node/runtime/renderPage/getPageAssets/retrieveAssetsDev.js +1 -17
  48. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +15 -113
  49. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -66
  50. package/dist/esm/node/runtime/renderPage.d.ts +74 -7
  51. package/dist/esm/node/runtime/renderPage.js +98 -77
  52. package/dist/esm/shared/hooks/getHook.d.ts +4 -2
  53. package/dist/esm/shared/hooks/getHook.js +47 -29
  54. package/dist/esm/shared/page-configs/Config.d.ts +6 -1
  55. package/dist/esm/shared/route/executeGuardHook.js +2 -2
  56. package/dist/esm/shared/route/loadPageRoutes.js +1 -0
  57. package/dist/esm/shared/types.d.ts +8 -6
  58. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  59. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  60. package/dist/esm/utils/objectAssign.js +2 -6
  61. package/package.json +1 -1
@@ -1,12 +1,13 @@
1
1
  export { renderPage };
2
2
  export { renderPage_addAsyncHookwrapper };
3
- import { getPageContextInitEnhanced, renderPageAlreadyRouted, createPageContext } from './renderPage/renderPageAlreadyRouted.js';
3
+ import { renderPageAlreadyRouted } from './renderPage/renderPageAlreadyRouted.js';
4
+ import { createPageContextServerSide, createPageContextServerSideWithoutGlobalContext } from './renderPage/createPageContextServerSide.js';
4
5
  import { route } from '../../shared/route/index.js';
5
6
  import { assert, hasProp, objectAssign, isUrl, parseUrl, onSetupRuntime, assertWarning, getGlobalObject, checkType, assertUsage, normalizeUrlPathname, removeBaseServer, modifyUrlPathname, prependBase, removeUrlOrigin, setUrlOrigin, isUri, getUrlPretty } from './utils.js';
6
7
  import { assertNoInfiniteAbortLoop, getPageContextFromAllRewrites, isAbortError, logAbortErrorHandled } from '../../shared/route/abort.js';
7
8
  import { getGlobalContextInternal, initGlobalContext_renderPage } from './globalContext.js';
8
9
  import { handlePageContextRequestUrl } from './renderPage/handlePageContextRequestUrl.js';
9
- import { createHttpResponseFavicon404, createHttpResponseRedirect, createHttpResponsePageContextJson, createHttpResponseError, createHttpResponseBaseIsMissing } from './renderPage/createHttpResponse.js';
10
+ import { createHttpResponseFavicon404, createHttpResponseRedirect, createHttpResponsePageContextJson, createHttpResponseError, createHttpResponseErrorWithoutGlobalContext, createHttpResponseBaseIsMissing } from './renderPage/createHttpResponse.js';
10
11
  import { logRuntimeError, logRuntimeInfo } from './renderPage/loggerRuntime.js';
11
12
  import { isNewError } from './renderPage/isNewError.js';
12
13
  import { assertArguments } from './renderPage/assertArguments.js';
@@ -27,13 +28,13 @@ async function renderPage(pageContextInit) {
27
28
  assert(hasProp(pageContextInit, 'urlOriginal', 'string')); // assertUsage() already implemented at assertArguments()
28
29
  assertIsUrl(pageContextInit.urlOriginal);
29
30
  onSetupRuntime();
30
- const pageContextInvalidRequest = renderInvalidRequest(pageContextInit);
31
+ const pageContextInvalidRequest = getPageContextInvalidRequest(pageContextInit);
31
32
  if (pageContextInvalidRequest)
32
33
  return pageContextInvalidRequest;
33
34
  const httpRequestId = getRequestId();
34
35
  const urlOriginalPretty = getUrlPretty(pageContextInit.urlOriginal);
35
36
  logHttpRequest(urlOriginalPretty, httpRequestId);
36
- const { pageContextReturn } = await asyncHookWrapper(httpRequestId, () => renderPageAndPrepare(pageContextInit, httpRequestId));
37
+ const { pageContextReturn } = await asyncHookWrapper(httpRequestId, () => renderPagePrepare(pageContextInit, httpRequestId));
37
38
  logHttpResponse(urlOriginalPretty, httpRequestId, pageContextReturn);
38
39
  checkType(pageContextReturn);
39
40
  assert(pageContextReturn.httpResponse);
@@ -47,13 +48,12 @@ let asyncHookWrapper = async (_httpRequestId, ret) => ({
47
48
  function renderPage_addAsyncHookwrapper(wrapper) {
48
49
  asyncHookWrapper = wrapper;
49
50
  }
50
- async function renderPageAndPrepare(pageContextInit, httpRequestId) {
51
+ async function renderPagePrepare(pageContextInit, httpRequestId) {
51
52
  // Invalid config
52
- if (isVikeConfigInvalid) {
53
- if (1 < 2 // Make TS happy
54
- ) {
55
- return renderInvalidVikeConfig(isVikeConfigInvalid.err, pageContextInit, httpRequestId);
56
- }
53
+ if (isVikeConfigInvalid &&
54
+ true // Make TS happy
55
+ ) {
56
+ return getPageContextInvalidVikeConfig(isVikeConfigInvalid.err, pageContextInit, httpRequestId);
57
57
  }
58
58
  // Prepare context
59
59
  try {
@@ -67,49 +67,52 @@ async function renderPageAndPrepare(pageContextInit, httpRequestId) {
67
67
  // initGlobalContext_renderPage() doens't call any user hook => err isn't thrown from user code.
68
68
  assert(!isAbortError(err));
69
69
  logRuntimeError(err, httpRequestId);
70
- const pageContextWithError = getPageContextHttpResponseError(err, pageContextInit, null);
70
+ const pageContextWithError = getPageContextHttpResponseErrorWithoutGlobalContext(err, pageContextInit);
71
71
  return pageContextWithError;
72
72
  }
73
73
  if (isVikeConfigInvalid) {
74
- return renderInvalidVikeConfig(isVikeConfigInvalid.err, pageContextInit, httpRequestId);
74
+ return getPageContextInvalidVikeConfig(isVikeConfigInvalid.err, pageContextInit, httpRequestId);
75
75
  }
76
76
  else {
77
77
  // `globalContext` now contains the entire Vike config and getVikeConfig() isn't called anymore for this request.
78
78
  }
79
79
  const globalContext = await getGlobalContextInternal();
80
+ const pageContextBegin = await getPageContextBegin(pageContextInit, globalContext, httpRequestId);
80
81
  // Check Base URL
81
82
  {
82
- const pageContextHttpResponse = await checkBaseUrl(pageContextInit, globalContext);
83
+ const pageContextHttpResponse = await checkBaseUrl(pageContextBegin, globalContext);
83
84
  if (pageContextHttpResponse)
84
85
  return pageContextHttpResponse;
85
86
  }
86
87
  // Normalize URL
87
88
  {
88
- const pageContextHttpResponse = await normalizeUrl(pageContextInit, globalContext, httpRequestId);
89
+ const pageContextHttpResponse = await normalizeUrl(pageContextBegin, globalContext, httpRequestId);
89
90
  if (pageContextHttpResponse)
90
91
  return pageContextHttpResponse;
91
92
  }
92
93
  // Permanent redirects (HTTP status code `301`)
93
94
  {
94
- const pageContextHttpResponse = await getPermanentRedirect(pageContextInit, globalContext, httpRequestId);
95
+ const pageContextHttpResponse = await getPermanentRedirect(pageContextBegin, globalContext, httpRequestId);
95
96
  if (pageContextHttpResponse)
96
97
  return pageContextHttpResponse;
97
98
  }
98
- return await renderPageAlreadyPrepared(pageContextInit, globalContext, httpRequestId, []);
99
+ return await renderPageAlreadyPrepared(pageContextBegin, globalContext, httpRequestId, []);
99
100
  }
100
- async function renderPageAlreadyPrepared(pageContextInit, globalContext, httpRequestId, pageContextsFromRewrite) {
101
+ async function renderPageAlreadyPrepared(pageContextBegin, globalContext, httpRequestId, pageContextsFromRewrite) {
102
+ const pageContextNominalPageBegin = forkPageContext(pageContextBegin);
101
103
  assertNoInfiniteAbortLoop(pageContextsFromRewrite.length,
102
104
  // There doesn't seem to be a way to count the number of HTTP redirects (vike don't have access to the HTTP request headers/cookies)
103
105
  // https://stackoverflow.com/questions/9683007/detect-infinite-http-redirect-loop-on-server-side
104
106
  0);
105
107
  let pageContextNominalPageSuccess;
106
108
  const pageContextFromAllRewrites = getPageContextFromAllRewrites(pageContextsFromRewrite);
107
- const pageContextNominalPageInit = await getPageContextInitEnhancedSSR(pageContextInit, globalContext, pageContextFromAllRewrites._urlRewrite, httpRequestId);
108
- objectAssign(pageContextNominalPageInit, pageContextFromAllRewrites);
109
+ // This is where pageContext._urlRewrite is set
110
+ assert(pageContextFromAllRewrites._urlRewrite === null || typeof pageContextFromAllRewrites._urlRewrite === 'string');
111
+ objectAssign(pageContextNominalPageBegin, pageContextFromAllRewrites);
109
112
  let errNominalPage;
110
113
  {
111
114
  try {
112
- pageContextNominalPageSuccess = await renderPageNominal(pageContextNominalPageInit);
115
+ pageContextNominalPageSuccess = await renderPageNominal(pageContextNominalPageBegin);
113
116
  }
114
117
  catch (err) {
115
118
  errNominalPage = err;
@@ -117,7 +120,7 @@ async function renderPageAlreadyPrepared(pageContextInit, globalContext, httpReq
117
120
  logRuntimeError(errNominalPage, httpRequestId);
118
121
  }
119
122
  if (!errNominalPage) {
120
- assert(pageContextNominalPageSuccess === pageContextNominalPageInit);
123
+ assert(pageContextNominalPageSuccess === pageContextNominalPageBegin);
121
124
  }
122
125
  }
123
126
  // Log upon 404
@@ -133,12 +136,12 @@ async function renderPageAlreadyPrepared(pageContextInit, globalContext, httpReq
133
136
  else {
134
137
  assert(errNominalPage);
135
138
  assert(pageContextNominalPageSuccess === undefined);
136
- assert(pageContextNominalPageInit);
137
- assert(hasProp(pageContextNominalPageInit, 'urlOriginal', 'string'));
138
- const pageContextErrorPageInit = await getPageContextErrorPageInit(pageContextInit, globalContext, errNominalPage, pageContextNominalPageInit, httpRequestId);
139
+ assert(pageContextNominalPageBegin);
140
+ assert(hasProp(pageContextNominalPageBegin, 'urlOriginal', 'string'));
141
+ const pageContextErrorPageInit = await getPageContextErrorPageInit(pageContextBegin, errNominalPage, pageContextNominalPageBegin);
139
142
  // Handle `throw redirect()` and `throw render()` while rendering nominal page
140
143
  if (isAbortError(errNominalPage)) {
141
- const handled = await handleAbortError(errNominalPage, pageContextsFromRewrite, pageContextInit, pageContextNominalPageInit, httpRequestId, pageContextErrorPageInit, globalContext);
144
+ const handled = await handleAbortError(errNominalPage, pageContextsFromRewrite, pageContextBegin, pageContextNominalPageBegin, httpRequestId, pageContextErrorPageInit, globalContext);
142
145
  if (handled.pageContextReturn) {
143
146
  // - throw redirect()
144
147
  // - throw render(url)
@@ -167,12 +170,12 @@ async function renderPageAlreadyPrepared(pageContextInit, globalContext, httpReq
167
170
  catch (errErrorPage) {
168
171
  // Handle `throw redirect()` and `throw render()` while rendering error page
169
172
  if (isAbortError(errErrorPage)) {
170
- const handled = await handleAbortError(errErrorPage, pageContextsFromRewrite, pageContextInit, pageContextNominalPageInit, httpRequestId, pageContextErrorPageInit, globalContext);
173
+ const handled = await handleAbortError(errErrorPage, pageContextsFromRewrite, pageContextBegin, pageContextNominalPageBegin, httpRequestId, pageContextErrorPageInit, globalContext);
171
174
  // throw render(abortStatusCode)
172
175
  if (!handled.pageContextReturn) {
173
176
  const pageContextAbort = errErrorPage._pageContextAbort;
174
177
  assertWarning(false, `Failed to render error page because ${pc.cyan(pageContextAbort._abortCall)} was called: make sure ${pc.cyan(pageContextAbort._abortCaller)} doesn't occur while the error page is being rendered.`, { onlyOnce: false });
175
- const pageContextHttpWithError = getPageContextHttpResponseError(errNominalPage, pageContextInit, pageContextErrorPageInit);
178
+ const pageContextHttpWithError = getPageContextHttpResponseError(errNominalPage, pageContextBegin);
176
179
  return pageContextHttpWithError;
177
180
  }
178
181
  // `throw redirect()` / `throw render(url)`
@@ -181,7 +184,7 @@ async function renderPageAlreadyPrepared(pageContextInit, globalContext, httpReq
181
184
  if (isNewError(errErrorPage, errNominalPage)) {
182
185
  logRuntimeError(errErrorPage, httpRequestId);
183
186
  }
184
- const pageContextWithError = getPageContextHttpResponseError(errNominalPage, pageContextInit, pageContextErrorPageInit);
187
+ const pageContextWithError = getPageContextHttpResponseError(errNominalPage, pageContextBegin);
185
188
  return pageContextWithError;
186
189
  }
187
190
  return pageContextErrorPage;
@@ -233,11 +236,26 @@ function logHttpResponse(urlOriginalPretty, httpRequestId, pageContextReturn) {
233
236
  logRuntimeInfo?.(msg, httpRequestId, isNominal ? 'info' : 'error');
234
237
  }
235
238
  function prettyUrl(url) {
236
- return pc.bold(decodeURI(url));
239
+ try {
240
+ url = decodeURI(url);
241
+ }
242
+ catch {
243
+ // https://github.com/vikejs/vike/pull/2367#issuecomment-2800967564
244
+ }
245
+ return pc.bold(url);
237
246
  }
238
- function getPageContextHttpResponseError(err, pageContextInit, pageContext) {
239
- const pageContextWithError = createPageContext(pageContextInit, false);
240
- const httpResponse = createHttpResponseError(pageContext);
247
+ function getPageContextHttpResponseError(err, pageContextBegin) {
248
+ const pageContextWithError = forkPageContext(pageContextBegin);
249
+ const httpResponse = createHttpResponseError(pageContextBegin);
250
+ objectAssign(pageContextWithError, {
251
+ httpResponse,
252
+ errorWhileRendering: err
253
+ });
254
+ return pageContextWithError;
255
+ }
256
+ function getPageContextHttpResponseErrorWithoutGlobalContext(err, pageContextInit) {
257
+ const pageContextWithError = createPageContextServerSideWithoutGlobalContext(pageContextInit);
258
+ const httpResponse = createHttpResponseErrorWithoutGlobalContext();
241
259
  objectAssign(pageContextWithError, {
242
260
  httpResponse,
243
261
  errorWhileRendering: err
@@ -267,8 +285,8 @@ async function renderPageNominal(pageContext) {
267
285
  assert(pageContext === pageContextAfterRender);
268
286
  return pageContextAfterRender;
269
287
  }
270
- async function getPageContextErrorPageInit(pageContextInit, globalContext, errNominalPage, pageContextNominalPagePartial, httpRequestId) {
271
- const pageContext = await getPageContextInitEnhancedSSR(pageContextInit, globalContext, null, httpRequestId);
288
+ async function getPageContextErrorPageInit(pageContextBegin, errNominalPage, pageContextNominalPagePartial) {
289
+ const pageContext = forkPageContext(pageContextBegin);
272
290
  assert(errNominalPage);
273
291
  objectAssign(pageContext, {
274
292
  is404: false,
@@ -281,17 +299,17 @@ async function getPageContextErrorPageInit(pageContextInit, globalContext, errNo
281
299
  assert(pageContext.errorWhileRendering);
282
300
  return pageContext;
283
301
  }
284
- async function getPageContextInitEnhancedSSR(pageContextInit, globalContext, urlRewrite, httpRequestId) {
302
+ async function getPageContextBegin(pageContextInit, globalContext, httpRequestId) {
285
303
  const { isClientSideNavigation, _urlHandler } = handlePageContextUrl(pageContextInit.urlOriginal);
286
- const pageContextInitEnhanced = await getPageContextInitEnhanced(pageContextInit, globalContext, false, {
304
+ const pageContextBegin = await createPageContextServerSide(pageContextInit, globalContext, {
305
+ isPrerendering: false,
287
306
  ssr: {
288
- urlRewrite,
289
307
  urlHandler: _urlHandler,
290
308
  isClientSideNavigation
291
309
  }
292
310
  });
293
- objectAssign(pageContextInitEnhanced, { _httpRequestId: httpRequestId });
294
- return pageContextInitEnhanced;
311
+ objectAssign(pageContextBegin, { _httpRequestId: httpRequestId });
312
+ return pageContextBegin;
295
313
  }
296
314
  function handlePageContextUrl(urlOriginal) {
297
315
  const { isPageContextRequest } = handlePageContextRequestUrl(urlOriginal);
@@ -314,11 +332,12 @@ function assertIsNotViteRequest(urlPathname, urlOriginal) {
314
332
  return;
315
333
  assertUsage(false, `${pc.code('renderPage(pageContextInit)')} called with ${pc.code(`pageContextInit.urlOriginal===${JSON.stringify(urlOriginal)}`)} which is unexpected because the URL ${pc.bold(urlOriginal)} should have already been handled by the development middleware: make sure the ${pc.cyan('createDevMiddleware()')} middleware is executed *before* the ${pc.cyan('renderPage()')} middleware, see ${pc.underline('https://vike.dev/renderPage')}`);
316
334
  }
317
- async function normalizeUrl(pageContextInit, globalContext, httpRequestId) {
335
+ async function normalizeUrl(pageContextBegin, globalContext, httpRequestId) {
336
+ const pageContext = forkPageContext(pageContextBegin);
318
337
  const { trailingSlash, disableUrlNormalization } = globalContext.config;
319
338
  if (disableUrlNormalization)
320
339
  return null;
321
- const { urlOriginal } = pageContextInit;
340
+ const { urlOriginal } = pageContext;
322
341
  const { isPageContextRequest } = handlePageContextRequestUrl(urlOriginal);
323
342
  if (isPageContextRequest)
324
343
  return null;
@@ -326,13 +345,13 @@ async function normalizeUrl(pageContextInit, globalContext, httpRequestId) {
326
345
  if (!urlNormalized)
327
346
  return null;
328
347
  logRuntimeInfo?.(`URL normalized from ${pc.cyan(urlOriginal)} to ${pc.cyan(urlNormalized)} (https://vike.dev/url-normalization)`, httpRequestId, 'info');
329
- const httpResponse = createHttpResponseRedirect({ url: urlNormalized, statusCode: 301 }, pageContextInit);
330
- const pageContextHttpResponse = createPageContext(pageContextInit, false);
331
- objectAssign(pageContextHttpResponse, { httpResponse });
332
- return pageContextHttpResponse;
348
+ const httpResponse = createHttpResponseRedirect({ url: urlNormalized, statusCode: 301 }, pageContext);
349
+ objectAssign(pageContext, { httpResponse });
350
+ return pageContext;
333
351
  }
334
- async function getPermanentRedirect(pageContextInit, globalContext, httpRequestId) {
335
- const urlWithoutBase = removeBaseServer(pageContextInit.urlOriginal, globalContext.baseServer);
352
+ async function getPermanentRedirect(pageContextBegin, globalContext, httpRequestId) {
353
+ const pageContext = forkPageContext(pageContextBegin);
354
+ const urlWithoutBase = removeBaseServer(pageContext.urlOriginal, globalContext.baseServer);
336
355
  let origin = null;
337
356
  let urlTargetExternal = null;
338
357
  let urlTarget = modifyUrlPathname(urlWithoutBase, (urlPathname) => {
@@ -365,32 +384,29 @@ async function getPermanentRedirect(pageContextInit, globalContext, httpRequestI
365
384
  return null;
366
385
  if (!originChanged)
367
386
  urlTarget = prependBase(urlTarget, globalContext.baseServer);
368
- assert(urlTarget !== pageContextInit.urlOriginal);
387
+ assert(urlTarget !== pageContext.urlOriginal);
369
388
  }
370
389
  logRuntimeInfo?.(`Permanent redirection defined by config.redirects (https://vike.dev/redirects)`, httpRequestId, 'info');
371
- const httpResponse = createHttpResponseRedirect({ url: urlTarget, statusCode: 301 }, pageContextInit);
372
- const pageContextHttpResponse = createPageContext(pageContextInit, false);
373
- objectAssign(pageContextHttpResponse, { httpResponse });
374
- return pageContextHttpResponse;
390
+ const httpResponse = createHttpResponseRedirect({ url: urlTarget, statusCode: 301 }, pageContext);
391
+ objectAssign(pageContext, { httpResponse });
392
+ return pageContext;
375
393
  }
376
394
  function normalize(url) {
377
395
  return url || '/';
378
396
  }
379
- async function handleAbortError(errAbort, pageContextsFromRewrite,
380
- // The original `pageContextInit` object passed to `renderPage(pageContextInit)`
381
- pageContextInit,
382
- // handleAbortError() creates a new pageContext object and we don't merge pageContextNominalPageInit to it: we only use some pageContextNominalPageInit information.
383
- pageContextNominalPageInit, httpRequestId, pageContextErrorPageInit, globalContext) {
384
- logAbortErrorHandled(errAbort, globalContext.isProduction, pageContextNominalPageInit);
397
+ async function handleAbortError(errAbort, pageContextsFromRewrite, pageContextBegin,
398
+ // handleAbortError() creates a new pageContext object and we don't merge pageContextNominalPageBegin to it: we only use some pageContextNominalPageBegin information.
399
+ pageContextNominalPageBegin, httpRequestId, pageContextErrorPageInit, globalContext) {
400
+ logAbortErrorHandled(errAbort, globalContext.isProduction, pageContextNominalPageBegin);
385
401
  const pageContextAbort = errAbort._pageContextAbort;
386
402
  let pageContextSerialized;
387
- if (pageContextNominalPageInit.isClientSideNavigation) {
403
+ if (pageContextNominalPageBegin.isClientSideNavigation) {
388
404
  if (pageContextAbort.abortStatusCode) {
389
405
  const errorPageId = getErrorPageId(globalContext.pageFilesAll, globalContext.pageConfigs);
390
406
  const abortCall = pageContextAbort._abortCall;
391
407
  assert(abortCall);
392
408
  assertUsage(errorPageId, `You called ${pc.cyan(abortCall)} but you didn't define an error page, make sure to define one https://vike.dev/error-page`);
393
- const pageContext = createPageContext({}, false);
409
+ const pageContext = forkPageContext(pageContextBegin);
394
410
  objectAssign(pageContext, { pageId: errorPageId });
395
411
  objectAssign(pageContext, pageContextAbort);
396
412
  objectAssign(pageContext, pageContextErrorPageInit, true);
@@ -406,7 +422,7 @@ pageContextNominalPageInit, httpRequestId, pageContextErrorPageInit, globalConte
406
422
  return { pageContextReturn };
407
423
  }
408
424
  if (pageContextAbort._urlRewrite) {
409
- const pageContextReturn = await renderPageAlreadyPrepared(pageContextInit, globalContext, httpRequestId, [
425
+ const pageContextReturn = await renderPageAlreadyPrepared(pageContextBegin, globalContext, httpRequestId, [
410
426
  ...pageContextsFromRewrite,
411
427
  pageContextAbort
412
428
  ]);
@@ -414,22 +430,22 @@ pageContextNominalPageInit, httpRequestId, pageContextErrorPageInit, globalConte
414
430
  return { pageContextReturn };
415
431
  }
416
432
  if (pageContextAbort._urlRedirect) {
417
- const pageContextReturn = createPageContext(pageContextInit, false);
433
+ const pageContextReturn = forkPageContext(pageContextBegin);
418
434
  objectAssign(pageContextReturn, pageContextAbort);
419
- const httpResponse = createHttpResponseRedirect(pageContextAbort._urlRedirect, pageContextInit);
435
+ const httpResponse = createHttpResponseRedirect(pageContextAbort._urlRedirect, pageContextBegin);
420
436
  objectAssign(pageContextReturn, { httpResponse });
421
437
  return { pageContextReturn };
422
438
  }
423
439
  assert(pageContextAbort.abortStatusCode);
424
440
  return { pageContextAbort };
425
441
  }
426
- async function checkBaseUrl(pageContextInit, globalContext) {
442
+ async function checkBaseUrl(pageContextBegin, globalContext) {
443
+ const pageContext = forkPageContext(pageContextBegin);
427
444
  const { baseServer } = globalContext;
428
- const { urlOriginal } = pageContextInit;
445
+ const { urlOriginal } = pageContext;
429
446
  const { isBaseMissing } = parseUrl(urlOriginal, baseServer);
430
447
  if (!isBaseMissing)
431
448
  return;
432
- const pageContext = createPageContext(pageContextInit, false);
433
449
  const httpResponse = createHttpResponseBaseIsMissing(urlOriginal, baseServer);
434
450
  objectAssign(pageContext, {
435
451
  httpResponse,
@@ -438,20 +454,25 @@ async function checkBaseUrl(pageContextInit, globalContext) {
438
454
  checkType(pageContext);
439
455
  return pageContext;
440
456
  }
441
- function renderInvalidRequest(pageContextInit) {
457
+ function getPageContextInvalidRequest(pageContextInit) {
442
458
  const urlPathnameWithBase = parseUrl(pageContextInit.urlOriginal, '/').pathname;
443
459
  assertIsNotViteRequest(urlPathnameWithBase, pageContextInit.urlOriginal);
444
- if (urlPathnameWithBase.endsWith('/favicon.ico')) {
445
- const pageContext = createPageContext(pageContextInit, false);
446
- const httpResponse = createHttpResponseFavicon404();
447
- objectAssign(pageContext, { httpResponse });
448
- checkType(pageContext);
449
- return pageContext;
450
- }
451
- return null;
460
+ if (!urlPathnameWithBase.endsWith('/favicon.ico'))
461
+ return;
462
+ const pageContext = createPageContextServerSideWithoutGlobalContext(pageContextInit);
463
+ const httpResponse = createHttpResponseFavicon404();
464
+ objectAssign(pageContext, { httpResponse });
465
+ checkType(pageContext);
466
+ return pageContext;
452
467
  }
453
- function renderInvalidVikeConfig(err, pageContextInit, httpRequestId) {
468
+ function getPageContextInvalidVikeConfig(err, pageContextInit, httpRequestId) {
454
469
  logRuntimeInfo?.(pc.bold(pc.red('Error while loading a Vike config file, see error above.')), httpRequestId, 'error');
455
- const pageContextWithError = getPageContextHttpResponseError(err, pageContextInit, null);
470
+ const pageContextWithError = getPageContextHttpResponseErrorWithoutGlobalContext(err, pageContextInit);
456
471
  return pageContextWithError;
457
472
  }
473
+ // Create pageContext forks to avoid leaks: upon an error (bug or abort) a brand new pageContext object is created, in order to avoid previous pageContext modifications that are now obsolete to leak to the new pageContext object.
474
+ function forkPageContext(pageContextBegin) {
475
+ const pageContext = {};
476
+ objectAssign(pageContext, pageContextBegin, true);
477
+ return pageContext;
478
+ }
@@ -1,6 +1,7 @@
1
- export { getHook };
1
+ export { getHookFromPageContext };
2
2
  export { getHookFromPageConfig };
3
3
  export { getHookFromPageConfigGlobal };
4
+ export { getHookFromPageConfigGlobalCumulative };
4
5
  export { assertHook };
5
6
  export { getHook_setIsPrerenderering };
6
7
  export type { Hook };
@@ -26,9 +27,10 @@ type HookTimeout = {
26
27
  warning: number | false;
27
28
  };
28
29
  type HooksTimeoutProvidedByUser = false | Partial<Record<HookName, false | Partial<HookTimeout>>>;
29
- declare function getHook(pageContext: PageConfigUserFriendlyOld, hookName: HookName): null | Hook;
30
+ declare function getHookFromPageContext(pageContext: PageConfigUserFriendlyOld, hookName: HookName): null | Hook;
30
31
  declare function getHookFromPageConfig(pageConfig: PageConfigRuntime, hookName: HookNamePage): null | Hook;
31
32
  declare function getHookFromPageConfigGlobal(pageConfigGlobal: PageConfigGlobalRuntime, hookName: HookNameGlobal): null | Hook;
33
+ declare function getHookFromPageConfigGlobalCumulative(pageConfigGlobal: PageConfigGlobalRuntime, hookName: HookNameGlobal): Hook[];
32
34
  declare function assertHook<TPageContext extends PageConfigUserFriendlyOld, THookName extends PropertyKey & HookName>(pageContext: TPageContext, hookName: THookName): asserts pageContext is TPageContext & {
33
35
  exports: Record<THookName, Function | undefined>;
34
36
  };
@@ -1,70 +1,88 @@
1
- export { getHook };
1
+ export { getHookFromPageContext };
2
2
  export { getHookFromPageConfig };
3
3
  export { getHookFromPageConfigGlobal };
4
+ export { getHookFromPageConfigGlobalCumulative };
4
5
  export { assertHook };
5
6
  export { getHook_setIsPrerenderering };
6
7
  // TODO/v1-release: remove
7
- // We export for old V0.4 design which doesn't support configooksTimeout
8
+ // We export for old V0.4 design which doesn't support config.hooksTimeout
8
9
  export { getHookTimeoutDefault };
9
10
  import { getGlobalObject } from '../../utils/getGlobalObject.js';
10
11
  import { getHookFilePathToShowToUser } from '../page-configs/helpers.js';
11
12
  import { getConfigValueRuntime } from '../page-configs/getConfigValueRuntime.js';
12
- import { assert, assertUsage, checkType, isCallable, isObject } from '../utils.js';
13
+ import { assert, assertUsage, checkType, isArray, isCallable, isObject } from '../utils.js';
13
14
  import pc from '@brillout/picocolors';
14
15
  const globalObject = getGlobalObject('hooks/getHook.ts', {});
15
- function getHook(pageContext, hookName) {
16
+ function getHookFromPageContext(pageContext, hookName) {
16
17
  if (!(hookName in pageContext.exports)) {
17
18
  return null;
18
19
  }
19
20
  const { hooksTimeout } = pageContext.config;
20
21
  const hookTimeout = getHookTimeout(hooksTimeout, hookName);
21
22
  const hookFn = pageContext.exports[hookName];
22
- const file = pageContext.exportsAll[hookName][0];
23
- assert(file.exportValue === hookFn);
24
23
  if (hookFn === null)
25
24
  return null;
25
+ const file = pageContext.exportsAll[hookName][0];
26
+ assert(file.exportValue === hookFn);
26
27
  const hookFilePath = file.filePath;
27
28
  assert(hookFilePath);
28
- assert(!hookFilePath.endsWith(' '));
29
- assertHookFn(hookFn, { hookName, hookFilePath });
30
- return { hookFn, hookName, hookFilePath, hookTimeout };
29
+ return getHook(hookFn, hookName, hookFilePath, hookTimeout);
31
30
  }
32
31
  function getHookFromPageConfig(pageConfig, hookName) {
33
32
  const configValue = getConfigValueRuntime(pageConfig, hookName);
34
- const hooksTimeout = getConfigValueRuntime(pageConfig, 'hooksTimeout')?.value;
35
- if (!configValue)
33
+ if (!configValue?.value)
36
34
  return null;
37
- const hookFn = configValue.value;
38
- if (!hookFn)
39
- return null;
40
- const hookFilePath = getHookFilePathToShowToUser(configValue.definedAtData);
41
- // hook isn't a computed nor a cumulative config => hookFilePath should always be defined
42
- assert(hookFilePath);
43
- assertHookFn(hookFn, { hookName, hookFilePath });
35
+ const { hookFn, hookFilePath } = getHookFromConfigValue(configValue);
36
+ const hooksTimeout = getConfigValueRuntime(pageConfig, 'hooksTimeout')?.value;
44
37
  const hookTimeout = getHookTimeout(hooksTimeout, hookName);
45
- return { hookFn, hookName, hookFilePath, hookTimeout };
38
+ return getHook(hookFn, hookName, hookFilePath, hookTimeout);
46
39
  }
47
40
  function getHookFromPageConfigGlobal(pageConfigGlobal, hookName) {
48
41
  const configValue = pageConfigGlobal.configValues[hookName];
49
- if (!configValue)
50
- return null;
51
- const hookFn = configValue.value;
52
- if (!hookFn)
42
+ if (!configValue?.value)
53
43
  return null;
54
- const hookFilePath = getHookFilePathToShowToUser(configValue.definedAtData);
55
- // hook isn't a computed nor a cumulative config => hookFilePath should always be defined
44
+ const { hookFn, hookFilePath } = getHookFromConfigValue(configValue);
45
+ const hookTimeout = getHookTimeoutGlobal(hookName);
46
+ return getHook(hookFn, hookName, hookFilePath, hookTimeout);
47
+ }
48
+ function getHookFromPageConfigGlobalCumulative(pageConfigGlobal, hookName) {
49
+ const configValue = pageConfigGlobal.configValues[hookName];
50
+ if (!configValue?.value)
51
+ return [];
52
+ const val = configValue.value;
53
+ assert(isArray(val));
54
+ return val.map((v, i) => {
55
+ const hookFn = v;
56
+ const hookTimeout = getHookTimeoutGlobal(hookName);
57
+ assert(isArray(configValue.definedAtData));
58
+ const hookFilePath = getHookFilePathToShowToUser(configValue.definedAtData[i]);
59
+ return getHook(hookFn, hookName, hookFilePath, hookTimeout);
60
+ });
61
+ }
62
+ function getHookTimeoutGlobal(hookName) {
63
+ // TO-DO/perfection: we could use the global value of configooksTimeout but it requires some non-trivial refactoring
64
+ const hookTimeout = getHookTimeoutDefault(hookName);
65
+ return hookTimeout;
66
+ }
67
+ function getHook(hookFn, hookName, hookFilePath, hookTimeout) {
56
68
  assert(hookFilePath);
57
69
  assertHookFn(hookFn, { hookName, hookFilePath });
58
- // We could use the global value of configooksTimeout but it requires some non-trivial refactoring
59
- const hookTimeout = getHookTimeoutDefault(hookName);
60
- return { hookFn, hookName, hookFilePath, hookTimeout };
70
+ const hook = { hookFn, hookName, hookFilePath, hookTimeout };
71
+ return hook;
72
+ }
73
+ function getHookFromConfigValue(configValue) {
74
+ const hookFn = configValue.value;
75
+ assert(hookFn);
76
+ const hookFilePath = getHookFilePathToShowToUser(configValue.definedAtData);
77
+ return { hookFn, hookFilePath };
61
78
  }
62
79
  function assertHook(pageContext, hookName) {
63
- getHook(pageContext, hookName);
80
+ getHookFromPageContext(pageContext, hookName);
64
81
  }
65
82
  function assertHookFn(hookFn, { hookName, hookFilePath }) {
66
83
  assert(hookName && hookFilePath);
67
84
  assert(!hookName.endsWith(')'));
85
+ assert(!hookFilePath.endsWith(' '));
68
86
  assertUsage(isCallable(hookFn), `Hook ${hookName}() defined by ${hookFilePath} should be a function`);
69
87
  checkType(hookFn);
70
88
  }
@@ -45,7 +45,7 @@ import type { PageContextClient, PageContextServer } from '../types.js';
45
45
  import type { InlineConfig } from 'vite';
46
46
  type HookName = HookNamePage | HookNameGlobal | HookNameOldDesign;
47
47
  type HookNamePage = 'onHydrationEnd' | 'onBeforePrerenderStart' | 'onBeforeRender' | 'onPageTransitionStart' | 'onPageTransitionEnd' | 'onRenderHtml' | 'onRenderClient' | 'guard' | 'data';
48
- type HookNameGlobal = 'onBeforePrerender' | 'onBeforeRoute' | 'onPrerenderStart';
48
+ type HookNameGlobal = 'onCreatePageContext' | 'onBeforePrerender' | 'onBeforeRoute' | 'onPrerenderStart';
49
49
  type HookNameOldDesign = 'render' | 'prerender';
50
50
  type ConfigNameBuiltIn = Exclude<keyof Config, keyof VikeVitePluginOptions | 'onBeforeRoute' | 'onPrerenderStart' | 'vite' | 'redirects'> | 'prerender' | 'isClientRuntimeLoaded' | 'onBeforeRenderEnv' | 'dataEnv' | 'hooksTimeout' | 'clientHooks' | 'middleware';
51
51
  type ConfigNameGlobal = 'onPrerenderStart' | 'onBeforeRoute' | 'prerender' | 'disableAutoFullBuild' | 'includeAssetsImportedByServer' | 'baseAssets' | 'baseServer' | 'redirects' | 'trailingSlash' | 'disableUrlNormalization' | 'vite';
@@ -330,6 +330,11 @@ type ConfigBuiltIn = {
330
330
  * https://vike.dev/onBeforeRender
331
331
  */
332
332
  onBeforeRender?: OnBeforeRenderAsync | OnBeforeRenderSync | ImportString | null;
333
+ /** Hook called when a page starts rendering.
334
+ *
335
+ * https://vike.dev/onCreatePageContext TODO/now
336
+ */
337
+ onCreatePageContext?: (pageContext: PageContextServer) => void | ImportString | null;
333
338
  /** Hook for fetching data.
334
339
  *
335
340
  * https://vike.dev/data
@@ -1,5 +1,5 @@
1
1
  export { executeGuardHook };
2
- import { getHook, getHookTimeoutDefault } from '../hooks/getHook.js';
2
+ import { getHookFromPageContext, getHookTimeoutDefault } from '../hooks/getHook.js';
3
3
  import { assert, assertUsage, isCallable } from './utils.js';
4
4
  import { executeHook } from '../hooks/executeHook.js';
5
5
  const errIntro = 'The guard() hook defined by';
@@ -12,7 +12,7 @@ async function executeGuardHook(pageContext, prepareForUserConsumption) {
12
12
  }
13
13
  else {
14
14
  // V1 design
15
- hook = getHook(pageContext, 'guard');
15
+ hook = getHookFromPageContext(pageContext, 'guard');
16
16
  }
17
17
  if (!hook)
18
18
  return;
@@ -45,6 +45,7 @@ function getPageRoutes(filesystemRoots, pageFilesAll, pageConfigs, allPageIds) {
45
45
  }
46
46
  else {
47
47
  assert(isCallable(route));
48
+ // TODO/next-major: remove
48
49
  if (getConfigValueRuntime(pageConfig, 'iKnowThePerformanceRisksOfAsyncRouteFunctions', 'boolean'))
49
50
  warnDeprecatedAllowKey();
50
51
  pageRoute = {
@@ -13,6 +13,7 @@ import type { Config } from './page-configs/Config.js';
13
13
  import type { PageContextConfig } from './page-configs/Config/PageContextConfig.js';
14
14
  import type { AbortStatusCode } from './route/abort.js';
15
15
  import type { GlobalContextPublic } from '../node/runtime/globalContext.js';
16
+ import type { GlobalContextPublicClientSide } from '../client/client-routing-runtime/globalContextClientSide.js';
16
17
  type PageContextServer<Data = unknown> = PageContextBuiltInServer<Data> & Vike.PageContext;
17
18
  type PageContext<Data = unknown> = PageContextClient<Data> | PageContextServer<Data>;
18
19
  type PageContextClient<Data = unknown> = PageContextBuiltInClientWithClientRouting<Data> & Vike.PageContext;
@@ -119,12 +120,6 @@ type PageContextBuiltInCommon<Data> = {
119
120
  source: Source;
120
121
  /** @experimental https://github.com/vikejs/vike/issues/1268 */
121
122
  sources: Sources;
122
- /**
123
- * Runtime information about your app.
124
- *
125
- * https://vike.dev/getGlobalContext
126
- */
127
- globalContext: GlobalContextPublic;
128
123
  /** @deprecated */
129
124
  url: string;
130
125
  /** @deprecated */
@@ -152,6 +147,12 @@ type PageContextBuiltInServer<Data> = PageContextBuiltInCommon<Data> & PageConte
152
147
  * https://vike.dev/pageContext
153
148
  */
154
149
  isPrerendering: boolean;
150
+ /**
151
+ * Runtime information about your app.
152
+ *
153
+ * https://vike.dev/getGlobalContext
154
+ */
155
+ globalContext: GlobalContextPublic;
155
156
  isHydration?: undefined;
156
157
  isBackwardNavigation?: undefined;
157
158
  previousPageContext?: undefined;
@@ -202,6 +203,7 @@ type PageContextClientCommon = {
202
203
  * https://vike.dev/pageContext
203
204
  */
204
205
  isPrerendering: false;
206
+ globalContext: GlobalContextPublicClientSide;
205
207
  };
206
208
  /** For Vike internal use */
207
209
  type PageContextBuiltInServerInternal = Omit<PageContextBuiltInCommon<unknown> & PageContextUrlInternal, 'data'>;
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.228-commit-d423e4f";
1
+ export declare const PROJECT_VERSION: "0.4.228-commit-ae4784f";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.228-commit-d423e4f';
2
+ export const PROJECT_VERSION = '0.4.228-commit-ae4784f';
@@ -2,15 +2,11 @@ export { objectAssign };
2
2
  import { assert } from './assert.js';
3
3
  // Same as Object.assign() but:
4
4
  // - With type inference
5
- // - Preserves property descriptors, which we need for preserving the getters added by getPageContextUrlComputed()
5
+ // - Preserves property descriptors, which we need for preserving the getters of getPageContextUrlComputed()
6
6
  function objectAssign(obj, objAddendum, objAddendumCanBePageContextObject) {
7
7
  if (objAddendum) {
8
- if (!objAddendumCanBePageContextObject) {
9
- // We only need this assert() in the rare case when the user is expected to mutate `pageContext` after the Vike hook was executed (and its promise resolved).
10
- // - The only use case I can think of is the user mutating `pageContext` after the onRenderClient() promise resolved (which can happen when client-side rendering finishes after onRenderClient() resolves). In that case, having Vike await async Vike hooks isn't enough.
11
- // - IIRC this assert() was mostly needed for preserving the getters added by getPageContextUrlComputed() but we don't need this anymore.
8
+ if (!objAddendumCanBePageContextObject)
12
9
  assert(!('_isPageContextObject' in objAddendum));
13
- }
14
10
  Object.defineProperties(obj, Object.getOwnPropertyDescriptors(objAddendum));
15
11
  }
16
12
  }