vike 0.4.160-commit-a1101c1 → 0.4.160-commit-facd36e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/cjs/node/plugin/plugins/autoFullBuild.js +2 -2
  2. package/dist/cjs/node/plugin/plugins/buildConfig.js +9 -0
  3. package/dist/cjs/node/plugin/plugins/commonConfig.js +1 -1
  4. package/dist/cjs/node/plugin/plugins/config/stemUtils.js +1 -1
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +1 -5
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +28 -46
  7. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{loadFileConfigEnv.js → loadFileAtConfigTime.js} +5 -5
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.js +33 -0
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +2 -2
  10. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformImports.js → transformFileImports.js} +7 -7
  11. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +21 -27
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +149 -110
  13. package/dist/cjs/node/plugin/utils.js +1 -2
  14. package/dist/cjs/node/prerender/runPrerender.js +12 -5
  15. package/dist/cjs/node/runtime/globalContext.js +7 -4
  16. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +1 -1
  17. package/dist/cjs/node/runtime/renderPage/{logHintForCjsEsmError.js → logErrorHint.js} +81 -43
  18. package/dist/cjs/node/runtime/renderPage/loggerProd.js +3 -3
  19. package/dist/cjs/node/runtime/utils.js +1 -1
  20. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +53 -26
  21. package/dist/cjs/shared/route/executeGuardHook.js +3 -2
  22. package/dist/cjs/shared/utils.js +0 -1
  23. package/dist/cjs/utils/{findUserPackageJsonPath.js → findFile.js} +11 -8
  24. package/dist/cjs/utils/nodeEnv.js +23 -1
  25. package/dist/cjs/utils/objectKeys.js +19 -3
  26. package/dist/cjs/utils/projectInfo.js +1 -1
  27. package/dist/cjs/utils/sorter.js +62 -1
  28. package/dist/esm/node/plugin/plugins/autoFullBuild.js +2 -2
  29. package/dist/esm/node/plugin/plugins/buildConfig.js +10 -1
  30. package/dist/esm/node/plugin/plugins/commonConfig.js +2 -2
  31. package/dist/esm/node/plugin/plugins/config/stemUtils.js +2 -2
  32. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +2 -0
  33. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.d.ts +0 -1
  34. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +1 -5
  35. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.d.ts +39 -12
  36. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +29 -47
  37. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{loadFileConfigEnv.js → loadFileAtConfigTime.js} +4 -4
  38. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.d.ts +5 -0
  39. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.js +27 -0
  40. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.d.ts +1 -1
  41. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +1 -1
  42. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformImports.d.ts → transformFileImports.d.ts} +2 -2
  43. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{transformImports.js → transformFileImports.js} +6 -6
  44. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.d.ts +1 -1
  45. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +20 -26
  46. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +2 -0
  47. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +148 -109
  48. package/dist/esm/node/plugin/utils.d.ts +1 -2
  49. package/dist/esm/node/plugin/utils.js +1 -2
  50. package/dist/esm/node/prerender/runPrerender.js +13 -6
  51. package/dist/esm/node/runtime/globalContext.js +8 -5
  52. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +1 -1
  53. package/dist/esm/node/runtime/renderPage/logErrorHint.d.ts +8 -0
  54. package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError.js → logErrorHint.js} +80 -42
  55. package/dist/esm/node/runtime/renderPage/loggerProd.js +3 -3
  56. package/dist/esm/node/runtime/utils.d.ts +1 -1
  57. package/dist/esm/node/runtime/utils.js +1 -1
  58. package/dist/esm/shared/page-configs/PageConfig.d.ts +2 -0
  59. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +53 -26
  60. package/dist/esm/shared/route/executeGuardHook.js +3 -2
  61. package/dist/esm/shared/utils.d.ts +0 -1
  62. package/dist/esm/shared/utils.js +0 -1
  63. package/dist/esm/utils/findFile.d.ts +3 -0
  64. package/dist/esm/utils/findFile.js +21 -0
  65. package/dist/esm/utils/nodeEnv.d.ts +4 -0
  66. package/dist/esm/utils/nodeEnv.js +19 -0
  67. package/dist/esm/utils/objectKeys.d.ts +10 -1
  68. package/dist/esm/utils/objectKeys.js +20 -3
  69. package/dist/esm/utils/projectInfo.d.ts +2 -2
  70. package/dist/esm/utils/projectInfo.js +1 -1
  71. package/dist/esm/utils/sorter.d.ts +59 -0
  72. package/dist/esm/utils/sorter.js +61 -0
  73. package/package.json +1 -1
  74. package/dist/cjs/utils/objectEntries.js +0 -8
  75. package/dist/esm/node/runtime/renderPage/logHintForCjsEsmError.d.ts +0 -13
  76. package/dist/esm/utils/findUserPackageJsonPath.d.ts +0 -2
  77. package/dist/esm/utils/findUserPackageJsonPath.js +0 -18
  78. package/dist/esm/utils/objectEntries.d.ts +0 -4
  79. package/dist/esm/utils/objectEntries.js +0 -5
  80. /package/dist/cjs/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.js +0 -0
  81. /package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/{loadFileConfigEnv.d.ts → loadFileAtConfigTime.d.ts} +0 -0
  82. /package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.d.ts +0 -0
  83. /package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.js +0 -0
