vike 0.4.144-commit-f7ab002 → 0.4.144-commit-de18325

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 (79) 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/getVikeConfig.js +58 -40
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +1 -0
  6. package/dist/cjs/node/plugin/plugins/previewConfig.js +5 -0
  7. package/dist/cjs/node/prerender/runPrerender.js +10 -11
  8. package/dist/cjs/node/prerender/utils.js +1 -1
  9. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +1 -0
  10. package/dist/cjs/node/runtime/renderPage/debugPageFiles.js +5 -5
  11. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -1
  12. package/dist/cjs/node/runtime/renderPage.js +3 -3
  13. package/dist/cjs/node/runtime/utils.js +1 -1
  14. package/dist/cjs/shared/addUrlComputedProps.js +24 -12
  15. package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +41 -15
  16. package/dist/cjs/shared/route/index.js +22 -32
  17. package/dist/cjs/shared/route/resolveRouteFunction.js +1 -1
  18. package/dist/cjs/shared/utils.js +1 -1
  19. package/dist/cjs/utils/{hasPropertyGetter.js → isPropertyGetter.js} +3 -3
  20. package/dist/cjs/utils/projectInfo.js +1 -1
  21. package/dist/esm/__internal/index.d.ts +6 -3
  22. package/dist/esm/__internal/index.js +8 -3
  23. package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -3
  24. package/dist/esm/client/client-routing-runtime/createPageContext.js +3 -3
  25. package/dist/esm/client/client-routing-runtime/entry.js +2 -2
  26. package/dist/esm/client/client-routing-runtime/getPageContext.d.ts +0 -1
  27. package/dist/esm/client/client-routing-runtime/getPageContext.js +6 -9
  28. package/dist/esm/client/client-routing-runtime/history.d.ts +3 -1
  29. package/dist/esm/client/client-routing-runtime/history.js +26 -8
  30. package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +21 -0
  31. package/dist/esm/client/client-routing-runtime/{useClientRouter.js → installClientRouter.js} +248 -242
  32. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.d.ts +8 -0
  33. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +15 -0
  34. package/dist/esm/client/client-routing-runtime/navigate.d.ts +0 -2
  35. package/dist/esm/client/client-routing-runtime/navigate.js +10 -8
  36. package/dist/esm/client/client-routing-runtime/prefetch.js +54 -28
  37. package/dist/esm/client/client-routing-runtime/skipLink.d.ts +0 -1
  38. package/dist/esm/client/client-routing-runtime/skipLink.js +1 -2
  39. package/dist/esm/client/server-routing-runtime/getPageContext.js +1 -1
  40. package/dist/esm/client/shared/executeOnRenderClientHook.js +6 -5
  41. package/dist/esm/client/shared/getPageContextProxyForUser.js +13 -7
  42. package/dist/esm/client/shared/loadPageFilesClientSide.d.ts +8 -3
  43. package/dist/esm/client/shared/loadPageFilesClientSide.js +5 -5
  44. package/dist/esm/node/plugin/plugins/commonConfig.js +0 -3
  45. package/dist/esm/node/plugin/plugins/devConfig/index.js +1 -0
  46. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +58 -40
  47. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +1 -0
  48. package/dist/esm/node/plugin/plugins/previewConfig.js +5 -0
  49. package/dist/esm/node/prerender/runPrerender.js +11 -12
  50. package/dist/esm/node/prerender/utils.d.ts +1 -1
  51. package/dist/esm/node/prerender/utils.js +1 -1
  52. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +1 -0
  53. package/dist/esm/node/runtime/renderPage/debugPageFiles.d.ts +5 -5
  54. package/dist/esm/node/runtime/renderPage/debugPageFiles.js +5 -5
  55. package/dist/esm/node/runtime/renderPage/loadPageFilesServerSide.d.ts +2 -2
  56. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -1
  57. package/dist/esm/node/runtime/renderPage.js +3 -3
  58. package/dist/esm/node/runtime/utils.d.ts +1 -1
  59. package/dist/esm/node/runtime/utils.js +1 -1
  60. package/dist/esm/shared/addUrlComputedProps.d.ts +1 -0
  61. package/dist/esm/shared/addUrlComputedProps.js +25 -13
  62. package/dist/esm/shared/route/executeOnBeforeRouteHook.d.ts +5 -8
  63. package/dist/esm/shared/route/executeOnBeforeRouteHook.js +41 -15
  64. package/dist/esm/shared/route/index.d.ts +12 -10
  65. package/dist/esm/shared/route/index.js +23 -33
  66. package/dist/esm/shared/route/resolveRouteFunction.js +1 -1
  67. package/dist/esm/shared/utils.d.ts +1 -1
  68. package/dist/esm/shared/utils.js +1 -1
  69. package/dist/esm/utils/isPropertyGetter.d.ts +1 -0
  70. package/dist/esm/utils/{hasPropertyGetter.js → isPropertyGetter.js} +1 -1
  71. package/dist/esm/utils/projectInfo.d.ts +1 -1
  72. package/dist/esm/utils/projectInfo.js +1 -1
  73. package/package.json +1 -1
  74. package/dist/esm/client/client-routing-runtime/getPageId.d.ts +0 -10
  75. package/dist/esm/client/client-routing-runtime/getPageId.js +0 -17
  76. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.d.ts +0 -2
  77. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.js +0 -15
  78. package/dist/esm/client/client-routing-runtime/useClientRouter.d.ts +0 -6
  79. package/dist/esm/utils/hasPropertyGetter.d.ts +0 -1
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- // Internal functions of vike needed by other plugins are exported via this file
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.getPagesAndRoutes = exports.route = void 0;
5
4
  const index_js_1 = require("../shared/route/index.js");
