vike 0.4.144-commit-6aef8a6 → 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 (112) hide show
  1. package/dist/cjs/__internal/index.js +6 -2
  2. package/dist/cjs/node/plugin/plugins/buildConfig.js +2 -2
  3. package/dist/cjs/node/plugin/plugins/commonConfig.js +0 -3
  4. package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +5 -5
  5. package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -0
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +4 -3
  7. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +29 -42
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +2 -2
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +14 -5
  10. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/helpers.js +1 -14
  11. package/dist/cjs/node/plugin/plugins/previewConfig.js +11 -2
  12. package/dist/cjs/node/prerender/runPrerender.js +16 -17
  13. package/dist/cjs/node/prerender/utils.js +1 -1
  14. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +20 -6
  15. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +2 -2
  16. package/dist/cjs/node/runtime/renderPage.js +2 -2
  17. package/dist/cjs/node/runtime/utils.js +1 -1
  18. package/dist/cjs/node/shared/getClientEntryFilePath.js +2 -2
  19. package/dist/cjs/shared/addUrlComputedProps.js +24 -12
  20. package/dist/cjs/shared/getPageFiles/analyzeClientSide.js +4 -6
  21. package/dist/cjs/shared/getPageFiles/getExports.js +3 -3
  22. package/dist/cjs/shared/hooks/getHook.js +1 -1
  23. package/dist/cjs/shared/page-configs/helpers/getConfigDefinedAtString.js +43 -0
  24. package/dist/cjs/shared/page-configs/helpers/getConfigValue.js +44 -0
  25. package/dist/cjs/shared/page-configs/helpers.js +33 -0
  26. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +6 -8
  27. package/dist/cjs/shared/page-configs/serialize/parsePageConfigs.js +2 -2
  28. package/dist/cjs/shared/page-configs/serialize/serializeConfigValue.js +2 -2
  29. package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +11 -13
  30. package/dist/cjs/shared/route/index.js +3 -3
  31. package/dist/cjs/shared/route/loadPageRoutes.js +11 -10
  32. package/dist/cjs/shared/route/resolveRouteFunction.js +1 -1
  33. package/dist/cjs/shared/utils.js +1 -1
  34. package/dist/cjs/utils/{hasPropertyGetter.js → isPropertyGetter.js} +3 -3
  35. package/dist/cjs/utils/projectInfo.js +1 -1
  36. package/dist/esm/__internal/index.d.ts +6 -3
  37. package/dist/esm/__internal/index.js +8 -3
  38. package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -3
  39. package/dist/esm/client/client-routing-runtime/createPageContext.js +3 -3
  40. package/dist/esm/client/client-routing-runtime/entry.js +2 -2
  41. package/dist/esm/client/client-routing-runtime/getPageContext.d.ts +0 -1
  42. package/dist/esm/client/client-routing-runtime/getPageContext.js +4 -7
  43. package/dist/esm/client/client-routing-runtime/getPageId.d.ts +1 -1
  44. package/dist/esm/client/client-routing-runtime/getPageId.js +4 -7
  45. package/dist/esm/client/client-routing-runtime/history.d.ts +3 -1
  46. package/dist/esm/client/client-routing-runtime/history.js +26 -8
  47. package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +21 -0
  48. package/dist/esm/client/client-routing-runtime/{useClientRouter.js → installClientRouter.js} +248 -242
  49. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.d.ts +8 -0
  50. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +15 -0
  51. package/dist/esm/client/client-routing-runtime/navigate.d.ts +0 -2
  52. package/dist/esm/client/client-routing-runtime/navigate.js +10 -8
  53. package/dist/esm/client/client-routing-runtime/prefetch.js +12 -5
  54. package/dist/esm/client/client-routing-runtime/skipLink.d.ts +0 -1
  55. package/dist/esm/client/client-routing-runtime/skipLink.js +1 -2
  56. package/dist/esm/client/shared/executeOnRenderClientHook.js +6 -5
  57. package/dist/esm/client/shared/getPageContextProxyForUser.js +13 -7
  58. package/dist/esm/node/plugin/plugins/buildConfig.js +1 -1
  59. package/dist/esm/node/plugin/plugins/commonConfig.js +0 -3
  60. package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +5 -5
  61. package/dist/esm/node/plugin/plugins/devConfig/index.js +1 -0
  62. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +2 -2
  63. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +4 -3
  64. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +29 -42
  65. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +1 -1
  66. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +15 -6
  67. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.js +1 -14
  68. package/dist/esm/node/plugin/plugins/previewConfig.js +11 -2
  69. package/dist/esm/node/prerender/runPrerender.js +11 -12
  70. package/dist/esm/node/prerender/utils.d.ts +1 -1
  71. package/dist/esm/node/prerender/utils.js +1 -1
  72. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +21 -7
  73. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -1
  74. package/dist/esm/node/runtime/renderPage.js +2 -2
  75. package/dist/esm/node/runtime/utils.d.ts +1 -1
  76. package/dist/esm/node/runtime/utils.js +1 -1
  77. package/dist/esm/node/shared/getClientEntryFilePath.js +1 -1
  78. package/dist/esm/shared/addUrlComputedProps.d.ts +1 -0
  79. package/dist/esm/shared/addUrlComputedProps.js +25 -13
  80. package/dist/esm/shared/getPageFiles/analyzeClientSide.js +2 -4
  81. package/dist/esm/shared/getPageFiles/getExports.js +2 -2
  82. package/dist/esm/shared/hooks/getHook.js +1 -1
  83. package/dist/esm/shared/page-configs/PageConfig.d.ts +4 -12
  84. package/dist/esm/shared/page-configs/helpers/getConfigDefinedAtString.d.ts +7 -0
  85. package/dist/esm/shared/page-configs/helpers/getConfigDefinedAtString.js +37 -0
  86. package/dist/esm/shared/page-configs/helpers/getConfigValue.d.ts +14 -0
  87. package/dist/esm/shared/page-configs/helpers/getConfigValue.js +38 -0
  88. package/dist/esm/shared/page-configs/helpers.d.ts +13 -0
  89. package/dist/esm/shared/page-configs/helpers.js +27 -0
  90. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +6 -8
  91. package/dist/esm/shared/page-configs/serialize/parsePageConfigs.js +2 -2
  92. package/dist/esm/shared/page-configs/serialize/serializeConfigValue.js +2 -2
  93. package/dist/esm/shared/route/executeOnBeforeRouteHook.d.ts +1 -1
  94. package/dist/esm/shared/route/executeOnBeforeRouteHook.js +11 -13
  95. package/dist/esm/shared/route/index.d.ts +11 -9
  96. package/dist/esm/shared/route/index.js +3 -3
  97. package/dist/esm/shared/route/loadPageRoutes.js +7 -6
  98. package/dist/esm/shared/route/resolveRouteFunction.js +1 -1
  99. package/dist/esm/shared/utils.d.ts +1 -1
  100. package/dist/esm/shared/utils.js +1 -1
  101. package/dist/esm/utils/isPropertyGetter.d.ts +1 -0
  102. package/dist/esm/utils/{hasPropertyGetter.js → isPropertyGetter.js} +1 -1
  103. package/dist/esm/utils/projectInfo.d.ts +1 -1
  104. package/dist/esm/utils/projectInfo.js +1 -1
  105. package/package.json +2 -2
  106. package/dist/cjs/shared/page-configs/utils.js +0 -96
  107. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.d.ts +0 -2
  108. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.js +0 -15
  109. package/dist/esm/client/client-routing-runtime/useClientRouter.d.ts +0 -6
  110. package/dist/esm/shared/page-configs/utils.d.ts +0 -35
  111. package/dist/esm/shared/page-configs/utils.js +0 -90
  112. package/dist/esm/utils/hasPropertyGetter.d.ts +0 -1
