vike 0.4.144-commit-f7ab002 → 0.4.144-commit-7f5e99a

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 (68) hide show
  1. package/dist/cjs/__internal/index.js +6 -2
  2. package/dist/cjs/node/plugin/plugins/commonConfig.js +0 -3
  3. package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -0
  4. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +1 -0
  5. package/dist/cjs/node/plugin/plugins/previewConfig.js +5 -0
  6. package/dist/cjs/node/prerender/runPrerender.js +8 -9
  7. package/dist/cjs/node/prerender/utils.js +1 -1
  8. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +1 -0
  9. package/dist/cjs/node/runtime/renderPage.js +2 -2
  10. package/dist/cjs/node/runtime/utils.js +1 -1
  11. package/dist/cjs/shared/addUrlComputedProps.js +24 -12
  12. package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +11 -13
  13. package/dist/cjs/shared/route/index.js +3 -3
  14. package/dist/cjs/shared/route/resolveRouteFunction.js +1 -1
  15. package/dist/cjs/shared/utils.js +1 -1
  16. package/dist/cjs/utils/{hasPropertyGetter.js → isPropertyGetter.js} +3 -3
  17. package/dist/cjs/utils/projectInfo.js +1 -1
  18. package/dist/esm/__internal/index.d.ts +6 -3
  19. package/dist/esm/__internal/index.js +8 -3
  20. package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -3
  21. package/dist/esm/client/client-routing-runtime/createPageContext.js +3 -3
  22. package/dist/esm/client/client-routing-runtime/entry.js +2 -2
  23. package/dist/esm/client/client-routing-runtime/getPageContext.d.ts +0 -1
  24. package/dist/esm/client/client-routing-runtime/getPageContext.js +3 -6
  25. package/dist/esm/client/client-routing-runtime/getPageId.d.ts +1 -1
  26. package/dist/esm/client/client-routing-runtime/getPageId.js +4 -7
  27. package/dist/esm/client/client-routing-runtime/history.d.ts +3 -1
  28. package/dist/esm/client/client-routing-runtime/history.js +26 -8
  29. package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +21 -0
  30. package/dist/esm/client/client-routing-runtime/{useClientRouter.js → installClientRouter.js} +248 -242
  31. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.d.ts +8 -0
  32. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +15 -0
  33. package/dist/esm/client/client-routing-runtime/navigate.d.ts +0 -2
  34. package/dist/esm/client/client-routing-runtime/navigate.js +10 -8
  35. package/dist/esm/client/client-routing-runtime/prefetch.js +12 -5
  36. package/dist/esm/client/client-routing-runtime/skipLink.d.ts +0 -1
  37. package/dist/esm/client/client-routing-runtime/skipLink.js +1 -2
  38. package/dist/esm/client/shared/executeOnRenderClientHook.js +6 -5
  39. package/dist/esm/client/shared/getPageContextProxyForUser.js +13 -7
  40. package/dist/esm/node/plugin/plugins/commonConfig.js +0 -3
  41. package/dist/esm/node/plugin/plugins/devConfig/index.js +1 -0
  42. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +1 -0
  43. package/dist/esm/node/plugin/plugins/previewConfig.js +5 -0
  44. package/dist/esm/node/prerender/runPrerender.js +9 -10
  45. package/dist/esm/node/prerender/utils.d.ts +1 -1
  46. package/dist/esm/node/prerender/utils.js +1 -1
  47. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +1 -0
  48. package/dist/esm/node/runtime/renderPage.js +2 -2
  49. package/dist/esm/node/runtime/utils.d.ts +1 -1
  50. package/dist/esm/node/runtime/utils.js +1 -1
  51. package/dist/esm/shared/addUrlComputedProps.d.ts +1 -0
  52. package/dist/esm/shared/addUrlComputedProps.js +25 -13
  53. package/dist/esm/shared/route/executeOnBeforeRouteHook.d.ts +1 -1
  54. package/dist/esm/shared/route/executeOnBeforeRouteHook.js +11 -13
  55. package/dist/esm/shared/route/index.d.ts +11 -9
  56. package/dist/esm/shared/route/index.js +3 -3
  57. package/dist/esm/shared/route/resolveRouteFunction.js +1 -1
  58. package/dist/esm/shared/utils.d.ts +1 -1
  59. package/dist/esm/shared/utils.js +1 -1
  60. package/dist/esm/utils/isPropertyGetter.d.ts +1 -0
  61. package/dist/esm/utils/{hasPropertyGetter.js → isPropertyGetter.js} +1 -1
  62. package/dist/esm/utils/projectInfo.d.ts +1 -1
  63. package/dist/esm/utils/projectInfo.js +1 -1
  64. package/package.json +1 -1
  65. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.d.ts +0 -2
  66. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.js +0 -15
  67. package/dist/esm/client/client-routing-runtime/useClientRouter.d.ts +0 -6
  68. package/dist/esm/utils/hasPropertyGetter.d.ts +0 -1
@@ -1,13 +1,16 @@
1
1
  export { prefetch };
2
2
  export { addLinkPrefetchHandlers };