6
- Object.defineProperty(exports, "route", { enumerable: true, get: function () { return index_js_1.route; } });
7
5
  const globalContext_js_1 = require("../node/runtime/globalContext.js");
8
6
  const nodeEnv_js_1 = require("../utils/nodeEnv.js");
9
7
  const assert_js_1 = require("../utils/assert.js");
@@ -29,3 +27,9 @@ async function getPagesAndRoutes() {
29
27
  };
30
28
  }
31
29
  exports.getPagesAndRoutes = getPagesAndRoutes;
30
+ async function route(pageContext) {
31
+ const pageContextFromRoute = await (0, index_js_1.route)(pageContext);
32
+ // Old interface
33
+ return { pageContextAddendum: pageContextFromRoute };
34
+ }
35
+ exports.route = route;
@@ -18,9 +18,6 @@ function commonConfig() {
18
18
  return [
19
19
  {
20
20
  name: 'vike-commonConfig-1',
21
- config: () => ({
22
- appType: 'custom'
23
- }),
24
21
  configResolved(config) {
25
22
  (0, require_shim_1.installRequireShim_setUserRootDir)(config.root);
26
23
  }
@@ -23,6 +23,7 @@ function devConfig() {
23
23
  apply,
24
24
  config() {
25
25
  return {
26
+ appType: 'custom',
26
27
  optimizeDeps: {
27
28
  exclude: [
28
29
  // We exclude the vike client to be able to use `import.meta.glob()`
@@ -110,11 +110,11 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
110
110
  configName
111
111
  };
112
112
  {
113
- // We don't have access to custom config definitions yet
114
- // - We load +{configName}.js later
115
- // - But we do need to eagerly load +meta.js (to get all the custom config definitions)
113
+ // We don't have access to the custom config definitions defined by the user yet.
114
+ // - If `configDef` is `undefined` => we load the file +{configName}.js later.
115
+ // - We already need to load +meta.js here (to get the custom config definitions defined by the user)
116
116
  const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn_js_1.configDefinitionsBuiltIn, configName);
117
- if (configDef?.env === 'config-only') {
117
+ if (configDef && isConfigEnv(configDef, configName)) {
118
118
  await loadValueFile(interfaceFile, configName, userRootDir);
119
119
  }
120
120
  }
@@ -144,6 +144,22 @@ async function loadValueFile(interfaceValueFile, configName, userRootDir) {
144
144
  interfaceValueFile.configMap[configName_] = { configValue };
145
145
  });
146
146
  }
147
+ async function loadImportedFile(filePath, userRootDir, importedFilesLoaded) {
148
+ const f = filePath.filePathAbsoluteFilesystem;
149
+ if (!importedFilesLoaded[f]) {
150
+ importedFilesLoaded[f] = (0, transpileAndExecuteFile_js_1.transpileAndExecuteFile)(filePath, true, userRootDir).then((r) => r.fileExports);
151
+ }
152
+ const fileExports = await importedFilesLoaded[f];
153
+ return fileExports;
154
+ }
155
+ function isConfigEnv(configDef, configName) {
156
+ if (configDef.cumulative)
157
+ return true;
158
+ if (configDef.env === 'config-only')
159
+ return true;
160
+ // TODO: replace with proper `env: { config: boolean }` implementation
161
+ return configName === 'clientRouting';
162
+ }
147
163
  function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
148
164
  const { fileExports, filePath, extendsFilePaths } = configFile;
149
165
  const interfaceFile = {
@@ -204,7 +220,8 @@ async function loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, isDev,
204
220
  }
205
221
  async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
206
222
  const interfaceFilesByLocationId = await loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions);
207
- const { globalVikeConfig, pageConfigGlobal } = getGlobalConfigs(interfaceFilesByLocationId, userRootDir);
223
+ const importedFilesLoaded = {};
224
+ const { globalVikeConfig, pageConfigGlobal } = await getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded);
208
225
  const pageConfigs = await Promise.all(Object.entries(interfaceFilesByLocationId)
209
226
  .filter(([_pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
210
227
  .map(async ([locationId]) => {
@@ -218,24 +235,24 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
218
235
  if (isGlobalConfig(configName))
219
236
  return;
220
237
  const configDef = getConfigDefinition(configDefinitionsRelevant, configName, interfaceFile.filePath.filePathToShowToUser);
221
- if (configDef.env !== 'config-only')
238
+ if (!isConfigEnv(configDef, configName))
222
239
  return;
223
240
  const isAlreadyLoaded = interfacefileIsAlreaydLoaded(interfaceFile);
224
241
  if (isAlreadyLoaded)
225
242
  return;
226
- // Value files for built-in confg-only configs should have already been loaded at loadInterfaceFiles()
243
+ // Value files of built-in configs should have already been loaded at loadInterfaceFiles()
227
244
  (0, utils_js_1.assert)(!(configName in configDefinitionsBuiltIn_js_1.configDefinitionsBuiltIn));
228
245
  await loadValueFile(interfaceFile, configName, userRootDir);
229
246
  }));
230
247
  const configValueSources = {};
231
- (0, utils_js_1.objectEntries)(configDefinitionsRelevant)
248
+ await Promise.all((0, utils_js_1.objectEntries)(configDefinitionsRelevant)
232
249
  .filter(([configName]) => !isGlobalConfig(configName))
233
- .forEach(([configName, configDef]) => {
234
- const sources = resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir);
235
- if (!sources)
250
+ .map(async ([configName, configDef]) => {
251
+ const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded);
252
+ if (sources.length === 0)
236
253
  return;
237
254
  configValueSources[configName] = sources;
238
- });
255
+ }));
239
256
  const { routeFilesystem, isErrorPage } = determineRouteFilesystem(locationId, configValueSources);
240
257
  applyEffectsAll(configValueSources, configDefinitionsRelevant);
241
258
  const configValuesComputed = getComputed(configValueSources, configDefinitionsRelevant);
@@ -285,7 +302,7 @@ function getInterfaceFileList(interfaceFilesByLocationId) {
285
302
  });
286
303
  return interfaceFiles;
287
304
  }
288
- function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
305
+ async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded) {
289
306
  const locationIds = Object.keys(interfaceFilesByLocationId);
290
307
  const interfaceFilesGlobal = Object.fromEntries(Object.entries(interfaceFilesByLocationId).filter(([locationId]) => {
291
308
  return (0, filesystemRouting_js_1.isGlobalLocation)(locationId, locationIds);
@@ -321,9 +338,9 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
321
338
  const pageConfigGlobal = {
322
339
  configValueSources: {}
323
340
  };
324
- (0, utils_js_1.objectEntries)(configDefinitionsBuiltIn_js_1.configDefinitionsBuiltInGlobal).forEach(([configName, configDef]) => {
325
- const sources = resolveConfigValueSources(configName, configDef, interfaceFilesGlobal, userRootDir);
326
- const configValueSource = sources?.[0];
341
+ await Promise.all((0, utils_js_1.objectEntries)(configDefinitionsBuiltIn_js_1.configDefinitionsBuiltInGlobal).map(async ([configName, configDef]) => {
342
+ const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesGlobal, userRootDir, importedFilesLoaded);
343
+ const configValueSource = sources[0];
327
344
  if (!configValueSource)
328
345
  return;
329
346
  if (configName === 'onBeforeRoute' || configName === 'onPrerenderStart') {
@@ -338,23 +355,21 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
338
355
  (0, utils_js_1.assertWarning)(false, `Being able to define config ${picocolors_1.default.cyan(configName)} in ${filePathToShowToUser} is experimental and will likely be removed. Define the config ${picocolors_1.default.cyan(configName)} in Vike's Vite plugin options instead.`, { onlyOnce: true });
339
356
  globalVikeConfig[configName] = configValueSource.value;
340
357
  }
341
- });
358
+ }));
342
359
  return { pageConfigGlobal, globalVikeConfig };
343
360
  }
344
- function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir) {
345
- let sources = null;
361
+ async function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded) {
362
+ const sourcesInfo = [];
346
363
  // interfaceFilesRelevant is sorted by sortAfterInheritanceOrder()
347
364
  for (const interfaceFiles of Object.values(interfaceFilesRelevant)) {
348
365
  const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.configMap[configName]);
349
366
  if (interfaceFilesDefiningConfig.length === 0)
350
367
  continue;
351
- sources = sources ?? [];
352
368
  const visited = new WeakSet();
353
369
  const add = (interfaceFile) => {
354
370
  (0, utils_js_1.assert)(!visited.has(interfaceFile));
355
371
  visited.add(interfaceFile);
356
- const configValueSource = getConfigValueSource(configName, interfaceFile, configDef, userRootDir);
357
- sources.push(configValueSource);
372
+ sourcesInfo.push([configName, interfaceFile, configDef, userRootDir, importedFilesLoaded]);
358
373
  };
359
374
  // Main resolution logic
360
375
  {
@@ -378,7 +393,7 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
378
393
  if (interfaceFileWinner) {
379
394
  const interfaceFilesOverriden = [...interfaceValueFiles, ...interfaceConfigFiles].filter((f) => f !== interfaceFileWinner);
380
395
  // A user-land conflict of interfaceFiles with the same locationId means that the user has superfluously defined the config twice; the user should remove such redundancy making things unnecessarily ambiguous
381
- warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName, configDef, userRootDir);
396
+ warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName);
382
397
  [interfaceFileWinner, ...interfaceFilesOverriden].forEach((interfaceFile) => {
383
398
  add(interfaceFile);
384
399
  });
@@ -403,7 +418,7 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
403
418
  (0, utils_js_1.assert)(visited.has(interfaceFile));
404
419
  });
405
420
  }
