vike 0.4.144 → 0.4.145-commit-2520555

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 (198) hide show
  1. package/dist/cjs/__internal/index.js +6 -2
  2. package/dist/cjs/node/plugin/plugins/buildConfig.js +3 -3
  3. package/dist/cjs/node/plugin/plugins/commonConfig.js +0 -3
  4. package/dist/cjs/node/plugin/plugins/config/index.js +3 -3
  5. package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +8 -8
  6. package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -0
  7. package/dist/cjs/node/plugin/plugins/envVars.js +34 -20
  8. package/dist/cjs/node/plugin/plugins/importBuild/index.js +3 -3
  9. package/dist/cjs/node/plugin/plugins/importUserCode/getVirtualFileImportUserCode.js +1 -1
  10. package/dist/cjs/node/plugin/plugins/importUserCode/index.js +3 -3
  11. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +5 -4
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +12 -12
  13. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +249 -228
  14. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +8 -6
  15. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +36 -14
  16. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/helpers.js +1 -14
  17. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +18 -0
  18. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +15 -17
  19. package/dist/cjs/node/plugin/plugins/previewConfig.js +11 -2
  20. package/dist/cjs/node/prerender/runPrerender.js +34 -26
  21. package/dist/cjs/node/prerender/utils.js +1 -1
  22. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +20 -6
  23. package/dist/cjs/node/runtime/renderPage/debugPageFiles.js +5 -5
  24. package/dist/cjs/node/runtime/renderPage/log404/index.js +28 -17
  25. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -3
  26. package/dist/cjs/node/runtime/renderPage.js +3 -3
  27. package/dist/cjs/node/runtime/utils.js +1 -1
  28. package/dist/cjs/node/shared/getClientEntryFilePath.js +2 -2
  29. package/dist/cjs/node/shared/getConfigVike.js +4 -1
  30. package/dist/cjs/shared/addUrlComputedProps.js +24 -12
  31. package/dist/cjs/shared/getPageFiles/analyzeClientSide.js +4 -6
  32. package/dist/cjs/shared/getPageFiles/getExports.js +3 -3
  33. package/dist/cjs/shared/hooks/getHook.js +1 -1
  34. package/dist/cjs/shared/page-configs/getExportPath.js +3 -3
  35. package/dist/cjs/shared/page-configs/helpers/getConfigDefinedAtString.js +43 -0
  36. package/dist/cjs/shared/page-configs/helpers/getConfigValue.js +44 -0
  37. package/dist/cjs/shared/page-configs/helpers.js +33 -0
  38. package/dist/cjs/shared/page-configs/loadConfigValues.js +2 -2
  39. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +14 -13
  40. package/dist/cjs/shared/page-configs/serialize/parsePageConfigs.js +2 -2
  41. package/dist/cjs/shared/page-configs/serialize/serializeConfigValue.js +9 -10
  42. package/dist/cjs/shared/route/abort.js +1 -1
  43. package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +41 -15
  44. package/dist/cjs/shared/route/index.js +22 -32
  45. package/dist/cjs/shared/route/loadPageRoutes.js +11 -10
  46. package/dist/cjs/shared/route/noRouteMatch.js +4 -0
  47. package/dist/cjs/shared/route/resolveRouteFunction.js +1 -1
  48. package/dist/cjs/shared/utils.js +1 -1
  49. package/dist/cjs/utils/getFilePathAbsolute.js +11 -11
  50. package/dist/cjs/utils/isExternalLink.js +7 -0
  51. package/dist/cjs/utils/{hasPropertyGetter.js → isPropertyGetter.js} +3 -3
  52. package/dist/cjs/utils/onPageVisibilityChange.js +19 -0
  53. package/dist/cjs/utils/parseUrl.js +1 -1
  54. package/dist/cjs/utils/projectInfo.js +1 -1
  55. package/dist/cjs/utils/truncateString.js +12 -7
  56. package/dist/esm/__internal/index.d.ts +6 -3
  57. package/dist/esm/__internal/index.js +8 -3
  58. package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -3
  59. package/dist/esm/client/client-routing-runtime/createPageContext.js +3 -4
  60. package/dist/esm/client/client-routing-runtime/entry.js +2 -2
  61. package/dist/esm/client/client-routing-runtime/getBaseServer.d.ts +2 -1
  62. package/dist/esm/client/client-routing-runtime/getBaseServer.js +2 -1
  63. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.d.ts +39 -0
  64. package/dist/esm/client/client-routing-runtime/{getPageContext.js → getPageContextFromHooks.js} +50 -79
  65. package/dist/esm/client/client-routing-runtime/history.d.ts +3 -1
  66. package/dist/esm/client/client-routing-runtime/history.js +31 -9
  67. package/dist/esm/client/client-routing-runtime/installClientRouter.d.ts +2 -0
  68. package/dist/esm/client/client-routing-runtime/installClientRouter.js +22 -0
  69. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.d.ts +8 -0
  70. package/dist/esm/client/client-routing-runtime/isClientSideRoutable.js +12 -0
  71. package/dist/esm/client/client-routing-runtime/navigate.d.ts +0 -2
  72. package/dist/esm/client/client-routing-runtime/navigate.js +9 -8
  73. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.d.ts +4 -0
  74. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +63 -0
  75. package/dist/esm/client/client-routing-runtime/onLinkClick.d.ts +2 -0
  76. package/dist/esm/client/client-routing-runtime/onLinkClick.js +40 -0
  77. package/dist/esm/client/client-routing-runtime/prefetch.js +54 -29
  78. package/dist/esm/client/client-routing-runtime/renderPageClientSide.d.ts +19 -0
  79. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +347 -0
  80. package/dist/esm/client/client-routing-runtime/scrollRestoration.d.ts +6 -0
  81. package/dist/esm/client/client-routing-runtime/scrollRestoration.js +25 -0
  82. package/dist/esm/client/client-routing-runtime/setScrollPosition.d.ts +7 -0
  83. package/dist/esm/client/client-routing-runtime/setScrollPosition.js +77 -0
  84. package/dist/esm/client/client-routing-runtime/skipLink.d.ts +0 -1
  85. package/dist/esm/client/client-routing-runtime/skipLink.js +9 -5
  86. package/dist/esm/client/client-routing-runtime/utils.d.ts +2 -0
  87. package/dist/esm/client/client-routing-runtime/utils.js +2 -0
  88. package/dist/esm/client/server-routing-runtime/getPageContext.js +1 -1
  89. package/dist/esm/client/shared/executeOnRenderClientHook.js +6 -5
  90. package/dist/esm/client/shared/getPageContextProxyForUser.js +13 -7
  91. package/dist/esm/client/shared/loadPageFilesClientSide.d.ts +8 -3
  92. package/dist/esm/client/shared/loadPageFilesClientSide.js +5 -5
  93. package/dist/esm/node/plugin/plugins/buildConfig.js +3 -3
  94. package/dist/esm/node/plugin/plugins/commonConfig.js +0 -3
  95. package/dist/esm/node/plugin/plugins/config/index.js +4 -4
  96. package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +9 -9
  97. package/dist/esm/node/plugin/plugins/devConfig/index.js +1 -0
  98. package/dist/esm/node/plugin/plugins/envVars.d.ts +2 -0
  99. package/dist/esm/node/plugin/plugins/envVars.js +35 -20
  100. package/dist/esm/node/plugin/plugins/importBuild/index.js +3 -3
  101. package/dist/esm/node/plugin/plugins/importUserCode/getVirtualFileImportUserCode.js +1 -1
  102. package/dist/esm/node/plugin/plugins/importUserCode/index.js +3 -3
  103. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +2 -1
  104. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +5 -4
  105. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.d.ts +1 -1
  106. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +12 -12
  107. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +2 -1
  108. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +250 -229
  109. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.d.ts +2 -2
  110. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +7 -5
  111. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +2 -2
  112. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +37 -15
  113. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.js +1 -14
  114. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.d.ts +7 -0
  115. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +15 -0
  116. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.d.ts +2 -2
  117. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +16 -18
  118. package/dist/esm/node/plugin/plugins/previewConfig.js +11 -2
  119. package/dist/esm/node/prerender/runPrerender.js +29 -21
  120. package/dist/esm/node/prerender/utils.d.ts +1 -1
  121. package/dist/esm/node/prerender/utils.js +1 -1
  122. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +21 -7
  123. package/dist/esm/node/runtime/renderPage/debugPageFiles.d.ts +5 -5
  124. package/dist/esm/node/runtime/renderPage/debugPageFiles.js +5 -5
  125. package/dist/esm/node/runtime/renderPage/loadPageFilesServerSide.d.ts +2 -2
  126. package/dist/esm/node/runtime/renderPage/log404/index.d.ts +2 -2
  127. package/dist/esm/node/runtime/renderPage/log404/index.js +28 -16
  128. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +2 -2
  129. package/dist/esm/node/runtime/renderPage.js +3 -3
  130. package/dist/esm/node/runtime/utils.d.ts +1 -1
  131. package/dist/esm/node/runtime/utils.js +1 -1
  132. package/dist/esm/node/shared/getClientEntryFilePath.js +1 -1
  133. package/dist/esm/node/shared/getConfigVike.d.ts +2 -1
  134. package/dist/esm/node/shared/getConfigVike.js +4 -1
  135. package/dist/esm/shared/addUrlComputedProps.d.ts +1 -0
  136. package/dist/esm/shared/addUrlComputedProps.js +25 -13
  137. package/dist/esm/shared/getPageFiles/analyzeClientSide.js +2 -4
  138. package/dist/esm/shared/getPageFiles/getExports.js +2 -2
  139. package/dist/esm/shared/hooks/getHook.js +1 -1
  140. package/dist/esm/shared/page-configs/PageConfig.d.ts +55 -31
  141. package/dist/esm/shared/page-configs/getExportPath.d.ts +1 -1
  142. package/dist/esm/shared/page-configs/getExportPath.js +3 -3
  143. package/dist/esm/shared/page-configs/helpers/getConfigDefinedAtString.d.ts +7 -0
  144. package/dist/esm/shared/page-configs/helpers/getConfigDefinedAtString.js +37 -0
  145. package/dist/esm/shared/page-configs/helpers/getConfigValue.d.ts +14 -0
  146. package/dist/esm/shared/page-configs/helpers/getConfigValue.js +38 -0
  147. package/dist/esm/shared/page-configs/helpers.d.ts +13 -0
  148. package/dist/esm/shared/page-configs/helpers.js +27 -0
  149. package/dist/esm/shared/page-configs/loadConfigValues.js +2 -2
  150. package/dist/esm/shared/page-configs/serialize/PageConfigSerialized.d.ts +4 -4
  151. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +15 -11
  152. package/dist/esm/shared/page-configs/serialize/parsePageConfigs.js +2 -2
  153. package/dist/esm/shared/page-configs/serialize/serializeConfigValue.js +9 -10
  154. package/dist/esm/shared/route/abort.js +1 -1
  155. package/dist/esm/shared/route/executeOnBeforeRouteHook.d.ts +5 -8
  156. package/dist/esm/shared/route/executeOnBeforeRouteHook.js +41 -15
  157. package/dist/esm/shared/route/index.d.ts +12 -10
  158. package/dist/esm/shared/route/index.js +23 -33
  159. package/dist/esm/shared/route/loadPageRoutes.js +8 -7
  160. package/dist/esm/shared/route/noRouteMatch.d.ts +1 -0
  161. package/dist/esm/shared/route/noRouteMatch.js +1 -0
  162. package/dist/esm/shared/route/resolveRouteFunction.js +1 -1
  163. package/dist/esm/shared/utils.d.ts +1 -1
  164. package/dist/esm/shared/utils.js +1 -1
  165. package/dist/esm/utils/getFilePathAbsolute.d.ts +1 -1
  166. package/dist/esm/utils/getFilePathAbsolute.js +11 -11
  167. package/dist/esm/utils/isPropertyGetter.d.ts +1 -0
  168. package/dist/esm/utils/{hasPropertyGetter.js → isPropertyGetter.js} +1 -1
  169. package/dist/esm/utils/onPageVisibilityChange.d.ts +4 -0
  170. package/dist/esm/utils/onPageVisibilityChange.js +16 -0
  171. package/dist/esm/utils/parseUrl.js +1 -1
  172. package/dist/esm/utils/projectInfo.d.ts +1 -1
  173. package/dist/esm/utils/projectInfo.js +1 -1
  174. package/dist/esm/utils/truncateString.d.ts +2 -1
  175. package/dist/esm/utils/truncateString.js +10 -7
  176. package/node/cli/bin-entry.js +1 -1
  177. package/package.json +2 -3
  178. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.js +0 -16
  179. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.js +0 -13
  180. package/dist/cjs/shared/page-configs/utils.js +0 -103
  181. package/dist/esm/client/client-routing-runtime/getPageContext.d.ts +0 -29
  182. package/dist/esm/client/client-routing-runtime/getPageId.d.ts +0 -10
  183. package/dist/esm/client/client-routing-runtime/getPageId.js +0 -17
  184. package/dist/esm/client/client-routing-runtime/navigationState.d.ts +0 -5
  185. package/dist/esm/client/client-routing-runtime/navigationState.js +0 -14
  186. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.d.ts +0 -2
  187. package/dist/esm/client/client-routing-runtime/skipLink/isClientSideRoutable.js +0 -15
  188. package/dist/esm/client/client-routing-runtime/useClientRouter.d.ts +0 -6
  189. package/dist/esm/client/client-routing-runtime/useClientRouter.js +0 -493
  190. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.d.ts +0 -24
  191. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getFilePathToShowToUser.js +0 -13
  192. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.d.ts +0 -3
  193. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isConfigEnvMatch.js +0 -10
  194. package/dist/esm/shared/page-configs/utils.d.ts +0 -35
  195. package/dist/esm/shared/page-configs/utils.js +0 -97
  196. package/dist/esm/utils/hasPropertyGetter.d.ts +0 -1
  197. /package/dist/esm/{client/client-routing-runtime → utils}/isExternalLink.d.ts +0 -0
  198. /package/dist/esm/{client/client-routing-runtime → utils}/isExternalLink.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, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar, isNpmPackageImport, joinEnglish, lowerFirst, scriptFileExtensions, mergeCumulativeValues, requireResolve } from '../../../utils.js';