@@ -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';
@@ -16,7 +16,7 @@ import { getConfigVike } from '../shared/getConfigVike.js';
16
16
  import { getPageFilesServerSide } from '../../shared/getPageFiles.js';
17
17
  import { getPageContextRequestUrl } from '../../shared/getPageContextRequestUrl.js';
18
18
  import { getUrlFromRouteString } from '../../shared/route/resolveRouteString.js';
19
- import { getConfigValue, getConfigValueFilePathToShowToUser, getHookFilePathToShowToUser } from '../../shared/page-configs/utils.js';
19
+ import { getConfigValue, getConfigValueFilePathToShowToUser, getHookFilePathToShowToUser } from '../../shared/page-configs/helpers.js';
20
20
  import { loadConfigValues } from '../../shared/page-configs/loadConfigValues.js';
21
21
  import { isErrorPage } from '../../shared/error-page.js';
22
22
  import { addUrlComputedProps } from '../../shared/addUrlComputedProps.js';
@@ -285,7 +285,7 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
285
285
  const configValue = pageConfigGlobal.configValues.onPrerenderStart;
286
286
  if (configValue?.value) {
287
287
  const { value: hookFn } = configValue;
288
- // config.onPrerenderStart isn't a computed nor a cumulative config => definedAtInfo should always be defined
288
+ // config.onPrerenderStart isn't a computed nor a cumulative config => definedAt should always be defined
289
289
  const hookFilePath = getHookFilePathToShowToUser(configValue);
290
290
  assert(hookFilePath);
291
291
  onPrerenderStartHook = {
@@ -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';
@@ -1,6 +1,6 @@
1
1
  export { serializePageContextClientSide };
2
2
  export { serializePageContextAbort };
3
- import { stringify } from '@brillout/json-serializer/stringify';
3
+ import { stringify, isJsonSerializerError } from '@brillout/json-serializer/stringify';
4
4
  import { assert, assertWarning, hasProp, unique } from '../utils.js';
5
5
  import { isErrorPage } from '../../../shared/error-page.js';
6
6
  import { addIs404ToPageProps } from '../../../shared/addIs404ToPageProps.js';
@@ -46,19 +46,33 @@ function serializePageContextClientSide(pageContext) {
46
46
  catch (err) {
47
47
  hasWarned = true;
48
48
  propsNonSerializable.push(prop);
49
- assert(hasProp(err, 'messageCore', 'string'));
50
- assertWarning(false, [
49
+ let msg = [
51
50
  `${varName} cannot be serialized and, therefore, cannot be passed to the client.`,
52
- `Make sure that ${varName} is serializable, or remove ${h(propName)} from ${h('passToClient')}.`,
53
- `Serialization error: ${err.messageCore}.`
54
- ].join(' '), { onlyOnce: false });
51
+ `Make sure that ${varName} is serializable, or remove ${h(propName)} from ${h('passToClient')}.`
52
+ ].join(' ');
53
+ if (isJsonSerializerError(err)) {
54
+ msg = `${msg} Serialization error: ${err.messageCore}.`;
55
+ }
56
+ else {
57
+ // When a property getter throws an error
58
+ console.warn('Serialization error:');
59
+ console.warn(err);
60
+ msg = `${msg} The serialization failed because of the error printed above.`;
61
+ }
62
+ // We warn (instead of throwing an error) since Vike's client runtime throws an error (with `assertUsage()`) if the user's client code tries to access the property that cannot be serialized
63
+ assertWarning(false, msg, { onlyOnce: false });
55
64
  }
56
65
  });
57
66
  assert(hasWarned);
58
67
  propsNonSerializable.forEach((prop) => {
59
68
  pageContextClient[prop] = notSerializable;
60
69
  });
61
- pageContextSerialized = serialize(pageContextClient);
70
+ try {
71
+ pageContextSerialized = serialize(pageContextClient);
72
+ }
73
+ catch (err) {
74
+ assert(false);
75
+ }
62
76
  }
