vike 0.4.143 → 0.4.144-commit-e40e9b1

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 (182) hide show
  1. package/dist/cjs/node/plugin/index.js +2 -2
  2. package/dist/cjs/node/plugin/plugins/buildConfig.js +1 -1
  3. package/dist/cjs/node/plugin/plugins/config/index.js +1 -1
  4. package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +31 -30
  5. package/dist/cjs/node/plugin/plugins/importUserCode/generateEagerImport.js +19 -8
  6. package/dist/cjs/node/plugin/plugins/importUserCode/getVirtualFileImportUserCode.js +19 -10
  7. package/dist/cjs/node/plugin/plugins/importUserCode/index.js +2 -2
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.js +6 -0
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +4 -4
  10. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +228 -186
  11. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +11 -35
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +60 -95
  13. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/helpers.js +12 -5
  14. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +18 -0
  15. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/replaceImportStatements.js +25 -25
  16. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +14 -13
  17. package/dist/cjs/node/plugin/shared/findPageFiles.js +2 -1
  18. package/dist/cjs/node/plugin/shared/{getConfigValueSource.js → getConfigValueSourcesRelevant.js} +1 -12
  19. package/dist/cjs/node/plugin/shared/loggerNotProd.js +1 -1
  20. package/dist/cjs/node/plugin/utils.js +2 -3
  21. package/dist/cjs/node/prerender/runPrerender.js +18 -20
  22. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +1 -1
  23. package/dist/cjs/node/runtime/renderPage/analyzePage.js +2 -2
  24. package/dist/cjs/node/runtime/renderPage/loadPageFilesServerSide.js +2 -2
  25. package/dist/cjs/node/runtime/renderPage/log404/index.js +10 -5
  26. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -2
  27. package/dist/cjs/node/runtime/renderPage.js +1 -1
  28. package/dist/cjs/node/shared/getClientEntryFilePath.js +1 -7
  29. package/dist/cjs/shared/assertPageContextProvidedByUser.js +1 -1
  30. package/dist/cjs/shared/error-page.js +1 -1
  31. package/dist/cjs/shared/getPageFiles/getExports.js +8 -11
  32. package/dist/cjs/shared/getPageFiles/parseGlobResults.js +10 -44
  33. package/dist/cjs/shared/hooks/getHook.js +3 -1
  34. package/dist/cjs/shared/page-configs/assertExports.js +60 -0
  35. package/dist/cjs/shared/page-configs/getExportPath.js +9 -10
  36. package/dist/cjs/shared/page-configs/loadConfigValues.js +18 -0
  37. package/dist/cjs/shared/page-configs/serialize/PageConfigSerialized.js +2 -0
  38. package/dist/cjs/shared/page-configs/serialize/assertPageConfigs.js +19 -0
  39. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +56 -0
  40. package/dist/cjs/shared/page-configs/serialize/parsePageConfigs.js +65 -0
  41. package/dist/cjs/shared/page-configs/serialize/serializeConfigValue.js +58 -0
  42. package/dist/cjs/shared/page-configs/utils.js +65 -42
  43. package/dist/cjs/shared/route/loadPageRoutes.js +12 -15
  44. package/dist/cjs/shared/route/resolveRedirects.js +1 -1
  45. package/dist/cjs/shared/route/resolveRouteFunction.js +1 -0
  46. package/dist/cjs/shared/utils.js +0 -1
  47. package/dist/cjs/utils/getOutDirs.js +25 -18
  48. package/dist/cjs/utils/getValuePrintable.js +1 -1
  49. package/dist/cjs/utils/objectAssign.js +3 -1
  50. package/dist/cjs/utils/projectInfo.js +1 -1
  51. package/dist/cjs/utils/{resolve.js → requireResolve.js} +3 -3
  52. package/dist/cjs/utils/warnIfErrorIsNotObject.js +1 -1
  53. package/dist/esm/__internal/index.d.ts +3 -3
  54. package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -2
  55. package/dist/esm/client/client-routing-runtime/getPageContext.d.ts +2 -2
  56. package/dist/esm/client/client-routing-runtime/getPageId.d.ts +2 -2
  57. package/dist/esm/client/client-routing-runtime/useClientRouter.js +3 -3
  58. package/dist/esm/client/server-routing-runtime/getPageContext.d.ts +1 -1
  59. package/dist/esm/client/shared/executeOnRenderClientHook.d.ts +2 -2
  60. package/dist/esm/client/shared/loadPageFilesClientSide.d.ts +2 -2
  61. package/dist/esm/client/shared/loadPageFilesClientSide.js +2 -2
  62. package/dist/esm/client/shared/preparePageContextForUserConsumptionClientSide.d.ts +2 -2
  63. package/dist/esm/node/plugin/index.js +3 -2
  64. package/dist/esm/node/plugin/plugins/buildConfig.js +2 -2
  65. package/dist/esm/node/plugin/plugins/config/index.js +2 -2
  66. package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +31 -30
  67. package/dist/esm/node/plugin/plugins/importUserCode/generateEagerImport.d.ts +13 -2
  68. package/dist/esm/node/plugin/plugins/importUserCode/generateEagerImport.js +19 -8
  69. package/dist/esm/node/plugin/plugins/importUserCode/getVirtualFileImportUserCode.js +20 -11
  70. package/dist/esm/node/plugin/plugins/importUserCode/index.js +3 -3
  71. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.d.ts +19 -2
  72. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.js +6 -0
  73. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +5 -4
  74. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +4 -4
  75. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +4 -4
  76. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +229 -187
  77. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.d.ts +1 -1
  78. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +11 -32
  79. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +3 -3
  80. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +60 -95
  81. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.d.ts +3 -3
  82. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.js +12 -5
  83. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.d.ts +7 -0
  84. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +15 -0
  85. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/replaceImportStatements.d.ts +18 -6
  86. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/replaceImportStatements.js +25 -25
  87. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.d.ts +2 -2
  88. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +14 -13
  89. package/dist/esm/node/plugin/shared/findPageFiles.js +3 -2
  90. package/dist/esm/node/plugin/shared/{getConfigValueSource.d.ts → getConfigValueSourcesRelevant.d.ts} +0 -2
  91. package/dist/esm/node/plugin/shared/{getConfigValueSource.js → getConfigValueSourcesRelevant.js} +0 -11
  92. package/dist/esm/node/plugin/shared/loggerNotProd.js +2 -2
  93. package/dist/esm/node/plugin/utils.d.ts +1 -2
  94. package/dist/esm/node/plugin/utils.js +2 -3
  95. package/dist/esm/node/prerender/runPrerender.js +20 -22
  96. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +1 -1
  97. package/dist/esm/node/runtime/html/injectAssets.d.ts +2 -2
  98. package/dist/esm/node/runtime/html/serializePageContextClientSide.d.ts +2 -2
  99. package/dist/esm/node/runtime/renderPage/analyzePage.d.ts +2 -2
  100. package/dist/esm/node/runtime/renderPage/analyzePage.js +2 -2
  101. package/dist/esm/node/runtime/renderPage/createHttpResponseObject.d.ts +2 -2
  102. package/dist/esm/node/runtime/renderPage/debugPageFiles.d.ts +2 -2
  103. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.d.ts +2 -2
  104. package/dist/esm/node/runtime/renderPage/handleErrorWithoutErrorPage.d.ts +2 -2
  105. package/dist/esm/node/runtime/renderPage/loadPageFilesServerSide.d.ts +2 -2
  106. package/dist/esm/node/runtime/renderPage/loadPageFilesServerSide.js +2 -2
  107. package/dist/esm/node/runtime/renderPage/log404/index.js +10 -5
  108. package/dist/esm/node/runtime/renderPage/preparePageContextForUserConsumptionServerSide.d.ts +2 -2
  109. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +13 -13
  110. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -2
  111. package/dist/esm/node/runtime/renderPage.js +1 -1
  112. package/dist/esm/node/shared/getClientEntryFilePath.d.ts +2 -2
  113. package/dist/esm/node/shared/getClientEntryFilePath.js +2 -8
  114. package/dist/esm/shared/addIs404ToPageProps.d.ts +2 -2
  115. package/dist/esm/shared/addUrlComputedProps.d.ts +4 -2
  116. package/dist/esm/shared/assertPageContextProvidedByUser.js +1 -1
  117. package/dist/esm/shared/error-page.d.ts +3 -3
  118. package/dist/esm/shared/error-page.js +1 -1
  119. package/dist/esm/shared/getPageFiles/analyzeClientSide.d.ts +2 -2
  120. package/dist/esm/shared/getPageFiles/getExports.d.ts +3 -4
  121. package/dist/esm/shared/getPageFiles/getExports.js +7 -10
  122. package/dist/esm/shared/getPageFiles/parseGlobResults.d.ts +3 -3
  123. package/dist/esm/shared/getPageFiles/parseGlobResults.js +9 -43
  124. package/dist/esm/shared/getPageFiles/setPageFiles.d.ts +3 -3
  125. package/dist/esm/shared/hooks/getHook.js +3 -1
  126. package/dist/esm/shared/page-configs/Config.d.ts +201 -14
  127. package/dist/esm/shared/page-configs/PageConfig.d.ts +80 -73
  128. package/dist/esm/shared/page-configs/assertExports.d.ts +6 -0
  129. package/dist/esm/shared/page-configs/assertExports.js +54 -0
  130. package/dist/esm/shared/page-configs/findPageConfig.d.ts +2 -2
  131. package/dist/esm/shared/page-configs/getExportPath.d.ts +1 -1
  132. package/dist/esm/shared/page-configs/getExportPath.js +9 -10
  133. package/dist/esm/shared/page-configs/loadConfigValues.d.ts +3 -0
  134. package/dist/esm/shared/page-configs/loadConfigValues.js +15 -0
  135. package/dist/esm/shared/page-configs/serialize/PageConfigSerialized.d.ts +32 -0
  136. package/dist/esm/shared/page-configs/serialize/PageConfigSerialized.js +1 -0
  137. package/dist/esm/shared/page-configs/serialize/assertPageConfigs.d.ts +5 -0
  138. package/dist/esm/shared/page-configs/serialize/assertPageConfigs.js +16 -0
  139. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.d.ts +4 -0
  140. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +50 -0
  141. package/dist/esm/shared/page-configs/serialize/parsePageConfigs.d.ts +7 -0
  142. package/dist/esm/shared/page-configs/serialize/parsePageConfigs.js +62 -0
  143. package/dist/esm/shared/page-configs/serialize/serializeConfigValue.d.ts +8 -0
  144. package/dist/esm/shared/page-configs/serialize/serializeConfigValue.js +52 -0
  145. package/dist/esm/shared/page-configs/utils.d.ts +21 -14
  146. package/dist/esm/shared/page-configs/utils.js +64 -41
  147. package/dist/esm/shared/route/executeGuardHook.d.ts +2 -2
  148. package/dist/esm/shared/route/index.d.ts +3 -3
  149. package/dist/esm/shared/route/loadPageRoutes.d.ts +2 -2
  150. package/dist/esm/shared/route/loadPageRoutes.js +13 -16
  151. package/dist/esm/shared/route/resolveRedirects.js +1 -1
  152. package/dist/esm/shared/route/resolveRouteFunction.js +1 -0
  153. package/dist/esm/shared/types.d.ts +8 -6
  154. package/dist/esm/shared/utils.d.ts +0 -1
  155. package/dist/esm/shared/utils.js +0 -1
  156. package/dist/esm/types/index.d.ts +2 -1
  157. package/dist/esm/utils/getOutDirs.d.ts +0 -2
  158. package/dist/esm/utils/getOutDirs.js +24 -17
  159. package/dist/esm/utils/getValuePrintable.js +1 -1
  160. package/dist/esm/utils/objectAssign.js +3 -1
  161. package/dist/esm/utils/projectInfo.d.ts +1 -1
  162. package/dist/esm/utils/projectInfo.js +1 -1
  163. package/dist/esm/utils/requireResolve.d.ts +2 -0
  164. package/dist/esm/utils/{resolve.js → requireResolve.js} +2 -2
  165. package/dist/esm/utils/warnIfErrorIsNotObject.js +1 -1
  166. package/package.json +2 -2
  167. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.js +0 -13
  168. package/dist/cjs/shared/getPageFiles/assertPageConfigs.js +0 -19
  169. package/dist/cjs/shared/page-configs/loadPageCode.js +0 -63
  170. package/dist/cjs/utils/assertDefaultExport.js +0 -53
  171. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.d.ts +0 -3
  172. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.js +0 -10
  173. package/dist/esm/shared/getPageFiles/assertPageConfigs.d.ts +0 -5
  174. package/dist/esm/shared/getPageFiles/assertPageConfigs.js +0 -16
  175. package/dist/esm/shared/page-configs/loadPageCode.d.ts +0 -3
  176. package/dist/esm/shared/page-configs/loadPageCode.js +0 -57
  177. package/dist/esm/utils/assertDefaultExport.d.ts +0 -8
  178. package/dist/esm/utils/assertDefaultExport.js +0 -47
  179. package/dist/esm/utils/resolve.d.ts +0 -2
  180. /package/dist/cjs/shared/getPageFiles/{assertExports.js → assert_exports_old_design.js} +0 -0
  181. /package/dist/esm/shared/getPageFiles/{assertExports.d.ts → assert_exports_old_design.d.ts} +0 -0
  182. /package/dist/esm/shared/getPageFiles/{assertExports.js → assert_exports_old_design.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, toPosixPath, assertWarning, assertDefaultExportUnknown, assertDefaultExportObject, objectEntries, hasProp, arrayIncludes, objectKeys, assertIsNotProductionRuntime, getMostSimilar, isNpmPackageImport, joinEnglish, lowerFirst, scriptFileExtensions, mergeCumulativeValues, resolve } from '../../../utils.js';
