vike 0.4.159 → 0.4.160-commit-30d535e

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 (125) hide show
  1. package/dist/cjs/node/plugin/index.js +20 -1
  2. package/dist/cjs/node/plugin/plugins/autoFullBuild.js +2 -2
  3. package/dist/cjs/node/plugin/plugins/buildConfig.js +9 -0
  4. package/dist/cjs/node/plugin/plugins/commonConfig.js +1 -1
  5. package/dist/cjs/node/plugin/plugins/config/stemUtils.js +1 -1
  6. package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -1
  7. package/dist/cjs/node/plugin/plugins/importBuild/index.js +1 -1
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.js +18 -0
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +1 -5
  10. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +28 -46
  11. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +129 -0
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.js +33 -0
  13. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +139 -0
  14. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → getVikeConfig/transformFileImports.js} +44 -13
  15. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.js → getVikeConfig/transpileAndExecuteFile.js} +105 -78
  16. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +201 -382
  17. package/dist/cjs/node/plugin/plugins/previewConfig.js +1 -1
  18. package/dist/cjs/node/plugin/shared/getHttpRequestAsyncStore.js +1 -1
  19. package/dist/cjs/node/plugin/shared/loggerNotProd/log.js +3 -3
  20. package/dist/cjs/node/plugin/shared/loggerNotProd.js +1 -1
  21. package/dist/cjs/node/plugin/utils.js +1 -2
  22. package/dist/cjs/node/prerender/runPrerender.js +12 -5
  23. package/dist/cjs/node/runtime/globalContext.js +7 -3
  24. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +2 -2
  25. package/dist/cjs/node/runtime/html/renderHtml.js +1 -1
  26. package/dist/cjs/node/runtime/html/stream.js +2 -2
  27. package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +2 -2
  28. package/dist/cjs/node/runtime/renderPage/getHttpResponseBody.js +1 -1
  29. package/dist/cjs/node/runtime/renderPage/loadUserFilesServerSide.js +1 -1
  30. package/dist/cjs/node/runtime/renderPage/{logHintForCjsEsmError.js → logErrorHint.js} +81 -43
  31. package/dist/cjs/node/runtime/renderPage/loggerProd.js +3 -3
  32. package/dist/cjs/node/runtime/utils.js +1 -1
  33. package/dist/cjs/shared/page-configs/assertPlusFileExport.js +44 -0
  34. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +54 -27
  35. package/dist/cjs/shared/route/abort.js +1 -1
  36. package/dist/cjs/shared/route/executeGuardHook.js +3 -2
  37. package/dist/cjs/shared/utils.js +0 -1
  38. package/dist/cjs/utils/assert.js +5 -6
  39. package/dist/cjs/utils/assertIsNotProductionRuntime.js +35 -17
  40. package/dist/cjs/utils/{findUserPackageJsonPath.js → findFile.js} +11 -8
  41. package/dist/cjs/utils/nodeEnv.js +33 -1
  42. package/dist/cjs/utils/objectKeys.js +19 -3
  43. package/dist/cjs/utils/projectInfo.js +2 -4
  44. package/dist/cjs/utils/sorter.js +62 -1
  45. package/dist/esm/node/plugin/index.js +21 -2
  46. package/dist/esm/node/plugin/plugins/autoFullBuild.js +2 -2
  47. package/dist/esm/node/plugin/plugins/buildConfig.js +10 -1
  48. package/dist/esm/node/plugin/plugins/commonConfig.js +2 -2
  49. package/dist/esm/node/plugin/plugins/config/stemUtils.js +2 -2
  50. package/dist/esm/node/plugin/plugins/devConfig/index.js +2 -2
  51. package/dist/esm/node/plugin/plugins/importBuild/index.js +2 -2
  52. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.d.ts +2 -0
  53. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.js +12 -0
  54. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +8 -1
  55. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.d.ts +0 -1
  56. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +1 -5
  57. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.d.ts +39 -12
  58. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +29 -47
  59. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.d.ts +21 -0
  60. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +123 -0
  61. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.d.ts +5 -0
  62. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.js +27 -0
  63. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.d.ts +12 -0
  64. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +133 -0
  65. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.d.ts → getVikeConfig/transformFileImports.d.ts} +5 -5
  66. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → getVikeConfig/transformFileImports.js} +43 -12
  67. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.d.ts → getVikeConfig/transpileAndExecuteFile.d.ts} +3 -3
  68. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.js → getVikeConfig/transpileAndExecuteFile.js} +105 -78
  69. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +16 -1
  70. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +199 -380
  71. package/dist/esm/node/plugin/plugins/previewConfig.js +2 -2
  72. package/dist/esm/node/plugin/shared/getHttpRequestAsyncStore.js +1 -1
  73. package/dist/esm/node/plugin/shared/loggerNotProd/log.js +3 -3
  74. package/dist/esm/node/plugin/shared/loggerNotProd.js +1 -1
  75. package/dist/esm/node/plugin/utils.d.ts +1 -2
  76. package/dist/esm/node/plugin/utils.js +1 -2
  77. package/dist/esm/node/prerender/runPrerender.js +13 -6
  78. package/dist/esm/node/runtime/globalContext.js +8 -4
  79. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +2 -2
  80. package/dist/esm/node/runtime/html/renderHtml.js +1 -1
  81. package/dist/esm/node/runtime/html/stream.js +2 -2
  82. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +2 -2
  83. package/dist/esm/node/runtime/renderPage/getHttpResponseBody.js +1 -1
  84. package/dist/esm/node/runtime/renderPage/loadUserFilesServerSide.js +1 -1
  85. package/dist/esm/node/runtime/renderPage/logErrorHint.d.ts +8 -0
  86. package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError.js → logErrorHint.js} +80 -42
  87. package/dist/esm/node/runtime/renderPage/loggerProd.js +3 -3
  88. package/dist/esm/node/runtime/utils.d.ts +1 -1
  89. package/dist/esm/node/runtime/utils.js +1 -1
  90. package/dist/esm/shared/page-configs/Config.d.ts +1 -1
  91. package/dist/esm/shared/page-configs/PageConfig.d.ts +6 -0
  92. package/dist/esm/shared/page-configs/assertPlusFileExport.d.ts +2 -0
  93. package/dist/esm/shared/page-configs/assertPlusFileExport.js +38 -0
  94. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +54 -27
  95. package/dist/esm/shared/route/abort.js +2 -2
  96. package/dist/esm/shared/route/executeGuardHook.js +3 -2
  97. package/dist/esm/shared/utils.d.ts +0 -1
  98. package/dist/esm/shared/utils.js +0 -1
  99. package/dist/esm/utils/assert.js +5 -6
  100. package/dist/esm/utils/assertIsNotProductionRuntime.d.ts +8 -6
  101. package/dist/esm/utils/assertIsNotProductionRuntime.js +35 -17
  102. package/dist/esm/utils/debug.d.ts +1 -1
  103. package/dist/esm/utils/findFile.d.ts +3 -0
  104. package/dist/esm/utils/findFile.js +21 -0
  105. package/dist/esm/utils/nodeEnv.d.ts +6 -0
  106. package/dist/esm/utils/nodeEnv.js +29 -0
  107. package/dist/esm/utils/objectKeys.d.ts +10 -1
  108. package/dist/esm/utils/objectKeys.js +20 -3
  109. package/dist/esm/utils/projectInfo.d.ts +2 -8
  110. package/dist/esm/utils/projectInfo.js +2 -4
  111. package/dist/esm/utils/sorter.d.ts +59 -0
  112. package/dist/esm/utils/sorter.js +61 -0
  113. package/package.json +1 -1
  114. package/dist/cjs/shared/page-configs/assertExports.js +0 -67
  115. package/dist/cjs/utils/objectEntries.js +0 -8
  116. package/dist/esm/node/runtime/renderPage/logHintForCjsEsmError.d.ts +0 -13
  117. package/dist/esm/shared/page-configs/assertExports.d.ts +0 -6
  118. package/dist/esm/shared/page-configs/assertExports.js +0 -61
  119. package/dist/esm/utils/findUserPackageJsonPath.d.ts +0 -2
  120. package/dist/esm/utils/findUserPackageJsonPath.js +0 -18
  121. package/dist/esm/utils/objectEntries.d.ts +0 -4
  122. package/dist/esm/utils/objectEntries.js +0 -5
  123. /package/dist/cjs/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.js +0 -0
  124. /package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.d.ts +0 -0
  125. /package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.js +0 -0