63
77
  return pageContextSerialized;
64
78
  }
@@ -20,7 +20,7 @@ import { preparePageContextForUserConsumptionServerSide } from './preparePageCon
20
20
  import { executeGuardHook } from '../../../shared/route/executeGuardHook.js';
21
21
  import { loadPageRoutes } from '../../../shared/route/loadPageRoutes.js';
22
22
  import pc from '@brillout/picocolors';
23
- import { getConfigValueFilePathToShowToUser } from '../../../shared/page-configs/utils.js';
23
+ import { getConfigValueFilePathToShowToUser } from '../../../shared/page-configs/helpers.js';
24
24
  async function renderPageAlreadyRouted(pageContext) {
25
25
  // pageContext._pageId can either be the:
26
26
  // - ID of the page matching the routing, or the
@@ -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';
@@ -1,5 +1,5 @@
1
1
  export { getClientEntryFilePath };
2
- import { getConfigValue } from '../../shared/page-configs/utils.js';
2
+ import { getConfigValue } from '../../shared/page-configs/helpers.js';
3
3
  function getClientEntryFilePath(pageConfig) {
4
4
  const configName = 'client';
5
5
  const configValue = getConfigValue(pageConfig, configName, 'string');
@@ -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);
@@ -1,5 +1,5 @@
1
1
  export { analyzeClientSide };
2
- import { getConfigValue } from '../page-configs/utils.js';
2
+ import { getConfigValue } from '../page-configs/helpers.js';
3
3
  import { analyzePageClientSide } from './analyzePageClientSide.js';
4
4
  function analyzeClientSide(pageConfig, pageFilesAll, pageId) {
5
5
  // V1 design
@@ -9,9 +9,7 @@ function analyzeClientSide(pageConfig, pageFilesAll, pageId) {
9
9
  return { isClientSideRenderable, isClientRouting };
10
10
  }
11
11
  else {
12
- // TODO/v1-release:
13
- // - remove V0.4 implementation
14
- // - globally rename isHtmlOnly to !isClientSideRenderable
12
+ // TODO/v1-release: remove
15
13
  // V0.4 design
16
14
  const { isHtmlOnly, isClientRouting } = analyzePageClientSide(pageFilesAll, pageId);
17
15
  return { isClientSideRenderable: !isHtmlOnly, isClientRouting };
@@ -3,7 +3,7 @@ export { getExports };
3
3
  import { isScriptFile, isTemplateFile } from '../../utils/isScriptFile.js';
4
4
  import { assert, hasProp, isObject, assertWarning, assertUsage, makeLast, isBrowser } from '../utils.js';
5
5
  import { assertDefaultExports, forbiddenDefaultExports } from './assert_exports_old_design.js';
6
- import { getConfigDefinedAtString, getConfigValueFilePathToShowToUser } from '../page-configs/utils.js';
6
+ import { getConfigDefinedAtString, getConfigValueFilePathToShowToUser } from '../page-configs/helpers.js';
7
7
  import pc from '@brillout/picocolors';
8
8
  function getExports(pageFiles, pageConfig) {
9
9
  const configEntries = {};
@@ -31,7 +31,7 @@ function getExports(pageFiles, pageConfig) {
31
31
  Object.entries(pageConfig.configValues).forEach(([configName, configValue]) => {
32
32
  const { value } = configValue;
33
33
  const configValueFilePathToShowToUser = getConfigValueFilePathToShowToUser(configValue);
34
- const configDefinedAt = getConfigDefinedAtString(configName, configValue, true);
34
+ const configDefinedAt = getConfigDefinedAtString('Config', configName, configValue);
35
35
  config[configName] = config[configName] ?? value;
36
36
  configEntries[configName] = configEntries[configName] ?? [];
37
37
  // Currently each configName has only one entry. Adding an entry for each overriden config value isn't implemented yet. (This is an isomorphic file and it isn't clear whether this can/should be implemented on the client-side. We should load a minimum amount of code on the client-side.)
@@ -23,6 +23,6 @@ function assertHook(pageContext, hookName) {
23
23
  function assertHookFn(hookFn, { hookName, hookFilePath }) {
24
24
  assert(hookName && hookFilePath);
25
25
  assert(!hookName.endsWith(')'));
26
- assertUsage(isCallable(hookFn), `hook ${hookName}() defined by ${hookFilePath} should be a function`);
26
+ assertUsage(isCallable(hookFn), `Hook ${hookName}() defined by ${hookFilePath} should be a function`);
27
27
  checkType(hookFn);
28
28
  }
@@ -13,7 +13,7 @@ export type { ConfigValueComputed };
13
13
  export type { ConfigValuesComputed };
14
14
  export type { DefinedAt };
15
15
  export type { DefinedAtFile };
16
- export type { DefinedAtFileInfo };
16
+ export type { DefinedAtFileFullInfo };
17
17
  export type { FilePathResolved };
18
18
  export type { FilePath };
19
19
  import type { ConfigValueImported } from './serialize/PageConfigSerialized.js';
@@ -56,15 +56,14 @@ type ConfigEnvInternal = ConfigEnv | '_routing-eager' | '_routing-lazy';
56
56
  type ConfigValueSource = {
57
57
  value?: unknown;
58
58
  configEnv: ConfigEnvInternal;
59
- definedAtInfo: DefinedAtFileInfo;
59
+ definedAt: DefinedAtFileFullInfo;
60
60
  /** Wether the config value is loaded at runtime, for example config.Page or config.onBeforeRender */
61
61
  valueIsImportedAtRuntime: boolean;
62
62
  /** Whether the config value is a file path, for example config.client */
63
63
  valueIsFilePath?: true;
64
64
  };
65
- type DefinedAtFileInfo = FilePath & {
65
+ type DefinedAtFileFullInfo = DefinedAtFile & FilePath & {
66
66
  fileExportName?: string;
67
- fileExportPathToShowToUser: null | string[];
68
67
  };
69
68
  type ConfigValueSources = Record<string, ConfigValueSource[]>;
70
69
  type ConfigValueComputed = {
@@ -76,17 +75,10 @@ type ConfigValue = {
76
75
  value: unknown;
77
76
  definedAt: DefinedAt;
78
77
  };
79
- type DefinedAt = {
80
- file: DefinedAtFile;
81
- isComputed?: undefined;
82
- isCumulative?: undefined;
83
- } | {
84
- isCumulative: true;
78
+ type DefinedAt = DefinedAtFile | {
85
79
  files: DefinedAtFile[];
86
- isComputed?: undefined;
87
80
  } | {
88
81
  isComputed: true;
89
- isCumulative?: undefined;
90
82
  };
91
83
  type DefinedAtFile = {
92
84
  filePathToShowToUser: string;
@@ -0,0 +1,7 @@
1
+ export { getConfigDefinedAtString };
2
+ export { getDefinedAtString };
3
+ import type { DefinedAt } from '../PageConfig.js';
4
+ declare function getConfigDefinedAtString<ConfigName extends string, SentenceBegin extends 'Config' | 'config' | 'Hook'>(sentenceBegin: SentenceBegin, configName: ConfigName, { definedAt }: {
5
+ definedAt: DefinedAt;
6
+ }): `${SentenceBegin} ${ConfigName}${string} defined ${'internally' | `at ${string}`}`;
7
+ declare function getDefinedAtString(definedAt: DefinedAt, configName: string): string;
@@ -0,0 +1,37 @@
1
+ export { getConfigDefinedAtString };
2
+ export { getDefinedAtString };
3
+ import { assert } from '../../utils.js';
4
+ import pc from '@brillout/picocolors';
5
+ import { getExportPath } from '../getExportPath.js';
6
+ function getConfigDefinedAtString(sentenceBegin, configName, { definedAt }) {
7
+ const definedAtString = getDefinedAtString(definedAt, configName);
8
+ const definedAtStr = definedAtString === 'internally' ? definedAtString : `at ${definedAtString}`;
9
+ let configNameStr = `${configName}${sentenceBegin === 'Hook' ? '()' : ''}`;
10
+ const configDefinedAt = `${sentenceBegin} ${pc.cyan(configNameStr)} defined ${definedAtStr}`;
11
+ return configDefinedAt;
12
+ }
13
+ function getDefinedAtString(definedAt, configName) {
14
+ if ('isComputed' in definedAt) {
15
+ return 'internally';
16
+ }
17
+ let files;
18
+ if ('files' in definedAt) {
19
+ files = definedAt.files;
20
+ }
21
+ else {
22
+ files = [definedAt];
23
+ }
24
+ assert(files.length >= 1);
25
+ const definedAtString = files
26
+ .map((source) => {
27
+ const { filePathToShowToUser, fileExportPathToShowToUser } = source;
28
+ let s = filePathToShowToUser;
29
+ const exportPath = getExportPath(fileExportPathToShowToUser, configName);
30
+ if (exportPath) {
31
+ s = `${s} > ${pc.cyan(exportPath)}`;
32
+ }
33
+ return s;
34
+ })
35
+ .join(' / ');
36
+ return definedAtString;
37
+ }
@@ -0,0 +1,14 @@
1
+ export { getConfigValue };
2
+ import type { PageConfigRuntime, PageConfigBuildTime, ConfigValue } from '../PageConfig.js';
3
+ import type { ConfigNameBuiltIn } from '../Config.js';
4
+ type PageConfigCommon = PageConfigRuntime | PageConfigBuildTime;
5
+ type ConfigName = ConfigNameBuiltIn;
6
+ declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName, type: 'string'): null | ConfigValue & {
7
+ value: string;
8
+ };
9
+ declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName, type: 'boolean'): null | ConfigValue & {
10
+ value: boolean;
11
+ };
12
+ declare function getConfigValue(pageConfig: PageConfigCommon, configName: ConfigName): null | ConfigValue & {
13
+ value: unknown;
14
+ };
@@ -0,0 +1,38 @@
1
+ export { getConfigValue };
2
+ import { assert, assertUsage, getValuePrintable } from '../../utils.js';
3
+ import pc from '@brillout/picocolors';
4
+ import { getConfigDefinedAtString } from './getConfigDefinedAtString.js';
5
+ // prettier-ignore
6
+ function getConfigValue(pageConfig, configName, type) {
7
+ const configValue = getConfigValueEntry(pageConfig, configName);
8
+ if (configValue === null)
9
+ return null;
10
+ const { value, definedAt } = configValue;
11
+ if (type)
12
+ assertConfigValueType(value, type, configName, definedAt);
13
+ return configValue;
14
+ }
15
+ function assertConfigValueType(value, type, configName, definedAt) {
16
+ assert(value !== null);
17
+ const typeActual = typeof value;
18
+ if (typeActual === type)
19
+ return;
20
+ const valuePrintable = getValuePrintable(value);
21
+ const problem = valuePrintable !== null
22
+ ? `value ${pc.cyan(valuePrintable)}`
23
+ : `type ${pc.cyan(typeActual)}`;
24
+ const configDefinedAt = getConfigDefinedAtString('Config', configName, {
25
+ definedAt
26
+ });
27
+ const errMsg = `${configDefinedAt} has an invalid ${problem}: it should be a ${pc.cyan(type)} instead`;
28
+ assertUsage(false, errMsg);
29
+ }
30
+ function getConfigValueEntry(pageConfig, configName) {
31
+ const configValue = pageConfig.configValues[configName];
32
+ if (!configValue)
33
+ return null;
34
+ // Enable users to suppress global config values by setting the local config value to null
35
+ if (configValue.value === null)
36
+ return null;
37
+ return configValue;
38
+ }
@@ -0,0 +1,13 @@
1
+ export { getPageConfig };
2
+ export { getConfigValueFilePathToShowToUser };
3
+ export { getHookFilePathToShowToUser };
4
+ export { getConfigDefinedAtString, getDefinedAtString } from './helpers/getConfigDefinedAtString.js';
5
+ export { getConfigValue } from './helpers/getConfigValue.js';
6
+ import type { PageConfigRuntime, DefinedAt } from './PageConfig.js';
7
+ declare function getPageConfig(pageId: string, pageConfigs: PageConfigRuntime[]): PageConfigRuntime;
8
+ declare function getConfigValueFilePathToShowToUser({ definedAt }: {
9
+ definedAt: DefinedAt;
10
+ }): null | string;
11
+ declare function getHookFilePathToShowToUser({ definedAt }: {
12
+ definedAt: DefinedAt;
13
+ }): string;
@@ -0,0 +1,27 @@
1
+ export { getPageConfig };
2
+ export { getConfigValueFilePathToShowToUser };
3
+ export { getHookFilePathToShowToUser };
4
+ export { getConfigDefinedAtString, getDefinedAtString } from './helpers/getConfigDefinedAtString.js';
5
+ export { getConfigValue } from './helpers/getConfigValue.js';
6
+ import { assert } from '../utils.js';
7
+ function getPageConfig(pageId, pageConfigs) {
8
+ const pageConfig = pageConfigs.find((p) => p.pageId === pageId);
9
+ assert(pageConfigs.length > 0);
10
+ assert(pageConfig);
11
+ return pageConfig;
12
+ }
13
+ function getConfigValueFilePathToShowToUser({ definedAt }) {
14
+ // A unique file path only exists if the config value isn't cumulative nor computed:
15
+ // - cumulative config values have multiple file paths
16
+ // - computed values don't have any file path
17
+ if ('isComputed' in definedAt || 'files' in definedAt)
18
+ return null;
19
+ const { filePathToShowToUser } = definedAt;
20
+ assert(filePathToShowToUser);
21
+ return filePathToShowToUser;
22
+ }
23
+ function getHookFilePathToShowToUser({ definedAt }) {
24
+ const filePathToShowToUser = getConfigValueFilePathToShowToUser({ definedAt });
25
+ assert(filePathToShowToUser);
26
+ return filePathToShowToUser;
27
+ }
@@ -8,14 +8,12 @@ function parseConfigValuesImported(configValuesImported) {
8
8
  configValues[configName] = {
9
9
  value,
10
10
  definedAt: {
11
- file: {
12
- // importPath cannot be relative to the current file, since the current file is a virtual file
13
- filePathToShowToUser: importPath,
14
- fileExportPathToShowToUser: [configName, 'default'].includes(exportName)
15
- ? []
16
- : // Side-effect config
17
- [exportName]
18
- }
11
+ // importPath cannot be relative to the current file, since the current file is a virtual file
12
+ filePathToShowToUser: importPath,
13
+ fileExportPathToShowToUser: [configName, 'default'].includes(exportName)
14
+ ? []
15
+ : // Side-effect config
16
+ [exportName]
19
17
  }
20
18
  };
21
19
  assertIsNotNull(value, configName, importPath);
@@ -2,7 +2,7 @@ export { parsePageConfigs };
2
2
  import { parse } from '@brillout/json-serializer/parse';
3
3
  import { parseConfigValuesImported } from './parseConfigValuesImported.js';
4
4
  import { assert, assertUsage, isCallable } from '../../utils.js';
5
- import { getConfigDefinedAtString } from '../utils.js';
5
+ import { getConfigDefinedAtString } from '../helpers.js';
6
6
  function parsePageConfigs(pageConfigsSerialized, pageConfigGlobalSerialized) {
7
7
  const pageConfigs = pageConfigsSerialized.map((pageConfigSerialized) => {
8
8
  const configValues = {};
@@ -49,7 +49,7 @@ function assertRouteConfigValue(configValues) {
49
49
  return;
50
50
  const { value } = configValue;
51
51
  const configValueType = typeof value;
52
- const configDefinedAt = getConfigDefinedAtString(configName, configValue, true);
52
+ const configDefinedAt = getConfigDefinedAtString('Config', configName, configValue);
53
53
  assertUsage(configValueType === 'string' || isCallable(value), `${configDefinedAt} has an invalid type '${configValueType}': it should be a string or a function instead, see https://vike.dev/route`);
54
54
  /* We don't use assertRouteString() in order to avoid unnecessarily bloating the client-side bundle when using Server Routing:
55
55
  * - When using Server Routing, this file is loaded => loading assertRouteString() would bloat the client bundle.
@@ -23,9 +23,9 @@ function serializeConfigValue(lines, configName, configValueSerialized) {
23
23
  function serializeConfigValueImported(configValueSource, configName, whitespace, varCounterContainer, importStatements) {
24
24
  assert(!configValueSource.valueIsFilePath);
25
25
  assert(whitespace.replaceAll(' ', '').length === 0);
26
- const { valueIsImportedAtRuntime, definedAtInfo } = configValueSource;
26
+ const { valueIsImportedAtRuntime, definedAt } = configValueSource;
27
27
  assert(valueIsImportedAtRuntime);
28
- const { filePathAbsoluteVite, fileExportName } = definedAtInfo;
28
+ const { filePathAbsoluteVite, fileExportName } = definedAt;
29
29
  assertPosixPath(filePathAbsoluteVite);
30
30
  const fileName = path.posix.basename(filePathAbsoluteVite);
31
31
  const isValueFile = fileName.startsWith('+');
@@ -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
  }