@@ -2,7 +2,7 @@ export { getVikeConfig };
2
2
  export { reloadVikeConfig };
3
3
  export { vikeConfigDependencies };
4
4
  export { isVikeConfigFile };
5
- import { assertPosixPath, assert, isObject, assertUsage, assertWarning, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar, joinEnglish, lowerFirst, mergeCumulativeValues, getOutDirs, assertKeys } from '../../../utils.js';
5
+ import { assertPosixPath, assert, isObject, assertUsage, assertWarning, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar, joinEnglish, lowerFirst, mergeCumulativeValues, getOutDirs, assertKeys, objectKeys, objectFromEntries, makeFirst, isNpmPackageImport, reverse } from '../../../utils.js';
6
6
  import path from 'path';
7
7
  import { configDefinitionsBuiltIn, configDefinitionsBuiltInGlobal } from './getVikeConfig/configDefinitionsBuiltIn.js';
8
8
  import { getLocationId, getFilesystemRouteString, getFilesystemRouteDefinedBy, isInherited, sortAfterInheritanceOrder, isGlobalLocation, applyFilesystemRoutingRootEffect } from './getVikeConfig/filesystemRouting.js';
@@ -17,8 +17,9 @@ import { getConfigVike } from '../../../../shared/getConfigVike.js';
17
17
  import { assertConfigValueIsSerializable } from './getConfigValuesSerialized.js';
18
18
  import { crawlPlusFiles } from './getVikeConfig/crawlPlusFiles.js';
19
19
  import { getConfigFileExport } from './getConfigFileExport.js';
20
- import { loadConfigFile, loadImportedFile, loadValueFile } from './getVikeConfig/loadFileConfigEnv.js';
20
+ import { loadConfigFile, loadImportedFile, loadValueFile } from './getVikeConfig/loadFileAtConfigTime.js';
21
21
  import { clearFilesEnvMap, resolveImport } from './getVikeConfig/resolveImportPath.js';
22
+ import { resolveFilePathRelativeToUserRootDir } from './getVikeConfig/resolveFilePath.js';
22
23
  assertIsNotProductionRuntime();
23
24
  let devServerIsCorrupt = false;
24
25
  let wasConfigInvalid = null;
@@ -82,69 +83,77 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
82
83
  }
83
84
  });
84
85
  let interfaceFilesByLocationId = {};
85
- // Config files
86
- await Promise.all(configFiles.map(async (filePath) => {
87
- const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, [], false);
88
- const interfaceFile = getInterfaceFileFromConfigFile(configFile, false);
89
- const locationId = getLocationId(filePath.filePathAbsoluteVite);
90
- interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
91
- interfaceFilesByLocationId[locationId].push(interfaceFile);
92
- extendsConfigs.forEach((extendsConfig) => {
93
- const interfaceFile = getInterfaceFileFromConfigFile(extendsConfig, true);
94
- interfaceFilesByLocationId[locationId].push(interfaceFile);
95
- });
96
- }));
97
- // Value files
98
- await Promise.all(valueFiles.map(async (filePath) => {
99
- const configName = getConfigName(filePath.filePathAbsoluteVite);
100
- assert(configName);
101
- const interfaceFile = {
102
- filePath,
103
- fileExportsByConfigName: {
104
- [configName]: {}
105
- },
106
- isConfigFile: false,
107
- isValueFile: true,
108
- configName
109
- };
110
- {
111
- // We don't have access to the custom config definitions defined by the user yet.
112
- // - If `configDef` is `undefined` => we load the file +{configName}.js later.
113
- // - We already need to load +meta.js here (to get the custom config definitions defined by the user)
114
- const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn, configName);
115
- if (configDef && isConfigEnv(configDef, configName)) {
116
- await loadValueFile(interfaceFile, configName, userRootDir);
117
- }
118
- }
119
- {
120
- const locationId = getLocationId(filePath.filePathAbsoluteVite);
86
+ await Promise.all([
87
+ // Config files
88
+ ...configFiles.map(async (filePath) => {
89
+ const { filePathRelativeToUserRootDir } = filePath;
90
+ assert(filePathRelativeToUserRootDir);
91
+ const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, [], false);
92
+ assert(filePath.filePathRelativeToUserRootDir);
93
+ const locationId = getLocationId(filePathRelativeToUserRootDir);
94
+ const interfaceFile = getInterfaceFileFromConfigFile(configFile, false, locationId);
121
95
  interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
122
96
  interfaceFilesByLocationId[locationId].push(interfaceFile);
123
- }
124
- }));
97
+ extendsConfigs.forEach((extendsConfig) => {
98
+ /* We purposely use the same locationId because the Vike extension's config should only apply to where it's being extended from, for example:
99
+ ```js
100
+ // /pages/admin/+config.h.js
101
+
102
+ import vikeVue from 'vike-vue/config'
103
+ // Should only apply to /pages/admin/**
104
+ export default { extends: [vikeVue] }
105
+ ```
106
+ ```js
107
+ // /pages/marketing/+config.h.js
108
+
109
+ import vikeReact from 'vike-react/config'
110
+ // Should only apply to /pages/marketing/**
111
+ export default { extends: [vikeReact] }
112
+ ```
113
+ */
114
+ const interfaceFile = getInterfaceFileFromConfigFile(extendsConfig, true, locationId);
115
+ interfaceFilesByLocationId[locationId].push(interfaceFile);
116
+ });
117
+ }),
118
+ // Value files
119
+ ...valueFiles.map(async (filePath) => {
120
+ const { filePathRelativeToUserRootDir } = filePath;
121
+ assert(filePathRelativeToUserRootDir);
122
+ const configName = getConfigName(filePathRelativeToUserRootDir);
123
+ assert(configName);
124
+ const locationId = getLocationId(filePathRelativeToUserRootDir);
125
+ const interfaceFile = {
126
+ locationId,
127
+ filePath,
128
+ fileExportsByConfigName: {
129
+ [configName]: {}
130
+ },
131
+ isConfigFile: false,
132
+ isValueFile: true,
133
+ configName
134
+ };
135
+ {
136
+ // We don't have access to the custom config definitions defined by the user yet.
137
+ // - If `configDef` is `undefined` => we load the file +{configName}.js later.
138
+ // - We already need to load +meta.js here (to get the custom config definitions defined by the user)
139
+ const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn, configName);
140
+ if (configDef && isConfigEnv(configDef, configName)) {
141
+ await loadValueFile(interfaceFile, configName, userRootDir);
142
+ }
143
+ }
144
+ {
145
+ interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
146
+ interfaceFilesByLocationId[locationId].push(interfaceFile);
147
+ }
148
+ })
149
+ ]);
125
150
  assertAllConfigsAreKnown(interfaceFilesByLocationId);
