vike 0.4.196-commit-df033dd → 0.4.197

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 (82) hide show
  1. package/dist/cjs/client/server-routing-runtime/onLoad.js +7 -0
  2. package/dist/cjs/client/server-routing-runtime/utils.js +34 -0
  3. package/dist/cjs/client/shared/getPageContextProxyForUser.js +79 -0
  4. package/dist/cjs/client/shared/preparePageContextForUserConsumptionClientSide.js +46 -0
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +3 -0
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -1
  7. package/dist/cjs/node/prerender/runPrerender.js +5 -5
  8. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +1 -1
  9. package/dist/cjs/node/runtime/html/injectAssets/injectAssets__public.js +1 -1
  10. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +2 -2
  11. package/dist/cjs/node/runtime/renderPage/createHttpResponse.js +3 -3
  12. package/dist/cjs/node/runtime/renderPage/debugPageFiles.js +1 -1
  13. package/dist/cjs/node/runtime/renderPage/handleErrorWithoutErrorPage.js +1 -1
  14. package/dist/cjs/node/runtime/renderPage/loadUserFilesServerSide.js +4 -4
  15. package/dist/cjs/node/runtime/renderPage/preparePageContextForUserConsumptionServerSide.js +2 -7
  16. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +4 -4
  17. package/dist/cjs/node/runtime/renderPage.js +8 -8
  18. package/dist/cjs/shared/addIs404ToPageProps.js +1 -1
  19. package/dist/cjs/shared/assertPageContextProvidedByUser.js +1 -1
  20. package/dist/cjs/shared/preparePageContextForUserConsumption.js +34 -0
  21. package/dist/cjs/shared/route/executeGuardHook.js +1 -1
  22. package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +6 -6
  23. package/dist/cjs/shared/route/index.js +3 -3
  24. package/dist/cjs/shared/route/resolveRouteString.js +10 -1
  25. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  26. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +3 -3
  27. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +4 -4
  28. package/dist/esm/client/client-routing-runtime/prefetch.js +4 -4
  29. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +59 -12
  30. package/dist/esm/client/server-routing-runtime/getPageContext.d.ts +1 -1
  31. package/dist/esm/client/server-routing-runtime/getPageContext.js +1 -1
  32. package/dist/esm/client/shared/executeOnRenderClientHook.d.ts +1 -1
  33. package/dist/esm/client/shared/getPageContextSerializedInHtml.d.ts +1 -1
  34. package/dist/esm/client/shared/getPageContextSerializedInHtml.js +1 -1
  35. package/dist/esm/client/shared/preparePageContextForUserConsumptionClientSide.d.ts +1 -1
  36. package/dist/esm/client/shared/preparePageContextForUserConsumptionClientSide.js +20 -29
  37. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +3 -0
  38. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -1
  39. package/dist/esm/node/prerender/runPrerender.js +5 -5
  40. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +1 -1
  41. package/dist/esm/node/runtime/html/injectAssets/injectAssets__public.js +1 -1
  42. package/dist/esm/node/runtime/html/injectAssets.d.ts +1 -1
  43. package/dist/esm/node/runtime/html/serializePageContextClientSide.d.ts +1 -1
  44. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +2 -2
  45. package/dist/esm/node/runtime/renderPage/createHttpResponse.d.ts +1 -1
  46. package/dist/esm/node/runtime/renderPage/createHttpResponse.js +3 -3
  47. package/dist/esm/node/runtime/renderPage/debugPageFiles.d.ts +1 -1
  48. package/dist/esm/node/runtime/renderPage/debugPageFiles.js +1 -1
  49. package/dist/esm/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.d.ts +1 -1
  50. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.d.ts +1 -1
  51. package/dist/esm/node/runtime/renderPage/handleErrorWithoutErrorPage.d.ts +1 -1
  52. package/dist/esm/node/runtime/renderPage/handleErrorWithoutErrorPage.js +1 -1
  53. package/dist/esm/node/runtime/renderPage/loadUserFilesServerSide.d.ts +1 -1
  54. package/dist/esm/node/runtime/renderPage/loadUserFilesServerSide.js +4 -4
  55. package/dist/esm/node/runtime/renderPage/preparePageContextForUserConsumptionServerSide.d.ts +1 -1
  56. package/dist/esm/node/runtime/renderPage/preparePageContextForUserConsumptionServerSide.js +3 -8
  57. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +6 -6
  58. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +4 -4
  59. package/dist/esm/node/runtime/renderPage.js +8 -8
  60. package/dist/esm/shared/addIs404ToPageProps.d.ts +1 -1
  61. package/dist/esm/shared/addIs404ToPageProps.js +1 -1
  62. package/dist/esm/shared/assertPageContextProvidedByUser.js +1 -1
  63. package/dist/esm/shared/page-configs/Config.d.ts +11 -0
  64. package/dist/esm/shared/preparePageContextForUserConsumption.d.ts +5 -0
  65. package/dist/esm/shared/preparePageContextForUserConsumption.js +32 -0
  66. package/dist/esm/shared/route/executeGuardHook.d.ts +1 -1
  67. package/dist/esm/shared/route/executeGuardHook.js +1 -1
  68. package/dist/esm/shared/route/executeOnBeforeRouteHook.js +6 -6
  69. package/dist/esm/shared/route/index.d.ts +1 -1
  70. package/dist/esm/shared/route/index.js +3 -3
  71. package/dist/esm/shared/route/resolveRouteString.d.ts +2 -15
  72. package/dist/esm/shared/route/resolveRouteString.js +10 -1
  73. package/dist/esm/shared/types.d.ts +6 -2
  74. package/dist/esm/types/index.d.ts +1 -1
  75. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  76. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  77. package/dist/esm/utils/projectInfo.d.ts +1 -1
  78. package/package.json +1 -1
  79. package/dist/cjs/shared/sortPageContext.js +0 -12
  80. package/dist/esm/shared/sortPageContext.d.ts +0 -2
  81. package/dist/esm/shared/sortPageContext.js +0 -10
  82. /package/{readme.md → README.md} +0 -0