3
- import { assert, assertClientRouting, assertUsage, checkIfClientRouting } from './utils.js';
3
+ import { assert, assertClientRouting, assertUsage, checkIfClientRouting, objectAssign } from './utils.js';
4
4
  import { isErrorFetchingStaticAssets, loadPageFilesClientSide } from '../shared/loadPageFilesClientSide.js';
5
- import { isClientSideRoutable, skipLink } from './skipLink.js';
5
+ import { skipLink } from './skipLink.js';
6
6
  import { getPageId } from './getPageId.js';
7
7
  import { getPrefetchSettings } from './prefetch/getPrefetchSettings.js';
8
8
  import { isAlreadyPrefetched, markAsAlreadyPrefetched } from './prefetch/alreadyPrefetched.js';
9
- import { disableClientRouting } from './useClientRouter.js';
9
+ import { disableClientRouting } from './installClientRouter.js';
10
10
  import { isExternalLink } from './isExternalLink.js';
11
+ import { isClientSideRoutable } from './isClientSideRoutable.js';
12
+ import { createPageContext } from './createPageContext.js';
13
+ import { route } from '../../shared/route/index.js';
11
14
  assertClientRouting();
12
15
  const linkPrefetchHandlerAdded = new Map();
13
16
  /**
@@ -79,13 +82,17 @@ function addLinkPrefetchHandlers(pageContext) {
79
82
  });
80
83
  }
81
84
  async function prefetchIfClientSideRoutable(url) {
85
+ const pageContext = await createPageContext(url);
86
+ let pageContextFromRoute;
82
87
  try {
83
- if (!(await isClientSideRoutable(url)))
84
- return;
88
+ pageContextFromRoute = await route(pageContext);
85
89
  }
86
90
  catch {
87
91
  // If a route() hook has a bug or `throw render()` / `throw redirect()`
88
92
  return;
89
93
  }
94
+ objectAssign(pageContext, pageContextFromRoute);
95
+ if (!(await isClientSideRoutable(pageContext)))
96
+ return;
90
97
  await prefetch(url);
91
98
  }
@@ -1,3 +1,2 @@
1
1
  export { skipLink };
2
- export { isClientSideRoutable } from './skipLink/isClientSideRoutable.js';
3
2
  declare function skipLink(linkTag: HTMLElement): boolean;
@@ -1,9 +1,8 @@
1
1
  export { skipLink };
2
- export { isClientSideRoutable } from './skipLink/isClientSideRoutable.js';
3
2
  import { getBaseServer } from './getBaseServer.js';
4
3
  import { isExternalLink } from './isExternalLink.js';
5
4
  import { assert, parseUrl, isBaseServer, isParsable } from './utils.js';
6
- import { isDisableAutomaticLinkInterception } from './useClientRouter.js';
5
+ import { isDisableAutomaticLinkInterception } from './installClientRouter.js';
7
6
  function skipLink(linkTag) {
8
7
  const url = linkTag.getAttribute('href');
9
8
  if (url === null)
@@ -19,10 +19,11 @@ async function executeOnRenderClientHook(pageContext, isClientRouting) {
19
19
  }
20
20
  }
21
21
  if (!hook) {
22
- const urlLogical = getUrlLogical(pageContext);
22
+ const urlToShowToUser = getUrlToShowToUser(pageContext);
23
+ assert(urlToShowToUser);
23
24
  if (pageContext._pageConfigs.length > 0) {
24
25
  // V1 design
25
- assertUsage(false, `No onRenderClient() hook defined for URL '${urlLogical}', but it's needed, see https://vike.dev/onRenderClient`);
26
+ assertUsage(false, `No onRenderClient() hook defined for URL '${urlToShowToUser}', but it's needed, see https://vike.dev/onRenderClient`);
26
27
  }
27
28
  else {
28
29
  // TODO/v1-release: remove
@@ -30,11 +31,11 @@ async function executeOnRenderClientHook(pageContext, isClientRouting) {
30
31
  const pageClientsFilesLoaded = pageContext._pageFilesLoaded.filter((p) => p.fileType === '.page.client');
31
32
  let errMsg;
32
33
  if (pageClientsFilesLoaded.length === 0) {
33
- errMsg = 'No file `*.page.client.*` found for URL ' + urlLogical;
34
+ errMsg = 'No file `*.page.client.*` found for URL ' + urlToShowToUser;
34
35
  }
35
36
  else {
36
37
  errMsg =
37
- 'One of the following files should export a `render()` hook: ' +
38
+ 'One of the following files should export a render() hook: ' +
38
39
  pageClientsFilesLoaded.map((p) => p.filePath).join(' ');
39
40
  }
40
41
  assertUsage(false, errMsg);
@@ -47,7 +48,7 @@ async function executeOnRenderClientHook(pageContext, isClientRouting) {
47
48
  const hookResult = await executeHook(() => renderHook(pageContextForUserConsumption), hookName, hook.hookFilePath);
48
49
  assertUsage(hookResult === undefined, `The ${hookName}() hook defined by ${hook.hookFilePath} isn't allowed to return a value`);
49
50
  }
50
- function getUrlLogical(pageContext) {
51
+ function getUrlToShowToUser(pageContext) {
51
52
  let url;
52
53
  // try/catch to avoid passToClient assertUsage() (although: this may not be needed anymore, since we're now accessing pageContext and not pageContextForUserConsumption)
53
54
  try {
@@ -14,14 +14,14 @@ function getPageContextProxyForUser(pageContext) {
14
14
  const val = pageContext[prop];
15
15
  const propName = JSON.stringify(prop);
16
16
  assertUsage(val !== notSerializable, `pageContext[${propName}] couldn't be serialized and, therefore, is missing on the client-side. Check the server logs for more information.`);
17
- assertPassToClient(pageContext, prop, `pageContext[${propName}] isn't available on the client-side because ${propName} is missing in passToClient, see https://vike.dev/passToClient`);
17
+ assertIsDefined(pageContext, prop);
18
18
  return val;
19
19
  }
20
20
  });
21
21
  }
22
- function assertPassToClient(pageContext, prop, errMsg) {
23
- // We disable assertPassToClient() for the next attempt to read `prop`, because of how Vue's reactivity work. When changing a reactive object:
24
- // - Vue tries to read its old value first. This triggers a `assertPassToClient()` failure if e.g. `pageContextOldReactive.routeParams = pageContextNew.routeParams` and `pageContextOldReactive` has no `routeParams`.
22
+ function assertIsDefined(pageContext, prop) {
23
+ // We disable assertIsDefined() for the next attempt to read `prop`, because of how Vue's reactivity work. When changing a reactive object:
24
+ // - Vue tries to read its old value first. This triggers a `assertIsDefined()` failure if e.g. `pageContextOldReactive.routeParams = pageContextNew.routeParams` and `pageContextOldReactive` has no `routeParams`.
25
25
  // - Vue seems to read __v_raw before reading the property
26
26
  if (globalObject.prev === prop || globalObject.prev === '__v_raw')
27
27
  return;
@@ -30,17 +30,23 @@ function assertPassToClient(pageContext, prop, errMsg) {
30
30
  return;
31
31
  if (isExpected(prop))
32
32
  return;
33
+ const propName = JSON.stringify(prop);
34
+ /* This handling would be the clearest but, unfortunately, it's fundamentally problematic:
35
+ * - It would force the pageContext value consumer to be synchronized with the pageContext value provider. For example, if vike-react wants to conditionally do something dependening on wehther some optional pageContext value was provided by some optional vike-react-* integration package.
36
+ * - If a pageContext value is set by an optional hook, then it's expected that the value is undefined if the hook doesn't exist.
37
+ const errMsg = `pageContext[${propName}] is \`undefined\` on the client-side. If it's defined on the server-side then add ${propName} to passToClient (https://vike.dev/passToClient), otherwise make sure your client-side hooks always define it (e.g. set it to \`null\` instead of \`undefined\`).`
38
+ assertUsage(false, errMsg)
39
+ */
33
40
  if (pageContext._hasPageContextFromServer && !pageContext._hasPageContextFromClient) {
34
41
  // We can safely assume that the property is missing in passToClient, because the server-side defines all passToClient properties even if they have an undefined value:
35
42
  // ```
36
43
  // <script id="vike_pageContext" type="application/json">{"_pageId":"/pages/admin","user":"!undefined","pageProps":"!undefined","title":"!undefined","abortReason":"!undefined","_urlRewrite":null}</script>
37
44
  // ```
38
45
  // Note how properties have "!undefined" values => we can tell whether an undefined pageContext value exists in passToClient.
39
- assertUsage(false, errMsg);
46
+ assertUsage(false, `pageContext[${propName}] isn't available on the client-side because ${propName} is missing in passToClient, see https://vike.dev/passToClient`);
40
47
  }