126
151
  return interfaceFilesByLocationId;
127
152
  }
128
- function getConfigDefinition(configDefinitionsRelevant, configName, filePathToShowToUser) {
129
- const configDef = configDefinitionsRelevant[configName];
130
- assertConfigExists(configName, Object.keys(configDefinitionsRelevant), filePathToShowToUser);
131
- assert(configDef);
132
- return configDef;
133
- }
134
- function getConfigDefinitionOptional(configDefinitions, configName) {
135
- return configDefinitions[configName] ?? null;
136
- }
137
- function isConfigEnv(configDef, configName) {
138
- const configEnv = configDef.env;
139
- if (configDef.cumulative) {
140
- // In principle we could lift that requirement (but it requires non-trivial modifications)
141
- assertUsage(configEnv.config, `Config ${pc.cyan(configName)} needs its ${pc.cyan('env')} to have ${pc.cyan('{ config: true }')} (because ${pc.cyan(configName)} is a ${pc.cyan('cumulative')} config)`);
142
- }
143
- return !!configEnv.config;
144
- }
145
- function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
153
+ function getInterfaceFileFromConfigFile(configFile, isConfigExtend, locationId) {
146
154
  const { fileExports, filePath, extendsFilePaths } = configFile;
147
155
  const interfaceFile = {
156
+ locationId,
148
157
  filePath,
149
158
  fileExportsByConfigName: {},
150
159
  isConfigFile: true,
@@ -160,12 +169,12 @@ function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
160
169
  }
161
170
  /** Show error message upon unknown config */
162
171
  function assertAllConfigsAreKnown(interfaceFilesByLocationId) {
163
- Object.entries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
172
+ objectEntries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
164
173
  const interfaceFilesRelevant = getInterfaceFilesRelevant(interfaceFilesByLocationId, locationId);
165
- const configDefinitionsRelevant = getConfigDefinitions(interfaceFilesRelevant);
174
+ const configDefinitions = getConfigDefinitions(interfaceFilesRelevant);
166
175
  interfaceFiles.forEach((interfaceFile) => {
167
176
  Object.keys(interfaceFile.fileExportsByConfigName).forEach((configName) => {
168
- assertConfigExists(configName, Object.keys(configDefinitionsRelevant), interfaceFile.filePath.filePathToShowToUser);
177
+ assertConfigExists(configName, Object.keys(configDefinitions), interfaceFile.filePath.filePathToShowToUser);
169
178
  });
170
179
  });
171
180
  });
@@ -215,11 +224,11 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
215
224
  const interfaceFilesByLocationId = await loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions);
216
225
  const importedFilesLoaded = {};
217
226
  const { globalVikeConfig, pageConfigGlobal } = await getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded);