406
- (0, utils_js_1.assert)(sources === null || sources.length > 0);
421
+ const sources = await Promise.all(sourcesInfo.map(async (args) => await getConfigValueSource(...args)));
407
422
  return sources;
408
423
  }
409
424
  function makeOrderDeterministic(interfaceFile1, interfaceFile2) {
@@ -414,22 +429,17 @@ function makeOrderDeterministic(interfaceFile1, interfaceFile2) {
414
429
  return filePathRelativeToUserRootDir.length;
415
430
  })(interfaceFile1, interfaceFile2);
416
431
  }
417
- function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName, configDef, userRootDir) {
432
+ function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName) {
418
433
  interfaceFilesOverriden.forEach((interfaceFileLoser) => {
419
- const configValueSourceLoser_ = getConfigValueSource(configName, interfaceFileLoser, configDef, userRootDir);
420
- const configValueSourceWinner = getConfigValueSource(configName, interfaceFileWinner, configDef, userRootDir);
421
- // prettier-ignore
422
- const configLoser_DefinedAt = (0, helpers_js_1.getConfigDefinedAtString)('Config', configName, configValueSourceLoser_);
423
- // prettier-ignore
424
- const configWinnerDefinedAt = (0, helpers_js_1.getConfigDefinedAtString)('config', configName, configValueSourceWinner);
425
- const errMsg = `${configLoser_DefinedAt} is overriden by another ${configWinnerDefinedAt}, remove one of the two`;
426
- (0, utils_js_1.assertWarning)(false, errMsg, { onlyOnce: false });
434
+ const loserFilePath = interfaceFileLoser.filePath.filePathToShowToUser;
435
+ const winnerFilePath = interfaceFileWinner.filePath.filePathToShowToUser;
436
+ (0, utils_js_1.assertWarning)(false, `Config ${configName} defined at ${loserFilePath} is always overwritten by ${configName} defined at ${winnerFilePath}, remove the superfluous ${configName} value defined at ${interfaceFileLoser}`, { onlyOnce: false });
427
437
  });
428
438
  }