41
48
  else {
42
- // Do nothing, not even a warning.
43
- // Because we don't know whether the user expects the pageContext value to be undefined. (E.g. a client-side onBeforeRender() hook conditionally setting a pageContext value.)
49
+ // Do nothing, not even a warning, because we don't know whether the user expects that the pageContext value can be undefined. (E.g. a pageContext value that is defined by an optional hook.)
44
50
  }
45
51
  }
46
52
  const IGNORE_LIST = [
@@ -13,9 +13,6 @@ function commonConfig() {
13
13
  return [
14
14
  {
15
15
  name: 'vike-commonConfig-1',
16
- config: () => ({
17
- appType: 'custom'
18
- }),
19
16
  configResolved(config) {
20
17
  installRequireShim_setUserRootDir(config.root);
21
18
  }
@@ -21,6 +21,7 @@ function devConfig() {
21
21
  apply,
22
22
  config() {
23
23
  return {
24
+ appType: 'custom',
24
25
  optimizeDeps: {
25
26
  exclude: [
26
27
  // We exclude the vike client to be able to use `import.meta.glob()`
@@ -113,6 +113,7 @@ function getConfigValueSerialized(value, configName, definedAt) {
113
113
  serializationErrMsg = err.messageCore;
114
114
  }
115
115
  else {
116
+ // When a property getter throws an error
116
117
  console.error('Serialization error:');
117
118
  console.error(err);
118
119
  serializationErrMsg = 'see serialization error printed above';
@@ -13,6 +13,7 @@ function previewConfig() {
13
13
  apply: 'serve',
14
14
  config(config) {
15
15
  return {
16
+ appType: 'custom',
16
17
  build: {
17
18
  outDir: resolveOutDir(config)
18
19
  }
@@ -23,6 +24,10 @@ function previewConfig() {
23
24
  configVike = await getConfigVike(config);
24
25
  },
25
26
  configurePreviewServer(server) {
27
+ /* - Couldn't make `appType: 'mpa'` work as of npm:@brillout/vite@5.0.0-beta.14.0426910c
28
+ - This ugly hack to set appType for preview won't be need once https://github.com/vitejs/vite/pull/14855 is merged.
29
+ config.appType = 'mpa'
30
+ */
26
31
  markEnvAsPreview();
27
32
  return () => {
28
33
  assertDist();
@@ -5,7 +5,7 @@ export { prerenderForceExit };
5
5
  import '../runtime/page-files/setup.js';
6
6
  import path from 'path';
7
7
  import { route } from '../../shared/route/index.js';
8
- import { assert, assertUsage, assertWarning, hasProp, projectInfo, objectAssign, isObjectWithKeys, isCallable, getOutDirs, hasPropertyGetter, assertPosixPath, urlToFile, executeHook, isPlainObject, setNodeEnvToProduction } from './utils.js';
8
+ import { assert, assertUsage, assertWarning, hasProp, projectInfo, objectAssign, isObjectWithKeys, isCallable, getOutDirs, isPropertyGetter, assertPosixPath, urlToFile, executeHook, isPlainObject, setNodeEnvToProduction } from './utils.js';
9
9
  import { pLimit } from '../../utils/pLimit.js';
10
10
  import { prerenderPage, prerender404Page, getRenderContext, getPageContextInitEnhanced } from '../runtime/renderPage/renderPageAlreadyRouted.js';
11
11
  import pc from '@brillout/picocolors';
@@ -343,7 +343,7 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
343
343
  enumerable: false,
344
344
  configurable: true
345
345
  });
346
- assert(hasPropertyGetter(pageContext, 'url'));
346
+ assert(isPropertyGetter(pageContext, 'url'));
347
347
  assert(pageContext.urlOriginal);
348
348
  pageContext._urlOriginalBeforeHook = pageContext.urlOriginal;
349
349
  });
@@ -382,7 +382,7 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
382
382
  prerenderContext.pageContexts = result.prerenderContext.pageContexts;
383
383
  prerenderContext.pageContexts.forEach((pageContext) => {
384
384
  // TODO/v1-release: remove
385
- if (!hasPropertyGetter(pageContext, 'url') && pageContext.url) {
385
+ if (pageContext.url && !isPropertyGetter(pageContext, 'url')) {
386
386
  assertWarning(false, msgPrefix +
387
387
  ' provided pageContext.url but it should provide pageContext.urlOriginal instead, see https://vike.dev/migration/0.4.23', { onlyOnce: true });
388
388
  pageContext.urlOriginal = pageContext.url;
@@ -407,10 +407,9 @@ async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds,
407
407
  await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
408
408
  const { urlOriginal } = pageContext;
409
409
  assert(urlOriginal);
410
- const routeResult = await route(pageContext);
411
- assert(hasProp(routeResult.pageContextAddendum, '_pageId', 'null') ||
412
- hasProp(routeResult.pageContextAddendum, '_pageId', 'string'));
413
- if (routeResult.pageContextAddendum._pageId === null) {
410
+ const pageContextFromRoute = await route(pageContext);
411
+ assert(hasProp(pageContextFromRoute, '_pageId', 'null') || hasProp(pageContextFromRoute, '_pageId', 'string'));
412
+ if (pageContextFromRoute._pageId === null) {
414
413
  let hookName;
415
414
  let hookFilePath;
416
415
  if (pageContext._providedByHook) {
@@ -427,13 +426,13 @@ async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds,
427
426
  }
428
427
  else {
429
428
  // `prerenderHookFile` is `null` when the URL was deduced by the Filesytem Routing of `.page.js` files. The `onBeforeRoute()` can override Filesystem Routing; it is therefore expected that the deduced URL may not match any page.
430
- assert(routeResult.pageContextAddendum._routingProvidedByOnBeforeRouteHook);
429
+ assert(pageContextFromRoute._routingProvidedByOnBeforeRouteHook);
431
430
  // Abort since the URL doesn't correspond to any page
432
431
  return;
433
432
  }
434
433
  }
435
- assert(routeResult.pageContextAddendum._pageId);
436
- objectAssign(pageContext, routeResult.pageContextAddendum);
434
+ assert(pageContextFromRoute._pageId);
435
+ objectAssign(pageContext, pageContextFromRoute);
437
436
  const { _pageId: pageId } = pageContext;
438
437
  objectAssign(pageContext, await loadPageFilesServerSide(pageContext));
439
438
  let usesClientRouter;
@@ -5,7 +5,7 @@ export * from '../../utils/objectAssign.js';
5
5
  export * from '../../utils/isObjectWithKeys.js';
6
6
  export * from '../../utils/isCallable.js';
7
7
  export * from '../../utils/getOutDirs.js';
8
- export * from '../../utils/hasPropertyGetter.js';
8
+ export * from '../../utils/isPropertyGetter.js';
9
9
  export * from '../../utils/filesystemPathHandling.js';
10
10
  export * from '../../utils/urlToFile.js';
11
11
  export * from '../../shared/hooks/executeHook.js';
@@ -7,7 +7,7 @@ export * from '../../utils/objectAssign.js';
7
7
  export * from '../../utils/isObjectWithKeys.js';
8
8
  export * from '../../utils/isCallable.js';
9
9
  export * from '../../utils/getOutDirs.js';
10
- export * from '../../utils/hasPropertyGetter.js';
10
+ export * from '../../utils/isPropertyGetter.js';
11
11
  export * from '../../utils/filesystemPathHandling.js';
12
12
  export * from '../../utils/urlToFile.js';
13
13
  export * from '../../shared/hooks/executeHook.js';
@@ -54,6 +54,7 @@ function serializePageContextClientSide(pageContext) {
54
54
  msg = `${msg} Serialization error: ${err.messageCore}.`;
55
55
  }
56
56
  else {
57
+ // When a property getter throws an error
57
58
  console.warn('Serialization error:');
58
59
  console.warn(err);
59
60
  msg = `${msg} The serialization failed because of the error printed above.`;
@@ -240,8 +240,8 @@ async function renderPageNominal(pageContext) {
240
240
  }
241
241
  // Route
242
242
  {
243
- const routeResult = await route(pageContext);
244
- objectAssign(pageContext, routeResult.pageContextAddendum);
243
+ const pageContextFromRoute = await route(pageContext);
244
+ objectAssign(pageContext, pageContextFromRoute);
245
245
  objectAssign(pageContext, { is404: pageContext._pageId ? null : true });
246
246
  if (pageContext._pageId === null) {
247
247
  const errorPageId = getErrorPageId(pageContext._pageFilesAll, pageContext._pageConfigs);
@@ -25,7 +25,7 @@ export * from '../../utils/capitalizeFirstLetter.js';
25
25
  export * from '../../utils/debugGlob.js';
26
26
  export * from '../../utils/isEquivalentError.js';
27
27
  export * from '../../utils/styleFileRE.js';
28
- export * from '../../utils/hasPropertyGetter.js';
28
+ export * from '../../utils/isPropertyGetter.js';
29
29
  export * from '../../utils/debug.js';
30
30
  export * from '../../utils/urlToFile.js';
31
31
  export * from '../../utils/getGlobalObject.js';
@@ -28,7 +28,7 @@ export * from '../../utils/capitalizeFirstLetter.js';
28
28
  export * from '../../utils/debugGlob.js';
29
29
  export * from '../../utils/isEquivalentError.js';
30
30
  export * from '../../utils/styleFileRE.js';
31
- export * from '../../utils/hasPropertyGetter.js';
31
+ export * from '../../utils/isPropertyGetter.js';
32
32
  export * from '../../utils/debug.js';
33
33
  export * from '../../utils/urlToFile.js';
34
34
  export * from '../../utils/getGlobalObject.js';
@@ -55,6 +55,7 @@ type PageContextUrlComputedPropsServer = PageContextUrlComputedPropsClient & {
55
55
  declare function addUrlComputedProps<PageContext extends Record<string, unknown> & PageContextUrlSources>(pageContext: PageContext, enumerable?: boolean): asserts pageContext is PageContext & PageContextUrlComputedPropsInternal;
56
56
  type PageContextUrlSources = {
57
57
  urlOriginal: string;
58
+ urlLogical?: string;
58
59
  _urlRewrite: string | null;
59
60
  _baseServer: string;
60
61
  _urlHandler: null | ((url: string) => string);
@@ -1,28 +1,40 @@
1
1
  // URLs props need to be computed props, because the user can modify the URL e.g. with onBeforeRoute() for i18n
2
2
  export { addUrlComputedProps };
3
3
  export { assertPageContextUrlComputedProps };
4
- import { assert, parseUrl, assertWarning, isPlainObject, hasPropertyGetter, isBrowser } from './utils.js';
4
+ import { assert, parseUrl, assertWarning, isPlainObject, isPropertyGetter, isBrowser } from './utils.js';
5
5
  function addUrlComputedProps(pageContext, enumerable = true) {
6
6
  assert(pageContext.urlOriginal);
7
7
  if ('urlPathname' in pageContext) {
8
- assert(hasPropertyGetter(pageContext, 'urlPathname'));
8
+ assert(typeof pageContext.urlPathname === 'string');
9
+ /* If this assert() fails then it's most likely because Object.assign() was used instead of objectAssign(), i.e.:
10
+ ```js
11
+ // Add property getters such as pageContext.urlPathname to pageContext
12
+ addUrlComputedProps(pageContext)
13
+ // ❌ Breaks the property getters of pageContext set by addUrlComputedProps() such as pageContext.urlPathname
14
+ Object.assign(pageContext2, pageContext)
15
+ // ❌ Also breaks the property getters
16
+ const pageContext3 = { ...pageContext }
17
+ // ✅ Preserves property getters of pageContext (see objectAssign() implementation)
18
+ objectAssign(pageContext2, pageContext)
19
+ ```
20
+ */
21
+ assert(isPropertyGetter(pageContext, 'urlPathname'));
9
22
  }
23
+ if ('urlParsed' in pageContext)
24
+ assert(isPropertyGetter(pageContext, 'urlParsed'));
25
+ // TODO/v1-release: move pageContext.urlParsed to pageContext.url
26
+ if ('url' in pageContext)
27
+ assert(isPropertyGetter(pageContext, 'url'));
10
28
  Object.defineProperty(pageContext, 'urlPathname', {
11
29
  get: urlPathnameGetter,
12
30
  enumerable,
13
31
  configurable: true
14
32
  });
15
- // TODO/v1-release: move pageContext.urlParsed to pageContext.url
16
- if ('url' in pageContext)
17
- assert(hasPropertyGetter(pageContext, 'url'));
18
33
  Object.defineProperty(pageContext, 'url', {
19
34
  get: urlGetter,
20
35
  enumerable: false,
21
36
  configurable: true
22
37
  });
23
- if ('urlParsed' in pageContext) {
24
- assert(hasPropertyGetter(pageContext, 'urlParsed'));
25
- }
26
38
  Object.defineProperty(pageContext, 'urlParsed', {
27
39
  get: urlParsedGetter,
28
40
  enumerable,
@@ -30,17 +42,17 @@ function addUrlComputedProps(pageContext, enumerable = true) {
30
42
  });
31
43
  }
32
44
  function getUrlParsed(pageContext) {
33
- // We use a url handler function because the onBeforeRoute() hook may modify pageContext.urlOriginal (e.g. for i18n)
45
+ // We need a url handler function because the onBeforeRoute() hook may set pageContext.urlLogical (typically for i18n)
34
46
  let urlHandler = pageContext._urlHandler;
35
47
  if (!urlHandler) {
36
48
  urlHandler = (url) => url;
37
49
  }
38
- const url = pageContext._urlRewrite ?? pageContext.urlOriginal;
39
- assert(url && typeof url === 'string');
40
- const urlLogical = urlHandler(url);
50
+ let urlResolved = pageContext._urlRewrite ?? pageContext.urlLogical ?? pageContext.urlOriginal;
51
+ urlResolved = urlHandler(urlResolved);
41
52
  const baseServer = pageContext._baseServer;
53
+ assert(urlResolved && typeof urlResolved === 'string');
42
54
  assert(baseServer.startsWith('/'));
43
- return parseUrl(urlLogical, baseServer);
55
+ return parseUrl(urlResolved, baseServer);
44
56
  }
45
57
  function urlPathnameGetter() {
46
58
  const { pathname } = getUrlParsed(this);
@@ -11,7 +11,7 @@ declare function executeOnBeforeRouteHook(onBeforeRouteHook: OnBeforeRouteHook,
11
11
  _allPageIds: string[];
12
12
  }): Promise<null | {
13
13
  urlOriginal?: string;
14
- _urlOriginalPristine?: string;
14
+ urlLogical?: string;
15
15
  _pageId?: string | null;
16
16
  routeParams?: Record<string, string>;
17
17
  }>;
@@ -6,6 +6,7 @@ export { executeOnBeforeRouteHook };
6
6
  async function executeOnBeforeRouteHook(onBeforeRouteHook, pageContext) {
7
7
  let hookReturn = onBeforeRouteHook.onBeforeRoute(pageContext);
8
8
  assertSyncRouting(hookReturn, `The onBeforeRoute() hook ${onBeforeRouteHook.hookFilePath}`);
9
+ // TODO/v1-release: make executeOnBeforeRouteHook() and route() sync
9
10
  hookReturn = await hookReturn;
10
11
  const errPrefix = `The onBeforeRoute() hook defined by ${onBeforeRouteHook.hookFilePath}`;
11
12
  assertUsage(hookReturn === null ||
@@ -23,28 +24,25 @@ async function executeOnBeforeRouteHook(onBeforeRouteHook, pageContext) {
23
24
  if (hasProp(hookReturn.pageContext, 'routeParams')) {
24
25
  assertRouteParams(hookReturn.pageContext, `${errPrefix} returned ${pc.cyan('{ pageContext: { routeParams } }')} but routeParams should`);
25
26
  }
26
- const pageContextAddendumHook = {};
27
+ const deprecatedReturn = (prop) => `${errPrefix} returned ${pc.cyan(`{ pageContext: { ${prop} } }`)} which is deprecated. Return ${pc.cyan('{ pageContext: { urlLogical } }')} instead.`;
27
28
  if (hasProp(hookReturn.pageContext, 'url')) {
28
- assertWarning(false, `${errPrefix} returned ${pc.cyan('{ pageContext: { url } }')} but ${pc.cyan('pageContext.url')} has been renamed to ${pc.cyan('pageContext.urlOriginal')}. Return ${pc.cyan('{ pageContext: { urlOriginal } }')} instead. (See https://vike.dev/migration/0.4.23 for more information.)`, { onlyOnce: true });
29
- hookReturn.pageContext.urlOriginal = hookReturn.pageContext.url;
29
+ assertWarning(false, deprecatedReturn('url'), { onlyOnce: true });
30
+ hookReturn.pageContext.urlLogical = hookReturn.pageContext.url;
30
31
  delete hookReturn.pageContext.url;
31
32
  }
32
33
  if (hasProp(hookReturn.pageContext, 'urlOriginal')) {
33
- assertUsageUrl(hookReturn.pageContext.urlOriginal, `${errPrefix} returned ${pc.cyan('{ pageContext: { urlOriginal } }')} but ${pc.cyan('urlOriginal')}`);
34
- // Ugly workaround: ideally urlOriginal should be immutable.
35
- // - Instead of using pageContext._urlOriginalPristine, maybe we can keep pageContext.urlOriginal immutable while re-using `pageContext._urlRewrite`.
36
- // - Or better yet we rename pageContext._urlRewrite to pageContext.urlLogical and we allow the user to override pageContext.urlLogical, and we rename pageContext.urlOriginal => `pageContext.urlReal`.
37
- // - pageContext.urlReal / pageContext.urlLogical
38
- // VS
39
- // pageContext.urlReal / pageContext.urlModified
40
- // VS
41
- // pageContext.urlOriginal / pageContext.urlModified
42
- objectAssign(pageContextAddendumHook, { _urlOriginalPristine: pageContext.urlOriginal });
34
+ assertWarning(false, deprecatedReturn('urlOriginal'), { onlyOnce: true });
35
+ hookReturn.pageContext.urlLogical = hookReturn.pageContext.urlOriginal;
36
+ delete hookReturn.pageContext.urlOriginal;
37
+ }
38
+ if (hasProp(hookReturn.pageContext, 'urlLogical')) {
39
+ assertUsageUrl(hookReturn.pageContext.urlLogical, `${errPrefix} returned ${pc.cyan('{ pageContext: { urlLogical } }')} but ${pc.cyan('urlLogical')}`);
43
40
  }
44
41
  assertPageContextProvidedByUser(hookReturn.pageContext, {
45
42
  hookFilePath: onBeforeRouteHook.hookFilePath,
46
43
  hookName: 'onBeforeRoute'
47
44
  });
45
+ const pageContextAddendumHook = {};
48
46
  objectAssign(pageContextAddendumHook, hookReturn.pageContext);
49
47
  return pageContextAddendumHook;
50
48
  }
@@ -1,5 +1,8 @@
1
1
  export { route };
2
- export type { PageRoutes, PageContextForRoute, RouteMatches };
2
+ export type { PageContextForRoute };
3
+ export type { PageContextFromRoute };
4
+ export type { PageRoutes };
5
+ export type { RouteMatches };
3
6
  import type { PageFile } from '../getPageFiles.js';
4
7
  import { PageContextUrlComputedPropsInternal, PageContextUrlSources } from '../addUrlComputedProps.js';
5
8
  import { type OnBeforeRouteHook } from './executeOnBeforeRouteHook.js';
@@ -13,6 +16,12 @@ type PageContextForRoute = PageContextUrlComputedPropsInternal & {
13
16
  _pageRoutes: PageRoutes;
14
17
  _onBeforeRouteHook: OnBeforeRouteHook | null;
15
18
  } & PageContextUrlSources;
19
+ type PageContextFromRoute = {
20
+ _pageId: string | null;
21
+ routeParams: Record<string, string>;
22
+ _routingProvidedByOnBeforeRouteHook: boolean;
23
+ _routeMatches: RouteMatches;
24
+ };
16
25
  type RouteMatch = {
17
26
  pageId: string;
18
27
  routeString?: string;
@@ -21,11 +30,4 @@ type RouteMatch = {
21
30
  routeParams: Record<string, string>;
22
31
  };
23
32
  type RouteMatches = 'CUSTOM_ROUTE' | RouteMatch[];
24
- declare function route(pageContext: PageContextForRoute): Promise<{
25
- pageContextAddendum: {
26
- _pageId: string | null;
27
- routeParams: Record<string, string>;
28
- _routingProvidedByOnBeforeRouteHook: boolean;
29
- _routeMatches: RouteMatches;
30
- } & Record<string, unknown>;
31
- }>;
33
+ declare function route(pageContext: PageContextForRoute): Promise<PageContextFromRoute>;
@@ -33,7 +33,7 @@ async function route(pageContext) {
33
33
  _routingProvidedByOnBeforeRouteHook: true,
34
34
  _routeMatches: 'CUSTOM_ROUTE'
35
35
  });
36
- return { pageContextAddendum };
36
+ return pageContextAddendum;
37
37
  }
38
38
  // We already assign so that `pageContext.urlOriginal === pageContextAddendum.urlOriginal`; enabling the `onBeforeRoute()` hook to mutate `pageContext.urlOriginal` before routing.
39
39
  objectAssign(pageContext, pageContextAddendum);
@@ -99,7 +99,7 @@ async function route(pageContext) {
99
99
  _pageId: null,
100
100
  routeParams: {}
101
101
  });
102
- return { pageContextAddendum };
102
+ return pageContextAddendum;
103
103
  }
104
104
  {
105
105
  const { routeParams } = winner;
@@ -109,5 +109,5 @@ async function route(pageContext) {
109
109
  routeParams: winner.routeParams
110
110
  });
111
111
  }
112
- return { pageContextAddendum };
112
+ return pageContextAddendum;
113
113
  }
@@ -9,7 +9,7 @@ async function resolveRouteFunction(routeFunction, pageContext, routeDefinedAt)
9
9
  assertPageContextUrlComputedProps(pageContext);
10
10
  let result = routeFunction(pageContext);
11
11
  assertSyncRouting(result, `The Route Function ${routeDefinedAt}`);
12
- // TODO/v1-release
12
+ // TODO/v1-release: make resolveRouteFunction() and route() sync
13
13
  //* We disallow asynchronous routing, because we need to check whether a link is a Vike link in a synchronous fashion before calling ev.preventDefault() in the 'click' event listener
14
14
  result = await result;
15
15
  //*/
@@ -15,7 +15,7 @@ export * from '../utils/stringifyStringArray.js';
15
15
  export * from '../utils/filesystemPathHandling.js';
16
16
  export * from '../utils/cast.js';
17
17
  export * from '../utils/projectInfo.js';
18
- export * from '../utils/hasPropertyGetter.js';
18
+ export * from '../utils/isPropertyGetter.js';
19
19
  export * from '../utils/isPromise.js';
20
20
  export * from '../utils/checkType.js';
21
21
  export * from '../utils/objectEntries.js';
@@ -19,7 +19,7 @@ export * from '../utils/stringifyStringArray.js';
19
19
  export * from '../utils/filesystemPathHandling.js';
20
20
  export * from '../utils/cast.js';
21
21
  export * from '../utils/projectInfo.js';
22
- export * from '../utils/hasPropertyGetter.js';
22
+ export * from '../utils/isPropertyGetter.js';
23
23
  export * from '../utils/isPromise.js';
24
24
  export * from '../utils/checkType.js';
25
25
  export * from '../utils/objectEntries.js';
@@ -0,0 +1 @@
1
+ export declare function isPropertyGetter(obj: Object, prop: string): boolean;
@@ -1,4 +1,4 @@
1
- export function hasPropertyGetter(obj, prop) {
1
+ export function isPropertyGetter(obj, prop) {
2
2
  const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
3
3
  return !!descriptor && !('value' in descriptor) && !!descriptor.get;
4
4
  }
@@ -5,7 +5,7 @@ type ProjectVersion = typeof projectInfo.projectVersion;
5
5
  type ProjectTag = `[${PackageName}]` | `[${PackageName}@${ProjectVersion}]`;
6
6
  declare const projectInfo: {
7
7
  projectName: "Vike";
8
- projectVersion: "0.4.144-commit-f7ab002";
8
+ projectVersion: "0.4.144-commit-7f5e99a";
9
9
  npmPackageName: "vike";
10
10
  githubRepository: "https://github.com/vikejs/vike";
11
11
  };
@@ -1,6 +1,6 @@
1
1
  export { projectInfo };
2
2
  import { onProjectInfo } from './assertSingleInstance.js';
3
- const PROJECT_VERSION = '0.4.144-commit-f7ab002';
3
+ const PROJECT_VERSION = '0.4.144-commit-7f5e99a';
4
4
  const projectInfo = {
5
5
  projectName: 'Vike',
6
6
  projectVersion: PROJECT_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.144-commit-f7ab002",
3
+ "version": "0.4.144-commit-7f5e99a",
4
4
  "scripts": {
5
5
  "dev": "tsc --watch",
6
6
  "build": "rimraf dist/ && pnpm run build:esm && pnpm run build:cjs",
@@ -1,2 +0,0 @@
1
- export { isClientSideRoutable };
2
- declare function isClientSideRoutable(url: string): Promise<boolean>;
@@ -1,15 +0,0 @@
1
- export { isClientSideRoutable };
2
- import { getPageId } from '../getPageId.js';
3
- import { analyzePageClientSideInit } from '../../../shared/getPageFiles/analyzePageClientSide.js';
4
- import { findPageConfig } from '../../../shared/page-configs/findPageConfig.js';
5
- import { analyzeClientSide } from '../../../shared/getPageFiles/analyzeClientSide.js';
6
- async function isClientSideRoutable(url) {
7
- const { pageId, pageFilesAll, pageConfigs } = await getPageId(url);
8
- if (!pageId) {
9
- return false;
10
- }
11
- await analyzePageClientSideInit(pageFilesAll, pageId, { sharedPageFilesAlreadyLoaded: false });
12
- const pageConfig = findPageConfig(pageConfigs, pageId);
13
- const { isClientSideRenderable, isClientRouting } = analyzeClientSide(pageConfig, pageFilesAll, pageId);
14
- return isClientSideRenderable && isClientRouting;
15
- }
@@ -1,6 +0,0 @@
1
- export { useClientRouter };
2
- export { disableClientRouting };
3
- export { isDisableAutomaticLinkInterception };
4
- declare function disableClientRouting(err: unknown, log: boolean): void;
5
- declare function useClientRouter(): void;
6
- declare function isDisableAutomaticLinkInterception(): boolean;
@@ -1 +0,0 @@
1
- export declare function hasPropertyGetter(obj: Object, prop: string): boolean;