218
- const pageConfigs = await Promise.all(Object.entries(interfaceFilesByLocationId)
227
+ const pageConfigs = await Promise.all(objectEntries(interfaceFilesByLocationId)
219
228
  .filter(([_pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
220
229
  .map(async ([locationId]) => {
221
230
  const interfaceFilesRelevant = getInterfaceFilesRelevant(interfaceFilesByLocationId, locationId);
222
- const configDefinitionsRelevant = getConfigDefinitions(interfaceFilesRelevant);
231
+ const configDefinitions = getConfigDefinitions(interfaceFilesRelevant);
223
232
  // Load value files of custom config-only configs
224
233
  await Promise.all(getInterfaceFileList(interfaceFilesRelevant).map(async (interfaceFile) => {
225
234
  if (!interfaceFile.isValueFile)
@@ -227,7 +236,7 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
227
236
  const { configName } = interfaceFile;
228
237
  if (isGlobalConfig(configName))
229
238
  return;
230
- const configDef = getConfigDefinition(configDefinitionsRelevant, configName, interfaceFile.filePath.filePathToShowToUser);
239
+ const configDef = getConfigDefinition(configDefinitions, configName, interfaceFile.filePath.filePathToShowToUser);
231
240
  if (!isConfigEnv(configDef, configName))
232
241
  return;
233
242
  const isAlreadyLoaded = interfacefileIsAlreaydLoaded(interfaceFile);
@@ -237,8 +246,8 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
237
246
  assert(!(configName in configDefinitionsBuiltIn));
238
247
  await loadValueFile(interfaceFile, configName, userRootDir);
239
248
  }));
240
- const configValueSources = {};
241
- await Promise.all(objectEntries(configDefinitionsRelevant)
249
+ let configValueSources = {};
250
+ await Promise.all(objectEntries(configDefinitions)
242
251
  .filter(([configName]) => !isGlobalConfig(configName))
243
252
  .map(async ([configName, configDef]) => {
244
253
  const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded);
@@ -246,10 +255,11 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
246
255
  return;
247
256
  configValueSources[configName] = sources;
248
257
  }));
258
+ configValueSources = sortConfigValueSources(configValueSources, locationId);
249
259
  const { routeFilesystem, isErrorPage } = determineRouteFilesystem(locationId, configValueSources);
250
- applyEffectsAll(configValueSources, configDefinitionsRelevant);
251
- const configValuesComputed = getComputed(configValueSources, configDefinitionsRelevant);
252
- const configValues = getConfigValues(configValueSources, configValuesComputed, configDefinitionsRelevant);
260
+ applyEffectsAll(configValueSources, configDefinitions);
261
+ const configValuesComputed = getComputed(configValueSources, configDefinitions);
262
+ const configValues = getConfigValues(configValueSources, configValuesComputed, configDefinitions);
253
263
  const pageConfig = {
254
264
  pageId: locationId,
255
265
  isErrorPage,
@@ -286,7 +296,7 @@ function interfacefileIsAlreaydLoaded(interfaceFile) {
286
296
  return isAlreadyLoaded;
287
297
  }
288
298
  function getInterfaceFilesRelevant(interfaceFilesByLocationId, locationIdPage) {
289
- const interfaceFilesRelevant = Object.fromEntries(Object.entries(interfaceFilesByLocationId)
299
+ const interfaceFilesRelevant = Object.fromEntries(objectEntries(interfaceFilesByLocationId)
290
300
  .filter(([locationId]) => {
291
301
  return isInherited(locationId, locationIdPage);
292
302
  })
@@ -301,14 +311,14 @@ function getInterfaceFileList(interfaceFilesByLocationId) {
301
311
  return interfaceFiles;
302
312
  }
303
313
  async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded) {
304
- const locationIds = Object.keys(interfaceFilesByLocationId);
305
- const interfaceFilesGlobal = Object.fromEntries(Object.entries(interfaceFilesByLocationId).filter(([locationId]) => {
314
+ const locationIds = objectKeys(interfaceFilesByLocationId);
315
+ const interfaceFilesGlobal = objectFromEntries(objectEntries(interfaceFilesByLocationId).filter(([locationId]) => {
306
316
  return isGlobalLocation(locationId, locationIds);
307
317
  }));
308
318
  // Validate that global configs live in global interface files
309
319
  {
310
320
  const interfaceFilesGlobalPaths = [];
311
- Object.entries(interfaceFilesGlobal).forEach(([locationId, interfaceFiles]) => {
321
+ objectEntries(interfaceFilesGlobal).forEach(([locationId, interfaceFiles]) => {
312
322
  assert(isGlobalLocation(locationId, locationIds));
313
323
  interfaceFiles.forEach(({ filePath: { filePathRelativeToUserRootDir } }) => {
314
324
  if (filePathRelativeToUserRootDir) {
@@ -317,7 +327,7 @@ async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importe
317
327
  });
318
328
  });
319
329
  const globalPaths = Array.from(new Set(interfaceFilesGlobalPaths.map((p) => path.posix.dirname(p))));
320
- Object.entries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
330
+ objectEntries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
321
331
  interfaceFiles.forEach((interfaceFile) => {
322
332
  Object.keys(interfaceFile.fileExportsByConfigName).forEach((configName) => {
323
333
  if (!isGlobalLocation(locationId, locationIds) && isGlobalConfig(configName)) {
@@ -441,6 +451,7 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
441
451
  const conf = interfaceFile.fileExportsByConfigName[configName];
442
452
  assert(conf);
443
453
  const configEnv = configDef.env;
454
+ const { locationId } = interfaceFile;
444
455
  const definedAtConfigFile = {
445
456
  ...interfaceFile.filePath,
446
457
  fileExportPathToShowToUser: ['default', configName]
@@ -466,6 +477,7 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
466
477
  };
467
478
  }
468
479
  const configValueSource = {
480
+ locationId,
469
481
  value: valueFilePath,
470
482
  valueIsFilePath: true,
471
483
  configEnv,
@@ -482,6 +494,7 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
482
494
  const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
483
495
  if (import_) {
484
496
  const configValueSource = {
497
+ locationId,
485
498
  configEnv,
486
499
  valueIsImportedAtRuntime: true,
487
500
  definedAt: import_
@@ -504,6 +517,7 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
504
517
  }
505
518
  // Defined by config file, i.e. +config.js file
506
519
  const configValueSource = {
520
+ locationId,
507
521
  value: configValue,
508
522
  configEnv,
509
523
  valueIsImportedAtRuntime: false,
@@ -516,6 +530,7 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
516
530
  const valueAlreadyLoaded = 'configValue' in conf;
517
531
  assert(valueAlreadyLoaded === !!configEnv.config);
518
532
  const configValueSource = {
533
+ locationId,
519
534
  configEnv,
520
535
  valueIsImportedAtRuntime: !valueAlreadyLoaded,
521
536
  definedAt: {
@@ -546,8 +561,10 @@ function isDefiningPageConfig(configName) {
546
561
  return ['Page', 'route'].includes(configName);
547
562
  }
548
563
  function getConfigDefinitions(interfaceFilesRelevant) {
549
- const configDefinitions = { ...configDefinitionsBuiltIn };
550
- Object.entries(interfaceFilesRelevant).reverse().forEach(([_locationId, interfaceFiles]) => {
564
+ const configDefinitionsMerged = { ...configDefinitionsBuiltIn };
565
+ Object.entries(interfaceFilesRelevant)
566
+ .reverse()
567
+ .forEach(([_locationId, interfaceFiles]) => {
551
568
  interfaceFiles.forEach((interfaceFile) => {
552
569
  const configMeta = interfaceFile.fileExportsByConfigName['meta'];
553
570
  if (!configMeta)
@@ -566,13 +583,14 @@ function getConfigDefinitions(interfaceFilesRelevant) {
566
583
  });
567
584
  objectEntries(meta).forEach(([configName, configDefinition]) => {
568
585
  // User can override an existing config definition
569
- configDefinitions[configName] = {
570
- ...configDefinitions[configName],
586
+ configDefinitionsMerged[configName] = {
587
+ ...configDefinitionsMerged[configName],
571
588
  ...configDefinition
572
589
  };
573
590
  });
574
591
  });
575
592
  });
593
+ const configDefinitions = configDefinitionsMerged;
576
594
  return configDefinitions;
577
595
  }
578
596
  function assertMetaValue(metaVal, configMetaDefinedAt) {
@@ -611,8 +629,8 @@ function assertMetaValue(metaVal, configMetaDefinedAt) {
611
629
  }
612
630
  });
613
631
  }
614
- function applyEffectsAll(configValueSources, configDefinitionsRelevant) {
615
- objectEntries(configDefinitionsRelevant).forEach(([configName, configDef]) => {
632
+ function applyEffectsAll(configValueSources, configDefinitions) {
633
+ objectEntries(configDefinitions).forEach(([configName, configDef]) => {
616
634
  if (!configDef.effect)
617
635
  return;
618
636
  // The value needs to be loaded at config time, that's why we only support effect for configs that are config-only for now.
@@ -671,9 +689,9 @@ function applyEffect(configModFromEffect, configValueSources, configDefEffect) {
671
689
  }
672
690
  });
673
691
  }
674
- function getComputed(configValueSources, configDefinitionsRelevant) {
692
+ function getComputed(configValueSources, configDefinitions) {
675
693
  const configValuesComputed = {};
676
- objectEntries(configDefinitionsRelevant).forEach(([configName, configDef]) => {
694
+ objectEntries(configDefinitions).forEach(([configName, configDef]) => {
677
695
  if (!configDef._computed)
678
696
  return;
679
697
  const value = configDef._computed(configValueSources);
@@ -688,15 +706,7 @@ function getComputed(configValueSources, configDefinitionsRelevant) {
688
706
  }
689
707
  async function findPlusFiles(userRootDir, outDirRoot, isDev, extensions) {
690
708
  const files = await crawlPlusFiles(userRootDir, outDirRoot, isDev);
691
- const plusFiles = files.map(({ filePathRelativeToUserRootDir, filePathAbsoluteFilesystem }) => {
692
- return {
693
- filePathRelativeToUserRootDir,
694
- filePathAbsoluteVite: filePathRelativeToUserRootDir,
695
- filePathAbsoluteFilesystem,
696
- filePathToShowToUser: filePathRelativeToUserRootDir,
697
- importPathAbsolute: null
698
- };
699
- });
709
+ const plusFiles = files.map(({ filePathRelativeToUserRootDir }) => resolveFilePathRelativeToUserRootDir(filePathRelativeToUserRootDir, userRootDir));
700
710
  // TODO/v1-release: remove
701
711
  extensions.forEach((extension) => {
702
712
  extension.pageConfigsDistFiles?.forEach((pageConfigDistFile) => {
@@ -748,22 +758,6 @@ function assertNoUnexpectedPlusSign(filePath: string, fileName: string) {
748
758
  )
749
759
  }
750
760
  */
751
- function isGlobalConfig(configName) {
752
- if (configName === 'prerender')
753
- return false;
754
- const configNamesGlobal = getConfigNamesGlobal();
755
- return arrayIncludes(configNamesGlobal, configName);
756
- }
757
- function getConfigNamesGlobal() {
758
- return Object.keys(configDefinitionsBuiltInGlobal);
759
- }
760
- function assertConfigExists(configName, configNamesRelevant, filePathToShowToUser) {
761
- const configNames = [...configNamesRelevant, ...getConfigNamesGlobal()];
762
- if (configNames.includes(configName))
763
- return;
764
- handleUnknownConfig(configName, configNames, filePathToShowToUser);
765
- assert(false);
766
- }
767
761
  function handleUnknownConfig(configName, configNames, filePathToShowToUser) {
768
762
  let errMsg = `${filePathToShowToUser} defines an unknown config ${pc.cyan(configName)}`;
769
763
  let configNameSimilar = null;
@@ -833,7 +827,7 @@ function determineIsErrorPage(routeFilesystem) {
833
827
  function isVikeConfigFile(filePath) {
834
828
  return !!getConfigName(filePath);
835
829
  }
836
- function getConfigValues(configValueSources, configValuesComputed, configDefinitionsRelevant) {
830
+ function getConfigValues(configValueSources, configValuesComputed, configDefinitions) {
837
831
  const configValues = {};
838
832
  Object.entries(configValuesComputed).forEach(([configName, configValueComputed]) => {
839
833
  configValues[configName] = {
@@ -842,7 +836,7 @@ function getConfigValues(configValueSources, configValuesComputed, configDefinit
842
836
  };
843
837
  });
844
838
  Object.entries(configValueSources).forEach(([configName, sources]) => {
845
- const configDef = configDefinitionsRelevant[configName];
839
+ const configDef = configDefinitions[configName];
846
840
  assert(configDef);
847
841
  if (!configDef.cumulative) {
848
842
  const configValueSource = sources[0];
@@ -956,3 +950,48 @@ function getConfigEnvValue(val, errMsgIntro) {
956
950
  */
957
951
  return val;
958
952
  }
953
+ function getConfigDefinition(configDefinitions, configName, filePathToShowToUser) {
954
+ const configDef = configDefinitions[configName];
955
+ assertConfigExists(configName, Object.keys(configDefinitions), filePathToShowToUser);
956
+ assert(configDef);
957
+ return configDef;
958
+ }
959
+ function getConfigDefinitionOptional(configDefinitions, configName) {
960
+ return configDefinitions[configName] ?? null;
961
+ }
962
+ function isConfigEnv(configDef, configName) {
963
+ const configEnv = configDef.env;
964
+ if (configDef.cumulative) {
965
+ // In principle we could lift that requirement (but it requires non-trivial modifications)
966
+ assertUsage(configEnv.config, `Config ${pc.cyan(configName)} needs its ${pc.cyan('env')} to have ${pc.cyan('{ config: true }')} (because ${pc.cyan(configName)} is a ${pc.cyan('cumulative')} config)`);
967
+ }
968
+ return !!configEnv.config;
969
+ }
970
+ function isGlobalConfig(configName) {
971
+ if (configName === 'prerender')
972
+ return false;
973
+ const configNamesGlobal = getConfigNamesGlobal();
974
+ return arrayIncludes(configNamesGlobal, configName);
975
+ }
976
+ function getConfigNamesGlobal() {
977
+ return Object.keys(configDefinitionsBuiltInGlobal);
978
+ }
979
+ function assertConfigExists(configName, configNamesRelevant, filePathToShowToUser) {
980
+ const configNames = [...configNamesRelevant, ...getConfigNamesGlobal()];
981
+ if (configNames.includes(configName))
982
+ return;
983
+ handleUnknownConfig(configName, configNames, filePathToShowToUser);
984
+ assert(false);
985
+ }
986
+ function sortConfigValueSources(configValueSources, locationIdPage) {
987
+ return Object.fromEntries(Object.entries(configValueSources)
988
+ // Make order deterministic (no other purpose)
989
+ .sort(([, [source1]], [, [source2]]) => source1.definedAt.filePathAbsoluteVite < source2.definedAt.filePathAbsoluteVite ? -1 : 1)
990
+ // Sort after whether the config value was defined by an npm package
991
+ .sort(makeFirst(([, [source]]) => {
992
+ const { importPathAbsolute } = source.definedAt;
993
+ return !!importPathAbsolute && isNpmPackageImport(importPathAbsolute);
994
+ }))
995
+ // Sort after the filesystem inheritance of the config value
996
+ .sort(([, [source1]], [, [source2]]) => reverse(sortAfterInheritanceOrder(source1.locationId, source2.locationId, locationIdPage))));
997
+ }
@@ -5,7 +5,6 @@ export * from '../../utils/getDependencyPackageJson.js';
5
5
  export * from '../../utils/requireResolve.js';
6
6
  export * from '../../utils/arrayIncludes.js';
7
7
  export * from '../../utils/isDev.js';
8
- export * from '../../utils/objectKeys.js';
9
8
  export * from '../../utils/getMostSimilar.js';
10
9
  export * from '../../utils/getRandomId.js';
11
10
  export * from '../../utils/joinEnglish.js';
@@ -13,7 +12,7 @@ export * from '../../utils/escapeRegex.js';
13
12
  export * from '../../utils/stripAnsi.js';
14
13
  export * from '../../utils/trimWithAnsi.js';
15
14
  export * from '../../utils/removeEmptyLines.js';
16
- export * from '../../utils/findUserPackageJsonPath.js';
15
+ export * from '../../utils/findFile.js';
17
16
  export * from '../../utils/getPropAccessNotation.js';
18
17
  export * from '../../utils/mergeCumulativeValues.js';
19
18
  export * from '../../utils/deepEqual.js';
@@ -11,7 +11,6 @@ export * from '../../utils/getDependencyPackageJson.js';
11
11
  export * from '../../utils/requireResolve.js';
12
12
  export * from '../../utils/arrayIncludes.js';
13
13
  export * from '../../utils/isDev.js';
14
- export * from '../../utils/objectKeys.js';
15
14
  export * from '../../utils/getMostSimilar.js';
16
15
  export * from '../../utils/getRandomId.js';
17
16
  export * from '../../utils/joinEnglish.js';
@@ -19,7 +18,7 @@ export * from '../../utils/escapeRegex.js';
19
18
  export * from '../../utils/stripAnsi.js';
20
19
  export * from '../../utils/trimWithAnsi.js';
21
20
  export * from '../../utils/removeEmptyLines.js';
22
- export * from '../../utils/findUserPackageJsonPath.js';
21
+ export * from '../../utils/findFile.js';
23
22
  export * from '../../utils/getPropAccessNotation.js';
24
23
  export * from '../../utils/mergeCumulativeValues.js';
25
24
  export * from '../../utils/deepEqual.js';
@@ -5,7 +5,7 @@ export { runPrerender_forceExit };
5
5
  import '../runtime/page-files/setup.js';
6
6
  import path from 'path';
7
7
  import { route } from '../../shared/route/index.js';
8
- import { assert, assertUsage, assertWarning, hasProp, projectInfo, objectAssign, isObjectWithKeys, isCallable, getOutDirs, isPropertyGetter, assertPosixPath, urlToFile, executeHook, isPlainObject, setNodeEnvToProduction, isUserHookError } from './utils.js';
8
+ import { assert, assertUsage, assertWarning, hasProp, projectInfo, objectAssign, isObjectWithKeys, isCallable, getOutDirs, isPropertyGetter, assertPosixPath, urlToFile, executeHook, isPlainObject, setNodeEnvToProduction, isUserHookError, assertNodeEnvIsNotDev, getNodeEnv } from './utils.js';
9
9
  import { pLimit } from '../../utils/pLimit.js';
10
10
  import { prerenderPage, prerender404Page, getRenderContext, getPageContextInitEnhanced } from '../runtime/renderPage/renderPageAlreadyRouted.js';
11
11
  import pc from '@brillout/picocolors';
@@ -26,11 +26,11 @@ import { loadUserFilesServerSide } from '../runtime/renderPage/loadUserFilesServ
26
26
  import { getHookFromPageConfig, getHookFromPageConfigGlobal, getHookTimeoutDefault, setIsPrerenderering } from '../../shared/hooks/getHook.js';
27
27
  import { noRouteMatch } from '../../shared/route/noRouteMatch.js';
28
28
  import { getVikeConfig } from '../plugin/plugins/importUserCode/v1-design/getVikeConfig.js';
29
- import { logHintForCjsEsmError } from '../runtime/renderPage/logHintForCjsEsmError.js';
29
+ import { logErrorHint } from '../runtime/renderPage/logErrorHint.js';
30
30
  async function runPrerenderFromAPI(options = {}) {
31
31
  await runPrerender(options, 'prerender()');
32
32
  // - We purposely propagate the error to the user land, so that the error interrupts the user land. It's also, I guess, a nice-to-have that the user has control over the error.
33
- // - We don't use logHintForCjsEsmError() because we don't have control over what happens with the error. For example, if the user land purposely swallows the error then the hint shouldn't be logged. Also, it's best if the hint is shown to the user *after* the error, but we cannot do/guarentee that.
33
+ // - We don't use logErrorHint() because we don't have control over what happens with the error. For example, if the user land purposely swallows the error then the hint shouldn't be logged. Also, it's best if the hint is shown to the user *after* the error, but we cannot do/guarentee that.
34
34
  }
35
35
  async function runPrerenderFromCLI(options) {
36
36
  try {
@@ -38,7 +38,7 @@ async function runPrerenderFromCLI(options) {
38
38
  }
39
39
  catch (err) {
40
40
  console.error(err);
41
- logHintForCjsEsmError(err);
41
+ logErrorHint(err);
42
42
  process.exit(1);
43
43
  }
44
44
  }
@@ -48,7 +48,7 @@ async function runPrerenderFromAutoFullBuild(options) {
48
48
  }
49
49
  catch (err) {
50
50
  console.error(err);
51
- logHintForCjsEsmError(err);
51
+ logErrorHint(err);
52
52
  process.exit(1);
53
53
  }
54
54
  }
@@ -59,7 +59,7 @@ async function runPrerender(options, manuallyTriggered) {
59
59
  if (logLevel === 'info') {
60
60
  console.log(`${pc.cyan(`vike v${projectInfo.projectVersion}`)} ${pc.green('pre-rendering HTML...')}`);
61
61
  }
62
- setNodeEnvToProduction();
62
+ handleNodeEnv();
63
63
  await disableReactStreaming();
64
64
  const viteConfig = await resolveConfig(options.viteConfig || {}, 'vike pre-rendering', 'production');
65
65
  assertLoadedConfig(viteConfig, options);
@@ -713,3 +713,10 @@ function assertIsNotAbort(err, urlOr404) {
713
713
  assert(abortCall);
714
714
  assertUsage(false, `${pc.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOr404} but ${pc.cyan(abortCaller)} isn't supported for pre-rendered pages`);
715
715
  }
716
+ function handleNodeEnv() {
717
+ const assertNodeEnv = () => assertNodeEnvIsNotDev('pre-rendering');
718
+ if (getNodeEnv())
719
+ assertNodeEnv();
720
+ setNodeEnvToProduction();
721
+ assertNodeEnv();
722
+ }
@@ -6,7 +6,7 @@ export { setGlobalContext_viteDevServer };
6
6
  export { setGlobalContext_vitePreviewServer };
7
7
  export { setGlobalContext_viteConfig };
8
8
  export { getRuntimeManifest };
9
- import { assert, assertUsage, getGlobalObject, getNodeEnv, isNodeEnvDev, isPlainObject, objectAssign } from './utils.js';
9
+ import { assert, assertUsage, getGlobalObject, getNodeEnv, getNodeEnvDesc, isNodeEnvDev, isPlainObject, objectAssign } from './utils.js';
10
10
  import { loadImportBuild } from './globalContext/loadImportBuild.js';
11
11
  import { setPageFiles } from '../../shared/getPageFiles.js';
12
12
  import { assertPluginManifest } from '../shared/assertPluginManifest.js';
@@ -151,8 +151,11 @@ function assertNodeEnv(hasViteDevServer) {
151
151
  const nodeEnv = getNodeEnv();
152
152
  if (nodeEnv === null || nodeEnv === 'test')
153
153
  return;
154
- const isDevNodeEnv = isNodeEnvDev();
155
- // - Calling Vite's createServer() is enough for hasViteDevServer to be true, even without actually adding Vite's development middleware to the server: https://github.com/vikejs/vike/issues/792#issuecomment-1516830759
156
- // - We should change this to be a warning if it blocks users (e.g. if a bad-citizen tool sets a wrong process.env.NODE_ENV value).
157
- assertUsage(hasViteDevServer === isDevNodeEnv, `Vite's development server was${hasViteDevServer ? '' : "n't"} instantiated while the environment is set to be a ${isDevNodeEnv ? 'development' : 'production'} environment by ${pc.cyan(`process.env.NODE_ENV === ${JSON.stringify(nodeEnv)}`)} which is contradictory, see https://vike.dev/NODE_ENV`);
154
+ const isDev = isNodeEnvDev();
155
+ // Calling Vite's createServer() is enough for hasViteDevServer to be true, even without actually adding Vite's development middleware to the server: https://github.com/vikejs/vike/issues/792#issuecomment-1516830759
156
+ if (hasViteDevServer === isDev)
157
+ return;
158
+ const nodeEnvDesc = getNodeEnvDesc();
159
+ // We should change this to be a warning if it blocks users (e.g. if a bad-citizen tool sets a wrong process.env.NODE_ENV value)
160
+ assertUsage(false, `Vite's development server was${hasViteDevServer ? '' : "n't"} instantiated while the ${nodeEnvDesc} which is contradictory, see https://vike.dev/NODE_ENV`);
158
161
  }
@@ -85,7 +85,7 @@ async function getHtmlTags(pageContext, injectToStream, injectFilter) {
85
85
  // See https://github.com/vikejs/vike/pull/1271
86
86
  const positionJavaScriptEntry = (() => {
87
87
  if (pageContext._pageContextPromise) {
88
- assertWarning(!injectToStream, "[getHtmlTags()] We recommend against using streaming and a pageContext promise at the same time as progressive hydration won't work", { onlyOnce: true });
88
+ assertWarning(!injectToStream, "[getHtmlTags()] We recommend against using streaming and a pageContext promise at the same time, because progressive hydration won't work.", { onlyOnce: true });
89
89
  // If there is a pageContext._pageContextPromise (which is resolved after the stream has ended) then the pageContext JSON data needs to await for it: https://vike.dev/streaming#initial-data-after-stream-end
90
90
  return 'HTML_END';
91
91
  }
@@ -0,0 +1,8 @@
1
+ export { logErrorHint };
2
+ export { isCjsEsmError };
3
+ export { isKnownError };
4
+ export { getHint };
5
+ declare function logErrorHint(error: unknown): void;
6
+ declare function getHint(error: unknown): null | string;
7
+ declare function isKnownError(error: unknown): false | string;
8
+ declare function isCjsEsmError(error: unknown): boolean | string[];