@@ -164,7 +164,7 @@ async function hasPageContextServer(pageContext) {
164
164
  async function hookServerOnlyExists(hookName, pageContext) {
165
165
  if (pageContext._pageConfigs.length > 0) {
166
166
  // V1
167
- const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
167
+ const pageConfig = getPageConfig(pageContext.pageId, pageContext._pageConfigs);
168
168
  const hookEnv = getConfigValueRuntime(pageConfig, `${hookName}Env`)?.value ?? {};
169
169
  assert(isObject(hookEnv));
170
170
  return !!hookEnv.server && !hookEnv.client;
@@ -176,7 +176,7 @@ async function hookServerOnlyExists(hookName, pageContext) {
176
176
  if (hookName === 'data')
177
177
  return false;
178
178
  assert(hookName === 'onBeforeRender');
179
- const { hasOnBeforeRenderServerSideOnlyHook } = await analyzePageServerSide(pageContext._pageFilesAll, pageContext._pageId);
179
+ const { hasOnBeforeRenderServerSideOnlyHook } = await analyzePageServerSide(pageContext._pageFilesAll, pageContext.pageId);
180
180
  return hasOnBeforeRenderServerSideOnlyHook;
181
181
  }
182
182
  }
@@ -188,7 +188,7 @@ async function hookServerOnlyExists(hookName, pageContext) {
188
188
  function hookClientOnlyExists(hookName, pageContext) {
189
189
  if (pageContext._pageConfigs.length > 0) {
190
190
  // V1
191
- const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
191
+ const pageConfig = getPageConfig(pageContext.pageId, pageContext._pageConfigs);
192
192
  const hookEnv = getConfigValueRuntime(pageConfig, `${hookName}Env`)?.value ?? {};
193
193
  assert(isObject(hookEnv));
194
194
  return !!hookEnv.client && !hookEnv.server;
@@ -223,7 +223,7 @@ async function fetchPageContextFromServer(pageContext) {
223
223
  if ('serverSideError' in pageContextFromServer || isServerSideError in pageContextFromServer) {
224
224
  throw getProjectError(`pageContext couldn't be fetched because an error occurred on the server-side`);
225
225
  }
226
- assert(hasProp(pageContextFromServer, '_pageId', 'string'));
226
+ assert(hasProp(pageContextFromServer, 'pageId', 'string'));
227
227
  processPageContextFromServer(pageContextFromServer);
228
228
  return { pageContextFromServer };
229
229
  }
@@ -51,7 +51,7 @@ async function prefetch(url) {
51
51
  // If a route() hook has a bug or `throw render()` / `throw redirect()`
52
52
  return;
53
53
  }
54
- const pageId = pageContextFromRoute._pageId;
54
+ const pageId = pageContextFromRoute.pageId;
55
55
  if (!pageId) {
56
56
  assertWarning(false, `${errPrefix} ${pc.string(url)} ${noRouteMatch}`, {
57
57
  showStackTrace: true,
@@ -109,9 +109,9 @@ async function prefetchIfPossible(url) {
109
109
  // If a route() hook has a bug or `throw render()` / `throw redirect()`
110
110
  return;
111
111
  }
112
- if (!pageContextFromRoute?._pageId)
112
+ if (!pageContextFromRoute?.pageId)
113
113
  return;
114
- if (!(await isClientSideRoutable(pageContextFromRoute._pageId, pageContext)))
114
+ if (!(await isClientSideRoutable(pageContextFromRoute.pageId, pageContext)))
115
115
  return;
116
- await prefetchAssets(pageContextFromRoute._pageId, pageContext);
116
+ await prefetchAssets(pageContextFromRoute.pageId, pageContext);
117
117
  }
@@ -2,7 +2,7 @@ export { renderPageClientSide };
2
2
  export { getRenderCount };
3
3
  export { disableClientRouting };
4
4
  export { firstRenderStartPromise };
5
- import { assert, getCurrentUrl, isSameErrorMessage, objectAssign, redirectHard, getGlobalObject, executeHook, hasProp, augmentType, genPromise } from './utils.js';
5
+ import { assert, getCurrentUrl, isSameErrorMessage, objectAssign, redirectHard, getGlobalObject, executeHook, hasProp, augmentType, genPromise, isCallable } from './utils.js';
6
6
  import { getPageContextFromHooks_isHydration, getPageContextFromHooks_isNotHydration, getPageContextFromHooks_serialized } from './getPageContextFromHooks.js';
7
7
  import { createPageContext } from './createPageContext.js';
8
8
  import { addLinkPrefetchHandlers } from './prefetch.js';
@@ -18,6 +18,7 @@ import { setScrollPosition } from './setScrollPosition.js';
18
18
  import { updateState } from './onBrowserHistoryNavigation.js';
19
19
  import { browserNativeScrollRestoration_disable, setInitialRenderIsDone } from './scrollRestoration.js';
20
20
  import { getErrorPageId } from '../../shared/error-page.js';
21
+ import { getRouteStringParameterList } from '../../shared/route/resolveRouteString.js';
21
22
  const globalObject = getGlobalObject('renderPageClientSide.ts', (() => {
22
23
  const { promise: firstRenderStartPromise, resolve: firstRenderStartPromiseResolve } = genPromise();
23
24
  return {
@@ -28,7 +29,8 @@ const globalObject = getGlobalObject('renderPageClientSide.ts', (() => {
28
29
  })());
29
30
  const { firstRenderStartPromise } = globalObject;
30
31
  async function renderPageClientSide(renderArgs) {
31
- const { scrollTarget, urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, isUserLandPushStateNavigation, isClientSideNavigation = true } = renderArgs;
32
+ const { urlOriginal = getCurrentUrl(), overwriteLastHistoryEntry = false, isBackwardNavigation, pageContextsFromRewrite = [], redirectCount = 0, isUserLandPushStateNavigation, isClientSideNavigation = true } = renderArgs;
33
+ let { scrollTarget } = renderArgs;
32
34
  const { previousPageContext } = globalObject;
33
35
  const { isRenderOutdated, setHydrationCanBeAborted, isFirstRender } = getIsRenderOutdated();
34
36
  // Note that pageContext.isHydration isn't equivalent to isFirstRender
@@ -93,7 +95,7 @@ async function renderPageClientSide(renderArgs) {
93
95
  }
94
96
  if (isRenderOutdated())
95
97
  return;
96
- if (!pageContextFromRoute._pageId) {
98
+ if (!pageContextFromRoute.pageId) {
97
99
  /*
98
100
  // We don't use the client router to render the 404 page:
99
101
  // - So that the +redirects setting (https://vike.dev/redirects) can be applied.
@@ -106,17 +108,17 @@ async function renderPageClientSide(renderArgs) {
106
108
  redirectHard(urlOriginal);
107
109
  return;
108
110
  }
109
- assert(hasProp(pageContextFromRoute, '_pageId', 'string')); // Help TS
110
- const isClientRoutable = await isClientSideRoutable(pageContextFromRoute._pageId, pageContext);
111
+ assert(hasProp(pageContextFromRoute, 'pageId', 'string')); // Help TS
112
+ const isClientRoutable = await isClientSideRoutable(pageContextFromRoute.pageId, pageContext);
111
113
  if (isRenderOutdated())
112
114
  return;
113
115
  if (!isClientRoutable) {
114
116
  redirectHard(urlOriginal);
115
117
  return;
116
118
  }
117
- const isSamePage = pageContextFromRoute._pageId &&
118
- previousPageContext?._pageId &&
119
- pageContextFromRoute._pageId === previousPageContext._pageId;
119
+ const isSamePage = pageContextFromRoute.pageId &&
120
+ previousPageContext?.pageId &&
121
+ pageContextFromRoute.pageId === previousPageContext.pageId;
120
122
  if (isUserLandPushStateNavigation && isSamePage) {
121
123
  // Skip's Vike's rendering; let the user handle the navigation
122
124
  return;
@@ -126,7 +128,7 @@ async function renderPageClientSide(renderArgs) {
126
128
  assert(!('urlOriginal' in pageContextRouted));
127
129
  objectAssign(pageContext, pageContextRouted);
128
130
  try {
129
- objectAssign(pageContext, await loadUserFilesClientSide(pageContext._pageId, pageContext._pageFilesAll, pageContext._pageConfigs));
131
+ objectAssign(pageContext, await loadUserFilesClientSide(pageContext.pageId, pageContext._pageFilesAll, pageContext._pageConfigs));
130
132
  }
131
133
  catch (err) {
132
134
  if (handleErrorFetchingStaticAssets(err, pageContext, isFirstRender)) {
@@ -284,9 +286,9 @@ async function renderPageClientSide(renderArgs) {
284
286
  if (!errorPageId)
285
287
  throw new Error('No error page defined.');
286
288
  objectAssign(pageContext, {
287
- _pageId: errorPageId
289
+ pageId: errorPageId
288
290
  });
289
- const isClientRoutable = await isClientSideRoutable(pageContext._pageId, pageContext);
291
+ const isClientRoutable = await isClientSideRoutable(pageContext.pageId, pageContext);
290
292
  if (isRenderOutdated())
291
293
  return;
292
294
  if (!isClientRoutable) {
@@ -294,7 +296,7 @@ async function renderPageClientSide(renderArgs) {
294
296
  return;
295
297
  }
296
298
  try {
297
- objectAssign(pageContext, await loadUserFilesClientSide(pageContext._pageId, pageContext._pageFilesAll, pageContext._pageConfigs));
299
+ objectAssign(pageContext, await loadUserFilesClientSide(pageContext.pageId, pageContext._pageFilesAll, pageContext._pageConfigs));
298
300
  }
299
301
  catch (err) {
300
302
  if (handleErrorFetchingStaticAssets(err, pageContext, isFirstRender)) {
@@ -323,6 +325,7 @@ async function renderPageClientSide(renderArgs) {
323
325
  if ('is404ServerSideRouted' in res)
324
326
  return;
325
327
  augmentType(pageContext, res.pageContextAugmented);
328
+ objectAssign(pageContext, { routeParams: {} });
326
329
  await renderPageView(pageContext, args);
327
330
  }
328
331
  async function renderPageView(pageContext, isErrorPage) {
@@ -411,6 +414,15 @@ async function renderPageClientSide(renderArgs) {
411
414
  return;
412
415
  }
413
416
  }
417
+ if (!scrollTarget && previousPageContext) {
418
+ const keepScrollPositionPrev = getKeepScrollPositionSetting(previousPageContext);
419
+ const keepScrollPositionNext = getKeepScrollPositionSetting(pageContext);
420
+ if (keepScrollPositionNext !== false &&
421
+ keepScrollPositionPrev !== false &&
422
+ areKeysEqual(keepScrollPositionNext, keepScrollPositionPrev)) {
423
+ scrollTarget = { preserveScroll: true };
424
+ }
425
+ }
414
426
  // Page scrolling
415
427
  setScrollPosition(scrollTarget);
416
428
  browserNativeScrollRestoration_disable();
@@ -486,3 +498,38 @@ function getIsRenderOutdated() {
486
498
  function getRenderCount() {
487
499
  return globalObject.renderCounter;
488
500
  }
501
+ function getKeepScrollPositionSetting(pageContext) {
502
+ const c = pageContext.from.configsStandard.keepScrollPosition;
503
+ if (!c)
504
+ return false;
505
+ let val = c.value;
506
+ const configDefinedAt = c.definedAt;
507
+ assert(configDefinedAt);
508
+ const routeParameterList = getRouteStringParameterList(configDefinedAt);
509
+ if (isCallable(val))
510
+ val = val(pageContext, {
511
+ configDefinedAt: c.definedAt
512
+ /* We don't pass routeParameterList because it's useless: the user knows the parameter list.
513
+ routeParameterList
514
+ */
515
+ });
516
+ if (val === true) {
517
+ return [
518
+ configDefinedAt,
519
+ ...routeParameterList.map((param) => {
520
+ const val = pageContext.routeParams[param];
521
+ assert(val);
522
+ return val;
523
+ })
524
+ ];
525
+ }
526
+ // We skip validation and type-cast instead of assertUsage() in order to save client-side KBs
527
+ return val;
528
+ }
529
+ function areKeysEqual(key1, key2) {
530
+ if (key1 === key2)
531
+ return true;
532
+ if (!Array.isArray(key1) || !Array.isArray(key2))
533
+ return false;
534
+ return key1.length === key2.length && key1.every((_, i) => key1[i] === key2[i]);
535
+ }
@@ -1,6 +1,6 @@
1
1
  export { getPageContext };
2
2
  declare function getPageContext(): Promise<{
3
- _pageId: string;
3
+ pageId: string;
4
4
  routeParams: Record<string, string>;
5
5
  } & {
6
6
  isHydration: true;
@@ -12,7 +12,7 @@ async function getPageContext() {
12
12
  _hasPageContextFromServer: true,
13
13
  _hasPageContextFromClient: false
14
14
  });
15
- objectAssign(pageContext, await loadPageUserFiles(pageContext._pageId));
15
+ objectAssign(pageContext, await loadPageUserFiles(pageContext.pageId));
16
16
  assertPristineUrl();
17
17
  return pageContext;
18
18
  }
@@ -7,7 +7,7 @@ type PageContextBeforeRenderClient = {
7
7
  _pageFilesLoaded: PageFile[];
8
8
  urlOriginal?: string;
9
9
  urlPathname?: string;
10
- _pageId: string;
10
+ pageId: string;
11
11
  _pageConfigs: PageConfigRuntime[];
12
12
  } & PageContextExports & PageContextForUserConsumptionClientSide;
13
13
  declare function executeOnRenderClientHook<PC extends PageContextBeforeRenderClient>(pageContext: PC, isClientRouting: boolean): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  export { getPageContextSerializedInHtml };
2
2
  declare function getPageContextSerializedInHtml(): {
3
- _pageId: string;
3
+ pageId: string;
4
4
  routeParams: Record<string, string>;
5
5
  };
@@ -14,7 +14,7 @@ function getPageContextSerializedInHtml() {
14
14
  const pageContextJson = elem.textContent;
15
15
  assert(pageContextJson);
16
16
  const pageContextSerializedInHtml = parse(pageContextJson);
17
- assert(hasProp(pageContextSerializedInHtml, '_pageId', 'string'));
17
+ assert(hasProp(pageContextSerializedInHtml, 'pageId', 'string'));
18
18
  assert(hasProp(pageContextSerializedInHtml, 'routeParams', 'string{}'));
19
19
  return pageContextSerializedInHtml;
20
20
  }
@@ -4,7 +4,7 @@ import type { PageContextExports } from '../../shared/getPageFiles.js';
4
4
  import type { PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
5
5
  import { PageContextForPassToClientWarning } from './getPageContextProxyForUser.js';
6
6
  type PageContextForUserConsumptionClientSide = PageContextExports & PageContextForPassToClientWarning & {
7
- _pageId: string;
7
+ pageId: string;
8
8
  _pageConfigs: PageConfigRuntime[];
9
9
  };
10
10
  declare function preparePageContextForUserConsumptionClientSide<T extends PageContextForUserConsumptionClientSide>(pageContext: T, isClientRouting: boolean): T & {
@@ -1,20 +1,7 @@
1
1
  export { preparePageContextForUserConsumptionClientSide };
2
- import { assert, isObject, objectAssign } from '../server-routing-runtime/utils.js';
3
- import { sortPageContext } from '../../shared/sortPageContext.js';
4
- import { addIs404ToPageProps } from '../../shared/addIs404ToPageProps.js';
2
+ import { assert, objectAssign } from '../server-routing-runtime/utils.js';
5
3
  import { getPageContextProxyForUser } from './getPageContextProxyForUser.js';
6
- // Release `pageContext` for user consumption.
7
- //
8
- // This adds `assertPassToClient()`.
9
- //
10
- // With Vue support (when `pageContext` is made reactive with Vue).
11
- //
12
- // For Vue + Cient Routing, the `pageContext` needs to be made reactive:
13
- // ```js
14
- // import { reactive } from 'vue'
15
- // // See entire example at `/examples/vue-full/`
16
- // const pageContextReactive = reactive(pageContext)
17
- // ```
4
+ import { preparePageContextForUserConsumption } from '../../shared/preparePageContextForUserConsumption.js';
18
5
  function preparePageContextForUserConsumptionClientSide(pageContext, isClientRouting) {
19
6
  if (isClientRouting) {
20
7
  const pageContextTyped = pageContext;
@@ -26,22 +13,26 @@ function preparePageContextForUserConsumptionClientSide(pageContext, isClientRou
26
13
  assert(pageContextTyped.isHydration === true);
27
14
  assert(pageContextTyped.isBackwardNavigation === null);
28
15
  }
29
- assert('config' in pageContext);
30
- assert('configEntries' in pageContext);
31
- // TODO/v1-release: remove
32
- assert('exports' in pageContext);
33
- assert('exportsAll' in pageContext);
34
- assert('pageExports' in pageContext);
35
- assert(isObject(pageContext.pageExports));
36
- const Page = pageContext.exports.Page;
16
+ const Page = pageContext.config.Page ||
17
+ // TODO/next-major-release: remove
18
+ pageContext.exports.Page;
37
19
  objectAssign(pageContext, { Page });
38
- // For Vue's reactivity
20
+ // TODO/next-major-release: remove
21
+ // - Requires https://github.com/vikejs/vike-vue/issues/198
22
+ // - Last time I tried to remove it (https://github.com/vikejs/vike/commit/705fd23598d9d69bf46a52c8550216cd7117ce71) the tests were failing as expected: only the Vue integrations that used shallowReactive() failed.
23
+ supportVueReactiviy(pageContext);
24
+ preparePageContextForUserConsumption(pageContext);
25
+ const pageContextProxy = getPageContextProxyForUser(pageContext);
26
+ return pageContextProxy;
27
+ }
28
+ // With Vue + Cient Routing, the `pageContext` is made reactive:
29
+ // ```js
30
+ // import { reactive } from 'vue'
31
+ // // See /examples/vue-full/renderer/createVueApp.ts
32
+ // const pageContextReactive = reactive(pageContext)
33
+ // ```
34
+ function supportVueReactiviy(pageContext) {
39
35
  resolveGetters(pageContext);
40
- // For prettier `console.log(pageContext)`
41
- sortPageContext(pageContext);
42
- const pageContextForUserConsumption = getPageContextProxyForUser(pageContext);
43
- addIs404ToPageProps(pageContext);
44
- return pageContextForUserConsumption;
45
36
  }
46
37
  // Remove propery descriptor getters because they break Vue's reactivity.
47
38
  // E.g. resolve the `pageContext.urlPathname` getter.
@@ -120,6 +120,9 @@ const configDefinitionsBuiltIn = {
120
120
  },
121
121
  require: {
122
122
  env: { config: true }
123
+ },
124
+ keepScrollPosition: {
125
+ env: { client: true }
123
126
  }
124
127
  };
125
128
  const configDefinitionsBuiltInGlobal = {
@@ -237,7 +237,7 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, crawlWithGit) {
237
237
  const importedFilesLoaded = {};
238
238
  const { globalVikeConfig, pageConfigGlobal } = await getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded);
239
239
  const pageConfigs = await Promise.all(objectEntries(interfaceFilesByLocationId)
240
- .filter(([_pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
240
+ .filter(([pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
241
241
  .map(async ([locationId]) => {
242
242
  const interfaceFilesRelevant = getInterfaceFilesRelevant(interfaceFilesByLocationId, locationId);
243
243
  const interfaceFilesRelevantList = Object.values(interfaceFilesRelevant).flat(1);
@@ -278,7 +278,7 @@ async function handlePagesWithStaticRoutes(prerenderContext, renderContext, doNo
278
278
  objectAssign(pageContext, {
279
279
  _providedByHook: null,
280
280
  routeParams,
281
- _pageId: pageId,
281
+ pageId: pageId,
282
282
  _debugRouteMatches: [
283
283
  {
284
284
  pageId,
@@ -441,8 +441,8 @@ async function routeAndPrerender(prerenderContext, concurrencyLimit, onComplete)
441
441
  const { urlOriginal } = pageContext;
442
442
  assert(urlOriginal);
443
443
  const pageContextFromRoute = await route(pageContext);
444
- assert(hasProp(pageContextFromRoute, '_pageId', 'null') || hasProp(pageContextFromRoute, '_pageId', 'string'));
445
- if (pageContextFromRoute._pageId === null) {
444
+ assert(hasProp(pageContextFromRoute, 'pageId', 'null') || hasProp(pageContextFromRoute, 'pageId', 'string'));
445
+ if (pageContextFromRoute.pageId === null) {
446
446
  let hookName;
447
447
  let hookFilePath;
448
448
  if (pageContext._providedByHook) {
@@ -464,9 +464,9 @@ async function routeAndPrerender(prerenderContext, concurrencyLimit, onComplete)
464
464
  return;
465
465
  }
466
466
  }
467
- assert(pageContextFromRoute._pageId);
467
+ assert(pageContextFromRoute.pageId);
468
468
  objectAssign(pageContext, pageContextFromRoute);
469
- const { _pageId: pageId } = pageContext;
469
+ const { pageId: pageId } = pageContext;
470
470
  objectAssign(pageContext, await loadUserFilesServerSide(pageContext));
471
471
  let usesClientRouter;
472
472
  {
@@ -14,7 +14,7 @@ function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectFilter,
14
14
  assert([true, false].includes(pageContext._isHtmlOnly));
15
15
  const isHtmlOnly = pageContext._isHtmlOnly;
16
16
  const { isProduction } = getGlobalContext();
17
- const injectScriptsAt = getInjectScriptsAt(pageContext._pageId, pageContext._pageConfigs);
17
+ const injectScriptsAt = getInjectScriptsAt(pageContext.pageId, pageContext._pageConfigs);
18
18
  const injectFilterEntries = pageAssets
19
19
  .filter((asset) => {
20
20
  if (asset.isEntry && asset.assetType === 'script') {
@@ -14,7 +14,7 @@ async function injectAssets__public(htmlString, pageContext) {
14
14
  assertUsage(hasProp(pageContext, 'urlPathname', 'string'), errMsg('`pageContext.urlPathname` should be a string'), {
15
15
  showStackTrace: true
16
16
  });
17
- assertUsage(hasProp(pageContext, '_pageId', 'string'), errMsg('`pageContext._pageId` should be a string'), {
17
+ assertUsage(hasProp(pageContext, 'pageId', 'string'), errMsg('`pageContext.pageId` should be a string'), {
18
18
  showStackTrace: true
19
19
  });
20
20
  assertUsage(hasProp(pageContext, '__getPageAssets'), errMsg('`pageContext.__getPageAssets` is missing'), {
@@ -11,7 +11,7 @@ import type { PageContextSerialization } from './serializePageContextClientSide.
11
11
  type PageContextInjectAssets = {
12
12
  urlPathname: string;
13
13
  __getPageAssets: () => Promise<PageAsset[]>;
14
- _pageId: string;
14
+ pageId: string;
15
15
  _isHtmlOnly: boolean;
16
16
  _pageContextPromise: PageContextPromise;
17
17
  _renderHook: {
@@ -4,7 +4,7 @@ export type { PageContextSerialization };
4
4
  import type { PageConfigRuntime } from '../../../shared/page-configs/PageConfig.js';
5
5
  import type { UrlRedirect } from '../../../shared/route/abort.js';
6
6
  type PageContextSerialization = {
7
- _pageId: string;
7
+ pageId: string;
8
8
  routeParams: Record<string, string>;
9
9
  _passToClient: string[];
10
10
  _pageConfigs: PageConfigRuntime[];
@@ -18,7 +18,7 @@ const PASS_TO_CLIENT = [
18
18
  '_abortCaller',
19
19
  */
20
20
  pageContextInitIsPassedToClient,
21
- '_pageId',
21
+ 'pageId',
22
22
  'routeParams',
23
23
  'data' // for data() hook
24
24
  ];
@@ -95,7 +95,7 @@ function serialize(value, varName) {
95
95
  }
96
96
  function getPassToClient(pageContext) {
97
97
  let passToClient = [...pageContext._passToClient, ...PASS_TO_CLIENT];
98
- if (isErrorPage(pageContext._pageId, pageContext._pageConfigs)) {
98
+ if (isErrorPage(pageContext.pageId, pageContext._pageConfigs)) {
99
99
  assert(hasProp(pageContext, 'is404', 'boolean'));
100
100
  addIs404ToPageProps(pageContext);
101
101
  passToClient.push(...PASS_TO_CLIENT_ERROR_PAGE);
@@ -20,7 +20,7 @@ type HttpResponse = {
20
20
  contentType: 'application/json' | 'text/html;charset=utf-8';
21
21
  } & HttpResponseBody;
22
22
  declare function createHttpResponsePage(htmlRender: HtmlRender, renderHook: null | RenderHook, pageContext: {
23
- _pageId: null | string;
23
+ pageId: null | string;
24
24
  is404: null | boolean;
25
25
  errorWhileRendering: null | Error;
26
26
  __getPageAssets: GetPageAssets;
@@ -12,7 +12,7 @@ import { assertNoInfiniteHttpRedirect } from './createHttpResponse/assertNoInfin
12
12
  async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
13
13
  let statusCode = pageContext.abortStatusCode;
14
14
  if (!statusCode) {
15
- const isError = !pageContext._pageId || isErrorPage(pageContext._pageId, pageContext._pageConfigs);
15
+ const isError = !pageContext.pageId || isErrorPage(pageContext.pageId, pageContext._pageConfigs);
16
16
  if (pageContext.errorWhileRendering) {
17
17
  assert(isError);
18
18
  }
@@ -27,8 +27,8 @@ async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
27
27
  }
28
28
  const earlyHints = getEarlyHints(await pageContext.__getPageAssets());
29
29
  const headers = [];
30
- assert(pageContext._pageId);
31
- const cacheControl = getCacheControl(pageContext._pageId, pageContext._pageConfigs);
30
+ assert(pageContext.pageId);
31
+ const cacheControl = getCacheControl(pageContext.pageId, pageContext._pageConfigs);
32
32
  if (cacheControl) {
33
33
  headers.push(['Cache-Control', cacheControl]);
34
34
  }
@@ -10,7 +10,7 @@ type PageContextDebugRouteMatches = {
10
10
  declare function debugPageFiles({ pageContext, isHtmlOnly, isClientRouting, pageFilesLoaded, pageFilesServerSide, pageFilesClientSide, clientEntries, clientDependencies }: {
11
11
  pageContext: {
12
12
  urlOriginal: string;
13
- _pageId: string;
13
+ pageId: string;
14
14
  _pageFilesAll: PageFile[];
15
15
  _pageConfigs: PageConfigRuntime[];
16
16
  } & PageContextDebugRouteMatches;
@@ -7,7 +7,7 @@ function debugPageFiles({ pageContext, isHtmlOnly, isClientRouting, pageFilesLoa
7
7
  debug('All page files:', printPageFiles(pageContext._pageFilesAll, true)); // TODO
8
8
  debug(`URL:`, pageContext.urlOriginal);
9
9
  debug.options({ serialization: { emptyArray: 'No match' } })(`Routing:`, printRouteMatches(pageContext._debugRouteMatches));
10
- debug(`pageId:`, pageContext._pageId);
10
+ debug(`pageId:`, pageContext.pageId);
11
11
  debug('Page type:', isHtmlOnly ? 'HTML-only' : 'SSR/SPA');
12
12
  debug(`Routing type:`, !isHtmlOnly && isClientRouting ? 'Client Routing' : 'Server Routing');
13
13
  debug('Server-side page files:', printPageFiles(pageFilesLoaded));
@@ -2,6 +2,6 @@ export { executeOnBeforeRenderAndDataHooks };
2
2
  import { type PageContextExports } from '../../../shared/getPageFiles.js';
3
3
  import { type PageContextForUserConsumptionServerSide } from './preparePageContextForUserConsumptionServerSide.js';
4
4
  declare function executeOnBeforeRenderAndDataHooks(pageContext: {
5
- _pageId: string;
5
+ pageId: string;
6
6
  _pageContextAlreadyProvidedByOnPrerenderHook?: true;
7
7
  } & PageContextExports & PageContextForUserConsumptionServerSide): Promise<void>;
@@ -12,7 +12,7 @@ type RenderHook = Hook & {
12
12
  };
13
13
  type HookName = 'onRenderHtml' | 'render';
14
14
  declare function executeOnRenderHtmlHook(pageContext: PageContextForUserConsumptionServerSide & PageContextSerialization & {
15
- _pageId: string;
15
+ pageId: string;
16
16
  _pageConfigs: PageConfigRuntime[];
17
17
  __getPageAssets: GetPageAssets;
18
18
  _isHtmlOnly: boolean;
@@ -6,7 +6,7 @@ declare function handleErrorWithoutErrorPage<PageContext extends {
6
6
  isClientSideNavigation: boolean;
7
7
  errorWhileRendering: null | Error;
8
8
  is404: null | boolean;
9
- _pageId: null;
9
+ pageId: null;
10
10
  _pageFilesAll: PageFile[];
11
11
  _pageConfigs: PageConfigRuntime[];
12
12
  urlOriginal: string;
@@ -6,7 +6,7 @@ import { createHttpResponsePage, createHttpResponseError } from './createHttpRes
6
6
  import pc from '@brillout/picocolors';
7
7
  // When the user hasn't defined _error.page.js
8
8
  async function handleErrorWithoutErrorPage(pageContext) {
9
- assert(pageContext._pageId === null);
9
+ assert(pageContext.pageId === null);
10
10
  assert(pageContext.errorWhileRendering || pageContext.is404);
11
11
  {
12
12
  const isV1 = pageContext._pageConfigs.length > 0;
@@ -13,7 +13,7 @@ type PageContext_loadUserFilesServerSide = PageContextGetPageAssets & PageContex
13
13
  };
14
14
  type PageFiles = PromiseType<ReturnType<typeof loadUserFilesServerSide>>;
15
15
  declare function loadUserFilesServerSide(pageContext: {
16
- _pageId: string;
16
+ pageId: string;
17
17
  } & PageContext_loadUserFilesServerSide): Promise<import("../../../shared/getPageFiles.js").PageContextExports & {
18
18
  Page: unknown;
19
19
  _isHtmlOnly: boolean;
@@ -9,12 +9,12 @@ import { analyzePage } from './analyzePage.js';
9
9
  import { getGlobalContext } from '../globalContext.js';
10
10
  import { loadConfigValues } from '../../../shared/page-configs/loadConfigValues.js';
11
11
  async function loadUserFilesServerSide(pageContext) {
12
- const pageConfig = findPageConfig(pageContext._pageConfigs, pageContext._pageId); // Make pageConfig globally available as pageContext._pageConfig?
12
+ const pageConfig = findPageConfig(pageContext._pageConfigs, pageContext.pageId); // Make pageConfig globally available as pageContext._pageConfig?
13
13
  const [{ pageFilesLoaded, pageContextExports }] = await Promise.all([
14
- loadPageUserFiles(pageContext._pageFilesAll, pageConfig, pageContext._pageId, !getGlobalContext().isProduction),
15
- analyzePageClientSideInit(pageContext._pageFilesAll, pageContext._pageId, { sharedPageFilesAlreadyLoaded: true })
14
+ loadPageUserFiles(pageContext._pageFilesAll, pageConfig, pageContext.pageId, !getGlobalContext().isProduction),
15
+ analyzePageClientSideInit(pageContext._pageFilesAll, pageContext.pageId, { sharedPageFilesAlreadyLoaded: true })
16
16
  ]);
17
- const { isHtmlOnly, isClientRouting, clientEntries, clientDependencies, pageFilesClientSide, pageFilesServerSide } = analyzePage(pageContext._pageFilesAll, pageConfig, pageContext._pageId);
17
+ const { isHtmlOnly, isClientRouting, clientEntries, clientDependencies, pageFilesClientSide, pageFilesServerSide } = analyzePage(pageContext._pageFilesAll, pageConfig, pageContext.pageId);
18
18
  const isV1Design = !!pageConfig;
19
19
  const passToClient = [];
20
20
  const errMsg = ' should be an array of strings.';
@@ -12,7 +12,7 @@ type PageContextForUserConsumptionServerSide = PageContextBuiltInServerInternal
12
12
  urlParsed: PageContextUrlInternal['urlParsed'];
13
13
  routeParams: Record<string, string>;
14
14
  Page: unknown;
15
- _pageId: string;
15
+ pageId: string;
16
16
  _pageConfigs: PageConfigRuntime[];
17
17
  is404: null | boolean;
18
18
  isClientSideNavigation: boolean;
@@ -1,16 +1,11 @@
1
1
  export { preparePageContextForUserConsumptionServerSide };
2
- import { assert, isPlainObject, isObject } from '../utils.js';
3
- import { sortPageContext } from '../../../shared/sortPageContext.js';
2
+ import { assert, isPlainObject } from '../utils.js';
4
3
  import { assertPageContextUrl } from '../../../shared/getPageContextUrlComputed.js';
5
- import { addIs404ToPageProps } from '../../../shared/addIs404ToPageProps.js';
4
+ import { preparePageContextForUserConsumption } from '../../../shared/preparePageContextForUserConsumption.js';
6
5
  function preparePageContextForUserConsumptionServerSide(pageContext) {
7
6
  assertPageContextUrl(pageContext);
8
7
  assert(isPlainObject(pageContext.routeParams));
9
8
  assert('Page' in pageContext);
10
- assert(isObject(pageContext.pageExports));
11
- assert(isObject(pageContext.exports));
12
- assert(isObject(pageContext.exportsAll));
13
9
  assert(typeof pageContext.isClientSideNavigation === 'boolean');
14
- sortPageContext(pageContext);
15
- addIs404ToPageProps(pageContext);
10
+ preparePageContextForUserConsumption(pageContext);
16
11
  }