@@ -8,28 +8,29 @@ const utils_js_1 = require("../../../utils.js");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const configDefinitionsBuiltIn_js_1 = require("./getVikeConfig/configDefinitionsBuiltIn.js");
10
10
  const filesystemRouting_js_1 = require("./getVikeConfig/filesystemRouting.js");
11
- const transpileAndExecuteFile_js_1 = require("./transpileAndExecuteFile.js");
12
- const replaceImportStatements_js_1 = require("./replaceImportStatements.js");
11
+ const transpileAndExecuteFile_js_1 = require("./getVikeConfig/transpileAndExecuteFile.js");
13
12
  const isConfigInvalid_js_1 = require("../../../../runtime/renderPage/isConfigInvalid.js");
14
13
  const globalContext_js_1 = require("../../../../runtime/globalContext.js");
15
14
  const loggerNotProd_js_1 = require("../../../shared/loggerNotProd.js");
16
15
  const removeSuperfluousViteLog_js_1 = require("../../../shared/loggerVite/removeSuperfluousViteLog.js");
17
16
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
18
17
  const helpers_js_1 = require("../../../../../shared/page-configs/helpers.js");
19
- const assertExports_js_1 = require("../../../../../shared/page-configs/assertExports.js");
20
18
  const getConfigVike_js_1 = require("../../../../shared/getConfigVike.js");
21
19
  const getConfigValuesSerialized_js_1 = require("./getConfigValuesSerialized.js");
22
20
  const crawlPlusFiles_js_1 = require("./getVikeConfig/crawlPlusFiles.js");
21
+ const getConfigFileExport_js_1 = require("./getConfigFileExport.js");
22
+ const loadFileAtConfigTime_js_1 = require("./getVikeConfig/loadFileAtConfigTime.js");
23
+ const resolveImportPath_js_1 = require("./getVikeConfig/resolveImportPath.js");
24
+ const resolveFilePath_js_1 = require("./getVikeConfig/resolveFilePath.js");
23
25
  (0, utils_js_1.assertIsNotProductionRuntime)();
24
26
  let devServerIsCorrupt = false;
25
27
  let wasConfigInvalid = null;
26
28
  let vikeConfigPromise = null;
27
29
  const vikeConfigDependencies = new Set();
28
30
  exports.vikeConfigDependencies = vikeConfigDependencies;
29
- const filesEnv = new Map();
30
31
  function reloadVikeConfig(userRootDir, outDirRoot, extensions) {
31
32
  vikeConfigDependencies.clear();
32
- filesEnv.clear();
33
+ (0, resolveImportPath_js_1.clearFilesEnvMap)();
33
34
  vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, true, extensions, true);
34
35
  handleReloadSideEffects();
35
36
  }
@@ -87,108 +88,98 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
87
88
  }
88
89
  });
89
90
  let interfaceFilesByLocationId = {};
90
- // Config files
91
- await Promise.all(configFiles.map(async (filePath) => {
92
- const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, []);
93
- const interfaceFile = getInterfaceFileFromConfigFile(configFile, false);
94
- const locationId = (0, filesystemRouting_js_1.getLocationId)(filePath.filePathAbsoluteVite);
95
- interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
96
- interfaceFilesByLocationId[locationId].push(interfaceFile);
97
- extendsConfigs.forEach((extendsConfig) => {
98
- const interfaceFile = getInterfaceFileFromConfigFile(extendsConfig, true);
99
- interfaceFilesByLocationId[locationId].push(interfaceFile);
100
- });
101
- }));
102
- // Value files
103
- await Promise.all(valueFiles.map(async (filePath) => {
104
- const configName = getConfigName(filePath.filePathAbsoluteVite);
105
- (0, utils_js_1.assert)(configName);
106
- const interfaceFile = {
107
- filePath,
108
- configMap: {
109
- [configName]: {}
110
- },
111
- isConfigFile: false,
112
- isValueFile: true,
113
- configName
114
- };
115
- {
116
- // We don't have access to the custom config definitions defined by the user yet.
117
- // - If `configDef` is `undefined` => we load the file +{configName}.js later.
118
- // - We already need to load +meta.js here (to get the custom config definitions defined by the user)
119
- const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn_js_1.configDefinitionsBuiltIn, configName);
120
- if (configDef && isConfigEnv(configDef, configName)) {
121
- await loadValueFile(interfaceFile, configName, userRootDir);
122
- }
123
- }
124
- {
125
- const locationId = (0, filesystemRouting_js_1.getLocationId)(filePath.filePathAbsoluteVite);
91
+ await Promise.all([
92
+ // Config files
93
+ ...configFiles.map(async (filePath) => {
94
+ const { filePathRelativeToUserRootDir } = filePath;
95
+ (0, utils_js_1.assert)(filePathRelativeToUserRootDir);
96
+ const { configFile, extendsConfigs } = await (0, loadFileAtConfigTime_js_1.loadConfigFile)(filePath, userRootDir, [], false);
97
+ (0, utils_js_1.assert)(filePath.filePathRelativeToUserRootDir);
98
+ const locationId = (0, filesystemRouting_js_1.getLocationId)(filePathRelativeToUserRootDir);
99
+ const interfaceFile = getInterfaceFileFromConfigFile(configFile, false, locationId);
126
100
  interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
127
101
  interfaceFilesByLocationId[locationId].push(interfaceFile);
128
- }
129
- }));
102
+ extendsConfigs.forEach((extendsConfig) => {
103
+ /* We purposely use the same locationId because the Vike extension's config should only apply to where it's being extended from, for example:
104
+ ```js
105
+ // /pages/admin/+config.h.js
106
+
107
+ import vikeVue from 'vike-vue/config'
108
+ // Should only apply to /pages/admin/**
109
+ export default { extends: [vikeVue] }
110
+ ```
111
+ ```js
112
+ // /pages/marketing/+config.h.js
113
+
114
+ import vikeReact from 'vike-react/config'
115
+ // Should only apply to /pages/marketing/**
116
+ export default { extends: [vikeReact] }
117
+ ```
118
+ */
119
+ const interfaceFile = getInterfaceFileFromConfigFile(extendsConfig, true, locationId);
120
+ interfaceFilesByLocationId[locationId].push(interfaceFile);
121
+ });
122
+ }),
123
+ // Value files
124
+ ...valueFiles.map(async (filePath) => {
125
+ const { filePathRelativeToUserRootDir } = filePath;
126
+ (0, utils_js_1.assert)(filePathRelativeToUserRootDir);
127
+ const configName = getConfigName(filePathRelativeToUserRootDir);
128
+ (0, utils_js_1.assert)(configName);
129
+ const locationId = (0, filesystemRouting_js_1.getLocationId)(filePathRelativeToUserRootDir);
130
+ const interfaceFile = {
131
+ locationId,
132
+ filePath,
133
+ fileExportsByConfigName: {
134
+ [configName]: {}
135
+ },
136
+ isConfigFile: false,
137
+ isValueFile: true,
138
+ configName
139
+ };
140
+ {
141
+ // We don't have access to the custom config definitions defined by the user yet.
142
+ // - If `configDef` is `undefined` => we load the file +{configName}.js later.
143
+ // - We already need to load +meta.js here (to get the custom config definitions defined by the user)
144
+ const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn_js_1.configDefinitionsBuiltIn, configName);
145
+ if (configDef && isConfigEnv(configDef, configName)) {
146
+ await (0, loadFileAtConfigTime_js_1.loadValueFile)(interfaceFile, configName, userRootDir);
147
+ }
148
+ }
149
+ {
150
+ interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
151
+ interfaceFilesByLocationId[locationId].push(interfaceFile);
152
+ }
153
+ })
154
+ ]);
130
155
  assertAllConfigsAreKnown(interfaceFilesByLocationId);
