vike 0.4.144-commit-7f5e99a → 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/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +58 -40
- package/dist/cjs/node/prerender/runPrerender.js +2 -2
- 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 +1 -1
- package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +30 -2
- package/dist/cjs/shared/route/index.js +22 -32
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/esm/client/client-routing-runtime/getPageContext.js +3 -3
- package/dist/esm/client/client-routing-runtime/prefetch.js +43 -24
- package/dist/esm/client/server-routing-runtime/getPageContext.js +1 -1
- 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/importUserCode/v1-design/getVikeConfig.js +58 -40
- package/dist/esm/node/prerender/runPrerender.js +2 -2
- 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 +1 -1
- package/dist/esm/shared/route/executeOnBeforeRouteHook.d.ts +5 -8
- package/dist/esm/shared/route/executeOnBeforeRouteHook.js +30 -2
- package/dist/esm/shared/route/index.d.ts +4 -4
- package/dist/esm/shared/route/index.js +23 -33
- 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 -14
|
@@ -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) => {
|
|
@@ -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,
|
|
@@ -450,7 +450,7 @@ async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds,
|
|
|
450
450
|
}
|
|
451
451
|
if (hookName) {
|
|
452
452
|
(0, utils_js_1.assert)(hookFilePath);
|
|
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 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.`);
|
|
454
454
|
}
|
|
455
455
|
else {
|
|
456
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.
|
|
@@ -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',
|
|
@@ -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;
|
|
@@ -8,7 +8,36 @@ 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}`);
|
|
14
43
|
// TODO/v1-release: make executeOnBeforeRouteHook() and route() sync
|
|
@@ -51,4 +80,3 @@ async function executeOnBeforeRouteHook(onBeforeRouteHook, pageContext) {
|
|
|
51
80
|
(0, utils_js_1.objectAssign)(pageContextAddendumHook, hookReturn.pageContext);
|
|
52
81
|
return pageContextAddendumHook;
|
|
53
82
|
}
|
|
54
|
-
exports.executeOnBeforeRouteHook = executeOnBeforeRouteHook;
|
|
@@ -18,35 +18,25 @@ const resolveRouteFunction_js_1 = require("./resolveRouteFunction.js");
|
|
|
18
18
|
const executeOnBeforeRouteHook_js_1 = require("./executeOnBeforeRouteHook.js");
|
|
19
19
|
const debug_js_1 = require("./debug.js");
|
|
20
20
|
const picocolors_1 = __importDefault(require("@brillout/picocolors"));
|
|
21
|
-
async function route(
|
|
22
|
-
(0,
|
|
23
|
-
(0,
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
else {
|
|
35
|
-
(0, utils_js_1.assert)((0, utils_js_1.hasProp)(pageContextAddendum, 'routeParams', 'object'));
|
|
36
|
-
}
|
|
37
|
-
(0, utils_js_1.objectAssign)(pageContextAddendum, {
|
|
38
|
-
_routingProvidedByOnBeforeRouteHook: true,
|
|
39
|
-
_routeMatches: 'CUSTOM_ROUTE'
|
|
40
|
-
});
|
|
41
|
-
return pageContextAddendum;
|
|
42
|
-
}
|
|
43
|
-
// We already assign so that `pageContext.urlOriginal === pageContextAddendum.urlOriginal`; enabling the `onBeforeRoute()` hook to mutate `pageContext.urlOriginal` before routing.
|
|
44
|
-
(0, utils_js_1.objectAssign)(pageContext, pageContextAddendum);
|
|
21
|
+
async function route(pageContextForRoute) {
|
|
22
|
+
(0, debug_js_1.debug)('Pages routes:', pageContextForRoute._pageRoutes);
|
|
23
|
+
(0, addUrlComputedProps_js_1.addUrlComputedProps)(pageContextForRoute);
|
|
24
|
+
const pageContextFromRoute = {};
|
|
25
|
+
// onBeforeRoute()
|
|
26
|
+
const pageContextFromOnBeforeRouteHook = await (0, executeOnBeforeRouteHook_js_1.executeOnBeforeRouteHook)(pageContextForRoute);
|
|
27
|
+
if (pageContextFromOnBeforeRouteHook) {
|
|
28
|
+
if (pageContextFromOnBeforeRouteHook._routingProvidedByOnBeforeRouteHook) {
|
|
29
|
+
(0, utils_js_1.assert)(pageContextFromOnBeforeRouteHook._pageId);
|
|
30
|
+
return pageContextFromOnBeforeRouteHook;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
(0, utils_js_1.objectAssign)(pageContextFromRoute, pageContextFromOnBeforeRouteHook);
|
|
45
34
|
}
|
|
46
35
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
// We take into account pageContext.urlLogical set by onBeforeRoute()
|
|
37
|
+
const pageContext = {};
|
|
38
|
+
(0, utils_js_1.objectAssign)(pageContext, pageContextForRoute);
|
|
39
|
+
(0, utils_js_1.objectAssign)(pageContext, pageContextFromOnBeforeRouteHook);
|
|
50
40
|
// Vike's routing
|
|
51
41
|
const allPageIds = pageContext._allPageIds;
|
|
52
42
|
(0, utils_js_1.assert)(allPageIds.length >= 0);
|
|
@@ -98,22 +88,22 @@ async function route(pageContext) {
|
|
|
98
88
|
(0, resolvePrecedence_js_1.resolvePrecendence)(routeMatches);
|
|
99
89
|
const winner = routeMatches[0];
|
|
100
90
|
(0, debug_js_1.debug)(`Route matches for URL ${picocolors_1.default.cyan(urlPathname)} (in precedence order):`, routeMatches);
|
|
101
|
-
(0, utils_js_1.objectAssign)(
|
|
91
|
+
(0, utils_js_1.objectAssign)(pageContextFromRoute, { _debugRouteMatches: routeMatches });
|
|
102
92
|
if (!winner) {
|
|
103
|
-
(0, utils_js_1.objectAssign)(
|
|
93
|
+
(0, utils_js_1.objectAssign)(pageContextFromRoute, {
|
|
104
94
|
_pageId: null,
|
|
105
95
|
routeParams: {}
|
|
106
96
|
});
|
|
107
|
-
return
|
|
97
|
+
return pageContextFromRoute;
|
|
108
98
|
}
|
|
109
99
|
{
|
|
110
100
|
const { routeParams } = winner;
|
|
111
101
|
(0, utils_js_1.assert)((0, utils_js_1.isPlainObject)(routeParams));
|
|
112
|
-
(0, utils_js_1.objectAssign)(
|
|
102
|
+
(0, utils_js_1.objectAssign)(pageContextFromRoute, {
|
|
113
103
|
_pageId: winner.pageId,
|
|
114
104
|
routeParams: winner.routeParams
|
|
115
105
|
});
|
|
116
106
|
}
|
|
117
|
-
return
|
|
107
|
+
return pageContextFromRoute;
|
|
118
108
|
}
|
|
119
109
|
exports.route = route;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.projectInfo = void 0;
|
|
4
4
|
const assertSingleInstance_js_1 = require("./assertSingleInstance.js");
|
|
5
|
-
const PROJECT_VERSION = '0.4.144-commit-
|
|
5
|
+
const PROJECT_VERSION = '0.4.144-commit-de18325';
|
|
6
6
|
const projectInfo = {
|
|
7
7
|
projectName: 'Vike',
|
|
8
8
|
projectVersion: PROJECT_VERSION,
|
|
@@ -38,7 +38,7 @@ async function getPageContextFirstRender(pageContext) {
|
|
|
38
38
|
isHydration: true,
|
|
39
39
|
_hasPageContextFromClient: false
|
|
40
40
|
});
|
|
41
|
-
objectAssign(pageContextAddendum, await loadPageFilesClientSide(
|
|
41
|
+
objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageContextAddendum._pageId, pageContext));
|
|
42
42
|
{
|
|
43
43
|
const pageContextForHook = { ...pageContext, ...pageContextAddendum };
|
|
44
44
|
if (await onBeforeRenderClientOnlyExists(pageContextForHook)) {
|
|
@@ -69,7 +69,7 @@ async function getPageContextUponNavigation(pageContext) {
|
|
|
69
69
|
}
|
|
70
70
|
async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
|
|
71
71
|
let pageContextAddendum = {};
|
|
72
|
-
objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageContext.
|
|
72
|
+
objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageContext._pageId, pageContext));
|
|
73
73
|
// Needs to be called before any client-side hook, because it may contain pageContextInit.user which is needed for guard() and onBeforeRender()
|
|
74
74
|
if (
|
|
75
75
|
// For the error page, we cannot fetch pageContext from the server because the pageContext JSON request is based on the URL
|
|
@@ -87,7 +87,7 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
|
|
|
87
87
|
isHydration: false,
|
|
88
88
|
_pageId: errorPageId
|
|
89
89
|
});
|
|
90
|
-
objectAssign(pageContextAddendum, await loadPageFilesClientSide(
|
|
90
|
+
objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageContextAddendum._pageId, pageContext));
|
|
91
91
|
assert(hasProp(pageContextFromServer, 'is404', 'boolean'));
|
|
92
92
|
assert(hasProp(pageContextFromServer, 'pageProps', 'object'));
|
|
93
93
|
assert(hasProp(pageContextFromServer.pageProps, 'is404', 'boolean'));
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
export { prefetch };
|
|
2
2
|
export { addLinkPrefetchHandlers };
|
|
3
|
-
import { assert, assertClientRouting, assertUsage, checkIfClientRouting, objectAssign } from './utils.js';
|
|
3
|
+
import { assert, assertClientRouting, assertUsage, assertWarning, checkIfClientRouting, getGlobalObject, objectAssign } from './utils.js';
|
|
4
4
|
import { isErrorFetchingStaticAssets, loadPageFilesClientSide } from '../shared/loadPageFilesClientSide.js';
|
|
5
5
|
import { skipLink } from './skipLink.js';
|
|
6
|
-
import { getPageId } from './getPageId.js';
|
|
7
6
|
import { getPrefetchSettings } from './prefetch/getPrefetchSettings.js';
|
|
8
7
|
import { isAlreadyPrefetched, markAsAlreadyPrefetched } from './prefetch/alreadyPrefetched.js';
|
|
9
8
|
import { disableClientRouting } from './installClientRouter.js';
|
|
@@ -12,7 +11,20 @@ import { isClientSideRoutable } from './isClientSideRoutable.js';
|
|
|
12
11
|
import { createPageContext } from './createPageContext.js';
|
|
13
12
|
import { route } from '../../shared/route/index.js';
|
|
14
13
|
assertClientRouting();
|
|
15
|
-
const
|
|
14
|
+
const globalObject = getGlobalObject('prefetch.ts', { linkPrefetchHandlerAdded: new Map() });
|
|
15
|
+
async function prefetchAssets(pageId, pageContext) {
|
|
16
|
+
try {
|
|
17
|
+
await loadPageFilesClientSide(pageId, pageContext);
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
if (isErrorFetchingStaticAssets(err)) {
|
|
21
|
+
disableClientRouting(err, true);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
throw err;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
16
28
|
/**
|
|
17
29
|
* Programmatically prefetch client assets.
|
|
18
30
|
*
|
|
@@ -24,33 +36,38 @@ async function prefetch(url) {
|
|
|
24
36
|
assertUsage(checkIfClientRouting(), 'prefetch() only works with Client Routing, see https://vike.dev/prefetch', {
|
|
25
37
|
showStackTrace: true
|
|
26
38
|
});
|
|
27
|
-
|
|
39
|
+
const errPrefix = `Cannot prefetch URL ${url} because it`;
|
|
40
|
+
assertUsage(!isExternalLink(url), `${errPrefix} lives on another domain`, { showStackTrace: true });
|
|
28
41
|
if (isAlreadyPrefetched(url))
|
|
29
42
|
return;
|
|
30
43
|
markAsAlreadyPrefetched(url);
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
catch (err) {
|
|
37
|
-
if (isErrorFetchingStaticAssets(err)) {
|
|
38
|
-
disableClientRouting(err, true);
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
throw err;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
+
const pageContext = await createPageContext(url);
|
|
45
|
+
let pageContextFromRoute;
|
|
46
|
+
try {
|
|
47
|
+
pageContextFromRoute = await route(pageContext);
|
|
44
48
|
}
|
|
49
|
+
catch {
|
|
50
|
+
// If a route() hook has a bug or `throw render()` / `throw redirect()`
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const pageId = pageContextFromRoute._pageId;
|
|
54
|
+
if (!pageId) {
|
|
55
|
+
assertWarning(false, `${errPrefix} doesn't match the route of any of your pages`, {
|
|
56
|
+
showStackTrace: true,
|
|
57
|
+
onlyOnce: false
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
await prefetchAssets(pageId, pageContext);
|
|
45
62
|
}
|
|
46
63
|
function addLinkPrefetchHandlers(pageContext) {
|
|
47
64
|
// Current URL is already prefetched
|
|
48
65
|
markAsAlreadyPrefetched(pageContext.urlPathname);
|
|
49
66
|
const linkTags = [...document.getElementsByTagName('A')];
|
|
50
67
|
linkTags.forEach((linkTag) => {
|
|
51
|
-
if (linkPrefetchHandlerAdded.has(linkTag))
|
|
68
|
+
if (globalObject.linkPrefetchHandlerAdded.has(linkTag))
|
|
52
69
|
return;
|
|
53
|
-
linkPrefetchHandlerAdded.set(linkTag, true);
|
|
70
|
+
globalObject.linkPrefetchHandlerAdded.set(linkTag, true);
|
|
54
71
|
const url = linkTag.getAttribute('href');
|
|
55
72
|
if (skipLink(linkTag))
|
|
56
73
|
return;
|
|
@@ -62,17 +79,17 @@ function addLinkPrefetchHandlers(pageContext) {
|
|
|
62
79
|
return;
|
|
63
80
|
if (prefetchStaticAssets === 'hover') {
|
|
64
81
|
linkTag.addEventListener('mouseover', () => {
|
|
65
|
-
|
|
82
|
+
prefetchIfPossible(url);
|
|
66
83
|
});
|
|
67
84
|
linkTag.addEventListener('touchstart', () => {
|
|
68
|
-
|
|
85
|
+
prefetchIfPossible(url);
|
|
69
86
|
}, { passive: true });
|
|
70
87
|
}
|
|
71
88
|
if (prefetchStaticAssets === 'viewport') {
|
|
72
89
|
const observer = new IntersectionObserver((entries) => {
|
|
73
90
|
entries.forEach((entry) => {
|
|
74
91
|
if (entry.isIntersecting) {
|
|
75
|
-
|
|
92
|
+
prefetchIfPossible(url);
|
|
76
93
|
observer.disconnect();
|
|
77
94
|
}
|
|
78
95
|
});
|
|
@@ -81,7 +98,7 @@ function addLinkPrefetchHandlers(pageContext) {
|
|
|
81
98
|
}
|
|
82
99
|
});
|
|
83
100
|
}
|
|
84
|
-
async function
|
|
101
|
+
async function prefetchIfPossible(url) {
|
|
85
102
|
const pageContext = await createPageContext(url);
|
|
86
103
|
let pageContextFromRoute;
|
|
87
104
|
try {
|
|
@@ -92,7 +109,9 @@ async function prefetchIfClientSideRoutable(url) {
|
|
|
92
109
|
return;
|
|
93
110
|
}
|
|
94
111
|
objectAssign(pageContext, pageContextFromRoute);
|
|
112
|
+
if (!pageContext._pageId)
|
|
113
|
+
return;
|
|
95
114
|
if (!(await isClientSideRoutable(pageContext)))
|
|
96
115
|
return;
|
|
97
|
-
await
|
|
116
|
+
await prefetchAssets(pageContext._pageId, pageContext);
|
|
98
117
|
}
|
|
@@ -26,7 +26,7 @@ async function loadPageFiles(pageId) {
|
|
|
26
26
|
_pageFilesAll: pageFilesAll,
|
|
27
27
|
_pageConfigs: pageConfigs
|
|
28
28
|
});
|
|
29
|
-
objectAssign(pageContextAddendum, await loadPageFilesClientSide(
|
|
29
|
+
objectAssign(pageContextAddendum, await loadPageFilesClientSide(pageId, pageContextAddendum));
|
|
30
30
|
pageFilesAll
|
|
31
31
|
.filter((p) => p.fileType !== '.page.server')
|
|
32
32
|
.forEach((p) => {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { type PageFile, type PageContextExports } from '../../shared/getPageFiles.js';
|
|
2
|
-
import type { PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
|
|
3
1
|
export { loadPageFilesClientSide };
|
|
4
2
|
export { isErrorFetchingStaticAssets };
|
|
5
|
-
|
|
3
|
+
export type { PageContextPageFiles };
|
|
4
|
+
import { type PageFile, type PageContextExports } from '../../shared/getPageFiles.js';
|
|
5
|
+
import type { PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
|
|
6
|
+
type PageContextPageFiles = {
|
|
7
|
+
_pageFilesAll: PageFile[];
|
|
8
|
+
_pageConfigs: PageConfigRuntime[];
|
|
9
|
+
};
|
|
10
|
+
declare function loadPageFilesClientSide(pageId: string, pageContext: PageContextPageFiles): Promise<PageContextExports & {
|
|
6
11
|
_pageFilesLoaded: PageFile[];
|
|
7
12
|
}>;
|
|
8
13
|
declare function isErrorFetchingStaticAssets(err: unknown): boolean;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
export { loadPageFilesClientSide };
|
|
2
|
+
export { isErrorFetchingStaticAssets };
|
|
1
3
|
import { getPageFilesClientSide, getExports } from '../../shared/getPageFiles.js';
|
|
2
4
|
import { findPageConfig } from '../../shared/page-configs/findPageConfig.js';
|
|
3
5
|
import { loadConfigValues } from '../../shared/page-configs/loadConfigValues.js';
|
|
4
|
-
export { loadPageFilesClientSide };
|
|
5
|
-
export { isErrorFetchingStaticAssets };
|
|
6
6
|
const stamp = '__whileFetchingAssets';
|
|
7
|
-
async function loadPageFilesClientSide(
|
|
8
|
-
const pageFilesClientSide = getPageFilesClientSide(
|
|
9
|
-
const pageConfig = findPageConfig(
|
|
7
|
+
async function loadPageFilesClientSide(pageId, pageContext) {
|
|
8
|
+
const pageFilesClientSide = getPageFilesClientSide(pageContext._pageFilesAll, pageId);
|
|
9
|
+
const pageConfig = findPageConfig(pageContext._pageConfigs, pageId);
|
|
10
10
|
let pageConfigLoaded;
|
|
11
11
|
// @ts-ignore Since dist/cjs/client/ is never used, we can ignore this error.
|
|
12
12
|
const isDev = import.meta.env.DEV;
|
|
@@ -105,11 +105,11 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
105
105
|
configName
|
|
106
106
|
};
|
|
107
107
|
{
|
|
108
|
-
// We don't have access to custom config definitions yet
|
|
109
|
-
// -
|
|
110
|
-
// -
|
|
108
|
+
// We don't have access to the custom config definitions defined by the user yet.
|
|
109
|
+
// - If `configDef` is `undefined` => we load the file +{configName}.js later.
|
|
110
|
+
// - We already need to load +meta.js here (to get the custom config definitions defined by the user)
|
|
111
111
|
const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn, configName);
|
|
112
|
-
if (configDef
|
|
112
|
+
if (configDef && isConfigEnv(configDef, configName)) {
|
|
113
113
|
await loadValueFile(interfaceFile, configName, userRootDir);
|
|
114
114
|
}
|
|
115
115
|
}
|
|
@@ -139,6 +139,22 @@ async function loadValueFile(interfaceValueFile, configName, userRootDir) {
|
|
|
139
139
|
interfaceValueFile.configMap[configName_] = { configValue };
|
|
140
140
|
});
|
|
141
141
|
}
|
|
142
|
+
async function loadImportedFile(filePath, userRootDir, importedFilesLoaded) {
|
|
143
|
+
const f = filePath.filePathAbsoluteFilesystem;
|
|
144
|
+
if (!importedFilesLoaded[f]) {
|
|
145
|
+
importedFilesLoaded[f] = transpileAndExecuteFile(filePath, true, userRootDir).then((r) => r.fileExports);
|
|
146
|
+
}
|
|
147
|
+
const fileExports = await importedFilesLoaded[f];
|
|
148
|
+
return fileExports;
|
|
149
|
+
}
|
|
150
|
+
function isConfigEnv(configDef, configName) {
|
|
151
|
+
if (configDef.cumulative)
|
|
152
|
+
return true;
|
|
153
|
+
if (configDef.env === 'config-only')
|
|
154
|
+
return true;
|
|
155
|
+
// TODO: replace with proper `env: { config: boolean }` implementation
|
|
156
|
+
return configName === 'clientRouting';
|
|
157
|
+
}
|
|
142
158
|
function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
|
|
143
159
|
const { fileExports, filePath, extendsFilePaths } = configFile;
|
|
144
160
|
const interfaceFile = {
|
|
@@ -199,7 +215,8 @@ async function loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, isDev,
|
|
|
199
215
|
}
|
|
200
216
|
async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
|
|
201
217
|
const interfaceFilesByLocationId = await loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions);
|
|
202
|
-
const
|
|
218
|
+
const importedFilesLoaded = {};
|
|
219
|
+
const { globalVikeConfig, pageConfigGlobal } = await getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded);
|
|
203
220
|
const pageConfigs = await Promise.all(Object.entries(interfaceFilesByLocationId)
|
|
204
221
|
.filter(([_pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
|
|
205
222
|
.map(async ([locationId]) => {
|
|
@@ -213,24 +230,24 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
213
230
|
if (isGlobalConfig(configName))
|
|
214
231
|
return;
|
|
215
232
|
const configDef = getConfigDefinition(configDefinitionsRelevant, configName, interfaceFile.filePath.filePathToShowToUser);
|
|
216
|
-
if (configDef
|
|
233
|
+
if (!isConfigEnv(configDef, configName))
|
|
217
234
|
return;
|
|
218
235
|
const isAlreadyLoaded = interfacefileIsAlreaydLoaded(interfaceFile);
|
|
219
236
|
if (isAlreadyLoaded)
|
|
220
237
|
return;
|
|
221
|
-
// Value files
|
|
238
|
+
// Value files of built-in configs should have already been loaded at loadInterfaceFiles()
|
|
222
239
|
assert(!(configName in configDefinitionsBuiltIn));
|
|
223
240
|
await loadValueFile(interfaceFile, configName, userRootDir);
|
|
224
241
|
}));
|
|
225
242
|
const configValueSources = {};
|
|
226
|
-
objectEntries(configDefinitionsRelevant)
|
|
243
|
+
await Promise.all(objectEntries(configDefinitionsRelevant)
|
|
227
244
|
.filter(([configName]) => !isGlobalConfig(configName))
|
|
228
|
-
.
|
|
229
|
-
const sources = resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir);
|
|
230
|
-
if (
|
|
245
|
+
.map(async ([configName, configDef]) => {
|
|
246
|
+
const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded);
|
|
247
|
+
if (sources.length === 0)
|
|
231
248
|
return;
|
|
232
249
|
configValueSources[configName] = sources;
|
|
233
|
-
});
|
|
250
|
+
}));
|
|
234
251
|
const { routeFilesystem, isErrorPage } = determineRouteFilesystem(locationId, configValueSources);
|
|
235
252
|
applyEffectsAll(configValueSources, configDefinitionsRelevant);
|
|
236
253
|
const configValuesComputed = getComputed(configValueSources, configDefinitionsRelevant);
|
|
@@ -280,7 +297,7 @@ function getInterfaceFileList(interfaceFilesByLocationId) {
|
|
|
280
297
|
});
|
|
281
298
|
return interfaceFiles;
|
|
282
299
|
}
|
|
283
|
-
function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
|
|
300
|
+
async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded) {
|
|
284
301
|
const locationIds = Object.keys(interfaceFilesByLocationId);
|
|
285
302
|
const interfaceFilesGlobal = Object.fromEntries(Object.entries(interfaceFilesByLocationId).filter(([locationId]) => {
|
|
286
303
|
return isGlobalLocation(locationId, locationIds);
|
|
@@ -316,9 +333,9 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
|
|
|
316
333
|
const pageConfigGlobal = {
|
|
317
334
|
configValueSources: {}
|
|
318
335
|
};
|
|
319
|
-
objectEntries(configDefinitionsBuiltInGlobal).
|
|
320
|
-
const sources = resolveConfigValueSources(configName, configDef, interfaceFilesGlobal, userRootDir);
|
|
321
|
-
const configValueSource = sources
|
|
336
|
+
await Promise.all(objectEntries(configDefinitionsBuiltInGlobal).map(async ([configName, configDef]) => {
|
|
337
|
+
const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesGlobal, userRootDir, importedFilesLoaded);
|
|
338
|
+
const configValueSource = sources[0];
|
|
322
339
|
if (!configValueSource)
|
|
323
340
|
return;
|
|
324
341
|
if (configName === 'onBeforeRoute' || configName === 'onPrerenderStart') {
|
|
@@ -333,23 +350,21 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
|
|
|
333
350
|
assertWarning(false, `Being able to define config ${pc.cyan(configName)} in ${filePathToShowToUser} is experimental and will likely be removed. Define the config ${pc.cyan(configName)} in Vike's Vite plugin options instead.`, { onlyOnce: true });
|
|
334
351
|
globalVikeConfig[configName] = configValueSource.value;
|
|
335
352
|
}
|
|
336
|
-
});
|
|
353
|
+
}));
|
|
337
354
|
return { pageConfigGlobal, globalVikeConfig };
|
|
338
355
|
}
|
|
339
|
-
function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir) {
|
|
340
|
-
|
|
356
|
+
async function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded) {
|
|
357
|
+
const sourcesInfo = [];
|
|
341
358
|
// interfaceFilesRelevant is sorted by sortAfterInheritanceOrder()
|
|
342
359
|
for (const interfaceFiles of Object.values(interfaceFilesRelevant)) {
|
|
343
360
|
const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.configMap[configName]);
|
|
344
361
|
if (interfaceFilesDefiningConfig.length === 0)
|
|
345
362
|
continue;
|
|
346
|
-
sources = sources ?? [];
|
|
347
363
|
const visited = new WeakSet();
|
|
348
364
|
const add = (interfaceFile) => {
|
|
349
365
|
assert(!visited.has(interfaceFile));
|
|
350
366
|
visited.add(interfaceFile);
|
|
351
|
-
|
|
352
|
-
sources.push(configValueSource);
|
|
367
|
+
sourcesInfo.push([configName, interfaceFile, configDef, userRootDir, importedFilesLoaded]);
|
|
353
368
|
};
|
|
354
369
|
// Main resolution logic
|
|
355
370
|
{
|
|
@@ -373,7 +388,7 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
|
|
|
373
388
|
if (interfaceFileWinner) {
|
|
374
389
|
const interfaceFilesOverriden = [...interfaceValueFiles, ...interfaceConfigFiles].filter((f) => f !== interfaceFileWinner);
|
|
375
390
|
// 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
|
|
376
|
-
warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName
|
|
391
|
+
warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName);
|
|
377
392
|
[interfaceFileWinner, ...interfaceFilesOverriden].forEach((interfaceFile) => {
|
|
378
393
|
add(interfaceFile);
|
|
379
394
|
});
|
|
@@ -398,7 +413,7 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
|
|
|
398
413
|
assert(visited.has(interfaceFile));
|
|
399
414
|
});
|
|
400
415
|
}
|
|
401
|
-
|
|
416
|
+
const sources = await Promise.all(sourcesInfo.map(async (args) => await getConfigValueSource(...args)));
|
|
402
417
|
return sources;
|
|
403
418
|
}
|
|
404
419
|
function makeOrderDeterministic(interfaceFile1, interfaceFile2) {
|
|
@@ -409,22 +424,17 @@ function makeOrderDeterministic(interfaceFile1, interfaceFile2) {
|
|
|
409
424
|
return filePathRelativeToUserRootDir.length;
|
|
410
425
|
})(interfaceFile1, interfaceFile2);
|
|
411
426
|
}
|
|
412
|
-
function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName
|
|
427
|
+
function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName) {
|
|
413
428
|
interfaceFilesOverriden.forEach((interfaceFileLoser) => {
|
|
414
|
-
const
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
const configLoser_DefinedAt = getConfigDefinedAtString('Config', configName, configValueSourceLoser_);
|
|
418
|
-
// prettier-ignore
|
|
419
|
-
const configWinnerDefinedAt = getConfigDefinedAtString('config', configName, configValueSourceWinner);
|
|
420
|
-
const errMsg = `${configLoser_DefinedAt} is overriden by another ${configWinnerDefinedAt}, remove one of the two`;
|
|
421
|
-
assertWarning(false, errMsg, { onlyOnce: false });
|
|
429
|
+
const loserFilePath = interfaceFileLoser.filePath.filePathToShowToUser;
|
|
430
|
+
const winnerFilePath = interfaceFileWinner.filePath.filePathToShowToUser;
|
|
431
|
+
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 });
|
|
422
432
|
});
|
|
423
433
|
}
|
|
424
434
|
function isInterfaceFileUserLand(interfaceFile) {
|
|
425
435
|
return (interfaceFile.isConfigFile && !interfaceFile.isConfigExtend) || interfaceFile.isValueFile;
|
|
426
436
|
}
|
|
427
|
-
function getConfigValueSource(configName, interfaceFile, configDef, userRootDir) {
|
|
437
|
+
async function getConfigValueSource(configName, interfaceFile, configDef, userRootDir, importedFilesLoaded) {
|
|
428
438
|
const conf = interfaceFile.configMap[configName];
|
|
429
439
|
assert(conf);
|
|
430
440
|
const configEnv = configDef.env;
|
|
@@ -470,6 +480,18 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
|
|
|
470
480
|
valueIsImportedAtRuntime: true,
|
|
471
481
|
definedAt: import_
|
|
472
482
|
};
|
|
483
|
+
// Load config value
|
|
484
|
+
if (isConfigEnv(configDef, configName)) {
|
|
485
|
+
if (import_.filePathAbsoluteFilesystem) {
|
|
486
|
+
assert(hasProp(import_, 'filePathAbsoluteFilesystem', 'string')); // Help TS
|
|
487
|
+
const fileExports = await loadImportedFile(import_, userRootDir, importedFilesLoaded);
|
|
488
|
+
configValueSource.value = fileExports[import_.fileExportName];
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
const configDefinedAt = getConfigDefinedAtString('Config', configName, configValueSource);
|
|
492
|
+
assertUsage(!configDef.cumulative, `${configDefinedAt} cannot be defined over an aliased import`);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
473
495
|
return configValueSource;
|
|
474
496
|
}
|
|
475
497
|
else {
|
|
@@ -1109,12 +1131,8 @@ function mergeCumulative(configName, configValueSources) {
|
|
|
1109
1131
|
let configValueSourcePrevious = null;
|
|
1110
1132
|
configValueSources.forEach((configValueSource) => {
|
|
1111
1133
|
const configDefinedAt = getConfigDefinedAtString('Config', configName, configValueSource);
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
assertUsage('value' in configValueSource, `${configDefinedAt} is only allowed to be defined in a +config.h.js file. (Because the values of ${configNameColored} are cumulative.)`);
|
|
1115
|
-
/* This is more confusing than adding value. For example, this explanation shouldn't be shown for the passToClient config.
|
|
1116
|
-
const explanation = `(Because the values of ${configNameColored} are cumulative and therefore merged together.)` as const
|
|
1117
|
-
*/
|
|
1134
|
+
// We could, in principle, also support cumulative for values that aren't loaded at config-time but it isn't completely trivial to implement.
|
|
1135
|
+
assert('value' in configValueSource);
|
|
1118
1136
|
// Make sure configValueSource.value is serializable
|
|
1119
1137
|
getConfigValueSerialized(configValueSource.value, configName, getDefinedAt(configValueSource));
|
|
1120
1138
|
const assertNoMixing = (isSet) => {
|
|
@@ -244,7 +244,7 @@ async function handlePagesWithStaticRoutes(prerenderContext, renderContext, doNo
|
|
|
244
244
|
_providedByHook: null,
|
|
245
245
|
routeParams,
|
|
246
246
|
_pageId: pageId,
|
|
247
|
-
|
|
247
|
+
_debugRouteMatches: [
|
|
248
248
|
{
|
|
249
249
|
pageId,
|
|
250
250
|
routeType: pageRoute.routeType,
|
|
@@ -422,7 +422,7 @@ async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds,
|
|
|
422
422
|
}
|
|
423
423
|
if (hookName) {
|
|
424
424
|
assert(hookFilePath);
|
|
425
|
-
assertUsage(false, `The ${hookName}() hook defined by ${hookFilePath} returns a URL ${pc.cyan(urlOriginal)} that doesn't match any of your
|
|
425
|
+
assertUsage(false, `The ${hookName}() hook defined by ${hookFilePath} returns a URL ${pc.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.`);
|
|
426
426
|
}
|
|
427
427
|
else {
|
|
428
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.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { debugPageFiles };
|
|
2
|
-
export type {
|
|
3
|
-
import { RouteMatches } from '../../../shared/route/index.js';
|
|
2
|
+
export type { PageContextDebugRouteMatches };
|
|
3
|
+
import type { RouteMatches } from '../../../shared/route/index.js';
|
|
4
4
|
import type { ClientDependency } from '../../../shared/getPageFiles/analyzePageClientSide/ClientDependency.js';
|
|
5
5
|
import type { PageFile } from '../../../shared/getPageFiles.js';
|
|
6
6
|
import type { PageConfigRuntime } from '../../../shared/page-configs/PageConfig.js';
|
|
7
|
-
type
|
|
8
|
-
|
|
7
|
+
type PageContextDebugRouteMatches = {
|
|
8
|
+
_debugRouteMatches: 'ROUTING_ERROR' | RouteMatches;
|
|
9
9
|
};
|
|
10
10
|
declare function debugPageFiles({ pageContext, isHtmlOnly, isClientRouting, pageFilesLoaded, pageFilesServerSide, pageFilesClientSide, clientEntries, clientDependencies }: {
|
|
11
11
|
pageContext: {
|
|
@@ -13,7 +13,7 @@ declare function debugPageFiles({ pageContext, isHtmlOnly, isClientRouting, page
|
|
|
13
13
|
_pageId: string;
|
|
14
14
|
_pageFilesAll: PageFile[];
|
|
15
15
|
_pageConfigs: PageConfigRuntime[];
|
|
16
|
-
} &
|
|
16
|
+
} & PageContextDebugRouteMatches;
|
|
17
17
|
isHtmlOnly: boolean;
|
|
18
18
|
isClientRouting: boolean;
|
|
19
19
|
pageFilesLoaded: PageFile[];
|
|
@@ -6,7 +6,7 @@ function debugPageFiles({ pageContext, isHtmlOnly, isClientRouting, pageFilesLoa
|
|
|
6
6
|
const padding = ' - ';
|
|
7
7
|
debug('All page files:', printPageFiles(pageContext._pageFilesAll, true)); // TODO
|
|
8
8
|
debug(`URL:`, pageContext.urlOriginal);
|
|
9
|
-
debug.options({ serialization: { emptyArray: 'No match' } })(`Routing:`, printRouteMatches(pageContext.
|
|
9
|
+
debug.options({ serialization: { emptyArray: 'No match' } })(`Routing:`, printRouteMatches(pageContext._debugRouteMatches));
|
|
10
10
|
debug(`pageId:`, pageContext._pageId);
|
|
11
11
|
debug('Page type:', isHtmlOnly ? 'HTML-only' : 'SSR/SPA');
|
|
12
12
|
debug(`Routing type:`, !isHtmlOnly && isClientRouting ? 'Client Routing' : 'Server Routing');
|
|
@@ -16,14 +16,14 @@ function debugPageFiles({ pageContext, isHtmlOnly, isClientRouting, pageFilesLoa
|
|
|
16
16
|
debug('Client-side entries:', clientEntries);
|
|
17
17
|
debug('Client-side dependencies:', clientDependencies);
|
|
18
18
|
return;
|
|
19
|
-
function printRouteMatches(
|
|
20
|
-
if (
|
|
19
|
+
function printRouteMatches(debugRouteMatches) {
|
|
20
|
+
if (debugRouteMatches === 'ROUTING_ERROR') {
|
|
21
21
|
return 'Routing Failed';
|
|
22
22
|
}
|
|
23
|
-
if (
|
|
23
|
+
if (debugRouteMatches === 'CUSTOM_ROUTING') {
|
|
24
24
|
return 'Custom Routing';
|
|
25
25
|
}
|
|
26
|
-
return
|
|
26
|
+
return debugRouteMatches;
|
|
27
27
|
}
|
|
28
28
|
function printPageFiles(pageFiles, genericPageFilesLast = false) {
|
|
29
29
|
if (pageFiles.length === 0) {
|
|
@@ -4,9 +4,9 @@ export type { PageContext_loadPageFilesServerSide };
|
|
|
4
4
|
import { type PageFile } from '../../../shared/getPageFiles.js';
|
|
5
5
|
import { PromiseType } from '../utils.js';
|
|
6
6
|
import { PageContextGetPageAssets, type PageAsset } from './getPageAssets.js';
|
|
7
|
-
import { type
|
|
7
|
+
import { type PageContextDebugRouteMatches } from './debugPageFiles.js';
|
|
8
8
|
import type { PageConfigRuntime } from '../../../shared/page-configs/PageConfig.js';
|
|
9
|
-
type PageContext_loadPageFilesServerSide = PageContextGetPageAssets &
|
|
9
|
+
type PageContext_loadPageFilesServerSide = PageContextGetPageAssets & PageContextDebugRouteMatches & {
|
|
10
10
|
urlOriginal: string;
|
|
11
11
|
_pageFilesAll: PageFile[];
|
|
12
12
|
_pageConfigs: PageConfigRuntime[];
|
|
@@ -102,7 +102,7 @@ async function prerender404Page(renderContext, pageContextInit_) {
|
|
|
102
102
|
routeParams: {},
|
|
103
103
|
// `prerender404Page()` is about generating `dist/client/404.html` for static hosts; there is no Client Routing.
|
|
104
104
|
_usesClientRouter: false,
|
|
105
|
-
|
|
105
|
+
_debugRouteMatches: []
|
|
106
106
|
};
|
|
107
107
|
const pageContextInit = {
|
|
108
108
|
urlOriginal: '/fake-404-url',
|
|
@@ -268,7 +268,7 @@ async function getPageContextErrorPageInit(pageContextInit, errNominalPage, page
|
|
|
268
268
|
routeParams: {}
|
|
269
269
|
};
|
|
270
270
|
objectAssign(pageContext, {
|
|
271
|
-
|
|
271
|
+
_debugRouteMatches: pageContextNominalPagePartial._debugRouteMatches || 'ROUTING_ERROR'
|
|
272
272
|
});
|
|
273
273
|
assert(pageContext.errorWhileRendering);
|
|
274
274
|
return pageContext;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PageContextForRoute, PageContextFromRoute } from './index.js';
|
|
1
2
|
export { executeOnBeforeRouteHook };
|
|
2
3
|
export type { OnBeforeRouteHook };
|
|
3
4
|
type OnBeforeRouteHook = {
|
|
@@ -6,12 +7,8 @@ type OnBeforeRouteHook = {
|
|
|
6
7
|
urlOriginal: string;
|
|
7
8
|
} & Record<string, unknown>) => unknown;
|
|
8
9
|
};
|
|
9
|
-
declare function executeOnBeforeRouteHook(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
urlOriginal?: string;
|
|
14
|
-
urlLogical?: string;
|
|
15
|
-
_pageId?: string | null;
|
|
16
|
-
routeParams?: Record<string, string>;
|
|
10
|
+
declare function executeOnBeforeRouteHook(pageContext: PageContextForRoute): Promise<null | ({
|
|
11
|
+
_routingProvidedByOnBeforeRouteHook: true;
|
|
12
|
+
} & PageContextFromRoute) | {
|
|
13
|
+
_routingProvidedByOnBeforeRouteHook: false;
|
|
17
14
|
}>;
|
|
@@ -1,9 +1,37 @@
|
|
|
1
1
|
import { assertPageContextProvidedByUser } from '../assertPageContextProvidedByUser.js';
|
|
2
|
-
import { assertUsage, hasProp, isObjectWithKeys, objectAssign, assertWarning, assertUsageUrl, joinEnglish } from './utils.js';
|
|
2
|
+
import { assertUsage, hasProp, isObjectWithKeys, objectAssign, assertWarning, assertUsageUrl, joinEnglish, assert } from './utils.js';
|
|
3
3
|
import { assertRouteParams, assertSyncRouting } from './resolveRouteFunction.js';
|
|
4
4
|
import pc from '@brillout/picocolors';
|
|
5
5
|
export { executeOnBeforeRouteHook };
|
|
6
|
-
async function executeOnBeforeRouteHook(
|
|
6
|
+
async function executeOnBeforeRouteHook(pageContext) {
|
|
7
|
+
const pageContextFromOnBeforeRouteHook = {};
|
|
8
|
+
if (!pageContext._onBeforeRouteHook)
|
|
9
|
+
return null;
|
|
10
|
+
const pageContextFromHook = await executeHook(pageContext._onBeforeRouteHook, pageContext);
|
|
11
|
+
if (pageContextFromHook) {
|
|
12
|
+
objectAssign(pageContextFromOnBeforeRouteHook, pageContextFromHook);
|
|
13
|
+
if (hasProp(pageContextFromOnBeforeRouteHook, '_pageId', 'string') ||
|
|
14
|
+
hasProp(pageContextFromOnBeforeRouteHook, '_pageId', 'null')) {
|
|
15
|
+
// We bypass Vike's routing
|
|
16
|
+
if (!hasProp(pageContextFromOnBeforeRouteHook, 'routeParams')) {
|
|
17
|
+
objectAssign(pageContextFromOnBeforeRouteHook, { routeParams: {} });
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
assert(hasProp(pageContextFromOnBeforeRouteHook, 'routeParams', 'object'));
|
|
21
|
+
}
|
|
22
|
+
objectAssign(pageContextFromOnBeforeRouteHook, {
|
|
23
|
+
_routingProvidedByOnBeforeRouteHook: true,
|
|
24
|
+
_debugRouteMatches: 'CUSTOM_ROUTING'
|
|
25
|
+
});
|
|
26
|
+
return pageContextFromOnBeforeRouteHook;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
objectAssign(pageContextFromOnBeforeRouteHook, {
|
|
30
|
+
_routingProvidedByOnBeforeRouteHook: false
|
|
31
|
+
});
|
|
32
|
+
return pageContextFromOnBeforeRouteHook;
|
|
33
|
+
}
|
|
34
|
+
async function executeHook(onBeforeRouteHook, pageContext) {
|
|
7
35
|
let hookReturn = onBeforeRouteHook.onBeforeRoute(pageContext);
|
|
8
36
|
assertSyncRouting(hookReturn, `The onBeforeRoute() hook ${onBeforeRouteHook.hookFilePath}`);
|
|
9
37
|
// TODO/v1-release: make executeOnBeforeRouteHook() and route() sync
|
|
@@ -19,8 +19,8 @@ type PageContextForRoute = PageContextUrlComputedPropsInternal & {
|
|
|
19
19
|
type PageContextFromRoute = {
|
|
20
20
|
_pageId: string | null;
|
|
21
21
|
routeParams: Record<string, string>;
|
|
22
|
-
_routingProvidedByOnBeforeRouteHook
|
|
23
|
-
|
|
22
|
+
_routingProvidedByOnBeforeRouteHook?: boolean;
|
|
23
|
+
_debugRouteMatches: RouteMatches;
|
|
24
24
|
};
|
|
25
25
|
type RouteMatch = {
|
|
26
26
|
pageId: string;
|
|
@@ -29,5 +29,5 @@ type RouteMatch = {
|
|
|
29
29
|
routeType: RouteType;
|
|
30
30
|
routeParams: Record<string, string>;
|
|
31
31
|
};
|
|
32
|
-
type RouteMatches = '
|
|
33
|
-
declare function route(
|
|
32
|
+
type RouteMatches = 'CUSTOM_ROUTING' | RouteMatch[];
|
|
33
|
+
declare function route(pageContextForRoute: PageContextForRoute): Promise<PageContextFromRoute>;
|
|
@@ -5,7 +5,7 @@ import { isBrowser } from '../../utils/isBrowser.js';
|
|
|
5
5
|
if (isBrowser()) {
|
|
6
6
|
assertClientRouting();
|
|
7
7
|
}
|
|
8
|
-
import { assert, assertUsage,
|
|
8
|
+
import { assert, assertUsage, isPlainObject, objectAssign } from './utils.js';
|
|
9
9
|
import { addUrlComputedProps } from '../addUrlComputedProps.js';
|
|
10
10
|
import { resolvePrecendence } from './resolvePrecedence.js';
|
|
11
11
|
import { resolveRouteString } from './resolveRouteString.js';
|
|
@@ -13,35 +13,25 @@ import { resolveRouteFunction } from './resolveRouteFunction.js';
|
|
|
13
13
|
import { executeOnBeforeRouteHook } from './executeOnBeforeRouteHook.js';
|
|
14
14
|
import { debug } from './debug.js';
|
|
15
15
|
import pc from '@brillout/picocolors';
|
|
16
|
-
async function route(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
else {
|
|
30
|
-
assert(hasProp(pageContextAddendum, 'routeParams', 'object'));
|
|
31
|
-
}
|
|
32
|
-
objectAssign(pageContextAddendum, {
|
|
33
|
-
_routingProvidedByOnBeforeRouteHook: true,
|
|
34
|
-
_routeMatches: 'CUSTOM_ROUTE'
|
|
35
|
-
});
|
|
36
|
-
return pageContextAddendum;
|
|
37
|
-
}
|
|
38
|
-
// We already assign so that `pageContext.urlOriginal === pageContextAddendum.urlOriginal`; enabling the `onBeforeRoute()` hook to mutate `pageContext.urlOriginal` before routing.
|
|
39
|
-
objectAssign(pageContext, pageContextAddendum);
|
|
16
|
+
async function route(pageContextForRoute) {
|
|
17
|
+
debug('Pages routes:', pageContextForRoute._pageRoutes);
|
|
18
|
+
addUrlComputedProps(pageContextForRoute);
|
|
19
|
+
const pageContextFromRoute = {};
|
|
20
|
+
// onBeforeRoute()
|
|
21
|
+
const pageContextFromOnBeforeRouteHook = await executeOnBeforeRouteHook(pageContextForRoute);
|
|
22
|
+
if (pageContextFromOnBeforeRouteHook) {
|
|
23
|
+
if (pageContextFromOnBeforeRouteHook._routingProvidedByOnBeforeRouteHook) {
|
|
24
|
+
assert(pageContextFromOnBeforeRouteHook._pageId);
|
|
25
|
+
return pageContextFromOnBeforeRouteHook;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
objectAssign(pageContextFromRoute, pageContextFromOnBeforeRouteHook);
|
|
40
29
|
}
|
|
41
30
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
// We take into account pageContext.urlLogical set by onBeforeRoute()
|
|
32
|
+
const pageContext = {};
|
|
33
|
+
objectAssign(pageContext, pageContextForRoute);
|
|
34
|
+
objectAssign(pageContext, pageContextFromOnBeforeRouteHook);
|
|
45
35
|
// Vike's routing
|
|
46
36
|
const allPageIds = pageContext._allPageIds;
|
|
47
37
|
assert(allPageIds.length >= 0);
|
|
@@ -93,21 +83,21 @@ async function route(pageContext) {
|
|
|
93
83
|
resolvePrecendence(routeMatches);
|
|
94
84
|
const winner = routeMatches[0];
|
|
95
85
|
debug(`Route matches for URL ${pc.cyan(urlPathname)} (in precedence order):`, routeMatches);
|
|
96
|
-
objectAssign(
|
|
86
|
+
objectAssign(pageContextFromRoute, { _debugRouteMatches: routeMatches });
|
|
97
87
|
if (!winner) {
|
|
98
|
-
objectAssign(
|
|
88
|
+
objectAssign(pageContextFromRoute, {
|
|
99
89
|
_pageId: null,
|
|
100
90
|
routeParams: {}
|
|
101
91
|
});
|
|
102
|
-
return
|
|
92
|
+
return pageContextFromRoute;
|
|
103
93
|
}
|
|
104
94
|
{
|
|
105
95
|
const { routeParams } = winner;
|
|
106
96
|
assert(isPlainObject(routeParams));
|
|
107
|
-
objectAssign(
|
|
97
|
+
objectAssign(pageContextFromRoute, {
|
|
108
98
|
_pageId: winner.pageId,
|
|
109
99
|
routeParams: winner.routeParams
|
|
110
100
|
});
|
|
111
101
|
}
|
|
112
|
-
return
|
|
102
|
+
return pageContextFromRoute;
|
|
113
103
|
}
|
|
@@ -5,7 +5,7 @@ type ProjectVersion = typeof projectInfo.projectVersion;
|
|
|
5
5
|
type ProjectTag = `[${PackageName}]` | `[${PackageName}@${ProjectVersion}]`;
|
|
6
6
|
declare const projectInfo: {
|
|
7
7
|
projectName: "Vike";
|
|
8
|
-
projectVersion: "0.4.144-commit-
|
|
8
|
+
projectVersion: "0.4.144-commit-de18325";
|
|
9
9
|
npmPackageName: "vike";
|
|
10
10
|
githubRepository: "https://github.com/vikejs/vike";
|
|
11
11
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { projectInfo };
|
|
2
2
|
import { onProjectInfo } from './assertSingleInstance.js';
|
|
3
|
-
const PROJECT_VERSION = '0.4.144-commit-
|
|
3
|
+
const PROJECT_VERSION = '0.4.144-commit-de18325';
|
|
4
4
|
const projectInfo = {
|
|
5
5
|
projectName: 'Vike',
|
|
6
6
|
projectVersion: PROJECT_VERSION,
|
package/package.json
CHANGED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export { getPageId };
|
|
2
|
-
declare function getPageId(urlOriginal: string): Promise<{
|
|
3
|
-
pageId: null;
|
|
4
|
-
pageFilesAll: import("../../shared/getPageFiles/getPageFileObject.js").PageFile[];
|
|
5
|
-
pageConfigs: import("../../shared/page-configs/PageConfig.js").PageConfigRuntime[];
|
|
6
|
-
} | {
|
|
7
|
-
pageId: string;
|
|
8
|
-
pageFilesAll: import("../../shared/getPageFiles/getPageFileObject.js").PageFile[];
|
|
9
|
-
pageConfigs: import("../../shared/page-configs/PageConfig.js").PageConfigRuntime[];
|
|
10
|
-
}>;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export { getPageId };
|
|
2
|
-
import { route } from '../../shared/route/index.js';
|
|
3
|
-
import { createPageContext } from './createPageContext.js';
|
|
4
|
-
async function getPageId(urlOriginal) {
|
|
5
|
-
const pageContext = await createPageContext(urlOriginal);
|
|
6
|
-
const pageFilesAll = pageContext._pageFilesAll;
|
|
7
|
-
const pageConfigs = pageContext._pageConfigs;
|
|
8
|
-
const pageContextFromRoute = await route(pageContext);
|
|
9
|
-
const pageId = pageContextFromRoute._pageId;
|
|
10
|
-
if (!pageId) {
|
|
11
|
-
return { pageId: null, pageFilesAll, pageConfigs };
|
|
12
|
-
}
|
|
13
|
-
return { pageId, pageFilesAll, pageConfigs };
|
|
14
|
-
}
|