5
+ import { assertPosixPath, assert, isObject, assertUsage, toPosixPath, assertWarning, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar, isNpmPackageImport, joinEnglish, lowerFirst, scriptFileExtensions, mergeCumulativeValues, requireResolve, getOutDirs } 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';
@@ -13,11 +13,11 @@ import { isConfigInvalid, isConfigInvalid_set } from '../../../../runtime/render
13
13
  import { getViteDevServer } from '../../../../runtime/globalContext.js';
14
14
  import { logConfigError, logConfigErrorRecover } from '../../../shared/loggerNotProd.js';
15
15
  import { removeSuperfluousViteLog_enable, removeSuperfluousViteLog_disable } from '../../../shared/loggerVite/removeSuperfluousViteLog.js';
16
- import { getFilePathToShowToUser } from './getFilePathToShowToUser.js';
17
16
  import pc from '@brillout/picocolors';
18
- import { getConfigDefinedAtString } from '../../../../../shared/page-configs/utils.js';
17
+ import { getConfigDefinedAtString } from '../../../../../shared/page-configs/helpers.js';
19
18
  import { assertExportsOfConfigFile, assertExportsOfValueFile } from '../../../../../shared/page-configs/assertExports.js';
20
19
  import { getConfigValueSerialized } from './getVirtualFilePageConfigs.js';
20
+ import { getConfigVike } from '../../../../shared/getConfigVike.js';
21
21
  assertIsNotProductionRuntime();
22
22
  let devServerIsCorrupt = false;
23
23
  let wasConfigInvalid = null;
@@ -61,9 +61,11 @@ async function handleReloadSideEffects() {
61
61
  }
62
62
  }
63
63
  }
64
- async function getVikeConfig(userRootDir, outDirRoot, isDev, extensions, tolerateInvalidConfig = false) {
64
+ async function getVikeConfig(config, isDev, tolerateInvalidConfig = false, extensions) {
65
+ const { outDirRoot } = getOutDirs(config);
66
+ const userRootDir = config.root;
65
67
  if (!vikeConfigPromise) {
66
- vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, isDev, extensions, tolerateInvalidConfig);
68
+ vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, isDev, extensions ?? (await getConfigVike(config)).extensions, tolerateInvalidConfig);
67
69
  }
68
70
  return await vikeConfigPromise;
69
71
  }
@@ -72,7 +74,7 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
72
74
  const configFiles = [];
73
75
  const valueFiles = [];