5
+ import { assertPosixPath, assert, isObject, assertUsage, toPosixPath, assertWarning, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar, isNpmPackageImport, joinEnglish, lowerFirst, scriptFileExtensions, mergeCumulativeValues, requireResolve } from '../../../utils.js';
6
6
  import path from 'path';
7
7
  import { configDefinitionsBuiltIn, configDefinitionsBuiltInGlobal } from './getVikeConfig/configDefinitionsBuiltIn.js';
8
8
  import glob from 'fast-glob';
@@ -16,17 +16,18 @@ import { removeSuperfluousViteLog_enable, removeSuperfluousViteLog_disable } fro
16
16
  import { getFilePathToShowToUser } from './getFilePathToShowToUser.js';
17
17
  import pc from '@brillout/picocolors';
18
18
  import { getConfigDefinedAtString } from '../../../../../shared/page-configs/utils.js';
19
+ import { assertExportsOfConfigFile, assertExportsOfValueFile } from '../../../../../shared/page-configs/assertExports.js';
19
20
  import { getConfigValueSerialized } from './getVirtualFilePageConfigs.js';
20
21
  assertIsNotProductionRuntime();
21
22
  let devServerIsCorrupt = false;
22
23
  let wasConfigInvalid = null;
23
24
  let vikeConfigPromise = null;
24
25
  const vikeConfigDependencies = new Set();
25
- const codeFilesEnv = new Map();
26
- function reloadVikeConfig(userRootDir, extensions) {
26
+ const filesEnv = new Map();
27
+ function reloadVikeConfig(userRootDir, outDirRoot, extensions) {
27
28
  vikeConfigDependencies.clear();
28
- codeFilesEnv.clear();
29
- vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, true, extensions, true);
29
+ filesEnv.clear();
30
+ vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, true, extensions, true);
30
31
  handleReloadSideEffects();
31
32
  }
32
33
  async function handleReloadSideEffects() {
@@ -60,14 +61,14 @@ async function handleReloadSideEffects() {
60
61
  }
61
62
  }
