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.
- package/dist/cjs/__internal/index.js +6 -2
- package/dist/cjs/node/plugin/plugins/commonConfig.js +0 -3
- package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +58 -40
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +1 -0
- package/dist/cjs/node/plugin/plugins/previewConfig.js +5 -0
- package/dist/cjs/node/prerender/runPrerender.js +10 -11
- package/dist/cjs/node/prerender/utils.js +1 -1
- package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +1 -0
- package/dist/cjs/node/runtime/renderPage/debugPageFiles.js +5 -5
- package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -1
- package/dist/cjs/node/runtime/renderPage.js +3 -3
- package/dist/cjs/node/runtime/utils.js +1 -1
- package/dist/cjs/shared/addUrlComputedProps.js +24 -12
- package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +41 -15
- package/dist/cjs/shared/route/index.js +22 -32
- package/dist/cjs/shared/route/resolveRouteFunction.js +1 -1
- package/dist/cjs/shared/utils.js +1 -1
- package/dist/cjs/utils/{hasPropertyGetter.js → isPropertyGetter.js} +3 -3
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/esm/__internal/index.d.ts +6 -3
- package/dist/esm/__internal/index.js +8 -3
- package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -3
- package/dist/esm/client/client-routing-runtime/createPageContext.js +3 -3
- package/dist/esm/client/client-routing-runtime/entry.js +2 -2
- package/dist/esm/client/client-routing-runtime/getPageContext.d.ts +0 -1
- package/dist/esm/client/client-routing-runtime/getPageContext.js +6 -9
- package/dist/esm/client/client-routing-runtime/history.d.ts +3 -1
- package/dist/esm/client/client-routing-runtime/history.js +26 -8
- package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +21 -0
- package/dist/esm/client/client-routing-runtime/{useClientRouter.js → installClientRouter.js} +248 -242
- package/dist/esm/client/client-routing-runtime/isClientSideRoutable.d.ts +8 -0
- package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +15 -0
- package/dist/esm/client/client-routing-runtime/navigate.d.ts +0 -2
- package/dist/esm/client/client-routing-runtime/navigate.js +10 -8
- package/dist/esm/client/client-routing-runtime/prefetch.js +54 -28
- package/dist/esm/client/client-routing-runtime/skipLink.d.ts +0 -1
- package/dist/esm/client/client-routing-runtime/skipLink.js +1 -2
- package/dist/esm/client/server-routing-runtime/getPageContext.js +1 -1
- package/dist/esm/client/shared/executeOnRenderClientHook.js +6 -5
- package/dist/esm/client/shared/getPageContextProxyForUser.js +13 -7
- package/dist/esm/client/shared/loadPageFilesClientSide.d.ts +8 -3
- package/dist/esm/client/shared/loadPageFilesClientSide.js +5 -5
- package/dist/esm/node/plugin/plugins/commonConfig.js +0 -3
- package/dist/esm/node/plugin/plugins/devConfig/index.js +1 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +58 -40
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +1 -0
- package/dist/esm/node/plugin/plugins/previewConfig.js +5 -0
- package/dist/esm/node/prerender/runPrerender.js +11 -12
- package/dist/esm/node/prerender/utils.d.ts +1 -1
- package/dist/esm/node/prerender/utils.js +1 -1
- package/dist/esm/node/runtime/html/serializePageContextClientSide.js +1 -0
- package/dist/esm/node/runtime/renderPage/debugPageFiles.d.ts +5 -5
- package/dist/esm/node/runtime/renderPage/debugPageFiles.js +5 -5
- package/dist/esm/node/runtime/renderPage/loadPageFilesServerSide.d.ts +2 -2
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -1
- package/dist/esm/node/runtime/renderPage.js +3 -3
- package/dist/esm/node/runtime/utils.d.ts +1 -1
- package/dist/esm/node/runtime/utils.js +1 -1
- package/dist/esm/shared/addUrlComputedProps.d.ts +1 -0
- package/dist/esm/shared/addUrlComputedProps.js +25 -13
- package/dist/esm/shared/route/executeOnBeforeRouteHook.d.ts +5 -8
- package/dist/esm/shared/route/executeOnBeforeRouteHook.js +41 -15
- package/dist/esm/shared/route/index.d.ts +12 -10
- package/dist/esm/shared/route/index.js +23 -33
- package/dist/esm/shared/route/resolveRouteFunction.js +1 -1
- package/dist/esm/shared/utils.d.ts +1 -1
- package/dist/esm/shared/utils.js +1 -1
- package/dist/esm/utils/isPropertyGetter.d.ts +1 -0
- package/dist/esm/utils/{hasPropertyGetter.js → isPropertyGetter.js} +1 -1
- package/dist/esm/utils/projectInfo.d.ts +1 -1
- package/dist/esm/utils/projectInfo.js +1 -1
- package/package.json +1 -1
- package/dist/esm/client/client-routing-runtime/getPageId.d.ts +0 -10
- package/dist/esm/client/client-routing-runtime/getPageId.js +0 -17
- package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.d.ts +0 -2
- package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.js +0 -15
- package/dist/esm/client/client-routing-runtime/useClientRouter.d.ts +0 -6
- 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;
|
|
@@ -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
|
-
// -
|
|
115
|
-
// -
|
|
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
|
|
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
|
|
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
|
|
238
|
+
if (!isConfigEnv(configDef, configName))
|
|
222
239
|
return;
|
|
223
240
|
const isAlreadyLoaded = interfacefileIsAlreaydLoaded(interfaceFile);
|
|
224
241
|
if (isAlreadyLoaded)
|
|
225
242
|
return;
|
|
226
|
-
// Value files
|
|
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
|
-
.
|
|
234
|
-
const sources = resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir);
|
|
235
|
-
if (
|
|
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).
|
|
325
|
-
const sources = resolveConfigValueSources(configName, configDef, interfaceFilesGlobal, userRootDir);
|
|
326
|
-
const configValueSource = sources
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
432
|
+
function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName) {
|
|
418
433
|
interfaceFilesOverriden.forEach((interfaceFileLoser) => {
|
|
419
|
-
const
|
|
420
|
-
const
|
|
421
|
-
|
|
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
|
-
|
|
1119
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
439
|
-
(0, utils_js_1.assert)((0, utils_js_1.hasProp)(
|
|
440
|
-
|
|
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
|
|
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)(
|
|
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)(
|
|
464
|
-
(0, utils_js_1.objectAssign)(pageContext,
|
|
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/
|
|
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.
|
|
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(
|
|
25
|
-
if (
|
|
24
|
+
function printRouteMatches(debugRouteMatches) {
|
|
25
|
+
if (debugRouteMatches === 'ROUTING_ERROR') {
|
|
26
26
|
return 'Routing Failed';
|
|
27
27
|
}
|
|
28
|
-
if (
|
|
28
|
+
if (debugRouteMatches === 'CUSTOM_ROUTING') {
|
|
29
29
|
return 'Custom Routing';
|
|
30
30
|
}
|
|
31
|
-
return
|
|
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
|
-
|
|
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
|
|
250
|
-
(0, utils_js_1.objectAssign)(pageContext,
|
|
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
|
-
|
|
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/
|
|
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)(
|
|
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
|
|
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
|
-
|
|
41
|
-
|
|
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)(
|
|
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(
|
|
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
|
|
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,
|
|
34
|
-
hookReturn.pageContext.
|
|
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.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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;
|