74
76
  plusFiles.forEach((f) => {
75
- if (getConfigName(f.filePathRelativeToUserRootDir) === 'config') {
77
+ if (getConfigName(f.filePathAbsoluteFilesystem) === 'config') {
76
78
  configFiles.push(f);
77
79
  }
78
80
  else {
@@ -81,15 +83,10 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
81
83
  });
82
84
  let interfaceFilesByLocationId = {};
83
85
  // Config files
84
- await Promise.all(configFiles.map(async ({ filePathAbsolute, filePathRelativeToUserRootDir }) => {
85
- const configFilePath = {
86
- filePathAbsolute: filePathAbsolute,
87
- filePathRelativeToUserRootDir: filePathRelativeToUserRootDir,
88
- importPathAbsolute: null
89
- };
90
- const { configFile, extendsConfigs } = await loadConfigFile(configFilePath, userRootDir, []);
86
+ await Promise.all(configFiles.map(async (filePath) => {
87
+ const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, []);
91
88
  const interfaceFile = getInterfaceFileFromConfigFile(configFile, false);
92
- const locationId = getLocationId(filePathRelativeToUserRootDir);
89
+ const locationId = getLocationId(filePath.filePathAbsoluteVite);
93
90
  interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
94
91
  interfaceFilesByLocationId[locationId].push(interfaceFile);
95
92
  extendsConfigs.forEach((extendsConfig) => {
@@ -98,15 +95,11 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
98
95
  });
99
96
  }));
100
97
  // Value files
101
- await Promise.all(valueFiles.map(async ({ filePathAbsolute, filePathRelativeToUserRootDir }) => {
102
- const configName = getConfigName(filePathRelativeToUserRootDir);
98
+ await Promise.all(valueFiles.map(async (filePath) => {
99
+ const configName = getConfigName(filePath.filePathAbsoluteVite);
103
100
  assert(configName);
104
101
  const interfaceFile = {
105
- filePath: {
106
- filePathRelativeToUserRootDir,
107
- filePathAbsolute,
108
- importPathAbsolute: null
109
- },
102
+ filePath,
110
103
  configMap: {
111
104
  [configName]: {}
112
105
  },
@@ -115,25 +108,25 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
115
108
  configName
116
109
  };
117
110
  {
118
- // We don't have access to custom config definitions yet
119
- // - We load +{configName}.js later
120
- // - But we do need to eagerly load +meta.js (to get all the custom config definitions)
111
+ // We don't have access to the custom config definitions defined by the user yet.
112
+ // - If `configDef` is `undefined` => we load the file +{configName}.js later.
113
+ // - We already need to load +meta.js here (to get the custom config definitions defined by the user)
121
114
  const configDef = getConfigDefinitionOptional(configDefinitionsBuiltIn, configName);
122
- if (configDef?.env === 'config-only') {
115
+ if (configDef && isConfigEnv(configDef, configName)) {
123
116
  await loadValueFile(interfaceFile, configName, userRootDir);
124
117
  }
125
118
  }
126
119
  {
127
- const locationId = getLocationId(filePathRelativeToUserRootDir);
120
+ const locationId = getLocationId(filePath.filePathAbsoluteVite);
128
121
  interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
129
122
  interfaceFilesByLocationId[locationId].push(interfaceFile);
130
123
  }
131
124
  }));
132
125
  return interfaceFilesByLocationId;
133
126
  }
134
- function getConfigDefinition(configDefinitionsRelevant, configName, definedByFile) {
127
+ function getConfigDefinition(configDefinitionsRelevant, configName, filePathToShowToUser) {
135
128
  const configDef = configDefinitionsRelevant[configName];
136
- assertConfigExists(configName, Object.keys(configDefinitionsRelevant), definedByFile);
129
+ assertConfigExists(configName, Object.keys(configDefinitionsRelevant), filePathToShowToUser);
137
130
  assert(configDef);
138
131
  return configDef;
139
132
  }
@@ -142,13 +135,29 @@ function getConfigDefinitionOptional(configDefinitions, configName) {
142
135
  }
143
136
  async function loadValueFile(interfaceValueFile, configName, userRootDir) {
144
137
  const { fileExports } = await transpileAndExecuteFile(interfaceValueFile.filePath, true, userRootDir);
145
- const filePathToShowToUser = getFilePathToShowToUser(interfaceValueFile.filePath);
138
+ const { filePathToShowToUser } = interfaceValueFile.filePath;
146
139
  assertExportsOfValueFile(fileExports, filePathToShowToUser, configName);
147
140
  Object.entries(fileExports).forEach(([exportName, configValue]) => {
148
141
  const configName_ = exportName === 'default' ? configName : exportName;
149
142
  interfaceValueFile.configMap[configName_] = { configValue };
150
143
  });
151
144
  }
145
+ async function loadImportedFile(filePath, userRootDir, importedFilesLoaded) {
146
+ const f = filePath.filePathAbsoluteFilesystem;
147
+ if (!importedFilesLoaded[f]) {
148
+ importedFilesLoaded[f] = transpileAndExecuteFile(filePath, true, userRootDir).then((r) => r.fileExports);
149
+ }
150
+ const fileExports = await importedFilesLoaded[f];
151
+ return fileExports;
152
+ }
153
+ function isConfigEnv(configDef, configName) {
154
+ if (configDef.cumulative)
155
+ return true;
156
+ if (configDef.env === 'config-only')
157
+ return true;
158
+ // TODO: replace with proper `env: { config: boolean }` implementation
159
+ return configName === 'clientRouting';
160
+ }
152
161
  function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
153
162
  const { fileExports, filePath, extendsFilePaths } = configFile;
154
163
  const interfaceFile = {
@@ -159,7 +168,7 @@ function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
159
168
  isConfigExtend,
160
169
  extendsFilePaths
161
170
  };
162
- const filePathToShowToUser = getFilePathToShowToUser(filePath);
171
+ const { filePathToShowToUser } = filePath;
163
172
  assertExportsOfConfigFile(fileExports, filePathToShowToUser);
164
173
  Object.entries(fileExports.default).forEach(([configName, configValue]) => {
165
174
  interfaceFile.configMap[configName] = { configValue };
@@ -209,7 +218,8 @@ async function loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, isDev,
209
218
  }
210
219
  async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
211
220
  const interfaceFilesByLocationId = await loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions);
212
- const { globalVikeConfig, pageConfigGlobal } = getGlobalConfigs(interfaceFilesByLocationId, userRootDir);
221
+ const importedFilesLoaded = {};
222
+ const { globalVikeConfig, pageConfigGlobal } = await getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded);
213
223
  const pageConfigs = await Promise.all(Object.entries(interfaceFilesByLocationId)
214
224
  .filter(([_pageId, interfaceFiles]) => isDefiningPage(interfaceFiles))
215
225
  .map(async ([locationId]) => {
@@ -222,25 +232,25 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
222
232
  const { configName } = interfaceFile;
223
233
  if (isGlobalConfig(configName))
224
234
  return;
225
- const configDef = getConfigDefinition(configDefinitionsRelevant, configName, getFilePathToShowToUser(interfaceFile.filePath));
226
- if (configDef.env !== 'config-only')
235
+ const configDef = getConfigDefinition(configDefinitionsRelevant, configName, interfaceFile.filePath.filePathToShowToUser);
236
+ if (!isConfigEnv(configDef, configName))
227
237
  return;
228
238
  const isAlreadyLoaded = interfacefileIsAlreaydLoaded(interfaceFile);
229
239
  if (isAlreadyLoaded)
230
240
  return;
231
- // Value files for built-in confg-only configs should have already been loaded at loadInterfaceFiles()
241
+ // Value files of built-in configs should have already been loaded at loadInterfaceFiles()
232
242
  assert(!(configName in configDefinitionsBuiltIn));
233
243
  await loadValueFile(interfaceFile, configName, userRootDir);
234
244
  }));
235
245
  const configValueSources = {};
236
- objectEntries(configDefinitionsRelevant)
246
+ await Promise.all(objectEntries(configDefinitionsRelevant)
237
247
  .filter(([configName]) => !isGlobalConfig(configName))
238
- .forEach(([configName, configDef]) => {
239
- const sources = resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir);
240
- if (!sources)
248
+ .map(async ([configName, configDef]) => {
249
+ const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded);
250
+ if (sources.length === 0)
241
251
  return;
242
252
  configValueSources[configName] = sources;
243
- });
253
+ }));
244
254
  const { routeFilesystem, isErrorPage } = determineRouteFilesystem(locationId, configValueSources);
245
255
  applyEffectsAll(configValueSources, configDefinitionsRelevant);
246
256
  const configValuesComputed = getComputed(configValueSources, configDefinitionsRelevant);
@@ -261,7 +271,7 @@ async function loadVikeConfig(userRootDir, outDirRoot, isDev, extensions) {
261
271
  const configDefinitionsRelevant = getConfigDefinitions(interfaceFilesRelevant);
262
272
  interfaceFiles.forEach((interfaceFile) => {
263
273
  Object.keys(interfaceFile.configMap).forEach((configName) => {
264
- assertConfigExists(configName, Object.keys(configDefinitionsRelevant), getFilePathToShowToUser(interfaceFile.filePath));
274
+ assertConfigExists(configName, Object.keys(configDefinitionsRelevant), interfaceFile.filePath.filePathToShowToUser);
265
275
  });
266
276
  });
267
277
  });
@@ -290,7 +300,7 @@ function getInterfaceFileList(interfaceFilesByLocationId) {
290
300
  });
291
301
  return interfaceFiles;
292
302
  }
293
- function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
303
+ async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importedFilesLoaded) {
294
304
  const locationIds = Object.keys(interfaceFilesByLocationId);
295
305
  const interfaceFilesGlobal = Object.fromEntries(Object.entries(interfaceFilesByLocationId).filter(([locationId]) => {
296
306
  return isGlobalLocation(locationId, locationIds);
@@ -312,7 +322,7 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
312
322
  Object.keys(interfaceFile.configMap).forEach((configName) => {
313
323
  if (!isGlobalLocation(locationId, locationIds) && isGlobalConfig(configName)) {
314
324
  assertUsage(false, [
315
- `${getFilePathToShowToUser(interfaceFile.filePath)} defines the config ${pc.cyan(configName)} which is global:`,
325
+ `${interfaceFile.filePath.filePathToShowToUser} defines the config ${pc.cyan(configName)} which is global:`,
316
326
  globalPaths.length
317
327
  ? `define ${pc.cyan(configName)} in ${joinEnglish(globalPaths, 'or')} instead`
318
328
  : `create a global config (e.g. /pages/+config.js) and define ${pc.cyan(configName)} there instead`
@@ -326,9 +336,9 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
326
336
  const pageConfigGlobal = {
327
337
  configValueSources: {}
328
338
  };
329
- objectEntries(configDefinitionsBuiltInGlobal).forEach(([configName, configDef]) => {
330
- const sources = resolveConfigValueSources(configName, configDef, interfaceFilesGlobal, userRootDir);
331
- const configValueSource = sources?.[0];
339
+ await Promise.all(objectEntries(configDefinitionsBuiltInGlobal).map(async ([configName, configDef]) => {
340
+ const sources = await resolveConfigValueSources(configName, configDef, interfaceFilesGlobal, userRootDir, importedFilesLoaded);
341
+ const configValueSource = sources[0];
332
342
  if (!configValueSource)
333
343
  return;
334
344
  if (configName === 'onBeforeRoute' || configName === 'onPrerenderStart') {
@@ -339,28 +349,25 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
339
349
  assert('value' in configValueSource);
340
350
  if (configName === 'prerender' && typeof configValueSource.value === 'boolean')
341
351
  return;
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 });
352
+ const { filePathToShowToUser } = configValueSource.definedAt;
353
+ assertWarning(false, `Being able to define config ${pc.cyan(configName)} in ${filePathToShowToUser} is experimental and will likely be removed. Define the config ${pc.cyan(configName)} in Vike's Vite plugin options instead.`, { onlyOnce: true });
345
354
  globalVikeConfig[configName] = configValueSource.value;
346
355
  }
347
- });
356
+ }));
348
357
  return { pageConfigGlobal, globalVikeConfig };
349
358
  }
350
- function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir) {
351
- let sources = null;
359
+ async function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant, userRootDir, importedFilesLoaded) {
360
+ const sourcesInfo = [];
352
361
  // interfaceFilesRelevant is sorted by sortAfterInheritanceOrder()
353
362
  for (const interfaceFiles of Object.values(interfaceFilesRelevant)) {
354
363
  const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.configMap[configName]);
355
364
  if (interfaceFilesDefiningConfig.length === 0)
356
365
  continue;
357
- sources = sources ?? [];
358
366
  const visited = new WeakSet();
359
367
  const add = (interfaceFile) => {
360
368
  assert(!visited.has(interfaceFile));
361
369
  visited.add(interfaceFile);
362
- const configValueSource = getConfigValueSource(configName, interfaceFile, configDef, userRootDir);
363
- sources.push(configValueSource);
370
+ sourcesInfo.push([configName, interfaceFile, configDef, userRootDir, importedFilesLoaded]);
364
371
  };
365
372
  // Main resolution logic
366
373
  {
@@ -384,7 +391,7 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
384
391
  if (interfaceFileWinner) {
385
392
  const interfaceFilesOverriden = [...interfaceValueFiles, ...interfaceConfigFiles].filter((f) => f !== interfaceFileWinner);
386
393
  // A user-land conflict of interfaceFiles with the same locationId means that the user has superfluously defined the config twice; the user should remove such redundancy making things unnecessarily ambiguous
387
- warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName, configDef, userRootDir);
394
+ warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName);
388
395
  [interfaceFileWinner, ...interfaceFilesOverriden].forEach((interfaceFile) => {
389
396
  add(interfaceFile);
390
397
  });
@@ -409,7 +416,7 @@ function resolveConfigValueSources(configName, configDef, interfaceFilesRelevant
409
416
  assert(visited.has(interfaceFile));
410
417
  });
411
418
  }
412
- assert(sources === null || sources.length > 0);
419
+ const sources = await Promise.all(sourcesInfo.map(async (args) => await getConfigValueSource(...args)));
413
420
  return sources;
414
421
  }
415
422
  function makeOrderDeterministic(interfaceFile1, interfaceFile2) {
@@ -420,41 +427,41 @@ function makeOrderDeterministic(interfaceFile1, interfaceFile2) {
420
427
  return filePathRelativeToUserRootDir.length;
421
428
  })(interfaceFile1, interfaceFile2);
422
429
  }
423
- function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName, configDef, userRootDir) {
430
+ function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden, configName) {
424
431
  interfaceFilesOverriden.forEach((interfaceFileLoser) => {
425
- const configValueSourceWinner = getConfigValueSource(configName, interfaceFileWinner, configDef, userRootDir);
426
- const configValueSourceLoser = getConfigValueSource(configName, interfaceFileLoser, configDef, userRootDir);
427
- assertWarning(false, `${getConfigSourceDefinedAtString(configName, configValueSourceLoser, undefined, true)} overriden by another ${getConfigSourceDefinedAtString(configName, configValueSourceWinner, undefined, false)}, remove one of the two`, { onlyOnce: false });
432
+ const loserFilePath = interfaceFileLoser.filePath.filePathToShowToUser;
433
+ const winnerFilePath = interfaceFileWinner.filePath.filePathToShowToUser;
434
+ assertWarning(false, `Config ${configName} defined at ${loserFilePath} is always overwritten by ${configName} defined at ${winnerFilePath}, remove the superfluous ${configName} value defined at ${interfaceFileLoser}`, { onlyOnce: false });
428
435
  });
429
436
  }
430
437
  function isInterfaceFileUserLand(interfaceFile) {
431
438
  return (interfaceFile.isConfigFile && !interfaceFile.isConfigExtend) || interfaceFile.isValueFile;
432
439
  }
433
- function getConfigValueSource(configName, interfaceFile, configDef, userRootDir) {
440
+ async function getConfigValueSource(configName, interfaceFile, configDef, userRootDir, importedFilesLoaded) {
434
441
  const conf = interfaceFile.configMap[configName];
435
442
  assert(conf);
436
443
  const configEnv = configDef.env;
437
444
  const definedAtConfigFile = {
438
445
  ...interfaceFile.filePath,
439
- fileExportPath: ['default', configName]
446
+ fileExportPathToShowToUser: ['default', configName]
440
447
  };
441
448
  if (configDef._valueIsFilePath) {
442
- let definedAtInfo;
449
+ let definedAt;
443
450
  let valueFilePath;
444
451
  if (interfaceFile.isConfigFile) {
445
452
  const { configValue } = conf;
446
453
  const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
447
- const configDefinedAt = getConfigSourceDefinedAtString(configName, { definedAtInfo: definedAtConfigFile });
454
+ const configDefinedAt = getConfigDefinedAtString('Config', configName, { definedAt: definedAtConfigFile });
448
455
  assertUsage(import_, `${configDefinedAt} should be an import`);
449
- valueFilePath = import_.filePathRelativeToUserRootDir ?? import_.importPathAbsolute;
450
- definedAtInfo = import_;
456
+ valueFilePath = import_.filePathAbsoluteVite;
457
+ definedAt = import_;
451
458
  }
452
459
  else {
453
460
  assert(interfaceFile.isValueFile);
454
- valueFilePath = interfaceFile.filePath.filePathRelativeToUserRootDir;
455
- definedAtInfo = {
461
+ valueFilePath = interfaceFile.filePath.filePathAbsoluteVite;
462
+ definedAt = {
456
463
  ...interfaceFile.filePath,
457
- fileExportPath: []
464
+ fileExportPathToShowToUser: []
458
465
  };
459
466
  }
460
467
  const configValueSource = {
@@ -462,7 +469,7 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
462
469
  valueIsFilePath: true,
463
470
  configEnv,
464
471
  valueIsImportedAtRuntime: true,
465
- definedAtInfo
472
+ definedAt
466
473
  };
467
474
  return configValueSource;
468
475
  }
@@ -474,8 +481,20 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
474
481
  const configValueSource = {
475
482
  configEnv,
476
483
  valueIsImportedAtRuntime: true,
477
- definedAtInfo: import_
484
+ definedAt: import_
478
485
  };
486
+ // Load config value
487
+ if (isConfigEnv(configDef, configName)) {
488
+ if (import_.filePathAbsoluteFilesystem) {
489
+ assert(hasProp(import_, 'filePathAbsoluteFilesystem', 'string')); // Help TS
490
+ const fileExports = await loadImportedFile(import_, userRootDir, importedFilesLoaded);
491
+ configValueSource.value = fileExports[import_.fileExportName];
492
+ }
493
+ else {
494
+ const configDefinedAt = getConfigDefinedAtString('Config', configName, configValueSource);
495
+ assertUsage(!configDef.cumulative, `${configDefinedAt} cannot be defined over an aliased import`);
496
+ }
497
+ }
479
498
  return configValueSource;
480
499
  }
481
500
  else {
@@ -483,7 +502,7 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
483
502
  value: configValue,
484
503
  configEnv,
485
504
  valueIsImportedAtRuntime: false,
486
- definedAtInfo: definedAtConfigFile
505
+ definedAt: definedAtConfigFile
487
506
  };
488
507
  return configValueSource;
489
508
  }
@@ -493,9 +512,9 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
493
512
  const configValueSource = {
494
513
  configEnv,
495
514
  valueIsImportedAtRuntime: !valueAlreadyLoaded,
496
- definedAtInfo: {
515
+ definedAt: {
497
516
  ...interfaceFile.filePath,
498
- fileExportPath: configName === interfaceFile.configName
517
+ fileExportPathToShowToUser: configName === interfaceFile.configName
499
518
  ? []
500
519
  : // Side-effect config (e.g. `export { frontmatter }` of .md files)
501
520
  [configName]
@@ -546,51 +565,61 @@ function resolveImport(configValue, importerFilePath, userRootDir, configEnv, co
546
565
  if (!importData)
547
566
  return null;
548
567
  const { importPath, exportName } = importData;
549
- const filePathAbsolute = resolveImportPath(importData, importerFilePath);
550
- assertFileEnv(filePathAbsolute ?? importPath, configEnv, configName);
551
- const fileExportPath = exportName === 'default' || exportName === configName ? [] : [exportName];
568
+ const filePathAbsoluteFilesystem = resolveImportPath(importData, importerFilePath);
569
+ assertFileEnv(filePathAbsoluteFilesystem ?? importPath, configEnv, configName);
570
+ const fileExportPathToShowToUser = exportName === 'default' || exportName === configName ? [] : [exportName];
552
571
  if (importPath.startsWith('.')) {
553
572
  // We need to resolve relative paths into absolute paths. Because the import paths are included in virtual files:
554
573
  // ```
555
574
  // [vite] Internal server error: Failed to resolve import "./onPageTransitionHooks" from "virtual:vike:pageConfigValuesAll:client:/pages/index". Does the file exist?
556
575
  // ```
557
- assertImportPath(filePathAbsolute, importData, importerFilePath);
558
- const filePathRelativeToUserRootDir = resolveImportPath_relativeToUserRootDir(filePathAbsolute, importData, importerFilePath, userRootDir);
559
- return {
560
- exportName,
561
- fileExportPath,
562
- filePathAbsolute,
576
+ assertImportPath(filePathAbsoluteFilesystem, importData, importerFilePath);
577
+ const filePathRelativeToUserRootDir = resolveImportPath_relativeToUserRootDir(filePathAbsoluteFilesystem, importData, importerFilePath, userRootDir);
578
+ const filePath = {
579
+ filePathAbsoluteFilesystem,
563
580
  filePathRelativeToUserRootDir,
581
+ filePathAbsoluteVite: filePathRelativeToUserRootDir,
582
+ filePathToShowToUser: filePathRelativeToUserRootDir,
564
583
  importPathAbsolute: null
565
584
  };
585
+ return {
586
+ ...filePath,
587
+ fileExportName: exportName,
588
+ fileExportPathToShowToUser
589
+ };
566
590
  }
567
591
  else {
568
592
  // importPath can be:
569
593
  // - an npm package import
570
594
  // - a path alias
571
- return {
572
- exportName,
573
- fileExportPath,
574
- filePathAbsolute,
595
+ const filePath = {
596
+ filePathAbsoluteFilesystem,
575
597
  filePathRelativeToUserRootDir: null,
598
+ filePathAbsoluteVite: importPath,
599
+ filePathToShowToUser: importPath,
576
600
  importPathAbsolute: importPath
577
601
  };
602
+ return {
603
+ ...filePath,
604
+ fileExportName: exportName,
605
+ fileExportPathToShowToUser
606
+ };
578
607
  }
579
608
  }
580
- function resolveImportPath_relativeToUserRootDir(filePathAbsolute, importData, configFilePath, userRootDir) {
609
+ function resolveImportPath_relativeToUserRootDir(filePathAbsoluteFilesystem, importData, configFilePath, userRootDir) {
581
610
  assertPosixPath(userRootDir);
582
611
  let filePathRelativeToUserRootDir;
583
- if (filePathAbsolute.startsWith(userRootDir)) {
584
- filePathRelativeToUserRootDir = getVitePathFromAbsolutePath(filePathAbsolute, userRootDir);
612
+ if (filePathAbsoluteFilesystem.startsWith(userRootDir)) {
613
+ filePathRelativeToUserRootDir = getVitePathFromAbsolutePath(filePathAbsoluteFilesystem, userRootDir);
585
614
  }
586
615
  else {
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`);
616
+ assertUsage(false, `${configFilePath.filePathToShowToUser} 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`);
588
617
  // None of the following works. Seems to be a Vite bug?
589
618
  // /*
590
- // assert(filePathAbsolute.startsWith('/'))
591
- // filePath = `/@fs${filePathAbsolute}`
619
+ // assert(filePathAbsoluteFilesystem.startsWith('/'))
620
+ // filePath = `/@fs${filePathAbsoluteFilesystem}`
592
621
  // /*/
593
- // filePathRelativeToUserRootDir = path.posix.relative(userRootDir, filePathAbsolute)
622
+ // filePathRelativeToUserRootDir = path.posix.relative(userRootDir, filePathAbsoluteFilesystem)
594
623
  // assert(filePathRelativeToUserRootDir.startsWith('../'))
595
624
  // filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir
596
625
  // //*/
@@ -599,11 +628,11 @@ function resolveImportPath_relativeToUserRootDir(filePathAbsolute, importData, c
599
628
  assert(filePathRelativeToUserRootDir.startsWith('/'));
600
629
  return filePathRelativeToUserRootDir;
601
630
  }
602
- function getVitePathFromAbsolutePath(filePathAbsolute, root) {
603
- assertPosixPath(filePathAbsolute);
631
+ function getVitePathFromAbsolutePath(filePathAbsoluteFilesystem, root) {
632
+ assertPosixPath(filePathAbsoluteFilesystem);
604
633
  assertPosixPath(root);
605
- assert(filePathAbsolute.startsWith(root));
606
- let vitePath = path.posix.relative(root, filePathAbsolute);
634
+ assert(filePathAbsoluteFilesystem.startsWith(root));
635
+ let vitePath = path.posix.relative(root, filePathAbsoluteFilesystem);
607
636
  assert(!vitePath.startsWith('/') && !vitePath.startsWith('.'));
608
637
  vitePath = '/' + vitePath;
609
638
  return vitePath;
@@ -616,9 +645,17 @@ function getConfigDefinitions(interfaceFilesRelevant) {
616
645
  if (!configMeta)
617
646
  return;
618
647
  const meta = configMeta.configValue;
619
- assertMetaValue(meta,
620
- // Maybe we should use the getConfigDefinedAtString() helper?
621
- `Config ${pc.cyan('meta')} defined at ${getFilePathToShowToUser(interfaceFile.filePath)}`);
648
+ assertMetaValue(meta, `Config ${pc.cyan('meta')} defined at ${interfaceFile.filePath.filePathToShowToUser}`);
649
+ // Set configDef._userEffectDefinedAt
650
+ Object.entries(meta).forEach(([configName, configDef]) => {
651
+ if (!configDef.effect)
652
+ return;
653
+ assert(interfaceFile.isConfigFile);
654
+ configDef._userEffectDefinedAt = {
655
+ ...interfaceFile.filePath,
656
+ fileExportPathToShowToUser: ['default', 'meta', configName, 'effect']
657
+ };
658
+ });
622
659
  objectEntries(meta).forEach(([configName, configDefinition]) => {
623
660
  // User can override an existing config definition
624
661
  configDefinitions[configName] = {
@@ -631,9 +668,15 @@ function getConfigDefinitions(interfaceFilesRelevant) {
631
668
  return configDefinitions;
632
669
  }
633
670
  function assertMetaValue(metaVal, configMetaDefinedAt) {
634
- assertUsage(isObject(metaVal), `${configMetaDefinedAt} has an invalid type ${pc.cyan(typeof metaVal)}: it should be an object instead.`);
671
+ if (!isObject(metaVal)) {
672
+ assert(configMetaDefinedAt); // We expect internal effects to return a valid meta value
673
+ assertUsage(false, `${configMetaDefinedAt} has an invalid type ${pc.cyan(typeof metaVal)}: it should be an object instead.`);
674
+ }
635
675
  objectEntries(metaVal).forEach(([configName, def]) => {
636
- assertUsage(isObject(def), `${configMetaDefinedAt} sets meta.${configName} to a value with an invalid type ${pc.cyan(typeof def)}: it should be an object instead.`);
676
+ if (!isObject(def)) {
677
+ assert(configMetaDefinedAt); // We expect internal effects to return a valid meta value
678
+ assertUsage(false, `${configMetaDefinedAt} sets ${pc.cyan(`meta.${configName}`)} to a value with an invalid type ${pc.cyan(typeof def)}: it should be an object instead.`);
679
+ }
637
680
  // env
638
681
  {
639
682
  const envValues = [
@@ -642,19 +685,34 @@ function assertMetaValue(metaVal, configMetaDefinedAt) {
642
685
  'server-and-client',
643
686
  'config-only'
644
687
  ];
645
- const hint = [
646
- `Set the value of ${pc.cyan('env')} to `,
688
+ const fix = [
689
+ `Set the value of ${pc.cyan(`meta.${configName}.env`)} to `,
647
690
  joinEnglish(envValues.map((s) => pc.cyan(`'${s}'`)), 'or'),
648
691
  '.'
649
692
  ].join('');
650
- assertUsage('env' in def, `${configMetaDefinedAt} doesn't set meta.${configName}.env but it's required. ${hint}`);
651
- assertUsage(hasProp(def, 'env', 'string'), `${configMetaDefinedAt} sets meta.${configName}.env to an invalid type ${pc.cyan(typeof def.env)}. ${hint}`);
652
- assertUsage(envValues.includes(def.env), `${configMetaDefinedAt} sets meta.${configName}.env to an invalid value ${pc.cyan(`'${def.env}'`)}. ${hint}`);
693
+ if (!('env' in def)) {
694
+ assert(configMetaDefinedAt); // We expect internal effects to return a valid meta value
695
+ assertUsage(false, `${configMetaDefinedAt} doesn't set ${pc.cyan(`meta.${configName}.env`)} but it's required. ${fix}`);
696
+ }
697
+ if (!hasProp(def, 'env', 'string')) {
698
+ assert(configMetaDefinedAt); // We expect internal effects to return a valid meta value
699
+ assertUsage(false, `${configMetaDefinedAt} sets ${pc.cyan(`meta.${configName}.env`)} to an invalid type ${pc.cyan(typeof def.env)}. ${fix}`);
700
+ }
701
+ if (!envValues.includes(def.env)) {
702
+ assert(configMetaDefinedAt); // We expect internal effects to return a valid meta value
703
+ assertUsage(false, `${configMetaDefinedAt} sets ${pc.cyan(`meta.${configName}.env`)} to an unknown value ${pc.cyan(`'${def.env}'`)}. ${fix}`);
704
+ }
653
705
  }
654
706
  // effect
655
707
  if ('effect' in def) {
656
- assertUsage(hasProp(def, 'effect', 'function'), `${configMetaDefinedAt} sets meta.${configName}.effect to an invalid type ${pc.cyan(typeof def.effect)}: it should be a function instead`);
657
- assertUsage(def.env === 'config-only', `${configMetaDefinedAt} sets meta.${configName}.effect but it's only supported if meta.${configName}.env is ${pc.cyan('config-only')} (but it's ${pc.cyan(def.env)} instead)`);
708
+ if (!hasProp(def, 'effect', 'function')) {
709
+ assert(configMetaDefinedAt); // We expect internal effects to return a valid meta value
710
+ assertUsage(false, `${configMetaDefinedAt} sets ${pc.cyan(`meta.${configName}.effect`)} to an invalid type ${pc.cyan(typeof def.effect)}: it should be a function instead`);
711
+ }
712
+ if (def.env !== 'config-only') {
713
+ assert(configMetaDefinedAt); // We expect internal effects to return a valid meta value
714
+ assertUsage(false, `${configMetaDefinedAt} sets ${pc.cyan(`meta.${configName}.effect`)} but it's only supported if meta.${configName}.env is ${pc.cyan('config-only')} (but it's ${pc.cyan(def.env)} instead)`);
715
+ }
658
716
  }
659
717
  });
660
718
  }
@@ -665,7 +723,7 @@ function applyEffectsAll(configValueSources, configDefinitionsRelevant) {
665
723
  // The value needs to be loaded at config time, that's why we only support effect for configs that are config-only for now.
666
724
  // (We could support effect for non config-only by always loading its value at config time, regardless of the config's `env` value.)
667
725
  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')}.`
726
+ `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 ${pc.cyan('env')} value of ${pc.cyan('config-only')}.`
669
727
  ].join(' '));
670
728
  const source = configValueSources[configName]?.[0];
671
729
  if (!source)
@@ -675,19 +733,28 @@ function applyEffectsAll(configValueSources, configDefinitionsRelevant) {
675
733
  // Call effect
676
734
  const configModFromEffect = configDef.effect({
677
735
  configValue: source.value,
678
- configDefinedAt: getConfigSourceDefinedAtString(configName, source)
736
+ configDefinedAt: getConfigDefinedAtString('Config', configName, source)
679
737
  });
680
738
  if (!configModFromEffect)
681
739
  return;
682
740
  assert(hasProp(source, 'value')); // We need to assume that the config value is loaded at build-time
683
- applyEffect(configModFromEffect, source, configValueSources);
741
+ applyEffect(configModFromEffect, configValueSources, configDef);
684
742
  });
685
743
  }
686
- function applyEffect(configModFromEffect, configValueEffectSource, configValueSources) {
744
+ function applyEffect(configModFromEffect, configValueSources, configDefEffect) {
687
745
  const notSupported = `Effects currently only supports modifying the the ${pc.cyan('env')} of a config.`;
688
746
  objectEntries(configModFromEffect).forEach(([configName, configValue]) => {
689
747
  if (configName === 'meta') {
690
- assertMetaValue(configValue, getConfigSourceDefinedAtString(configName, configValueEffectSource, true));
748
+ let configDefinedAtString;
749
+ if (configDefEffect._userEffectDefinedAt) {
750
+ configDefinedAtString = getConfigDefinedAtString('Config', configName, {
751
+ definedAt: configDefEffect._userEffectDefinedAt
752
+ });
753
+ }
754
+ else {
755
+ configDefinedAtString = null;
756
+ }
757
+ assertMetaValue(configValue, configDefinedAtString);
691
758
  objectEntries(configValue).forEach(([configTargetName, configTargetDef]) => {
692
759
  {
693
760
  const keys = Object.keys(configTargetDef);
@@ -705,7 +772,7 @@ function applyEffect(configModFromEffect, configValueEffectSource, configValueSo
705
772
  else {
706
773
  assertUsage(false, notSupported);
707
774
  // If we do end implementing being able to set the value of a config:
708
- // - For setting definedAtInfo: we could take the definedAtInfo of the effect config while appending '(effect)' to definedAtInfo.fileExportPath
775
+ // - For setting definedAt: we could take the definedAt of the effect config while appending '(effect)' to definedAt.fileExportPathToShowToUser
709
776
  }
710
777
  });
711
778
  }
@@ -756,20 +823,29 @@ async function findPlusFiles(userRootDir, ignoreDirs, isDev, extensions) {
756
823
  const plusFiles = result.map((p) => {
757
824
  p = toPosixPath(p);
758
825
  const filePathRelativeToUserRootDir = path.posix.join('/', p);
759
- const filePathAbsolute = path.posix.join(userRootDir, p);
760
- return { filePathRelativeToUserRootDir, filePathAbsolute };
826
+ const filePathAbsoluteFilesystem = path.posix.join(userRootDir, p);
827
+ return {
828
+ filePathRelativeToUserRootDir,
829
+ filePathAbsoluteVite: filePathRelativeToUserRootDir,
830
+ filePathAbsoluteFilesystem,
831
+ filePathToShowToUser: filePathRelativeToUserRootDir,
832
+ importPathAbsolute: null
833
+ };
761
834
  });
835
+ // TODO/v1-release: remove
762
836
  extensions.forEach((extension) => {
763
837
  extension.pageConfigsDistFiles?.forEach((pageConfigDistFile) => {
764
- // TODO/v1-release: remove
765
838
  if (!pageConfigDistFile.importPath.includes('+'))
766
839
  return;
767
840
  assert(pageConfigDistFile.importPath.includes('+'));
768
841
  assert(path.posix.basename(pageConfigDistFile.importPath).startsWith('+'));
769
842
  const { importPath, filePath } = pageConfigDistFile;
770
843
  plusFiles.push({
771
- filePathRelativeToUserRootDir: importPath,
772
- filePathAbsolute: filePath
844
+ filePathRelativeToUserRootDir: null,
845
+ filePathAbsoluteVite: importPath,
846
+ filePathAbsoluteFilesystem: filePath,
847
+ filePathToShowToUser: importPath,
848
+ importPathAbsolute: importPath
773
849
  });
774
850
  });
775
851
  });
@@ -799,12 +875,12 @@ function assertNoUnexpectedPlusSign(filePath, fileName) {
799
875
  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`);
800
876
  }
801
877
  async function loadConfigFile(configFilePath, userRootDir, visited) {
802
- const { filePathAbsolute } = configFilePath;
803
- assertNoInfiniteLoop(visited, filePathAbsolute);
878
+ const { filePathAbsoluteFilesystem } = configFilePath;
879
+ assertNoInfiniteLoop(visited, filePathAbsoluteFilesystem);
804
880
  const { fileExports } = await transpileAndExecuteFile(configFilePath, false, userRootDir);
805
881
  const { extendsConfigs, extendsFilePaths } = await loadExtendsConfigs(fileExports, configFilePath, userRootDir, [
806
882
  ...visited,
807
- filePathAbsolute
883
+ filePathAbsoluteFilesystem
808
884
  ]);
809
885
  const configFile = {
810
886
  fileExports,
@@ -813,31 +889,31 @@ async function loadConfigFile(configFilePath, userRootDir, visited) {
813
889
  };
814
890
  return { configFile, extendsConfigs };
815
891
  }
816
- function assertNoInfiniteLoop(visited, filePathAbsolute) {
817
- const idx = visited.indexOf(filePathAbsolute);
892
+ function assertNoInfiniteLoop(visited, filePathAbsoluteFilesystem) {
893
+ const idx = visited.indexOf(filePathAbsoluteFilesystem);
818
894
  if (idx === -1)
819
895
  return;
820
896
  const loop = visited.slice(idx);
821
- assert(loop[0] === filePathAbsolute);
822
- assertUsage(idx === -1, `Infinite extends loop ${[...loop, filePathAbsolute].join('>')}`);
897
+ assert(loop[0] === filePathAbsoluteFilesystem);
898
+ assertUsage(idx === -1, `Infinite extends loop ${[...loop, filePathAbsoluteFilesystem].join('>')}`);
823
899
  }
824
900
  async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir, visited) {
825
901
  const extendsImportData = getExtendsImportData(configFileExports, configFilePath);
826
902
  const extendsConfigFiles = [];
827
903
  extendsImportData.map((importData) => {
828
904
  const { importPath: importPath } = importData;
829
- // TODO
830
- // - validate extends configs
831
- const filePathAbsolute = resolveImportPath(importData, configFilePath);
832
- assertImportPath(filePathAbsolute, importData, configFilePath);
833
- assertExtendsImportPath(importPath, filePathAbsolute, configFilePath);
905
+ const filePathAbsoluteFilesystem = resolveImportPath(importData, configFilePath);
906
+ assertImportPath(filePathAbsoluteFilesystem, importData, configFilePath);
907
+ assertExtendsImportPath(importPath, filePathAbsoluteFilesystem, configFilePath);
834
908
  // - 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);
909
+ // - Using importPath would be visually nicer but it's ambigous => we rather pick filePathAbsoluteFilesystem for added clarity
910
+ const filePathRelativeToUserRootDir = determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir);
911
+ const filePathAbsoluteVite = filePathRelativeToUserRootDir ?? importPath;
837
912
  extendsConfigFiles.push({
838
- filePathAbsolute,
839
- // TODO: fix type cast
840
- filePathRelativeToUserRootDir: filePathRelativeToUserRootDir,
913
+ filePathAbsoluteFilesystem,
914
+ filePathAbsoluteVite,
915
+ filePathRelativeToUserRootDir,
916
+ filePathToShowToUser: filePathAbsoluteVite,
841
917
  importPathAbsolute: importPath
842
918
  });
843
919
  });
@@ -847,16 +923,16 @@ async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir
847
923
  extendsConfigs.push(result.configFile);
848
924
  extendsConfigs.push(...result.extendsConfigs);
849
925
  }));
850
- const extendsFilePaths = extendsConfigFiles.map((f) => f.filePathAbsolute);
926
+ const extendsFilePaths = extendsConfigFiles.map((f) => f.filePathAbsoluteFilesystem);
851
927
  return { extendsConfigs, extendsFilePaths };
852
928
  }
853
- function determineFilePathRelativeToUserDir(filePathAbsolute, userRootDir) {
854
- assertPosixPath(filePathAbsolute);
929
+ function determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir) {
930
+ assertPosixPath(filePathAbsoluteFilesystem);
855
931
  assertPosixPath(userRootDir);
856
- if (!filePathAbsolute.startsWith(userRootDir)) {
932
+ if (!filePathAbsoluteFilesystem.startsWith(userRootDir)) {
857
933
  return null;
858
934
  }
859
- let filePathRelativeToUserRootDir = filePathAbsolute.slice(userRootDir.length);
935
+ let filePathRelativeToUserRootDir = filePathAbsoluteFilesystem.slice(userRootDir.length);
860
936
  if (!filePathRelativeToUserRootDir.startsWith('/'))
861
937
  filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir;
862
938
  return filePathRelativeToUserRootDir;
@@ -873,14 +949,14 @@ function assertExtendsImportPath(importPath, filePath, configFilePath) {
873
949
  });
874
950
  }
875
951
  else {
876
- assertWarning(false, `${getFilePathToShowToUser(configFilePath)} uses ${pc.cyan('extends')} to inherit from ${pc.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 });
952
+ assertWarning(false, `${configFilePath.filePathToShowToUser} uses ${pc.cyan('extends')} to inherit from ${pc.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 });
877
953
  }
878
954
  }
879
955
  function getExtendsImportData(configFileExports, configFilePath) {
880
- const filePathToShowToUser = getFilePathToShowToUser(configFilePath);
956
+ const { filePathToShowToUser } = configFilePath;
881
957
  assertExportsOfConfigFile(configFileExports, filePathToShowToUser);
882
958
  const defaultExports = configFileExports.default;
883
- const wrongUsage = `${filePathToShowToUser} sets the config 'extends' to an invalid value, see https://vike.dev/extends`;
959
+ const wrongUsage = `${filePathToShowToUser} sets the config ${pc.cyan('extends')} to an invalid value, see https://vike.dev/extends`;
884
960
  let extendList;
885
961
  if (!('extends' in defaultExports)) {
886
962
  return [];
@@ -901,38 +977,6 @@ function getExtendsImportData(configFileExports, configFilePath) {
901
977
  });
902
978
  return extendsImportData;
903
979
  }
904
- // TODO: re-use this
905
- function handleUserFileError(err, isDev) {
906
- // Properly handle error during transpilation so that we can use assertUsage() during transpilation
907
- if (isDev) {
908
- throw err;
909
- }
910
- else {
911
- // Avoid ugly error format:
912
- // ```
913
- // [vike:importUserCode] Could not load virtual:vike:importUserCode:server: [vike@0.4.70][Wrong Usage] /pages/+config.ts sets the config 'onRenderHtml' to the value './+config/onRenderHtml-i-dont-exist.js' but no file was found at /home/rom/code/vike/examples/v1/pages/+config/onRenderHtml-i-dont-exist.js
914
- // Error: [vike@0.4.70][Wrong Usage] /pages/+config.ts sets the config 'onRenderHtml' to the value './+config/onRenderHtml-i-dont-exist.js' but no file was found at /home/rom/code/vike/examples/v1/pages/+config/onRenderHtml-i-dont-exist.js
915
- // at ...
916
- // at ...
917
- // at ...
918
- // at ...
919
- // at ...
920
- // at ...
921
- // code: 'PLUGIN_ERROR',
922
- // plugin: 'vike:importUserCode',
923
- // hook: 'load',
924
- // watchFiles: [
925
- // '/home/rom/code/vike/vike/dist/esm/node/importBuild.js',
926
- // '\x00virtual:vike:importUserCode:server'
927
- // ]
928
- // }
929
- //  ELIFECYCLE  Command failed with exit code 1.
930
- // ```
931
- console.log('');
932
- console.error(err);
933
- process.exit(1);
934
- }
935
- }
936
980
  function isGlobalConfig(configName) {
937
981
  if (configName === 'prerender')
938
982
  return false;
@@ -942,15 +986,15 @@ function isGlobalConfig(configName) {
942
986
  function getConfigNamesGlobal() {
943
987
  return Object.keys(configDefinitionsBuiltInGlobal);
944
988
  }
945
- function assertConfigExists(configName, configNamesRelevant, definedByFile) {
989
+ function assertConfigExists(configName, configNamesRelevant, filePathToShowToUser) {
946
990
  const configNames = [...configNamesRelevant, ...getConfigNamesGlobal()];
947
991
  if (configNames.includes(configName))
948
992
  return;
949
- handleUnknownConfig(configName, configNames, definedByFile);
993
+ handleUnknownConfig(configName, configNames, filePathToShowToUser);
950
994
  assert(false);
951
995
  }
952
- function handleUnknownConfig(configName, configNames, definedByFile) {
953
- let errMsg = `${definedByFile} defines an unknown config ${pc.cyan(configName)}`;
996
+ function handleUnknownConfig(configName, configNames, filePathToShowToUser) {
997
+ let errMsg = `${filePathToShowToUser} defines an unknown config ${pc.cyan(configName)}`;
954
998
  let configNameSimilar = null;
955
999
  if (configName === 'page') {
956
1000
  configNameSimilar = 'Page';
@@ -982,11 +1026,11 @@ function determineRouteFilesystem(locationId, configValueSources) {
982
1026
  if (configFilesystemRoutingRoot) {
983
1027
  const routingRoot = getFilesystemRoutingRootEffect(configFilesystemRoutingRoot, configName);
984
1028
  if (routingRoot) {
985
- const { filesystemRoutingRootEffect, filesystemRoutingRootDefinedAt } = routingRoot;
1029
+ const { filesystemRoutingRootEffect /*, filesystemRoutingRootDefinedAt*/ } = routingRoot;
986
1030
  const debugInfo = { locationId, routeFilesystem: filesystemRouteString, configFilesystemRoutingRoot };
987
1031
  assert(filesystemRouteString.startsWith(filesystemRoutingRootEffect.before), debugInfo);
988
1032
  filesystemRouteString = applyFilesystemRoutingRootEffect(filesystemRouteString, filesystemRoutingRootEffect);
989
- filesystemRouteDefinedBy = `${filesystemRouteDefinedBy} (with ${filesystemRoutingRootDefinedAt})`;
1033
+ // filesystemRouteDefinedBy = `${filesystemRouteDefinedBy} (with ${filesystemRoutingRootDefinedAt})`
990
1034
  }
991
1035
  }
992
1036
  assert(filesystemRouteString.startsWith('/'));
@@ -1001,10 +1045,10 @@ function getFilesystemRoutingRootEffect(configFilesystemRoutingRoot, configName)
1001
1045
  // Eagerly loaded since it's config-only
1002
1046
  assert('value' in configFilesystemRoutingRoot);
1003
1047
  const { value } = configFilesystemRoutingRoot;
1004
- const configDefinedAt = getConfigSourceDefinedAtString(configName, configFilesystemRoutingRoot);
1048
+ const configDefinedAt = getConfigDefinedAtString('Config', configName, configFilesystemRoutingRoot);
1005
1049
  assertUsage(typeof value === 'string', `${configDefinedAt} should be a string`);
1006
1050
  assertUsage(value.startsWith('/'), `${configDefinedAt} is ${pc.cyan(value)} but it should start with a leading slash ${pc.cyan('/')}`);
1007
- const { filePathRelativeToUserRootDir } = configFilesystemRoutingRoot.definedAtInfo;
1051
+ const { filePathRelativeToUserRootDir } = configFilesystemRoutingRoot.definedAt;
1008
1052
  assert(filePathRelativeToUserRootDir);
1009
1053
  const before = getFilesystemRouteString(getLocationId(filePathRelativeToUserRootDir));
1010
1054
  const after = value;
@@ -1016,17 +1060,17 @@ function determineIsErrorPage(routeFilesystem) {
1016
1060
  return routeFilesystem.split('/').includes('_error');
1017
1061
  }
1018
1062
  function resolveImportPath(importData, importerFilePath) {
1019
- const importerFilePathAbsolute = importerFilePath.filePathAbsolute;
1063
+ const importerFilePathAbsolute = importerFilePath.filePathAbsoluteFilesystem;
1020
1064
  assertPosixPath(importerFilePathAbsolute);
1021
1065
  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;
1066
+ // filePathAbsoluteFilesystem is expected to be null when importData.importPath is a Vite path alias
1067
+ const filePathAbsoluteFilesystem = requireResolve(importData.importPath, cwd);
1068
+ return filePathAbsoluteFilesystem;
1025
1069
  }
1026
- function assertImportPath(filePathAbsolute, importData, importerFilePath) {
1070
+ function assertImportPath(filePathAbsoluteFilesystem, importData, importerFilePath) {
1027
1071
  const { importPath: importPath, importStringWasGenerated, importString } = importData;
1028
- const filePathToShowToUser = getFilePathToShowToUser(importerFilePath);
1029
- if (!filePathAbsolute) {
1072
+ const { filePathToShowToUser } = importerFilePath;
1073
+ if (!filePathAbsoluteFilesystem) {
1030
1074
  const importPathString = pc.cyan(`'${importPath}'`);
1031
1075
  const errIntro = importStringWasGenerated
1032
1076
  ? `The import path ${importPathString} in ${filePathToShowToUser}`
@@ -1068,7 +1112,6 @@ function getConfigValues(configValueSources, configValuesComputed, configDefinit
1068
1112
  configValues[configName] = {
1069
1113
  value,
1070
1114
  definedAt: {
1071
- isCumulative: true,
1072
1115
  files: sources.map((source) => getDefinedAtFile(source))
1073
1116
  }
1074
1117
  };
@@ -1076,18 +1119,23 @@ function getConfigValues(configValueSources, configValuesComputed, configDefinit
1076
1119
  });
1077
1120
  return configValues;
1078
1121
  }
1122
+ function getDefinedAtFile(configValueSource) {
1123
+ return {
1124
+ filePathToShowToUser: configValueSource.definedAt.filePathToShowToUser,
1125
+ fileExportPathToShowToUser: configValueSource.definedAt.fileExportPathToShowToUser
1126
+ };
1127
+ }
1128
+ function getDefinedAt(configValueSource) {
1129
+ return getDefinedAtFile(configValueSource);
1130
+ }
1079
1131
  function mergeCumulative(configName, configValueSources) {
1080
1132
  const valuesArr = [];
1081
1133
  const valuesSet = [];
1082
1134
  let configValueSourcePrevious = null;
1083
1135
  configValueSources.forEach((configValueSource) => {
1084
- const configDefinedAt = getConfigSourceDefinedAtString(configName, configValueSource);
1085
- const configNameColored = pc.cyan(configName);
1086
- // We could, in principle, also support cumulative values to be defined in +${configName}.js but it ins't completely trivial to implement
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.)`);
1088
- /* This is more confusing than adding value. For example, this explanation shouldn't be shown for the passToClient config.
1089
- const explanation = `(Because the values of ${configNameColored} are cumulative and therefore merged together.)` as const
1090
- */
1136
+ const configDefinedAt = getConfigDefinedAtString('Config', configName, configValueSource);
1137
+ // We could, in principle, also support cumulative for values that aren't loaded at config-time but it isn't completely trivial to implement.
1138
+ assert('value' in configValueSource);
1091
1139
  // Make sure configValueSource.value is serializable
1092
1140
  getConfigValueSerialized(configValueSource.value, configName, getDefinedAt(configValueSource));
1093
1141
  const assertNoMixing = (isSet) => {
@@ -1099,7 +1147,7 @@ function mergeCumulative(configName, configValueSources) {
1099
1147
  if (vals2.length === 0)
1100
1148
  return;
1101
1149
  assert(configValueSourcePrevious);
1102
- const configPreviousDefinedAt = getConfigSourceDefinedAtString(configName, configValueSourcePrevious, undefined, false);
1150
+ const configPreviousDefinedAt = getConfigDefinedAtString('Config', configName, configValueSourcePrevious);
1103
1151
  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).`);
1104
1152
  };
1105
1153
  const { value } = configValueSource;
@@ -1130,30 +1178,3 @@ function mergeCumulative(configName, configValueSources) {
1130
1178
  }
1131
1179
  assert(false);
1132
1180
  }
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
- }