429
439
  function isInterfaceFileUserLand(interfaceFile) {
430
440
  return (interfaceFile.isConfigFile && !interfaceFile.isConfigExtend) || interfaceFile.isValueFile;
431
441
  }
432
- function getConfigValueSource(configName, interfaceFile, configDef, userRootDir) {
442
+ async function getConfigValueSource(configName, interfaceFile, configDef, userRootDir, importedFilesLoaded) {
433
443
  const conf = interfaceFile.configMap[configName];
434
444
  (0, utils_js_1.assert)(conf);
435
445
  const configEnv = configDef.env;
@@ -475,6 +485,18 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
475
485
  valueIsImportedAtRuntime: true,
476
486
  definedAt: import_
477
487
  };
488
+ // Load config value
489
+ if (isConfigEnv(configDef, configName)) {
490
+ if (import_.filePathAbsoluteFilesystem) {
491
+ (0, utils_js_1.assert)((0, utils_js_1.hasProp)(import_, 'filePathAbsoluteFilesystem', 'string')); // Help TS
492
+ const fileExports = await loadImportedFile(import_, userRootDir, importedFilesLoaded);
493
+ configValueSource.value = fileExports[import_.fileExportName];
494
+ }
495
+ else {
496
+ const configDefinedAt = (0, helpers_js_1.getConfigDefinedAtString)('Config', configName, configValueSource);
497
+ (0, utils_js_1.assertUsage)(!configDef.cumulative, `${configDefinedAt} cannot be defined over an aliased import`);
498
+ }
499
+ }
478
500
  return configValueSource;
479
501
  }