62
63
  }
63
- async function getVikeConfig(userRootDir, isDev, extensions, tolerateInvalidConfig = false) {
64
+ async function getVikeConfig(userRootDir, outDirRoot, isDev, extensions, tolerateInvalidConfig = false) {
64
65
  if (!vikeConfigPromise) {
65
- vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, isDev, extensions, tolerateInvalidConfig);
66
+ vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, isDev, extensions, tolerateInvalidConfig);
66
67
  }
67
68
  return await vikeConfigPromise;
68
69
  }
69
- async function loadInterfaceFiles(userRootDir, isDev, extensions) {
70
- const plusFiles = await findPlusFiles(userRootDir, isDev, extensions);
70
+ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
71
+ const plusFiles = await findPlusFiles(userRootDir, [outDirRoot], isDev, extensions);
71
72
  const configFiles = [];
72
73
  const valueFiles = [];
73
74
  plusFiles.forEach((f) => {
@@ -83,7 +84,8 @@ async function loadInterfaceFiles(userRootDir, isDev, extensions) {
83
84
  await Promise.all(configFiles.map(async ({ filePathAbsolute, filePathRelativeToUserRootDir }) => {
84
85
  const configFilePath = {
85
86
  filePathAbsolute: filePathAbsolute,
86
- filePathRelativeToUserRootDir: filePathRelativeToUserRootDir
87
+ filePathRelativeToUserRootDir: filePathRelativeToUserRootDir,
88
+ importPathAbsolute: null
87
89
  };
88
90
  const { configFile, extendsConfigs } = await loadConfigFile(configFilePath, userRootDir, []);
89
91
  const interfaceFile = getInterfaceFileFromConfigFile(configFile, false);
@@ -97,27 +99,28 @@ async function loadInterfaceFiles(userRootDir, isDev, extensions) {
97
99
  }));
98
100
  // Value files
99
101
  await Promise.all(valueFiles.map(async ({ filePathAbsolute, filePathRelativeToUserRootDir }) => {
100
- const configNameDefault = getConfigName(filePathRelativeToUserRootDir);
101
- assert(configNameDefault);
102
+ const configName = getConfigName(filePathRelativeToUserRootDir);
103
+ assert(configName);
102
104
  const interfaceFile = {
103
105
  filePath: {
104
106
  filePathRelativeToUserRootDir,
105
- filePathAbsolute
107
+ filePathAbsolute,
108
+ importPathAbsolute: null
106
109
  },
107
110
  configMap: {
108
- [configNameDefault]: {}
111
+ [configName]: {}
109
112
  },
110
113
  isConfigFile: false,
111
114
  isValueFile: true,
112
- configNameDefault
115
+ configName
113
116
  };
114
117
  {
115
118
  // We don't have access to custom config definitions yet
116
- // - We load +someCustomConifg.js later
119
+ // - We load +{configName}.js later
117
120
  // - But we do need to eagerly load +meta.js (to get all the custom config definitions)
118
- const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn, configNameDefault);
121
+ const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn, configName);
119
122
  if (configDef?.env === 'config-only') {
120
- await loadValueFile(interfaceFile, configNameDefault, userRootDir);
123
+ await loadValueFile(interfaceFile, configName, userRootDir);
121
124
  }
122
125
  }
123
126
  {
@@ -137,14 +140,13 @@ function getConfigDefinition(configDefinitionsRelevant, configName, definedByFil
137
140
  function getConfigDefinitionOptional(configDefinitions, configName) {
138
141
  return configDefinitions[configName] ?? null;
139
142
  }
140
- async function loadValueFile(interfaceValueFile, configNameDefault, userRootDir) {
143
+ async function loadValueFile(interfaceValueFile, configName, userRootDir) {
141
144
  const { fileExports } = await transpileAndExecuteFile(interfaceValueFile.filePath, true, userRootDir);
142
- assertDefaultExportUnknown(fileExports, getFilePathToShowToUser(interfaceValueFile.filePath));
143
- Object.entries(fileExports).forEach(([configName, configValue]) => {
144
- if (configName === 'default') {
145
- configName = configNameDefault;
146
- }
147
- interfaceValueFile.configMap[configName] = { configValue };
145
+ const filePathToShowToUser = getFilePathToShowToUser(interfaceValueFile.filePath);
146
+ assertExportsOfValueFile(fileExports, filePathToShowToUser, configName);
147
+ Object.entries(fileExports).forEach(([exportName, configValue]) => {
148
+ const configName_ = exportName === 'default' ? configName : exportName;
149
+ interfaceValueFile.configMap[configName_] = { configValue };
148
150
  });
149
151
  }
150
152
  function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
@@ -157,19 +159,19 @@ function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
157
159
  isConfigExtend,
158
160
  extendsFilePaths
159
161
  };
160
- const interfaceFilePathToShowToUser = getFilePathToShowToUser(filePath);
161
- assertDefaultExportObject(fileExports, interfaceFilePathToShowToUser);
162
+ const filePathToShowToUser = getFilePathToShowToUser(filePath);
163
+ assertExportsOfConfigFile(fileExports, filePathToShowToUser);
162
164
  Object.entries(fileExports.default).forEach(([configName, configValue]) => {
163
165
  interfaceFile.configMap[configName] = { configValue };
164
166
  });
165
167
  return interfaceFile;
166
168
  }
167
- async function loadVikeConfig_withErrorHandling(userRootDir, isDev, extensions, tolerateInvalidConfig) {
169
+ async function loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, isDev, extensions, tolerateInvalidConfig) {
168
170
  let hasError = false;
169
171
  let ret;
170
172
  let err;
171
173
  try {
172
- ret = await loadVikeConfig(userRootDir, isDev, extensions);
174
+ ret = await loadVikeConfig(userRootDir, outDirRoot, isDev, extensions);
173
175
  }
174
176
  catch (err_) {
175
177
  hasError = true;
@@ -197,8 +199,7 @@ async function loadVikeConfig_withErrorHandling(userRootDir, isDev, extensions,
197
199
  const dummyData = {
198
200
  pageConfigs: [],
199
201
  pageConfigGlobal: {
200
- onPrerenderStart: null,
201
- onBeforeRoute: null
202
+ configValueSources: {}
202
203
  },
203
204
  globalVikeConfig: {}
204
205
  };
@@ -206,8 +207,8 @@ async function loadVikeConfig_withErrorHandling(userRootDir, isDev, extensions,
206
207
  }
207
208
  }
208
209
  }
209
- async function loadVikeConfig(userRootDir, isDev, extensions) {
210
- const interfaceFilesByLocationId = await loadInterfaceFiles(userRootDir, isDev, extensions);
210
+ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
211
+ const interfaceFilesByLocationId = await loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions);
211
212
  const { globalVikeConfig, pageConfigGlobal } = getGlobalConfigs(interfaceFilesByLocationId, userRootDir);
212
213
  const pageConfigs = await Promise.all(Object.entries(interfaceFilesByLocationId)
213
214
  .filter(([_pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
@@ -218,18 +219,18 @@ async function loadVikeConfig(userRootDir, isDev, extensions) {
218
219
  await Promise.all(getInterfaceFileList(interfaceFilesRelevant).map(async (interfaceFile) => {
219
220
  if (!interfaceFile.isValueFile)
220
221
  return;
221
- const { configNameDefault } = interfaceFile;
222
- if (isGlobalConfig(configNameDefault))
222
+ const { configName } = interfaceFile;
223
+ if (isGlobalConfig(configName))
223
224
  return;
224
- const configDef = getConfigDefinition(configDefinitionsRelevant, configNameDefault, getFilePathToShowToUser(interfaceFile.filePath));
225
+ const configDef = getConfigDefinition(configDefinitionsRelevant, configName, getFilePathToShowToUser(interfaceFile.filePath));
225
226
  if (configDef.env !== 'config-only')
226
227
  return;
227
228
  const isAlreadyLoaded = interfacefileIsAlreaydLoaded(interfaceFile);
228
229
  if (isAlreadyLoaded)
229
230
  return;
230
231
  // Value files for built-in confg-only configs should have already been loaded at loadInterfaceFiles()
231
- assert(!(configNameDefault in configDefinitionsBuiltIn));
232
- await loadValueFile(interfaceFile, configNameDefault, userRootDir);
232
+ assert(!(configName in configDefinitionsBuiltIn));
233
+ await loadValueFile(interfaceFile, configName, userRootDir);
233
234
  }));
234
235
  const configValueSources = {};
235
236
  objectEntries(configDefinitionsRelevant)
@@ -241,17 +242,17 @@ async function loadVikeConfig(userRootDir, isDev, extensions) {
241
242
  configValueSources[configName] = sources;
242
243
  });
243
244
  const { routeFilesystem, isErrorPage } = determineRouteFilesystem(locationId, configValueSources);
245
+ applyEffectsAll(configValueSources, configDefinitionsRelevant);
246
+ const configValuesComputed = getComputed(configValueSources, configDefinitionsRelevant);
247
+ const configValues = getConfigValues(configValueSources, configValuesComputed, configDefinitionsRelevant);
244
248
  const pageConfig = {
245
249
  pageId: locationId,
246
250
  isErrorPage,
247
251
  routeFilesystem,
248
252
  configValueSources,
249
- configValues: getConfigValues(configValueSources, configDefinitionsRelevant)
253
+ configValuesComputed,
254
+ configValues
250
255
  };
251
- applyEffects(pageConfig, configDefinitionsRelevant);
252
- pageConfig.configValues = getConfigValues(configValueSources, configDefinitionsRelevant);
253
- applyComputed(pageConfig, configDefinitionsRelevant);
254
- pageConfig.configValues = getConfigValues(configValueSources, configDefinitionsRelevant);
255
256
  return pageConfig;
256
257
  }));
257
258
  // Show error message upon unknown config
@@ -323,24 +324,24 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
323
324
  }
324
325
  const globalVikeConfig = {};
325
326
  const pageConfigGlobal = {
326
- onBeforeRoute: null,
327
- onPrerenderStart: null
327
+ configValueSources: {}
328
328
  };
329
329
  objectEntries(configDefinitionsBuiltInGlobal).forEach(([configName, configDef]) => {
330
330
  const sources = resolveConfigValueSources(configName, configDef, interfaceFilesGlobal, userRootDir);
331
331
  const configValueSource = sources?.[0];
332
332
  if (!configValueSource)
333
333
  return;
334
- if (arrayIncludes(objectKeys(pageConfigGlobal), configName)) {
334
+ if (configName === 'onBeforeRoute' || configName === 'onPrerenderStart') {
335
335
  assert(!('value' in configValueSource));
336
- pageConfigGlobal[configName] = configValueSource;
336
+ pageConfigGlobal.configValueSources[configName] = [configValueSource];
337
337
  }
338
338
  else {
339
339
  assert('value' in configValueSource);
340
340
  if (configName === 'prerender' && typeof configValueSource.value === 'boolean')
341
341
  return;
342
- assert(!configValueSource.isComputed);
343
- assertWarning(false, `Being able to define config ${pc.cyan(configName)} in ${configValueSource.definedAtInfo.filePath} is experimental and will likely be removed. Define the config ${pc.cyan(configName)} in vike's Vite plugin options instead.`, { onlyOnce: true });
342
+ const sourceFilePath = getDefinedAtFilePathToShowToUser(configValueSource.definedAtInfo);
343
+ assert(sourceFilePath);
344
+ assertWarning(false, `Being able to define config ${pc.cyan(configName)} in ${sourceFilePath} is experimental and will likely be removed. Define the config ${pc.cyan(configName)} in Vike's Vite plugin options instead.`, { onlyOnce: true });
344
345
  globalVikeConfig[configName] = configValueSource.value;
345
346
  }
346
347
  });
@@ -365,8 +366,8 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
365
366
  {
366
367
  const interfaceValueFiles = interfaceFilesDefiningConfig
367
368
  .filter((interfaceFile) => interfaceFile.isValueFile &&
368
- // We consider side-effect exports (e.g. `export { frontmatter }` of .mdx files) later (i.e. with less priority)
369
- interfaceFile.configNameDefault === configName)
369
+ // We consider side-effect configs (e.g. `export { frontmatter }` of .mdx files) later (i.e. with less priority)
370
+ interfaceFile.configName === configName)
370
371
  .sort(makeOrderDeterministic);
371
372
  const interfaceConfigFiles = interfaceFilesDefiningConfig
372
373
  .filter((interfaceFile) => interfaceFile.isConfigFile &&
@@ -376,9 +377,9 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
376
377
  const interfaceValueFile = interfaceValueFiles[0];
377
378
  const interfaceConfigFile = interfaceConfigFiles[0];
378
379
  // Make this value:
379
- // /pages/some-page/+someConfig.js > `export default`
380
+ // /pages/some-page/+{configName}.js > `export default`
380
381
  // override that value:
381
- // /pages/some-page/+config > `export default { someConfig }`
382
+ // /pages/some-page/+config.h.js > `export default { someConfig }`
382
383
  const interfaceFileWinner = interfaceValueFile ?? interfaceConfigFile;
383
384
  if (interfaceFileWinner) {
384
385
  const interfaceFilesOverriden = [...interfaceValueFiles, ...interfaceConfigFiles].filter((f) => f !== interfaceFileWinner);
@@ -392,8 +393,8 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
392
393
  // Side-effect configs such as `export { frontmatter }` in .mdx files
393
394
  interfaceFilesDefiningConfig
394
395
  .filter((interfaceFile) => interfaceFile.isValueFile &&
395
- // Is side-effect export
396
- interfaceFile.configNameDefault !== configName)
396
+ // Is side-effect config
397
+ interfaceFile.configName !== configName)
397
398
  .forEach((interfaceValueFileSideEffect) => {
398
399
  add(interfaceValueFileSideEffect);
399
400
  });
@@ -423,66 +424,57 @@ function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden,
423
424
  interfaceFilesOverriden.forEach((interfaceFileLoser) => {
424
425
  const configValueSourceWinner = getConfigValueSource(configName, interfaceFileWinner, configDef, userRootDir);
425
426
  const configValueSourceLoser = getConfigValueSource(configName, interfaceFileLoser, configDef, userRootDir);
426
- assertWarning(false, `${getConfigDefinedAtString(configName, configValueSourceLoser, true)} overriden by another ${getConfigDefinedAtString(configName, configValueSourceWinner, false)}, remove one of the two`, { onlyOnce: false });
427
+ assertWarning(false, `${getConfigSourceDefinedAtString(configName, configValueSourceLoser, undefined, true)} overriden by another ${getConfigSourceDefinedAtString(configName, configValueSourceWinner, undefined, false)}, remove one of the two`, { onlyOnce: false });
427
428
  });
428
429
  }
429
430
  function isInterfaceFileUserLand(interfaceFile) {
430
431
  return (interfaceFile.isConfigFile && !interfaceFile.isConfigExtend) || interfaceFile.isValueFile;
431
432
  }
432
433
  function getConfigValueSource(configName, interfaceFile, configDef, userRootDir) {
433
- // TODO: rethink file paths of ConfigElement
434
- const configFilePath = interfaceFile.filePath.filePathRelativeToUserRootDir ?? interfaceFile.filePath.filePathAbsolute;
435
434
  const conf = interfaceFile.configMap[configName];
436
435
  assert(conf);
437
436
  const configEnv = configDef.env;
438
- const definedAtInfoConfigFile = {
439
- filePath: configFilePath,
437
+ const definedAtConfigFile = {
438
+ ...interfaceFile.filePath,
440
439
  fileExportPath: ['default', configName]
441
440
  };
442
441
  if (configDef._valueIsFilePath) {
443
- let filePath;
442
+ let definedAtInfo;
443
+ let valueFilePath;
444
444
  if (interfaceFile.isConfigFile) {
445
445
  const { configValue } = conf;
446
- const import_ = getImport(configValue, interfaceFile.filePath, userRootDir);
447
- const configDefinedAt = getConfigDefinedAtString(configName, { definedAtInfo: definedAtInfoConfigFile }, true);
446
+ const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
447
+ const configDefinedAt = getConfigSourceDefinedAtString(configName, { definedAtInfo: definedAtConfigFile });
448
448
  assertUsage(import_, `${configDefinedAt} should be an import`);
449
- filePath = import_.importFilePath;
449
+ valueFilePath = import_.filePathRelativeToUserRootDir ?? import_.importPathAbsolute;
450
+ definedAtInfo = import_;
450
451
  }
451
452
  else {
452
453
  assert(interfaceFile.isValueFile);
453
- filePath =
454
- interfaceFile.filePath.filePathRelativeToUserRootDir ??
455
- // Experimental: is this needed? Would it work?
456
- interfaceFile.filePath.filePathAbsolute;
454
+ valueFilePath = interfaceFile.filePath.filePathRelativeToUserRootDir;
455
+ definedAtInfo = {
456
+ ...interfaceFile.filePath,
457
+ fileExportPath: []
458
+ };
457
459
  }
458
460
  const configValueSource = {
459
- value: filePath,
461
+ value: valueFilePath,
460
462
  valueIsFilePath: true,
461
463
  configEnv,
462
464
  valueIsImportedAtRuntime: true,
463
- isComputed: false,
464
- definedAtInfo: {
465
- filePath,
466
- fileExportPath: []
467
- }
465
+ definedAtInfo
468
466
  };
469
467
  return configValueSource;
470
468
  }
471
469
  if (interfaceFile.isConfigFile) {
472
470
  assert('configValue' in conf);
473
471
  const { configValue } = conf;
474
- const import_ = getImport(configValue, interfaceFile.filePath, userRootDir);
472
+ const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
475
473
  if (import_) {
476
- const { importFilePath, importFileExportName } = import_;
477
- assertCodeFileEnv(importFilePath, configEnv, configName);
478
474
  const configValueSource = {
479
475
  configEnv,
480
476
  valueIsImportedAtRuntime: true,
481
- isComputed: false,
482
- definedAtInfo: {
483
- filePath: importFilePath,
484
- fileExportPath: [importFileExportName]
485
- }
477
+ definedAtInfo: import_
486
478
  };
487
479
  return configValueSource;
488
480
  }
@@ -491,24 +483,22 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
491
483
  value: configValue,
492
484
  configEnv,
493
485
  valueIsImportedAtRuntime: false,
494
- isComputed: false,
495
- definedAtInfo: definedAtInfoConfigFile
486
+ definedAtInfo: definedAtConfigFile
496
487
  };
497
488
  return configValueSource;
498
489
  }
499
490
  }
500
491
  else if (interfaceFile.isValueFile) {
501
- // TODO: rethink file paths of ConfigElement
502
- const importFilePath = interfaceFile.filePath.filePathRelativeToUserRootDir ?? interfaceFile.filePath.filePathAbsolute;
503
- const importFileExportName = configName === interfaceFile.configNameDefault ? 'default' : configName;
504
492
  const valueAlreadyLoaded = 'configValue' in conf;
505
493
  const configValueSource = {
506
494
  configEnv,
507
495
  valueIsImportedAtRuntime: !valueAlreadyLoaded,
508
- isComputed: false,
509
496
  definedAtInfo: {
510
- filePath: importFilePath,
511
- fileExportPath: [importFileExportName]
497
+ ...interfaceFile.filePath,
498
+ fileExportPath: configName === interfaceFile.configName
499
+ ? []
500
+ : // Side-effect config (e.g. `export { frontmatter }` of .md files)
501
+ [configName]
512
502
  }
513
503
  };
514
504
  if (valueAlreadyLoaded) {
@@ -521,16 +511,17 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
521
511
  }
522
512
  assert(false);
523
513
  }
524
- function assertCodeFileEnv(importFilePath, configEnv, configName) {
525
- if (!codeFilesEnv.has(importFilePath)) {
526
- codeFilesEnv.set(importFilePath, []);
514
+ function assertFileEnv(filePathForEnvCheck, configEnv, configName) {
515
+ assertPosixPath(filePathForEnvCheck);
516
+ if (!filesEnv.has(filePathForEnvCheck)) {
517
+ filesEnv.set(filePathForEnvCheck, []);
527
518
  }
528
- const codeFileEnv = codeFilesEnv.get(importFilePath);
529
- codeFileEnv.push({ configEnv, configName });
530
- const configDifferentEnv = codeFileEnv.filter((c) => c.configEnv !== configEnv)[0];
519
+ const fileEnv = filesEnv.get(filePathForEnvCheck);
520
+ fileEnv.push({ configEnv, configName });
521
+ const configDifferentEnv = fileEnv.filter((c) => c.configEnv !== configEnv)[0];
531
522
  if (configDifferentEnv) {
532
523
  assertUsage(false, [
533
- `${importFilePath} defines the value of configs living in different environments:`,
524
+ `${filePathForEnvCheck} defines the value of configs living in different environments:`,
534
525
  ...[configDifferentEnv, { configName, configEnv }].map((c) => ` - config ${pc.cyan(c.configName)} which value lives in environment ${pc.cyan(c.configEnv)}`),
535
526
  'Defining config values in the same file is allowed only if they live in the same environment, see https://vike.dev/header-file/import-from-same-file'
536
527
  ].join('\n'));
@@ -548,53 +539,65 @@ function isDefiningPage(interfaceFiles) {
548
539
  function isDefiningPageConfig(configName) {
549
540
  return ['Page', 'route'].includes(configName);
550
541
  }
551
- function getImport(configValue, configFilePath, userRootDir) {
542
+ function resolveImport(configValue, importerFilePath, userRootDir, configEnv, configName) {
552
543
  if (typeof configValue !== 'string')
553
544
  return null;
554
545
  const importData = parseImportData(configValue);
555
546
  if (!importData)
556
547
  return null;
557
- let { importFilePath, importFileExportName } = importData;
558
- if (importFilePath.startsWith('.')) {
548
+ const { importPath, exportName } = importData;
549
+ const filePathAbsolute = resolveImportPath(importData, importerFilePath);
550
+ assertFileEnv(filePathAbsolute ?? importPath, configEnv, configName);
551
+ const fileExportPath = exportName === 'default' || exportName === configName ? [] : [exportName];
552
+ if (importPath.startsWith('.')) {
559
553
  // We need to resolve relative paths into absolute paths. Because the import paths are included in virtual files:
560
554
  // ```
561
555
  // [vite] Internal server error: Failed to resolve import "./onPageTransitionHooks" from "virtual:vike:pageConfigValuesAll:client:/pages/index". Does the file exist?
562
556
  // ```
563
- importFilePath = resolveRelativeCodeFilePath(importData, configFilePath, userRootDir);
557
+ assertImportPath(filePathAbsolute, importData, importerFilePath);
558
+ const filePathRelativeToUserRootDir = resolveImportPath_relativeToUserRootDir(filePathAbsolute, importData, importerFilePath, userRootDir);
559
+ return {
560
+ exportName,
561
+ fileExportPath,
562
+ filePathAbsolute,
563
+ filePathRelativeToUserRootDir,
564
+ importPathAbsolute: null
565
+ };
564
566
  }
565
567
  else {
566
- // importFilePath can be:
568
+ // importPath can be:
567
569
  // - an npm package import
568
570
  // - a path alias
571
+ return {
572
+ exportName,
573
+ fileExportPath,
574
+ filePathAbsolute,
575
+ filePathRelativeToUserRootDir: null,
576
+ importPathAbsolute: importPath
577
+ };
569
578
  }
570
- return {
571
- importFilePath,
572
- importFileExportName
573
- };
574
579
  }
575
- function resolveRelativeCodeFilePath(importData, configFilePath, userRootDir) {
576
- let importFilePath = resolveImport(importData, configFilePath);
577
- // Make it a Vite path
580
+ function resolveImportPath_relativeToUserRootDir(filePathAbsolute, importData, configFilePath, userRootDir) {
578
581
  assertPosixPath(userRootDir);
579
- assertPosixPath(importFilePath);
580
- if (importFilePath.startsWith(userRootDir)) {
581
- importFilePath = getVitePathFromAbsolutePath(importFilePath, userRootDir);
582
+ let filePathRelativeToUserRootDir;
583
+ if (filePathAbsolute.startsWith(userRootDir)) {
584
+ filePathRelativeToUserRootDir = getVitePathFromAbsolutePath(filePathAbsolute, userRootDir);
582
585
  }
583
586
  else {
584
- assertUsage(false, `${getFilePathToShowToUser(configFilePath)} imports from a relative path ${pc.cyan(importData.importFilePath)} outside of ${userRootDir} which is forbidden: import from a relative path inside ${userRootDir}, or import from a dependency's package.json#exports entry instead`);
587
+ assertUsage(false, `${getFilePathToShowToUser(configFilePath)} imports from a relative path ${pc.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`);
585
588
  // None of the following works. Seems to be a Vite bug?
586
589
  // /*
587
- // assert(importFilePath.startsWith('/'))
588
- // importFilePath = `/@fs${importFilePath}`
590
+ // assert(filePathAbsolute.startsWith('/'))
591
+ // filePath = `/@fs${filePathAbsolute}`
589
592
  // /*/
590
- // importFilePath = path.posix.relative(userRootDir, importFilePath)
591
- // assert(importFilePath.startsWith('../'))
592
- // importFilePath = '/' + importFilePath
593
+ // filePathRelativeToUserRootDir = path.posix.relative(userRootDir, filePathAbsolute)
594
+ // assert(filePathRelativeToUserRootDir.startsWith('../'))
595
+ // filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir
593
596
  // //*/
594
597
  }
595
- assertPosixPath(importFilePath);
596
- assert(importFilePath.startsWith('/'));
597
- return importFilePath;
598
+ assertPosixPath(filePathRelativeToUserRootDir);
599
+ assert(filePathRelativeToUserRootDir.startsWith('/'));
600
+ return filePathRelativeToUserRootDir;
598
601
  }
599
602
  function getVitePathFromAbsolutePath(filePathAbsolute, root) {
600
603
  assertPosixPath(filePathAbsolute);
@@ -655,34 +658,36 @@ function assertMetaValue(metaVal, configMetaDefinedAt) {
655
658
  }
656
659
  });
657
660
  }
658
- function applyEffects(pageConfig, configDefinitionsRelevant) {
661
+ function applyEffectsAll(configValueSources, configDefinitionsRelevant) {
659
662
  objectEntries(configDefinitionsRelevant).forEach(([configName, configDef]) => {
660
663
  if (!configDef.effect)
661
664
  return;
662
665
  // The value needs to be loaded at config time, that's why we only support effect for configs that are config-only for now.
663
666
  // (We could support effect for non config-only by always loading its value at config time, regardless of the config's `env` value.)
664
- assertWarning(configDef.env === 'config-only', [
665
- `Adding an effect to ${pc.cyan(configName)} may not work as expected because ${pc.cyan(configName)} has an ${pc.cyan('env')} that is different than ${pc.cyan('config-only')} (its env is ${pc.cyan(configDef.env)}).`,
666
- 'Reach out to a maintainer if you want to use this in production.'
667
- ].join(' '), { onlyOnce: true });
668
- const configValue = pageConfig.configValueSources[configName]?.[0];
669
- if (!configValue)
667
+ assertUsage(configDef.env === 'config-only', [
668
+ `Cannot add effect to ${pc.cyan(configName)} because its ${pc.cyan('env')} is ${pc.cyan(configDef.env)}: effects can only be added to configs with an env that is ${pc.cyan('config-only')}.`
669
+ ].join(' '));
670
+ const source = configValueSources[configName]?.[0];
671
+ if (!source)
670
672
  return;
673
+ // The config value is eagerly loaded since `configDef.env === 'config-only``
674
+ assert('value' in source);
675
+ // Call effect
671
676
  const configModFromEffect = configDef.effect({
672
- configValue: configValue.value,
673
- configDefinedAt: getConfigDefinedAtString(configName, configValue, true)
677
+ configValue: source.value,
678
+ configDefinedAt: getConfigSourceDefinedAtString(configName, source)
674
679
  });
675
680
  if (!configModFromEffect)
676
681
  return;
677
- assert(hasProp(configValue, 'value')); // We need to assume that the config value is loaded at build-time
678
- applyEffect(configModFromEffect, configValue, pageConfig.configValueSources);
682
+ assert(hasProp(source, 'value')); // We need to assume that the config value is loaded at build-time
683
+ applyEffect(configModFromEffect, source, configValueSources);
679
684
  });
680
685
  }
681
686
  function applyEffect(configModFromEffect, configValueEffectSource, configValueSources) {
682
- const notSupported = `config.meta[configName].effect currently only supports modifying the the ${pc.cyan('env')} of a config. Reach out to a maintainer if you need more capabilities.`;
687
+ const notSupported = `Effects currently only supports modifying the the ${pc.cyan('env')} of a config.`;
683
688
  objectEntries(configModFromEffect).forEach(([configName, configValue]) => {
684
689
  if (configName === 'meta') {
685
- assertMetaValue(configValue, getConfigDefinedAtString(configName, configValueEffectSource, true, 'effect'));
690
+ assertMetaValue(configValue, getConfigSourceDefinedAtString(configName, configValueEffectSource, true));
686
691
  objectEntries(configValue).forEach(([configTargetName, configTargetDef]) => {
687
692
  {
688
693
  const keys = Object.keys(configTargetDef);
@@ -692,6 +697,7 @@ function applyEffect(configModFromEffect, configValueEffectSource, configValueSo
692
697
  const envOverriden = configTargetDef.env;
693
698
  const sources = configValueSources[configTargetName];
694
699
  sources?.forEach((configValueSource) => {
700
+ // Apply effect
695
701
  configValueSource.configEnv = envOverriden;
696
702
  });
697
703
  });
@@ -703,30 +709,29 @@ function applyEffect(configModFromEffect, configValueEffectSource, configValueSo
703
709
  }
704
710
  });
705
711
  }
706
- function applyComputed(pageConfig, configDefinitionsRelevant) {
712
+ function getComputed(configValueSources, configDefinitionsRelevant) {
713
+ const configValuesComputed = {};
707
714
  objectEntries(configDefinitionsRelevant).forEach(([configName, configDef]) => {
708
- var _a;
709
- const computed = configDef._computed;
710
- if (!computed)
715
+ if (!configDef._computed)
711
716
  return;
712
- const value = computed(pageConfig);
717
+ const value = configDef._computed(configValueSources);
713
718
  if (value === undefined)
714
719
  return;
715
- const configValueSource = {
720
+ configValuesComputed[configName] = {
716
721
  value,
717
- configEnv: configDef.env,
718
- definedAtInfo: null,
719
- isComputed: true,
720
- valueIsImportedAtRuntime: false
722
+ configEnv: configDef.env
721
723
  };
722
- (_a = pageConfig.configValueSources)[configName] ?? (_a[configName] = []);
723
- // Computed values are inserted last: they have the least priority (i.e. computed can be overriden)
724
- pageConfig.configValueSources[configName].push(configValueSource);
725
724
  });
725
+ return configValuesComputed;
726
726
  }
727
- async function findPlusFiles(userRootDir, isDev, extensions) {
727
+ async function findPlusFiles(userRootDir, ignoreDirs, isDev, extensions) {
728
728
  const timeBase = new Date().getTime();
729
729
  assertPosixPath(userRootDir);
730
+ const ignorePatterns = [];
731
+ for (const dir of ignoreDirs) {
732
+ assertPosixPath(dir);
733
+ ignorePatterns.push(`${path.posix.relative(userRootDir, dir)}/**`);
734
+ }
730
735
  const result = await glob(`**/+*.${scriptFileExtensions}`, {
731
736
  ignore: [
732
737
  '**/node_modules/**',
@@ -735,7 +740,8 @@ async function findPlusFiles(userRootDir, isDev, extensions) {
735
740
  // +Page.js
736
741
  // +Page.telefunc.js
737
742
  // ```
738
- '**/*.telefunc.*'
743
+ '**/*.telefunc.*',
744
+ ...ignorePatterns
739
745
  ],
740
746
  cwd: userRootDir,
741
747
  dot: false
@@ -743,7 +749,7 @@ async function findPlusFiles(userRootDir, isDev, extensions) {
743
749
  const time = new Date().getTime() - timeBase;
744
750
  if (isDev) {
745
751
  // We only warn in dev, because while building it's expected to take a long time as fast-glob is competing for resources with other tasks
746
- assertWarning(time < 2 * 1000, `Crawling your user files took an unexpected long time (${time}ms). Create a new issue on vike's GitHub.`, {
752
+ assertWarning(time < 2 * 1000, `Crawling your user files took an unexpected long time (${time}ms). Create a new issue on Vike's GitHub.`, {
747
753
  onlyOnce: 'slow-page-files-search'
748
754
  });
749
755
  }
@@ -793,7 +799,7 @@ function assertNoUnexpectedPlusSign(filePath, fileName) {
793
799
  assertUsage(!fileName.slice(1).includes('+'), `Character '+' is only allowed at the beginning of filenames: make sure ${filePath} doesn't contain any '+' in its filename other than its first letter`);
794
800
  }
795
801
  async function loadConfigFile(configFilePath, userRootDir, visited) {
796
- const { filePathAbsolute, filePathRelativeToUserRootDir } = configFilePath;
802
+ const { filePathAbsolute } = configFilePath;
797
803
  assertNoInfiniteLoop(visited, filePathAbsolute);
798
804
  const { fileExports } = await transpileAndExecuteFile(configFilePath, false, userRootDir);
799
805
  const { extendsConfigs, extendsFilePaths } = await loadExtendsConfigs(fileExports, configFilePath, userRootDir, [
@@ -802,10 +808,7 @@ async function loadConfigFile(configFilePath, userRootDir, visited) {
802
808
  ]);
803
809
  const configFile = {
804
810
  fileExports,
805
- filePath: {
806
- filePathRelativeToUserRootDir,
807
- filePathAbsolute
808
- },
811
+ filePath: configFilePath,
809
812
  extendsFilePaths
810
813
  };
811
814
  return { configFile, extendsConfigs };
@@ -822,16 +825,20 @@ async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir
822
825
  const extendsImportData = getExtendsImportData(configFileExports, configFilePath);
823
826
  const extendsConfigFiles = [];
824
827
  extendsImportData.map((importData) => {
825
- const { importFilePath: importPath } = importData;
828
+ const { importPath: importPath } = importData;
826
829
  // TODO
827
830
  // - validate extends configs
828
- const filePathAbsolute = resolveImport(importData, configFilePath);
831
+ const filePathAbsolute = resolveImportPath(importData, configFilePath);
832
+ assertImportPath(filePathAbsolute, importData, configFilePath);
829
833
  assertExtendsImportPath(importPath, filePathAbsolute, configFilePath);
834
+ // - filePathRelativeToUserRootDir has no functionality beyond nicer error messages for user
835
+ // - Using importPath would be visually nicer but it's ambigous => we rather pick filePathAbsolute for added clarity
836
+ const filePathRelativeToUserRootDir = determineFilePathRelativeToUserDir(filePathAbsolute, userRootDir);
830
837
  extendsConfigFiles.push({
831
838
  filePathAbsolute,
832
- // - filePathRelativeToUserRootDir has no functionality beyond nicer error messages for user
833
- // - Using importPath would be visually nicer but it's ambigous => we rather pick filePathAbsolute for added clarity
834
- filePathRelativeToUserRootDir: determineFilePathRelativeToUserDir(filePathAbsolute, userRootDir)
839
+ // TODO: fix type cast
840
+ filePathRelativeToUserRootDir: filePathRelativeToUserRootDir,
841
+ importPathAbsolute: importPath
835
842
  });
836
843
  });
837
844
  const extendsConfigs = [];
@@ -871,7 +878,7 @@ function assertExtendsImportPath(importPath, filePath, configFilePath) {
871
878
  }
872
879
  function getExtendsImportData(configFileExports, configFilePath) {
873
880
  const filePathToShowToUser = getFilePathToShowToUser(configFilePath);
874
- assertDefaultExportObject(configFileExports, filePathToShowToUser);
881
+ assertExportsOfConfigFile(configFileExports, filePathToShowToUser);
875
882
  const defaultExports = configFileExports.default;
876
883
  const wrongUsage = `${filePathToShowToUser} sets the config 'extends' to an invalid value, see https://vike.dev/extends`;
877
884
  let extendList;
@@ -969,7 +976,7 @@ function determineRouteFilesystem(locationId, configValueSources) {
969
976
  const configFilesystemRoutingRoot = configValueSources[configName]?.[0];
970
977
  let filesystemRouteString = getFilesystemRouteString(locationId);
971
978
  if (determineIsErrorPage(filesystemRouteString)) {
972
- return { isErrorPage: true, routeFilesystem: null };
979
+ return { isErrorPage: true, routeFilesystem: undefined };
973
980
  }
974
981
  let filesystemRouteDefinedBy = getFilesystemRouteDefinedBy(locationId); // for log404()
975
982
  if (configFilesystemRoutingRoot) {
@@ -987,18 +994,19 @@ function determineRouteFilesystem(locationId, configValueSources) {
987
994
  routeString: filesystemRouteString,
988
995
  definedBy: filesystemRouteDefinedBy
989
996
  };
990
- return { routeFilesystem, isErrorPage: false };
997
+ return { routeFilesystem, isErrorPage: undefined };
991
998
  }
992
999
  function getFilesystemRoutingRootEffect(configFilesystemRoutingRoot, configName) {
993
1000
  assert(configFilesystemRoutingRoot.configEnv === 'config-only');
994
1001
  // Eagerly loaded since it's config-only
995
1002
  assert('value' in configFilesystemRoutingRoot);
996
1003
  const { value } = configFilesystemRoutingRoot;
997
- const configDefinedAt = getConfigDefinedAtString(configName, configFilesystemRoutingRoot, false);
1004
+ const configDefinedAt = getConfigSourceDefinedAtString(configName, configFilesystemRoutingRoot);
998
1005
  assertUsage(typeof value === 'string', `${configDefinedAt} should be a string`);
999
1006
  assertUsage(value.startsWith('/'), `${configDefinedAt} is ${pc.cyan(value)} but it should start with a leading slash ${pc.cyan('/')}`);
1000
- assert(!configFilesystemRoutingRoot.isComputed);
1001
- const before = getFilesystemRouteString(getLocationId(configFilesystemRoutingRoot.definedAtInfo.filePath));
1007
+ const { filePathRelativeToUserRootDir } = configFilesystemRoutingRoot.definedAtInfo;
1008
+ assert(filePathRelativeToUserRootDir);
1009
+ const before = getFilesystemRouteString(getLocationId(filePathRelativeToUserRootDir));
1002
1010
  const after = value;
1003
1011
  const filesystemRoutingRootEffect = { before, after };
1004
1012
  return { filesystemRoutingRootEffect, filesystemRoutingRootDefinedAt: configDefinedAt };
@@ -1007,22 +1015,22 @@ function determineIsErrorPage(routeFilesystem) {
1007
1015
  assertPosixPath(routeFilesystem);
1008
1016
  return routeFilesystem.split('/').includes('_error');
1009
1017
  }
1010
- function resolveImport(importData, importerFilePath) {
1011
- const { filePathAbsolute } = importerFilePath;
1012
- assertPosixPath(filePathAbsolute);
1013
- const plusConfigFilDirPathAbsolute = path.posix.dirname(filePathAbsolute);
1014
- const importedFile = resolve(importData.importFilePath, plusConfigFilDirPathAbsolute);
1015
- assertImport(importedFile, importData, importerFilePath);
1016
- return importedFile;
1018
+ function resolveImportPath(importData, importerFilePath) {
1019
+ const importerFilePathAbsolute = importerFilePath.filePathAbsolute;
1020
+ assertPosixPath(importerFilePathAbsolute);
1021
+ const cwd = path.posix.dirname(importerFilePathAbsolute);
1022
+ // filePathAbsolute is expected to be null when importData.importPath is a Vite path alias
1023
+ const filePathAbsolute = requireResolve(importData.importPath, cwd);
1024
+ return filePathAbsolute;
1017
1025
  }
1018
- function assertImport(importedFile, importData, importerFilePath) {
1019
- const { importFilePath: importPath, importWasGenerated, importDataString } = importData;
1026
+ function assertImportPath(filePathAbsolute, importData, importerFilePath) {
1027
+ const { importPath: importPath, importStringWasGenerated, importString } = importData;
1020
1028
  const filePathToShowToUser = getFilePathToShowToUser(importerFilePath);
1021
- if (!importedFile) {
1029
+ if (!filePathAbsolute) {
1022
1030
  const importPathString = pc.cyan(`'${importPath}'`);
1023
- const errIntro = importWasGenerated
1031
+ const errIntro = importStringWasGenerated
1024
1032
  ? `The import path ${importPathString} in ${filePathToShowToUser}`
1025
- : `The import ${pc.cyan(importDataString)} defined in ${filePathToShowToUser}`;
1033
+ : `The import ${pc.cyan(importString)} defined in ${filePathToShowToUser}`;
1026
1034
  const errIntro2 = `${errIntro} couldn't be resolved: does ${importPathString}`;
1027
1035
  if (importPath.startsWith('.')) {
1028
1036
  assertUsage(false, `${errIntro2} point to an existing file?`);
@@ -1035,18 +1043,23 @@ function assertImport(importedFile, importData, importerFilePath) {
1035
1043
  function isVikeConfigFile(filePath) {
1036
1044
  return !!getConfigName(filePath);
1037
1045
  }
1038
- function getConfigValues(configValueSources, configDefinitionsRelevant) {
1046
+ function getConfigValues(configValueSources, configValuesComputed, configDefinitionsRelevant) {
1039
1047
  const configValues = {};
1048
+ Object.entries(configValuesComputed).forEach(([configName, configValueComputed]) => {
1049
+ configValues[configName] = {
1050
+ value: configValueComputed.value,
1051
+ definedAt: { isComputed: true }
1052
+ };
1053
+ });
1040
1054
  Object.entries(configValueSources).forEach(([configName, sources]) => {
1041
1055
  const configDef = configDefinitionsRelevant[configName];
1042
1056
  assert(configDef);
1043
1057
  if (!configDef.cumulative) {
1044
1058
  const configValueSource = sources[0];
1045
1059
  if ('value' in configValueSource) {
1046
- const { value, definedAtInfo } = configValueSource;
1047
1060
  configValues[configName] = {
1048
- value,
1049
- definedAtInfo
1061
+ value: configValueSource.value,
1062
+ definedAt: getDefinedAt(configValueSource)
1050
1063
  };
1051
1064
  }
1052
1065
  }
@@ -1054,7 +1067,10 @@ function getConfigValues(configValueSources, configDefinitionsRelevant) {
1054
1067
  const value = mergeCumulative(configName, sources);
1055
1068
  configValues[configName] = {
1056
1069
  value,
1057
- definedAtInfo: null
1070
+ definedAt: {
1071
+ isCumulative: true,
1072
+ files: sources.map((source) => getDefinedAtFile(source))
1073
+ }
1058
1074
  };
1059
1075
  }
1060
1076
  });
@@ -1065,8 +1081,7 @@ function mergeCumulative(configName, configValueSources) {
1065
1081
  const valuesSet = [];
1066
1082
  let configValueSourcePrevious = null;
1067
1083
  configValueSources.forEach((configValueSource) => {
1068
- assert(!configValueSource.isComputed);
1069
- const configDefinedAt = getConfigDefinedAtString(configName, configValueSource, true);
1084
+ const configDefinedAt = getConfigSourceDefinedAtString(configName, configValueSource);
1070
1085
  const configNameColored = pc.cyan(configName);
1071
1086
  // We could, in principle, also support cumulative values to be defined in +${configName}.js but it ins't completely trivial to implement
1072
1087
  assertUsage('value' in configValueSource, `${configDefinedAt} is only allowed to be defined in a +config.h.js file. (Because the values of ${configNameColored} are cumulative.)`);
@@ -1074,7 +1089,7 @@ function mergeCumulative(configName, configValueSources) {
1074
1089
  const explanation = `(Because the values of ${configNameColored} are cumulative and therefore merged together.)` as const
1075
1090
  */
1076
1091
  // Make sure configValueSource.value is serializable
1077
- getConfigValueSerialized(configValueSource.value, configName, configValueSource.definedAtInfo);
1092
+ getConfigValueSerialized(configValueSource.value, configName, getDefinedAt(configValueSource));
1078
1093
  const assertNoMixing = (isSet) => {
1079
1094
  const vals1 = isSet ? valuesSet : valuesArr;
1080
1095
  const t1 = isSet ? 'a Set' : 'an array';
@@ -1084,7 +1099,7 @@ function mergeCumulative(configName, configValueSources) {
1084
1099
  if (vals2.length === 0)
1085
1100
  return;
1086
1101
  assert(configValueSourcePrevious);
1087
- const configPreviousDefinedAt = getConfigDefinedAtString(configName, configValueSourcePrevious, false);
1102
+ const configPreviousDefinedAt = getConfigSourceDefinedAtString(configName, configValueSourcePrevious, undefined, false);
1088
1103
  assertUsage(false, `${configDefinedAt} sets ${t1} but another ${configPreviousDefinedAt} sets ${t2} which is forbidden: the values must be all arrays or all sets (you cannot mix).`);
1089
1104
  };
1090
1105
  const { value } = configValueSource;
@@ -1115,3 +1130,30 @@ function mergeCumulative(configName, configValueSources) {
1115
1130
  }
1116
1131
  assert(false);
1117
1132
  }
1133
+ // TODO: rename
1134
+ // TODO: refactor
1135
+ function getConfigSourceDefinedAtString(configName, { definedAtInfo }, isEffect = undefined, sentenceBegin = true) {
1136
+ return getConfigDefinedAtString(configName, {
1137
+ definedAt: {
1138
+ isEffect,
1139
+ file: {
1140
+ filePathToShowToUser: getDefinedAtFilePathToShowToUser(definedAtInfo),
1141
+ fileExportPath: definedAtInfo.fileExportPath
1142
+ }
1143
+ }
1144
+ }, sentenceBegin);
1145
+ }
1146
+ function getDefinedAtFilePathToShowToUser(definedAtInfo) {
1147
+ return definedAtInfo.filePathRelativeToUserRootDir ?? definedAtInfo.importPathAbsolute;
1148
+ }
1149
+ function getDefinedAtFile(source) {
1150
+ return {
1151
+ filePathToShowToUser: getDefinedAtFilePathToShowToUser(source.definedAtInfo),
1152
+ fileExportPath: source.definedAtInfo.fileExportPath
1153
+ };
1154
+ }
1155
+ function getDefinedAt(configValueSource) {
1156
+ return {
1157
+ file: getDefinedAtFile(configValueSource)
1158
+ };
1159
+ }