131
156
  return interfaceFilesByLocationId;
132
157
  }
133
- function getConfigDefinition(configDefinitionsRelevant, configName, filePathToShowToUser) {
134
- const configDef = configDefinitionsRelevant[configName];
135
- assertConfigExists(configName, Object.keys(configDefinitionsRelevant), filePathToShowToUser);
136
- (0, utils_js_1.assert)(configDef);
137
- return configDef;
138
- }
139
- function getConfigDefinitionOptional(configDefinitions, configName) {
140
- return configDefinitions[configName] ?? null;
141
- }
142
- async function loadValueFile(interfaceValueFile, configName, userRootDir) {
143
- const { fileExports } = await (0, transpileAndExecuteFile_js_1.transpileAndExecuteFile)(interfaceValueFile.filePath, true, userRootDir);
144
- const { filePathToShowToUser } = interfaceValueFile.filePath;
145
- (0, assertExports_js_1.assertExportsOfValueFile)(fileExports, filePathToShowToUser, configName);
146
- Object.entries(fileExports).forEach(([exportName, configValue]) => {
147
- const configName_ = exportName === 'default' ? configName : exportName;
148
- interfaceValueFile.configMap[configName_] = { configValue };
149
- });
150
- }
151
- async function loadImportedFile(filePath, userRootDir, importedFilesLoaded) {
152
- const f = filePath.filePathAbsoluteFilesystem;
153
- if (!importedFilesLoaded[f]) {
154
- importedFilesLoaded[f] = (0, transpileAndExecuteFile_js_1.transpileAndExecuteFile)(filePath, true, userRootDir).then((r) => r.fileExports);
155
- }
156
- const fileExports = await importedFilesLoaded[f];
157
- return fileExports;
158
- }
159
- function isConfigEnv(configDef, configName) {
160
- const configEnv = configDef.env;
161
- if (configDef.cumulative) {
162
- // In principle we could lift that requirement (but it requires non-trivial modifications)
163
- (0, utils_js_1.assertUsage)(configEnv.config, `Config ${picocolors_1.default.cyan(configName)} needs its ${picocolors_1.default.cyan('env')} to have ${picocolors_1.default.cyan('{ config: true }')} (because ${picocolors_1.default.cyan(configName)} is a ${picocolors_1.default.cyan('cumulative')} config)`);
164
- }
165
- return !!configEnv.config;
166
- }
167
- function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
158
+ function getInterfaceFileFromConfigFile(configFile, isConfigExtend, locationId) {
168
159
  const { fileExports, filePath, extendsFilePaths } = configFile;
169
160
  const interfaceFile = {
161
+ locationId,
170
162
  filePath,
171
- configMap: {},
163
+ fileExportsByConfigName: {},
172
164
  isConfigFile: true,
173
165
  isValueFile: false,
174
166
  isConfigExtend,
175
167
  extendsFilePaths
176
168
  };
177
- const { filePathToShowToUser } = filePath;
178
- (0, assertExports_js_1.assertExportsOfConfigFile)(fileExports, filePathToShowToUser);
179
- Object.entries(fileExports.default).forEach(([configName, configValue]) => {
180
- interfaceFile.configMap[configName] = { configValue };
169
+ const fileExport = (0, getConfigFileExport_js_1.getConfigFileExport)(fileExports, filePath.filePathToShowToUser);
170
+ Object.entries(fileExport).forEach(([configName, configValue]) => {
171
+ interfaceFile.fileExportsByConfigName[configName] = { configValue };
181
172
  });
182
173
  return interfaceFile;
183
174
  }
184
175
  /** Show error message upon unknown config */
185
176
  function assertAllConfigsAreKnown(interfaceFilesByLocationId) {
186
- Object.entries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
177
+ (0, utils_js_1.objectEntries)(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
187
178
  const interfaceFilesRelevant = getInterfaceFilesRelevant(interfaceFilesByLocationId, locationId);
188
- const configDefinitionsRelevant = getConfigDefinitions(interfaceFilesRelevant);
179
+ const configDefinitions = getConfigDefinitions(interfaceFilesRelevant);
189
180
  interfaceFiles.forEach((interfaceFile) => {
190
- Object.keys(interfaceFile.configMap).forEach((configName) => {
191
- assertConfigExists(configName, Object.keys(configDefinitionsRelevant), interfaceFile.filePath.filePathToShowToUser);
181
+ Object.keys(interfaceFile.fileExportsByConfigName).forEach((configName) => {
182
+ assertConfigExists(configName, Object.keys(configDefinitions), interfaceFile.filePath.filePathToShowToUser);
192
183
  });
193
184
  });
194
185
  });
@@ -238,11 +229,11 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
238
229
  const interfaceFilesByLocationId = await loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions);
239
230
  const importedFilesLoaded = {};
240
231
  const { globalVikeConfig, pageConfigGlobal } = await getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded);
241
- const pageConfigs = await Promise.all(Object.entries(interfaceFilesByLocationId)
232
+ const pageConfigs = await Promise.all((0, utils_js_1.objectEntries)(interfaceFilesByLocationId)
242
233
  .filter(([_pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
243
234
  .map(async ([locationId]) => {
244
235
  const interfaceFilesRelevant = getInterfaceFilesRelevant(interfaceFilesByLocationId, locationId);
245
- const configDefinitionsRelevant = getConfigDefinitions(interfaceFilesRelevant);
236
+ const configDefinitions = getConfigDefinitions(interfaceFilesRelevant);
246
237
  // Load value files of custom config-only configs
247
238
  await Promise.all(getInterfaceFileList(interfaceFilesRelevant).map(async (interfaceFile) => {
248
239
  if (!interfaceFile.isValueFile)
@@ -250,7 +241,7 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
250
241
  const { configName } = interfaceFile;
251
242
  if (isGlobalConfig(configName))
252
243
  return;
253
- const configDef = getConfigDefinition(configDefinitionsRelevant, configName, interfaceFile.filePath.filePathToShowToUser);
244
+ const configDef = getConfigDefinition(configDefinitions, configName, interfaceFile.filePath.filePathToShowToUser);
254
245
  if (!isConfigEnv(configDef, configName))
255
246
  return;
256
247
  const isAlreadyLoaded = interfacefileIsAlreaydLoaded(interfaceFile);
@@ -258,10 +249,10 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
258
249
  return;
259
250
  // Value files of built-in configs should have already been loaded at loadInterfaceFiles()
260
251
  (0, utils_js_1.assert)(!(configName in configDefinitionsBuiltIn_js_1.configDefinitionsBuiltIn));
261
- await loadValueFile(interfaceFile, configName, userRootDir);
252
+ await (0, loadFileAtConfigTime_js_1.loadValueFile)(interfaceFile, configName, userRootDir);
262
253
  }));
263
- const configValueSources = {};
264
- await Promise.all((0, utils_js_1.objectEntries)(configDefinitionsRelevant)
254
+ let configValueSources = {};
255
+ await Promise.all((0, utils_js_1.objectEntries)(configDefinitions)
265
256
  .filter(([configName]) => !isGlobalConfig(configName))
266
257
  .map(async ([configName, configDef]) => {
267
258
  const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded);
@@ -269,10 +260,12 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
269
260
  return;
270
261
  configValueSources[configName] = sources;
271
262
  }));
263
+ configValueSources = sortConfigValueSources(configValueSources, locationId);
264
+ console.log(JSON.stringify(configValueSources, null, 2));
272
265
  const { routeFilesystem, isErrorPage } = determineRouteFilesystem(locationId, configValueSources);
273
- applyEffectsAll(configValueSources, configDefinitionsRelevant);
274
- const configValuesComputed = getComputed(configValueSources, configDefinitionsRelevant);
275
- const configValues = getConfigValues(configValueSources, configValuesComputed, configDefinitionsRelevant);
266
+ applyEffectsAll(configValueSources, configDefinitions);
267
+ const configValuesComputed = getComputed(configValueSources, configDefinitions);
268
+ const configValues = getConfigValues(configValueSources, configValuesComputed, configDefinitions);
276
269
  const pageConfig = {
277
270
  pageId: locationId,
278
271
  isErrorPage,
@@ -301,7 +294,7 @@ function assertOnBeforeRenderEnv(pageConfig) {
301
294
  (0, utils_js_1.assertUsage)(!(onBeforeRenderEnv.client && !isClientRouting), `Page ${pageConfig.pageId} has an onBeforeRender() hook with env ${picocolors_1.default.cyan(JSON.stringify(onBeforeRenderEnv))} which doesn't make sense because the page is using Server Routing: onBeforeRender() can be run in the client only when using Client Routing.`);
302
295
  }
303
296
  function interfacefileIsAlreaydLoaded(interfaceFile) {
304
- const configMapValues = Object.values(interfaceFile.configMap);
297
+ const configMapValues = Object.values(interfaceFile.fileExportsByConfigName);
305
298
  const isAlreadyLoaded = configMapValues.some((conf) => 'configValue' in conf);
306
299
  if (isAlreadyLoaded) {
307
300
  (0, utils_js_1.assert)(configMapValues.every((conf) => 'configValue' in conf));
@@ -309,7 +302,7 @@ function interfacefileIsAlreaydLoaded(interfaceFile) {
309
302
  return isAlreadyLoaded;
310
303
  }
311
304
  function getInterfaceFilesRelevant(interfaceFilesByLocationId, locationIdPage) {
312
- const interfaceFilesRelevant = Object.fromEntries(Object.entries(interfaceFilesByLocationId)
305
+ const interfaceFilesRelevant = Object.fromEntries((0, utils_js_1.objectEntries)(interfaceFilesByLocationId)
313
306
  .filter(([locationId]) => {
314
307
  return (0, filesystemRouting_js_1.isInherited)(locationId, locationIdPage);
315
308
  })
@@ -324,14 +317,14 @@ function getInterfaceFileList(interfaceFilesByLocationId) {
324
317
  return interfaceFiles;
325
318
  }
326
319
  async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded) {
327
- const locationIds = Object.keys(interfaceFilesByLocationId);
328
- const interfaceFilesGlobal = Object.fromEntries(Object.entries(interfaceFilesByLocationId).filter(([locationId]) => {
320
+ const locationIds = (0, utils_js_1.objectKeys)(interfaceFilesByLocationId);
321
+ const interfaceFilesGlobal = (0, utils_js_1.objectFromEntries)((0, utils_js_1.objectEntries)(interfaceFilesByLocationId).filter(([locationId]) => {
329
322
  return (0, filesystemRouting_js_1.isGlobalLocation)(locationId, locationIds);
330
323
  }));
331
324
  // Validate that global configs live in global interface files
332
325
  {
333
326
  const interfaceFilesGlobalPaths = [];
334
- Object.entries(interfaceFilesGlobal).forEach(([locationId, interfaceFiles]) => {
327
+ (0, utils_js_1.objectEntries)(interfaceFilesGlobal).forEach(([locationId, interfaceFiles]) => {
335
328
  (0, utils_js_1.assert)((0, filesystemRouting_js_1.isGlobalLocation)(locationId, locationIds));
336
329
  interfaceFiles.forEach(({ filePath: { filePathRelativeToUserRootDir } }) => {
337
330
  if (filePathRelativeToUserRootDir) {
@@ -340,9 +333,9 @@ async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importe
340
333
  });
341
334
  });
342
335
  const globalPaths = Array.from(new Set(interfaceFilesGlobalPaths.map((p) => path_1.default.posix.dirname(p))));
343
- Object.entries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
336
+ (0, utils_js_1.objectEntries)(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
344
337
  interfaceFiles.forEach((interfaceFile) => {
345
- Object.keys(interfaceFile.configMap).forEach((configName) => {
338
+ Object.keys(interfaceFile.fileExportsByConfigName).forEach((configName) => {
346
339
  if (!(0, filesystemRouting_js_1.isGlobalLocation)(locationId, locationIds) && isGlobalConfig(configName)) {
347
340
  (0, utils_js_1.assertUsage)(false, [
348
341
  `${interfaceFile.filePath.filePathToShowToUser} defines the config ${picocolors_1.default.cyan(configName)} which is global:`,
@@ -383,7 +376,7 @@ async function resolveConfigValueSources(configName, configDef, interfaceFilesRe
383
376
  const sourcesInfo = [];
384
377
  // interfaceFilesRelevant is sorted by sortAfterInheritanceOrder()
385
378
  for (const interfaceFiles of Object.values(interfaceFilesRelevant)) {
386
- const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.configMap[configName]);
379
+ const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.fileExportsByConfigName[configName]);
387
380
  if (interfaceFilesDefiningConfig.length === 0)
388
381
  continue;
389
382
  const visited = new WeakSet();
@@ -461,19 +454,21 @@ function isInterfaceFileUserLand(interfaceFile) {
461
454
  return (interfaceFile.isConfigFile && !interfaceFile.isConfigExtend) || interfaceFile.isValueFile;
462
455
  }
463
456
  async function getConfigValueSource(configName, interfaceFile, configDef, userRootDir, importedFilesLoaded) {
464
- const conf = interfaceFile.configMap[configName];
457
+ const conf = interfaceFile.fileExportsByConfigName[configName];
465
458
  (0, utils_js_1.assert)(conf);
466
459
  const configEnv = configDef.env;
460
+ const { locationId } = interfaceFile;
467
461
  const definedAtConfigFile = {
468
462
  ...interfaceFile.filePath,
469
463
  fileExportPathToShowToUser: ['default', configName]
470
464
  };
465
+ // +client.js
471
466
  if (configDef._valueIsFilePath) {
472
467
  let definedAt;
473
468
  let valueFilePath;
474
469
  if (interfaceFile.isConfigFile) {
475
470
  const { configValue } = conf;
476
- const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
471
+ const import_ = (0, resolveImportPath_js_1.resolveImport)(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
477
472
  const configDefinedAt = (0, helpers_js_1.getConfigDefinedAtString)('Config', configName, { definedAt: definedAtConfigFile });
478
473
  (0, utils_js_1.assertUsage)(import_, `${configDefinedAt} should be an import`);
479
474
  valueFilePath = import_.filePathAbsoluteVite;
@@ -488,6 +483,7 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
488
483
  };
489
484
  }
490
485
  const configValueSource = {
486
+ locationId,
491
487
  value: valueFilePath,
492
488
  valueIsFilePath: true,
493
489
  configEnv,
@@ -496,22 +492,27 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
496
492
  };
497
493
  return configValueSource;
498
494
  }
495
+ // +config.js
499
496
  if (interfaceFile.isConfigFile) {
500
497
  (0, utils_js_1.assert)('configValue' in conf);
501
498
  const { configValue } = conf;
502
- const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
499
+ // fake import
500
+ const import_ = (0, resolveImportPath_js_1.resolveImport)(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
503
501
  if (import_) {
504
502
  const configValueSource = {
503
+ locationId,
505
504
  configEnv,
506
505
  valueIsImportedAtRuntime: true,
507
506
  definedAt: import_
508
507
  };
509
- // Load config value
510
- if (isConfigEnv(configDef, configName)) {
508
+ // Load fake import
509
+ if (isConfigEnv(configDef, configName) &&
510
+ // The value of `extends` was already loaded and already used: we don't need the value of `extends` anymore
511
+ configName !== 'extends') {
511
512
  if (import_.filePathAbsoluteFilesystem) {
512
513
  (0, utils_js_1.assert)((0, utils_js_1.hasProp)(import_, 'filePathAbsoluteFilesystem', 'string')); // Help TS
513
- const fileExports = await loadImportedFile(import_, userRootDir, importedFilesLoaded);
514
- configValueSource.value = fileExports[import_.fileExportName];
514
+ const fileExport = await (0, loadFileAtConfigTime_js_1.loadImportedFile)(import_, userRootDir, importedFilesLoaded);
515
+ configValueSource.value = fileExport;
515
516
  }
516
517
  else {
517
518
  const configDefinedAt = (0, helpers_js_1.getConfigDefinedAtString)('Config', configName, configValueSource);
@@ -520,20 +521,22 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
520
521
  }
521
522
  return configValueSource;
522
523
  }
523
- else {
524
- const configValueSource = {
525
- value: configValue,
526
- configEnv,
527
- valueIsImportedAtRuntime: false,
528
- definedAt: definedAtConfigFile
529
- };
530
- return configValueSource;
531
- }
524
+ // Defined by config file, i.e. +config.js file
525
+ const configValueSource = {
526
+ locationId,
527
+ value: configValue,
528
+ configEnv,
529
+ valueIsImportedAtRuntime: false,
530
+ definedAt: definedAtConfigFile
531
+ };
532
+ return configValueSource;
532
533
  }
533
- else if (interfaceFile.isValueFile) {
534
+ // Defined by value file, i.e. +{configName}.js
535
+ if (interfaceFile.isValueFile) {
534
536
  const valueAlreadyLoaded = 'configValue' in conf;
535
537
  (0, utils_js_1.assert)(valueAlreadyLoaded === !!configEnv.config);
536
538
  const configValueSource = {
539
+ locationId,
537
540
  configEnv,
538
541
  valueIsImportedAtRuntime: !valueAlreadyLoaded,
539
542
  definedAt: {
@@ -551,25 +554,9 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
551
554
  }
552
555
  (0, utils_js_1.assert)(false);
553
556
  }
554
- function assertFileEnv(filePathForEnvCheck, configEnv, configName) {
555
- (0, utils_js_1.assertPosixPath)(filePathForEnvCheck);
556
- if (!filesEnv.has(filePathForEnvCheck)) {
557
- filesEnv.set(filePathForEnvCheck, []);
558
- }
559
- const fileEnv = filesEnv.get(filePathForEnvCheck);
560
- fileEnv.push({ configEnv, configName });
561
- const configDifferentEnv = fileEnv.filter((c) => !(0, utils_js_1.deepEqual)(c.configEnv, configEnv))[0];
562
- if (configDifferentEnv) {
563
- (0, utils_js_1.assertUsage)(false, [
564
- `${filePathForEnvCheck} defines the value of configs living in different environments:`,
565
- ...[configDifferentEnv, { configName, configEnv }].map((c) => ` - config ${picocolors_1.default.cyan(c.configName)} which value lives in environment ${picocolors_1.default.cyan(JSON.stringify(c.configEnv))}`),
566
- 'Defining config values in the same file is allowed only if they live in the same environment, see https://vike.dev/header-file'
567
- ].join('\n'));
568
- }
569
- }
570
557
  function isDefiningPage(interfaceFiles) {
571
558
  for (const interfaceFile of interfaceFiles) {
572
- const configNames = Object.keys(interfaceFile.configMap);
559
+ const configNames = Object.keys(interfaceFile.fileExportsByConfigName);
573
560
  if (configNames.some((configName) => isDefiningPageConfig(configName))) {
574
561
  return true;
575
562
  }
@@ -579,90 +566,13 @@ function isDefiningPage(interfaceFiles) {
579
566
  function isDefiningPageConfig(configName) {
580
567
  return ['Page', 'route'].includes(configName);
581
568
  }
582
- function resolveImport(configValue, importerFilePath, userRootDir, configEnv, configName) {
583
- if (typeof configValue !== 'string')
584
- return null;
585
- const importData = (0, replaceImportStatements_js_1.parseImportData)(configValue);
586
- if (!importData)
587
- return null;
588
- const { importPath, exportName } = importData;
589
- const filePathAbsoluteFilesystem = resolveImportPath(importData, importerFilePath);
590
- assertFileEnv(filePathAbsoluteFilesystem ?? importPath, configEnv, configName);
591
- const fileExportPathToShowToUser = exportName === 'default' || exportName === configName ? [] : [exportName];
592
- if (importPath.startsWith('.')) {
593
- // We need to resolve relative paths into absolute paths. Because the import paths are included in virtual files:
594
- // ```
595
- // [vite] Internal server error: Failed to resolve import "./onPageTransitionHooks" from "virtual:vike:pageConfigValuesAll:client:/pages/index". Does the file exist?
596
- // ```
597
- assertImportPath(filePathAbsoluteFilesystem, importData, importerFilePath);
598
- const filePathRelativeToUserRootDir = resolveImportPath_relativeToUserRootDir(filePathAbsoluteFilesystem, importData, importerFilePath, userRootDir);
599
- const filePath = {
600
- filePathAbsoluteFilesystem,
601
- filePathRelativeToUserRootDir,
602
- filePathAbsoluteVite: filePathRelativeToUserRootDir,
603
- filePathToShowToUser: filePathRelativeToUserRootDir,
604
- importPathAbsolute: null
605
- };
606
- return {
607
- ...filePath,
608
- fileExportName: exportName,
609
- fileExportPathToShowToUser
610
- };
611
- }
612
- else {
613
- // importPath can be:
614
- // - an npm package import
615
- // - a path alias
616
- const filePath = {
617
- filePathAbsoluteFilesystem,
618
- filePathRelativeToUserRootDir: null,
619
- filePathAbsoluteVite: importPath,
620
- filePathToShowToUser: importPath,
621
- importPathAbsolute: importPath
622
- };
623
- return {
624
- ...filePath,
625
- fileExportName: exportName,
626
- fileExportPathToShowToUser
627
- };
628
- }
629
- }
630
- function resolveImportPath_relativeToUserRootDir(filePathAbsoluteFilesystem, importData, configFilePath, userRootDir) {
631
- (0, utils_js_1.assertPosixPath)(userRootDir);
632
- let filePathRelativeToUserRootDir;
633
- if (filePathAbsoluteFilesystem.startsWith(userRootDir)) {
634
- filePathRelativeToUserRootDir = getVitePathFromAbsolutePath(filePathAbsoluteFilesystem, userRootDir);
635
- }
636
- else {
637
- (0, utils_js_1.assertUsage)(false, `${configFilePath.filePathToShowToUser} imports from a relative path ${picocolors_1.default.cyan(importData.importPath)} outside of ${userRootDir} which is forbidden: import from a relative path inside ${userRootDir}, or import from a dependency's package.json#exports entry instead`);
638
- // None of the following works. Seems to be a Vite bug?
639
- // /*
640
- // assert(filePathAbsoluteFilesystem.startsWith('/'))
641
- // filePath = `/@fs${filePathAbsoluteFilesystem}`
642
- // /*/
643
- // filePathRelativeToUserRootDir = path.posix.relative(userRootDir, filePathAbsoluteFilesystem)
644
- // assert(filePathRelativeToUserRootDir.startsWith('../'))
645
- // filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir
646
- // //*/
647
- }
648
- (0, utils_js_1.assertPosixPath)(filePathRelativeToUserRootDir);
649
- (0, utils_js_1.assert)(filePathRelativeToUserRootDir.startsWith('/'));
650
- return filePathRelativeToUserRootDir;
651
- }
652
- function getVitePathFromAbsolutePath(filePathAbsoluteFilesystem, root) {
653
- (0, utils_js_1.assertPosixPath)(filePathAbsoluteFilesystem);
654
- (0, utils_js_1.assertPosixPath)(root);
655
- (0, utils_js_1.assert)(filePathAbsoluteFilesystem.startsWith(root));
656
- let vitePath = path_1.default.posix.relative(root, filePathAbsoluteFilesystem);
657
- (0, utils_js_1.assert)(!vitePath.startsWith('/') && !vitePath.startsWith('.'));
658
- vitePath = '/' + vitePath;
659
- return vitePath;
660
- }
661
569
  function getConfigDefinitions(interfaceFilesRelevant) {
662
- const configDefinitions = { ...configDefinitionsBuiltIn_js_1.configDefinitionsBuiltIn };
663
- Object.entries(interfaceFilesRelevant).forEach(([_locationId, interfaceFiles]) => {
570
+ const configDefinitionsMerged = { ...configDefinitionsBuiltIn_js_1.configDefinitionsBuiltIn };
571
+ Object.entries(interfaceFilesRelevant)
572
+ .reverse()
573
+ .forEach(([_locationId, interfaceFiles]) => {
664
574
  interfaceFiles.forEach((interfaceFile) => {
665
- const configMeta = interfaceFile.configMap['meta'];
575
+ const configMeta = interfaceFile.fileExportsByConfigName['meta'];
666
576
  if (!configMeta)
667
577
  return;
668
578
  const meta = configMeta.configValue;
@@ -679,13 +589,14 @@ function getConfigDefinitions(interfaceFilesRelevant) {
679
589
  });
680
590
  (0, utils_js_1.objectEntries)(meta).forEach(([configName, configDefinition]) => {
681
591
  // User can override an existing config definition
682
- configDefinitions[configName] = {
683
- ...configDefinitions[configName],
592
+ configDefinitionsMerged[configName] = {
593
+ ...configDefinitionsMerged[configName],
684
594
  ...configDefinition
685
595
  };
686
596
  });
687
597
  });
688
598
  });
599
+ const configDefinitions = configDefinitionsMerged;
689
600
  return configDefinitions;
690
601
  }
691
602
  function assertMetaValue(metaVal, configMetaDefinedAt) {
@@ -724,8 +635,8 @@ function assertMetaValue(metaVal, configMetaDefinedAt) {
724
635
  }
725
636
  });
726
637
  }
727
- function applyEffectsAll(configValueSources, configDefinitionsRelevant) {
728
- (0, utils_js_1.objectEntries)(configDefinitionsRelevant).forEach(([configName, configDef]) => {
638
+ function applyEffectsAll(configValueSources, configDefinitions) {
639
+ (0, utils_js_1.objectEntries)(configDefinitions).forEach(([configName, configDef]) => {
729
640
  if (!configDef.effect)
730
641
  return;
731
642
  // The value needs to be loaded at config time, that's why we only support effect for configs that are config-only for now.
@@ -784,9 +695,9 @@ function applyEffect(configModFromEffect, configValueSources, configDefEffect) {
784
695
  }
785
696
  });
786
697
  }
787
- function getComputed(configValueSources, configDefinitionsRelevant) {
698
+ function getComputed(configValueSources, configDefinitions) {
788
699
  const configValuesComputed = {};
789
- (0, utils_js_1.objectEntries)(configDefinitionsRelevant).forEach(([configName, configDef]) => {
700
+ (0, utils_js_1.objectEntries)(configDefinitions).forEach(([configName, configDef]) => {
790
701
  if (!configDef._computed)
791
702
  return;
792
703
  const value = configDef._computed(configValueSources);
@@ -801,15 +712,7 @@ function getComputed(configValueSources, configDefinitionsRelevant) {
801
712
  }
802
713
  async function findPlusFiles(userRootDir, outDirRoot, isDev, extensions) {
803
714
  const files = await (0, crawlPlusFiles_js_1.crawlPlusFiles)(userRootDir, outDirRoot, isDev);
804
- const plusFiles = files.map(({ filePathRelativeToUserRootDir, filePathAbsoluteFilesystem }) => {
805
- return {
806
- filePathRelativeToUserRootDir,
807
- filePathAbsoluteVite: filePathRelativeToUserRootDir,
808
- filePathAbsoluteFilesystem,
809
- filePathToShowToUser: filePathRelativeToUserRootDir,
810
- importPathAbsolute: null
811
- };
812
- });
715
+ const plusFiles = files.map(({ filePathRelativeToUserRootDir }) => (0, resolveFilePath_js_1.resolveFilePathRelativeToUserRootDir)(filePathRelativeToUserRootDir, userRootDir));
813
716
  // TODO/v1-release: remove
814
717
  extensions.forEach((extension) => {
815
718
  extension.pageConfigsDistFiles?.forEach((pageConfigDistFile) => {
@@ -845,125 +748,22 @@ function getConfigName(filePath) {
845
748
  return configName;
846
749
  }
847
750
  }
848
- async function loadConfigFile(configFilePath, userRootDir, visited) {
849
- const { filePathAbsoluteFilesystem } = configFilePath;
850
- assertNoInfiniteLoop(visited, filePathAbsoluteFilesystem);
851
- const { fileExports } = await (0, transpileAndExecuteFile_js_1.transpileAndExecuteFile)(configFilePath, false, userRootDir);
852
- const { extendsConfigs, extendsFilePaths } = await loadExtendsConfigs(fileExports, configFilePath, userRootDir, [
853
- ...visited,
854
- filePathAbsoluteFilesystem
855
- ]);
856
- const configFile = {
857
- fileExports,
858
- filePath: configFilePath,
859
- extendsFilePaths
860
- };
861
- return { configFile, extendsConfigs };
862
- }
863
- function assertNoInfiniteLoop(visited, filePathAbsoluteFilesystem) {
864
- const idx = visited.indexOf(filePathAbsoluteFilesystem);
865
- if (idx === -1)
866
- return;
867
- const loop = visited.slice(idx);
868
- (0, utils_js_1.assert)(loop[0] === filePathAbsoluteFilesystem);
869
- (0, utils_js_1.assertUsage)(idx === -1, `Infinite extends loop ${[...loop, filePathAbsoluteFilesystem].join('>')}`);
870
- }
871
- async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir, visited) {
872
- const extendsImportData = getExtendsImportData(configFileExports, configFilePath);
873
- const extendsConfigFiles = [];
874
- extendsImportData.map((importData) => {
875
- const { importPath: importPath } = importData;
876
- const filePathAbsoluteFilesystem = resolveImportPath(importData, configFilePath);
877
- assertImportPath(filePathAbsoluteFilesystem, importData, configFilePath);
878
- assertExtendsImportPath(importPath, filePathAbsoluteFilesystem, configFilePath);
879
- // - filePathRelativeToUserRootDir has no functionality beyond nicer error messages for user
880
- // - Using importPath would be visually nicer but it's ambigous => we rather pick filePathAbsoluteFilesystem for added clarity
881
- const filePathRelativeToUserRootDir = determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir);
882
- const filePathAbsoluteVite = filePathRelativeToUserRootDir ?? importPath;
883
- extendsConfigFiles.push({
884
- filePathAbsoluteFilesystem,
885
- filePathAbsoluteVite,
886
- filePathRelativeToUserRootDir,
887
- filePathToShowToUser: filePathAbsoluteVite,
888
- importPathAbsolute: importPath
889
- });
890
- });
891
- const extendsConfigs = [];
892
- await Promise.all(extendsConfigFiles.map(async (configFilePath) => {
893
- const result = await loadConfigFile(configFilePath, userRootDir, visited);
894
- extendsConfigs.push(result.configFile);
895
- extendsConfigs.push(...result.extendsConfigs);
896
- }));
897
- const extendsFilePaths = extendsConfigFiles.map((f) => f.filePathAbsoluteFilesystem);
898
- return { extendsConfigs, extendsFilePaths };
899
- }
900
- function determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir) {
901
- (0, utils_js_1.assertPosixPath)(filePathAbsoluteFilesystem);
902
- (0, utils_js_1.assertPosixPath)(userRootDir);
903
- if (!filePathAbsoluteFilesystem.startsWith(userRootDir)) {
904
- return null;
905
- }
906
- let filePathRelativeToUserRootDir = filePathAbsoluteFilesystem.slice(userRootDir.length);
907
- if (!filePathRelativeToUserRootDir.startsWith('/'))
908
- filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir;
909
- return filePathRelativeToUserRootDir;
910
- }
911
- function assertExtendsImportPath(importPath, filePath, configFilePath) {
912
- if ((0, utils_js_1.isNpmPackageImport)(importPath)) {
913
- const fileDir = path_1.default.posix.dirname(filePath) + '/';
914
- const fileName = path_1.default.posix.basename(filePath);
915
- const fileNameBaseCorrect = '+config';
916
- const [fileNameBase, ...fileNameRest] = fileName.split('.');
917
- const fileNameCorrect = [fileNameBaseCorrect, ...fileNameRest].join('.');
918
- (0, utils_js_1.assertWarning)(fileNameBase === fileNameBaseCorrect, `Rename ${fileName} to ${fileNameCorrect} in ${fileDir}`, {
919
- onlyOnce: true
920
- });
921
- }
922
- else {
923
- (0, utils_js_1.assertWarning)(false, `${configFilePath.filePathToShowToUser} uses ${picocolors_1.default.cyan('extends')} to inherit from ${picocolors_1.default.cyan(importPath)} which is a user-land file: this is experimental and may be remove at any time. Reach out to a maintainer if you need this feature.`, { onlyOnce: true });
924
- }
925
- }
926
- function getExtendsImportData(configFileExports, configFilePath) {
927
- const { filePathToShowToUser } = configFilePath;
928
- (0, assertExports_js_1.assertExportsOfConfigFile)(configFileExports, filePathToShowToUser);
929
- const defaultExports = configFileExports.default;
930
- const wrongUsage = `${filePathToShowToUser} sets the config ${picocolors_1.default.cyan('extends')} to an invalid value, see https://vike.dev/extends`;
931
- let extendList;
932
- if (!('extends' in defaultExports)) {
933
- return [];
934
- }
935
- else if ((0, utils_js_1.hasProp)(defaultExports, 'extends', 'string')) {
936
- extendList = [defaultExports.extends];
937
- }
938
- else if ((0, utils_js_1.hasProp)(defaultExports, 'extends', 'string[]')) {
939
- extendList = defaultExports.extends;
940
- }
941
- else {
942
- (0, utils_js_1.assertUsage)(false, wrongUsage);
943
- }
944
- const extendsImportData = extendList.map((importDataSerialized) => {
945
- const importData = (0, replaceImportStatements_js_1.parseImportData)(importDataSerialized);
946
- (0, utils_js_1.assertUsage)(importData, wrongUsage);
947
- return importData;
948
- });
949
- return extendsImportData;
950
- }
951
- function isGlobalConfig(configName) {
952
- if (configName === 'prerender')
953
- return false;
954
- const configNamesGlobal = getConfigNamesGlobal();
955
- return (0, utils_js_1.arrayIncludes)(configNamesGlobal, configName);
956
- }
957
- function getConfigNamesGlobal() {
958
- return Object.keys(configDefinitionsBuiltIn_js_1.configDefinitionsBuiltInGlobal);
959
- }
960
- function assertConfigExists(configName, configNamesRelevant, filePathToShowToUser) {
961
- const configNames = [...configNamesRelevant, ...getConfigNamesGlobal()];
962
- if (configNames.includes(configName))
963
- return;
964
- handleUnknownConfig(configName, configNames, filePathToShowToUser);
965
- (0, utils_js_1.assert)(false);
966
- }
751
+ /* https://github.com/vikejs/vike/issues/1407
752
+ function assertNoUnexpectedPlusSign(filePath: string, fileName: string) {
753
+ const dirs = path.posix.dirname(filePath).split('/')
754
+ dirs.forEach((dir, i) => {
755
+ const dirPath = dirs.slice(0, i + 1).join('/')
756
+ assertUsage(
757
+ !dir.includes('+'),
758
+ `Character '+' is a reserved character: remove '+' from the directory name ${dirPath}/`
759
+ )
760
+ })
761
+ assertUsage(
762
+ !fileName.slice(1).includes('+'),
763
+ `Character '+' is only allowed at the beginning of filenames: make sure ${filePath} doesn't contain any '+' in its filename other than its first letter`
764
+ )
765
+ }
766
+ */
967
767
  function handleUnknownConfig(configName, configNames, filePathToShowToUser) {
968
768
  let errMsg = `${filePathToShowToUser} defines an unknown config ${picocolors_1.default.cyan(configName)}`;
969
769
  let configNameSimilar = null;
@@ -1030,37 +830,11 @@ function determineIsErrorPage(routeFilesystem) {
1030
830
  (0, utils_js_1.assertPosixPath)(routeFilesystem);
1031
831
  return routeFilesystem.split('/').includes('_error');
1032
832
  }
1033
- function resolveImportPath(importData, importerFilePath) {
1034
- const importerFilePathAbsolute = importerFilePath.filePathAbsoluteFilesystem;
1035
- (0, utils_js_1.assertPosixPath)(importerFilePathAbsolute);
1036
- const cwd = path_1.default.posix.dirname(importerFilePathAbsolute);
1037
- // We can't use import.meta.resolve() as of Junary 2023 (and probably for a lot longer): https://stackoverflow.com/questions/54977743/do-require-resolve-for-es-modules#comment137174954_62272600:~:text=But%20the%20argument%20parent%20(aka%20cwd)%20still%20requires%20a%20flag
1038
- // filePathAbsoluteFilesystem is expected to be null when importData.importPath is a Vite path alias
1039
- const filePathAbsoluteFilesystem = (0, utils_js_1.requireResolve)(importData.importPath, cwd);
1040
- return filePathAbsoluteFilesystem;
1041
- }
1042
- function assertImportPath(filePathAbsoluteFilesystem, importData, importerFilePath) {
1043
- const { importPath: importPath, importStringWasGenerated, importString } = importData;
1044
- const { filePathToShowToUser } = importerFilePath;
1045
- if (!filePathAbsoluteFilesystem) {
1046
- const importPathString = picocolors_1.default.cyan(`'${importPath}'`);
1047
- const errIntro = importStringWasGenerated
1048
- ? `The import path ${importPathString} in ${filePathToShowToUser}`
1049
- : `The import ${picocolors_1.default.cyan(importString)} defined in ${filePathToShowToUser}`;
1050
- const errIntro2 = `${errIntro} couldn't be resolved: does ${importPathString}`;
1051
- if (importPath.startsWith('.')) {
1052
- (0, utils_js_1.assertUsage)(false, `${errIntro2} point to an existing file?`);
1053
- }
1054
- else {
1055
- (0, utils_js_1.assertUsage)(false, `${errIntro2} exist?`);
1056
- }
1057
- }
1058
- }
1059
833
  function isVikeConfigFile(filePath) {
1060
834
  return !!getConfigName(filePath);
1061
835
  }
1062
836
  exports.isVikeConfigFile = isVikeConfigFile;
1063
- function getConfigValues(configValueSources, configValuesComputed, configDefinitionsRelevant) {
837
+ function getConfigValues(configValueSources, configValuesComputed, configDefinitions) {
1064
838
  const configValues = {};
1065
839
  Object.entries(configValuesComputed).forEach(([configName, configValueComputed]) => {
1066
840
  configValues[configName] = {
@@ -1069,7 +843,7 @@ function getConfigValues(configValueSources, configValuesComputed, configDefinit
1069
843
  };
1070
844
  });
1071
845
  Object.entries(configValueSources).forEach(([configName, sources]) => {
1072
- const configDef = configDefinitionsRelevant[configName];
846
+ const configDef = configDefinitions[configName];
1073
847
  (0, utils_js_1.assert)(configDef);
1074
848
  if (!configDef.cumulative) {
1075
849
  const configValueSource = sources[0];
@@ -1183,3 +957,48 @@ function getConfigEnvValue(val, errMsgIntro) {
1183
957
  */
1184
958
  return val;
1185
959
  }
960
+ function getConfigDefinition(configDefinitions, configName, filePathToShowToUser) {
961
+ const configDef = configDefinitions[configName];
962
+ assertConfigExists(configName, Object.keys(configDefinitions), filePathToShowToUser);
963
+ (0, utils_js_1.assert)(configDef);
964
+ return configDef;
965
+ }
966
+ function getConfigDefinitionOptional(configDefinitions, configName) {
967
+ return configDefinitions[configName] ?? null;
968
+ }
969
+ function isConfigEnv(configDef, configName) {
970
+ const configEnv = configDef.env;
971
+ if (configDef.cumulative) {
972
+ // In principle we could lift that requirement (but it requires non-trivial modifications)
973
+ (0, utils_js_1.assertUsage)(configEnv.config, `Config ${picocolors_1.default.cyan(configName)} needs its ${picocolors_1.default.cyan('env')} to have ${picocolors_1.default.cyan('{ config: true }')} (because ${picocolors_1.default.cyan(configName)} is a ${picocolors_1.default.cyan('cumulative')} config)`);
974
+ }
975
+ return !!configEnv.config;
976
+ }
977
+ function isGlobalConfig(configName) {
978
+ if (configName === 'prerender')
979
+ return false;
980
+ const configNamesGlobal = getConfigNamesGlobal();
981
+ return (0, utils_js_1.arrayIncludes)(configNamesGlobal, configName);
982
+ }
983
+ function getConfigNamesGlobal() {
984
+ return Object.keys(configDefinitionsBuiltIn_js_1.configDefinitionsBuiltInGlobal);
985
+ }
986
+ function assertConfigExists(configName, configNamesRelevant, filePathToShowToUser) {
987
+ const configNames = [...configNamesRelevant, ...getConfigNamesGlobal()];
988
+ if (configNames.includes(configName))
989
+ return;
990
+ handleUnknownConfig(configName, configNames, filePathToShowToUser);
991
+ (0, utils_js_1.assert)(false);
992
+ }
993
+ function sortConfigValueSources(configValueSources, locationIdPage) {
994
+ return Object.fromEntries(Object.entries(configValueSources)
995
+ // Make order deterministic (no other purpose)
996
+ .sort(([, [source1]], [, [source2]]) => source1.definedAt.filePathAbsoluteVite < source2.definedAt.filePathAbsoluteVite ? -1 : 1)
997
+ // Sort after whether the config value was defined by an npm package
998
+ .sort((0, utils_js_1.makeFirst)(([, [source]]) => {
999
+ const { importPathAbsolute } = source.definedAt;
1000
+ return !!importPathAbsolute && (0, utils_js_1.isNpmPackageImport)(importPathAbsolute);
1001
+ }))
1002
+ // Sort after the filesystem inheritance of the config value
1003
+ .sort(([, [source1]], [, [source2]]) => (0, utils_js_1.reverse)((0, filesystemRouting_js_1.sortAfterInheritanceOrder)(source1.locationId, source2.locationId, locationIdPage))));
1004
+ }