480
502
  else {
@@ -1115,12 +1137,8 @@ function mergeCumulative(configName, configValueSources) {
1115
1137
  let configValueSourcePrevious = null;
1116
1138
  configValueSources.forEach((configValueSource) => {
1117
1139
  const configDefinedAt = (0, helpers_js_1.getConfigDefinedAtString)('Config', configName, configValueSource);
1118
- const configNameColored = picocolors_1.default.cyan(configName);
1119
- // We could, in principle, also support cumulative values to be defined in +${configName}.js but it ins't completely trivial to implement
1120
- (0, utils_js_1.assertUsage)('value' in configValueSource, `${configDefinedAt} is only allowed to be defined in a +config.h.js file. (Because the values of ${configNameColored} are cumulative.)`);
1121
- /* This is more confusing than adding value. For example, this explanation shouldn't be shown for the passToClient config.
1122
- const explanation = `(Because the values of ${configNameColored} are cumulative and therefore merged together.)` as const
1123
- */
1140
+ // We could, in principle, also support cumulative for values that aren't loaded at config-time but it isn't completely trivial to implement.
1141
+ (0, utils_js_1.assert)('value' in configValueSource);
1124
1142
  // Make sure configValueSource.value is serializable
1125
1143
  (0, getVirtualFilePageConfigs_js_1.getConfigValueSerialized)(configValueSource.value, configName, getDefinedAt(configValueSource));
1126
1144
  const assertNoMixing = (isSet) => {
@@ -118,6 +118,7 @@ function getConfigValueSerialized(value, configName, definedAt) {
118
118
  serializationErrMsg = err.messageCore;
119
119
  }
120
120
  else {
121
+ // When a property getter throws an error
121
122
  console.error('Serialization error:');
122
123
  console.error(err);
123
124
  serializationErrMsg = 'see serialization error printed above';
@@ -18,6 +18,7 @@ function previewConfig() {
18
18
  apply: 'serve',
19
19
  config(config) {
20
20
  return {
21
+ appType: 'custom',
21
22
  build: {
22
23
  outDir: (0, utils_js_1.resolveOutDir)(config)
23
24
  }
@@ -28,6 +29,10 @@ function previewConfig() {
28
29
  configVike = await (0, getConfigVike_js_1.getConfigVike)(config);
29
30
  },
30
31
  configurePreviewServer(server) {
32
+ /* - Couldn't make `appType: 'mpa'` work as of npm:@brillout/vite@5.0.0-beta.14.0426910c
33
+ - This ugly hack to set appType for preview won't be need once https://github.com/vitejs/vite/pull/14855 is merged.
34
+ config.appType = 'mpa'
35
+ */
31
36
  (0, utils_js_1.markEnvAsPreview)();
32
37
  return () => {
33
38
  assertDist();
@@ -272,7 +272,7 @@ async function handlePagesWithStaticRoutes(prerenderContext, renderContext, doNo
272
272
  _providedByHook: null,
273
273
  routeParams,
274
274
  _pageId: pageId,
275
- _routeMatches: [
275
+ _debugRouteMatches: [
276
276
  {
277
277
  pageId,
278
278
  routeType: pageRoute.routeType,
@@ -371,7 +371,7 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
371
371
  enumerable: false,
372
372
  configurable: true
373
373
  });
374
- (0, utils_js_1.assert)((0, utils_js_1.hasPropertyGetter)(pageContext, 'url'));
374
+ (0, utils_js_1.assert)((0, utils_js_1.isPropertyGetter)(pageContext, 'url'));
375
375
  (0, utils_js_1.assert)(pageContext.urlOriginal);
376
376
  pageContext._urlOriginalBeforeHook = pageContext.urlOriginal;
377
377
  });
@@ -410,7 +410,7 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
410
410
  prerenderContext.pageContexts = result.prerenderContext.pageContexts;
411
411
  prerenderContext.pageContexts.forEach((pageContext) => {
412
412
  // TODO/v1-release: remove
413
- if (!(0, utils_js_1.hasPropertyGetter)(pageContext, 'url') && pageContext.url) {
413
+ if (pageContext.url && !(0, utils_js_1.isPropertyGetter)(pageContext, 'url')) {
414
414
  (0, utils_js_1.assertWarning)(false, msgPrefix +
415
415
  ' provided pageContext.url but it should provide pageContext.urlOriginal instead, see https://vike.dev/migration/0.4.23', { onlyOnce: true });
416
416
  pageContext.urlOriginal = pageContext.url;
@@ -435,10 +435,9 @@ async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds,
435
435
  await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
436
436
  const { urlOriginal } = pageContext;
437
437
  (0, utils_js_1.assert)(urlOriginal);
438
- const routeResult = await (0, index_js_1.route)(pageContext);
439
- (0, utils_js_1.assert)((0, utils_js_1.hasProp)(routeResult.pageContextAddendum, '_pageId', 'null') ||
440
- (0, utils_js_1.hasProp)(routeResult.pageContextAddendum, '_pageId', 'string'));
441
- if (routeResult.pageContextAddendum._pageId === null) {
438
+ const pageContextFromRoute = await (0, index_js_1.route)(pageContext);
439
+ (0, utils_js_1.assert)((0, utils_js_1.hasProp)(pageContextFromRoute, '_pageId', 'null') || (0, utils_js_1.hasProp)(pageContextFromRoute, '_pageId', 'string'));
440
+ if (pageContextFromRoute._pageId === null) {
442
441
  let hookName;
443
442
  let hookFilePath;
444
443
  if (pageContext._providedByHook) {
@@ -451,17 +450,17 @@ async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds,
451
450
  }
452
451
  if (hookName) {
453
452
  (0, utils_js_1.assert)(hookFilePath);
454
- (0, utils_js_1.assertUsage)(false, `The ${hookName}() hook defined by ${hookFilePath} returns a URL ${picocolors_1.default.cyan(urlOriginal)} that doesn't match any of your page routes. Make sure that the URLs returned by ${hookName}() always match the route of a page.`);
453
+ (0, utils_js_1.assertUsage)(false, `The ${hookName}() hook defined by ${hookFilePath} returns a URL ${picocolors_1.default.cyan(urlOriginal)} that doesn't match the route of any of your pages. Make sure that the URLs returned by ${hookName}() always match the route of a page.`);
455
454
  }
456
455
  else {
457
456
  // `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.
458
- (0, utils_js_1.assert)(routeResult.pageContextAddendum._routingProvidedByOnBeforeRouteHook);
457
+ (0, utils_js_1.assert)(pageContextFromRoute._routingProvidedByOnBeforeRouteHook);
459
458
  // Abort since the URL doesn't correspond to any page
460
459
  return;
461
460
  }
462
461
  }
463
- (0, utils_js_1.assert)(routeResult.pageContextAddendum._pageId);
464
- (0, utils_js_1.objectAssign)(pageContext, routeResult.pageContextAddendum);
462
+ (0, utils_js_1.assert)(pageContextFromRoute._pageId);
463
+ (0, utils_js_1.objectAssign)(pageContext, pageContextFromRoute);
465
464
  const { _pageId: pageId } = pageContext;
466
465
  (0, utils_js_1.objectAssign)(pageContext, await (0, loadPageFilesServerSide_js_1.loadPageFilesServerSide)(pageContext));
467
466
  let usesClientRouter;
@@ -23,7 +23,7 @@ __exportStar(require("../../utils/objectAssign.js"), exports);
23
23
  __exportStar(require("../../utils/isObjectWithKeys.js"), exports);
24
24
  __exportStar(require("../../utils/isCallable.js"), exports);
25
25
  __exportStar(require("../../utils/getOutDirs.js"), exports);
26
- __exportStar(require("../../utils/hasPropertyGetter.js"), exports);
26
+ __exportStar(require("../../utils/isPropertyGetter.js"), exports);
27
27
  __exportStar(require("../../utils/filesystemPathHandling.js"), exports);
28
28
  __exportStar(require("../../utils/urlToFile.js"), exports);
29
29
  __exportStar(require("../../shared/hooks/executeHook.js"), exports);
@@ -58,6 +58,7 @@ function serializePageContextClientSide(pageContext) {
58
58
  msg = `${msg} Serialization error: ${err.messageCore}.`;
59
59
  }
60
60
  else {
61
+ // When a property getter throws an error
61
62
  console.warn('Serialization error:');
62
63
  console.warn(err);
63
64
  msg = `${msg} The serialization failed because of the error printed above.`;
@@ -11,7 +11,7 @@ function debugPageFiles({ pageContext, isHtmlOnly, isClientRouting, pageFilesLoa
11
11
  const padding = ' - ';
12
12
  debug('All page files:', printPageFiles(pageContext._pageFilesAll, true)); // TODO
13
13
  debug(`URL:`, pageContext.urlOriginal);
14
- debug.options({ serialization: { emptyArray: 'No match' } })(`Routing:`, printRouteMatches(pageContext._routeMatches));
14
+ debug.options({ serialization: { emptyArray: 'No match' } })(`Routing:`, printRouteMatches(pageContext._debugRouteMatches));
15
15
  debug(`pageId:`, pageContext._pageId);
16
16
  debug('Page type:', isHtmlOnly ? 'HTML-only' : 'SSR/SPA');
17
17
  debug(`Routing type:`, !isHtmlOnly && isClientRouting ? 'Client Routing' : 'Server Routing');
@@ -21,14 +21,14 @@ function debugPageFiles({ pageContext, isHtmlOnly, isClientRouting, pageFilesLoa
21
21
  debug('Client-side entries:', clientEntries);
22
22
  debug('Client-side dependencies:', clientDependencies);
23
23
  return;
24
- function printRouteMatches(routeMatches) {
25
- if (routeMatches === 'ROUTE_ERROR') {
24
+ function printRouteMatches(debugRouteMatches) {
25
+ if (debugRouteMatches === 'ROUTING_ERROR') {
26
26
  return 'Routing Failed';
27
27
  }
28
- if (routeMatches === 'CUSTOM_ROUTE') {
28
+ if (debugRouteMatches === 'CUSTOM_ROUTING') {
29
29
  return 'Custom Routing';
30
30
  }
31
- return routeMatches;
31
+ return debugRouteMatches;
32
32
  }
33
33
  function printPageFiles(pageFiles, genericPageFilesLast = false) {
34
34
  if (pageFiles.length === 0) {
@@ -105,7 +105,7 @@ async function prerender404Page(renderContext, pageContextInit_) {
105
105
  routeParams: {},
106
106
  // `prerender404Page()` is about generating `dist/client/404.html` for static hosts; there is no Client Routing.
107
107
  _usesClientRouter: false,
108
- _routeMatches: []
108
+ _debugRouteMatches: []
109
109
  };
110
110
  const pageContextInit = {
111
111
  urlOriginal: '/fake-404-url',
@@ -246,8 +246,8 @@ async function renderPageNominal(pageContext) {
246
246
  }
247
247
  // Route
248
248
  {
249
- const routeResult = await (0, index_js_1.route)(pageContext);
250
- (0, utils_js_1.objectAssign)(pageContext, routeResult.pageContextAddendum);
249
+ const pageContextFromRoute = await (0, index_js_1.route)(pageContext);
250
+ (0, utils_js_1.objectAssign)(pageContext, pageContextFromRoute);
251
251
  (0, utils_js_1.objectAssign)(pageContext, { is404: pageContext._pageId ? null : true });
252
252
  if (pageContext._pageId === null) {
253
253
  const errorPageId = (0, error_page_js_1.getErrorPageId)(pageContext._pageFilesAll, pageContext._pageConfigs);
@@ -274,7 +274,7 @@ async function getPageContextErrorPageInit(pageContextInit, errNominalPage, page
274
274
  routeParams: {}
275
275
  };
276
276
  (0, utils_js_1.objectAssign)(pageContext, {
277
- _routeMatches: pageContextNominalPagePartial._routeMatches || 'ROUTE_ERROR'
277
+ _debugRouteMatches: pageContextNominalPagePartial._debugRouteMatches || 'ROUTING_ERROR'
278
278
  });
279
279
  (0, utils_js_1.assert)(pageContext.errorWhileRendering);
280
280
  return pageContext;
@@ -44,7 +44,7 @@ __exportStar(require("../../utils/capitalizeFirstLetter.js"), exports);
44
44
  __exportStar(require("../../utils/debugGlob.js"), exports);
45
45
  __exportStar(require("../../utils/isEquivalentError.js"), exports);
46
46
  __exportStar(require("../../utils/styleFileRE.js"), exports);
47
- __exportStar(require("../../utils/hasPropertyGetter.js"), exports);
47
+ __exportStar(require("../../utils/isPropertyGetter.js"), exports);
48
48
  __exportStar(require("../../utils/debug.js"), exports);
49
49
  __exportStar(require("../../utils/urlToFile.js"), exports);
50
50
  __exportStar(require("../../utils/getGlobalObject.js"), exports);
@@ -6,24 +6,36 @@ const utils_js_1 = require("./utils.js");
6
6
  function addUrlComputedProps(pageContext, enumerable = true) {
7
7
  (0, utils_js_1.assert)(pageContext.urlOriginal);
8
8
  if ('urlPathname' in pageContext) {
9
- (0, utils_js_1.assert)((0, utils_js_1.hasPropertyGetter)(pageContext, 'urlPathname'));
9
+ (0, utils_js_1.assert)(typeof pageContext.urlPathname === 'string');
10
+ /* If this assert() fails then it's most likely because Object.assign() was used instead of objectAssign(), i.e.:
11
+ ```js
12
+ // Add property getters such as pageContext.urlPathname to pageContext
13
+ addUrlComputedProps(pageContext)
14
+ // ❌ Breaks the property getters of pageContext set by addUrlComputedProps() such as pageContext.urlPathname
15
+ Object.assign(pageContext2, pageContext)
16
+ // ❌ Also breaks the property getters
17
+ const pageContext3 = { ...pageContext }
18
+ // ✅ Preserves property getters of pageContext (see objectAssign() implementation)
19
+ objectAssign(pageContext2, pageContext)
20
+ ```
21
+ */
22
+ (0, utils_js_1.assert)((0, utils_js_1.isPropertyGetter)(pageContext, 'urlPathname'));
10
23
  }
24
+ if ('urlParsed' in pageContext)
25
+ (0, utils_js_1.assert)((0, utils_js_1.isPropertyGetter)(pageContext, 'urlParsed'));
26
+ // TODO/v1-release: move pageContext.urlParsed to pageContext.url
27
+ if ('url' in pageContext)
28
+ (0, utils_js_1.assert)((0, utils_js_1.isPropertyGetter)(pageContext, 'url'));
11
29
  Object.defineProperty(pageContext, 'urlPathname', {
12
30
  get: urlPathnameGetter,
13
31
  enumerable,
14
32
  configurable: true
15
33
  });
16
- // TODO/v1-release: move pageContext.urlParsed to pageContext.url
17
- if ('url' in pageContext)
18
- (0, utils_js_1.assert)((0, utils_js_1.hasPropertyGetter)(pageContext, 'url'));
19
34
  Object.defineProperty(pageContext, 'url', {
20
35
  get: urlGetter,
21
36
  enumerable: false,
22
37
  configurable: true
23
38
  });
24
- if ('urlParsed' in pageContext) {
25
- (0, utils_js_1.assert)((0, utils_js_1.hasPropertyGetter)(pageContext, 'urlParsed'));
26
- }
27
39
  Object.defineProperty(pageContext, 'urlParsed', {
28
40
  get: urlParsedGetter,
29
41
  enumerable,
@@ -32,17 +44,17 @@ function addUrlComputedProps(pageContext, enumerable = true) {
32
44
  }
33
45
  exports.addUrlComputedProps = addUrlComputedProps;
34
46
  function getUrlParsed(pageContext) {
35
- // We use a url handler function because the onBeforeRoute() hook may modify pageContext.urlOriginal (e.g. for i18n)
47
+ // We need a url handler function because the onBeforeRoute() hook may set pageContext.urlLogical (typically for i18n)
36
48
  let urlHandler = pageContext._urlHandler;
37
49
  if (!urlHandler) {
38
50
  urlHandler = (url) => url;
39
51
  }
40
- const url = pageContext._urlRewrite ?? pageContext.urlOriginal;
41
- (0, utils_js_1.assert)(url && typeof url === 'string');
42
- const urlLogical = urlHandler(url);
52
+ let urlResolved = pageContext._urlRewrite ?? pageContext.urlLogical ?? pageContext.urlOriginal;
53
+ urlResolved = urlHandler(urlResolved);
43
54
  const baseServer = pageContext._baseServer;
55
+ (0, utils_js_1.assert)(urlResolved && typeof urlResolved === 'string');
44
56
  (0, utils_js_1.assert)(baseServer.startsWith('/'));
45
- return (0, utils_js_1.parseUrl)(urlLogical, baseServer);
57
+ return (0, utils_js_1.parseUrl)(urlResolved, baseServer);
46
58
  }
47
59
  function urlPathnameGetter() {
48
60
  const { pathname } = getUrlParsed(this);
@@ -8,9 +8,39 @@ const assertPageContextProvidedByUser_js_1 = require("../assertPageContextProvid
8
8
  const utils_js_1 = require("./utils.js");
9
9
  const resolveRouteFunction_js_1 = require("./resolveRouteFunction.js");
10
10
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
11
- async function executeOnBeforeRouteHook(onBeforeRouteHook, pageContext) {
11
+ async function executeOnBeforeRouteHook(pageContext) {
12
+ const pageContextFromOnBeforeRouteHook = {};
13
+ if (!pageContext._onBeforeRouteHook)
14
+ return null;
15
+ const pageContextFromHook = await executeHook(pageContext._onBeforeRouteHook, pageContext);
16
+ if (pageContextFromHook) {
17
+ (0, utils_js_1.objectAssign)(pageContextFromOnBeforeRouteHook, pageContextFromHook);
18
+ if ((0, utils_js_1.hasProp)(pageContextFromOnBeforeRouteHook, '_pageId', 'string') ||
19
+ (0, utils_js_1.hasProp)(pageContextFromOnBeforeRouteHook, '_pageId', 'null')) {
20
+ // We bypass Vike's routing
21
+ if (!(0, utils_js_1.hasProp)(pageContextFromOnBeforeRouteHook, 'routeParams')) {
22
+ (0, utils_js_1.objectAssign)(pageContextFromOnBeforeRouteHook, { routeParams: {} });
23
+ }
24
+ else {
25
+ (0, utils_js_1.assert)((0, utils_js_1.hasProp)(pageContextFromOnBeforeRouteHook, 'routeParams', 'object'));
26
+ }
27
+ (0, utils_js_1.objectAssign)(pageContextFromOnBeforeRouteHook, {
28
+ _routingProvidedByOnBeforeRouteHook: true,
29
+ _debugRouteMatches: 'CUSTOM_ROUTING'
30
+ });
31
+ return pageContextFromOnBeforeRouteHook;
32
+ }
33
+ }
34
+ (0, utils_js_1.objectAssign)(pageContextFromOnBeforeRouteHook, {
35
+ _routingProvidedByOnBeforeRouteHook: false
36
+ });
37
+ return pageContextFromOnBeforeRouteHook;
38
+ }
39
+ exports.executeOnBeforeRouteHook = executeOnBeforeRouteHook;
40
+ async function executeHook(onBeforeRouteHook, pageContext) {
12
41
  let hookReturn = onBeforeRouteHook.onBeforeRoute(pageContext);
13
42
  (0, resolveRouteFunction_js_1.assertSyncRouting)(hookReturn, `The onBeforeRoute() hook ${onBeforeRouteHook.hookFilePath}`);
43
+ // TODO/v1-release: make executeOnBeforeRouteHook() and route() sync
14
44
  hookReturn = await hookReturn;
15
45
  const errPrefix = `The onBeforeRoute() hook defined by ${onBeforeRouteHook.hookFilePath}`;
16
46
  (0, utils_js_1.assertUsage)(hookReturn === null ||
@@ -28,29 +58,25 @@ async function executeOnBeforeRouteHook(onBeforeRouteHook, pageContext) {
28
58
  if ((0, utils_js_1.hasProp)(hookReturn.pageContext, 'routeParams')) {
29
59
  (0, resolveRouteFunction_js_1.assertRouteParams)(hookReturn.pageContext, `${errPrefix} returned ${picocolors_1.default.cyan('{ pageContext: { routeParams } }')} but routeParams should`);
30
60
  }
31
- const pageContextAddendumHook = {};
61
+ const deprecatedReturn = (prop) => `${errPrefix} returned ${picocolors_1.default.cyan(`{ pageContext: { ${prop} } }`)} which is deprecated. Return ${picocolors_1.default.cyan('{ pageContext: { urlLogical } }')} instead.`;
32
62
  if ((0, utils_js_1.hasProp)(hookReturn.pageContext, 'url')) {
33
- (0, utils_js_1.assertWarning)(false, `${errPrefix} returned ${picocolors_1.default.cyan('{ pageContext: { url } }')} but ${picocolors_1.default.cyan('pageContext.url')} has been renamed to ${picocolors_1.default.cyan('pageContext.urlOriginal')}. Return ${picocolors_1.default.cyan('{ pageContext: { urlOriginal } }')} instead. (See https://vike.dev/migration/0.4.23 for more information.)`, { onlyOnce: true });
34
- hookReturn.pageContext.urlOriginal = hookReturn.pageContext.url;
63
+ (0, utils_js_1.assertWarning)(false, deprecatedReturn('url'), { onlyOnce: true });
64
+ hookReturn.pageContext.urlLogical = hookReturn.pageContext.url;
35
65
  delete hookReturn.pageContext.url;
36
66
  }
37
67
  if ((0, utils_js_1.hasProp)(hookReturn.pageContext, 'urlOriginal')) {
38
- (0, utils_js_1.assertUsageUrl)(hookReturn.pageContext.urlOriginal, `${errPrefix} returned ${picocolors_1.default.cyan('{ pageContext: { urlOriginal } }')} but ${picocolors_1.default.cyan('urlOriginal')}`);
39
- // Ugly workaround: ideally urlOriginal should be immutable.
40
- // - Instead of using pageContext._urlOriginalPristine, maybe we can keep pageContext.urlOriginal immutable while re-using `pageContext._urlRewrite`.
41
- // - 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`.
42
- // - pageContext.urlReal / pageContext.urlLogical
43
- // VS
44
- // pageContext.urlReal / pageContext.urlModified
45
- // VS
46
- // pageContext.urlOriginal / pageContext.urlModified
47
- (0, utils_js_1.objectAssign)(pageContextAddendumHook, { _urlOriginalPristine: pageContext.urlOriginal });
68
+ (0, utils_js_1.assertWarning)(false, deprecatedReturn('urlOriginal'), { onlyOnce: true });
69
+ hookReturn.pageContext.urlLogical = hookReturn.pageContext.urlOriginal;
70
+ delete hookReturn.pageContext.urlOriginal;
71
+ }
72
+ if ((0, utils_js_1.hasProp)(hookReturn.pageContext, 'urlLogical')) {
73
+ (0, utils_js_1.assertUsageUrl)(hookReturn.pageContext.urlLogical, `${errPrefix} returned ${picocolors_1.default.cyan('{ pageContext: { urlLogical } }')} but ${picocolors_1.default.cyan('urlLogical')}`);
48
74
  }
49
75
  (0, assertPageContextProvidedByUser_js_1.assertPageContextProvidedByUser)(hookReturn.pageContext, {
50
76
  hookFilePath: onBeforeRouteHook.hookFilePath,
51
77
  hookName: 'onBeforeRoute'
52
78
  });
79
+ const pageContextAddendumHook = {};
53
80
  (0, utils_js_1.objectAssign)(pageContextAddendumHook, hookReturn.pageContext);
54
81
  return pageContextAddendumHook;
55
82
  }
56
- exports.executeOnBeforeRouteHook = executeOnBeforeRouteHook;