vike 0.4.143-commit-dc6fea0 → 0.4.143-commit-fa295e1

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 (37) hide show
  1. package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +30 -27
  2. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +107 -54
  3. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +11 -10
  4. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +11 -11
  5. package/dist/cjs/node/prerender/runPrerender.js +9 -8
  6. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -2
  7. package/dist/cjs/node/shared/getClientEntryFilePath.js +1 -7
  8. package/dist/cjs/shared/getPageFiles/getExports.js +2 -5
  9. package/dist/cjs/shared/getPageFiles/parsePageConfigsSerialized.js +9 -6
  10. package/dist/cjs/shared/hooks/getHook.js +3 -1
  11. package/dist/cjs/shared/page-configs/getExportPath.js +2 -2
  12. package/dist/cjs/shared/page-configs/parseConfigValuesImported.js +8 -5
  13. package/dist/cjs/shared/page-configs/utils.js +66 -42
  14. package/dist/cjs/shared/route/loadPageRoutes.js +5 -6
  15. package/dist/cjs/utils/projectInfo.js +1 -1
  16. package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +30 -27
  17. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +107 -54
  18. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +11 -10
  19. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +2 -2
  20. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +11 -11
  21. package/dist/esm/node/prerender/runPrerender.js +10 -9
  22. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -2
  23. package/dist/esm/node/shared/getClientEntryFilePath.js +2 -8
  24. package/dist/esm/shared/getPageFiles/getExports.d.ts +1 -2
  25. package/dist/esm/shared/getPageFiles/getExports.js +3 -6
  26. package/dist/esm/shared/getPageFiles/parsePageConfigsSerialized.js +9 -6
  27. package/dist/esm/shared/hooks/getHook.js +3 -1
  28. package/dist/esm/shared/page-configs/PageConfig.d.ts +34 -10
  29. package/dist/esm/shared/page-configs/getExportPath.d.ts +1 -1
  30. package/dist/esm/shared/page-configs/getExportPath.js +2 -2
  31. package/dist/esm/shared/page-configs/parseConfigValuesImported.js +8 -5
  32. package/dist/esm/shared/page-configs/utils.d.ts +19 -13
  33. package/dist/esm/shared/page-configs/utils.js +65 -41
  34. package/dist/esm/shared/route/loadPageRoutes.js +6 -7
  35. package/dist/esm/utils/projectInfo.d.ts +1 -1
  36. package/dist/esm/utils/projectInfo.js +1 -1
  37. package/package.json +1 -1
@@ -11,7 +11,9 @@ function getHook(pageContext, hookName) {
11
11
  (0, utils_js_1.assert)(file.exportValue === hookFn);
12
12
  if (hookFn === null)
13
13
  return null;
14
- const hookFilePath = file.exportSource;
14
+ const hookFilePath = file.filePath;
15
+ (0, utils_js_1.assert)(hookFilePath);
16
+ (0, utils_js_1.assert)(!hookFilePath.endsWith(' '));
15
17
  assertHookFn(hookFn, { hookName, hookFilePath });
16
18
  return { hookFn, hookName, hookFilePath };
17
19
  }
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getExportPath = void 0;
4
4
  const utils_js_1 = require("../utils.js");
5
- // TODO: return null instead of 'export default'
6
- // - Also return null insead of 'export *'?
7
5
  function getExportPath(fileExportPath) {
6
+ if (!fileExportPath)
7
+ return null;
8
8
  let prefix = '';
9
9
  let suffix = '';
10
10
  let [exportName, ...exportObjectPath] = fileExportPath;
@@ -9,15 +9,18 @@ const assertExports_js_1 = require("./assertExports.js");
9
9
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
10
10
  function parseConfigValuesImported(configValuesImported) {
11
11
  const configValues = {};
12
- const addConfigValue = (configName, value, filePath, exportName) => {
12
+ const addConfigValue = (configName, value, importPath, exportName) => {
13
13
  configValues[configName] = {
14
14
  value,
15
- definedAtInfo: {
16
- filePath,
17
- fileExportPath: [exportName]
15
+ definedAt: {
16
+ source: {
17
+ // importPath is always relative the user's root directory (it cannot be relative to the current file since the current file is a virtual file)
18
+ filePathToShowToUser: importPath,
19
+ fileExportPath: [exportName]
20
+ }
18
21
  }
19
22
  };
20
- assertIsNotNull(value, configName, filePath);
23
+ assertIsNotNull(value, configName, importPath);
21
24
  };
22
25
  configValuesImported.forEach((configValueLoaded) => {
23
26
  if (configValueLoaded.isValueFile) {
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getDefinedAtString = exports.getConfigDefinedAtInfo = exports.getConfigDefinedAtString = exports.getPageConfig = exports.getConfigValue = void 0;
6
+ exports.getHookFilePathToShowToUser = exports.getConfigValueFilePathToShowToUser = exports.getDefinedAtString = exports.getConfigDefinedAtString = exports.getPageConfig = exports.getConfigValue = void 0;
7
7
  const utils_js_1 = require("../utils.js");
8
8
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
9
9
  const getExportPath_js_1 = require("./getExportPath.js");
@@ -12,33 +12,30 @@ function getConfigValue(pageConfig, configName, type) {
12
12
  const configValue = getConfigValueEntry(pageConfig, configName);
13
13
  if (configValue === null)
14
14
  return null;
15
- const { value, definedAtInfo } = configValue;
15
+ const { value, definedAt } = configValue;
16
16
  if (type)
17
- assertConfigValueType(value, type, configName, definedAtInfo);
18
- return { value };
17
+ assertConfigValueType(value, type, configName, definedAt);
18
+ return configValue;
19
19
  }
20
20
  exports.getConfigValue = getConfigValue;
21
- function getConfigDefinedAtInfo(pageConfig, configName) {
22
- const configValue = getConfigValueEntry(pageConfig, configName);
23
- // We assume the caller to have ensured that the config value exists prior to calling getConfigDefinedAtInfo()
24
- (0, utils_js_1.assert)(configValue);
25
- const { definedAtInfo } = configValue;
26
- // definedAtInfo is available only for config values that aren't:
27
- // - computed, nor
28
- // - cumulative
29
- (0, utils_js_1.assert)(definedAtInfo);
30
- return definedAtInfo;
21
+ function assertConfigValueType(value, type, configName, definedAt) {
22
+ (0, utils_js_1.assert)(value !== null);
23
+ const typeActual = typeof value;
24
+ if (typeActual === type)
25
+ return;
26
+ const valuePrintable = (0, utils_js_1.getValuePrintable)(value);
27
+ const problem = valuePrintable !== null ? `value ${picocolors_1.default.cyan(valuePrintable)}` : `type ${picocolors_1.default.cyan(typeActual)}`;
28
+ const configDefinedAt = getConfigDefinedAtString(configName, { definedAt }, true);
29
+ (0, utils_js_1.assertUsage)(false, `${configDefinedAt} has an invalid ${problem}: it should be a ${picocolors_1.default.cyan(type)} instead`);
31
30
  }
32
- exports.getConfigDefinedAtInfo = getConfigDefinedAtInfo;
33
31
  function getConfigValueEntry(pageConfig, configName) {
34
32
  const configValue = pageConfig.configValues[configName];
35
33
  if (!configValue)
36
34
  return null;
37
- const { value, definedAtInfo } = configValue;
38
35
  // Enable users to suppress global config values by setting the local config value to null
39
- if (value === null)
36
+ if (configValue.value === null)
40
37
  return null;
41
- return { value, definedAtInfo };
38
+ return configValue;
42
39
  }
43
40
  function getPageConfig(pageId, pageConfigs) {
44
41
  const pageConfig = pageConfigs.find((p) => p.pageId === pageId);
@@ -47,34 +44,61 @@ function getPageConfig(pageId, pageConfigs) {
47
44
  return pageConfig;
48
45
  }
49
46
  exports.getPageConfig = getPageConfig;
50
- function assertConfigValueType(value, type, configName, definedAtInfo) {
51
- (0, utils_js_1.assert)(value !== null);
52
- const typeActual = typeof value;
53
- if (typeActual === type)
54
- return;
55
- const valuePrintable = (0, utils_js_1.getValuePrintable)(value);
56
- const problem = valuePrintable !== null ? `value ${picocolors_1.default.cyan(valuePrintable)}` : `type ${picocolors_1.default.cyan(typeActual)}`;
57
- const configDefinedAt = getConfigDefinedAtString(configName, { definedAtInfo }, true);
58
- (0, utils_js_1.assertUsage)(false, `${configDefinedAt} has an invalid ${problem}: it should be a ${picocolors_1.default.cyan(type)} instead`);
59
- }
60
- function getConfigDefinedAtString(configName, { definedAtInfo }, sentenceBegin, append) {
61
- let configDefinedAt = `${sentenceBegin ? `Config` : `config`} ${picocolors_1.default.cyan(configName)}`;
62
- if (definedAtInfo !== null) {
63
- configDefinedAt = `${configDefinedAt} defined at ${getDefinedAtString(definedAtInfo, append)}`;
64
- }
47
+ function getConfigDefinedAtString(configName, { definedAt }, sentenceBegin) {
48
+ const configDefinedAt = `${sentenceBegin ? `Config` : `config`} ${picocolors_1.default.cyan(configName)} defined ${getSourceString(definedAt)}`;
65
49
  return configDefinedAt;
66
50
  }
67
51
  exports.getConfigDefinedAtString = getConfigDefinedAtString;
68
- function getDefinedAtString(definedAtInfo, append) {
69
- const { filePath, fileExportPath } = definedAtInfo;
70
- let definedAt = filePath;
71
- const exportPath = (0, getExportPath_js_1.getExportPath)(fileExportPath);
72
- if (exportPath) {
73
- definedAt = `${definedAt} > ${picocolors_1.default.cyan(exportPath)}`;
52
+ function getSourceString(definedAt) {
53
+ if (definedAt.isComputed) {
54
+ return 'internally';
74
55
  }
75
- if (append) {
76
- definedAt = `${definedAt} > (${picocolors_1.default.blue(append)})`;
56
+ let sources;
57
+ if (definedAt.isCumulative) {
58
+ sources = definedAt.sources;
77
59
  }
78
- return definedAt;
60
+ else {
61
+ sources = [definedAt.source];
62
+ }
63
+ (0, utils_js_1.assert)(sources.length >= 1);
64
+ const sourceString = sources
65
+ .map((source) => {
66
+ const { filePathToShowToUser, fileExportPath } = source;
67
+ let s = filePathToShowToUser;
68
+ const exportPath = (0, getExportPath_js_1.getExportPath)(fileExportPath);
69
+ if (exportPath) {
70
+ s = `${s} > ${picocolors_1.default.cyan(exportPath)}`;
71
+ }
72
+ if (definedAt.isEffect) {
73
+ s = `${s} > (${picocolors_1.default.blue('effect')})`;
74
+ }
75
+ return s;
76
+ })
77
+ .join(' / ');
78
+ return `at ${sourceString}`;
79
+ }
80
+ function getDefinedAtString(configValue) {
81
+ let sourceString = getSourceString(configValue.definedAt);
82
+ if (sourceString.startsWith('at '))
83
+ sourceString = sourceString.slice('at '.length);
84
+ return sourceString;
79
85
  }
80
86
  exports.getDefinedAtString = getDefinedAtString;
87
+ function getConfigValueFilePathToShowToUser({ definedAt }) {
88
+ // A unique file path only exists if the config value isn't cumulative nor computed:
89
+ // - cumulative config values have multiple file paths
90
+ // - computed values don't have any file path
91
+ if (definedAt.isComputed || definedAt.isCumulative)
92
+ return null;
93
+ const { source } = definedAt;
94
+ const { filePathToShowToUser } = source;
95
+ (0, utils_js_1.assert)(filePathToShowToUser);
96
+ return filePathToShowToUser;
97
+ }
98
+ exports.getConfigValueFilePathToShowToUser = getConfigValueFilePathToShowToUser;
99
+ function getHookFilePathToShowToUser({ definedAt }) {
100
+ const filePathToShowToUser = getConfigValueFilePathToShowToUser({ definedAt });
101
+ (0, utils_js_1.assert)(filePathToShowToUser);
102
+ return filePathToShowToUser;
103
+ }
104
+ exports.getHookFilePathToShowToUser = getHookFilePathToShowToUser;
@@ -33,9 +33,8 @@ function getPageRoutes(filesystemRoots, pageFilesAll, pageConfigs, allPageIds) {
33
33
  const configName = 'route';
34
34
  const configValue = (0, utils_js_3.getConfigValue)(pageConfig, configName);
35
35
  if (configValue) {
36
- const definedAtInfo = (0, utils_js_3.getConfigDefinedAtInfo)(pageConfig, configName);
37
36
  const route = configValue.value;
38
- const definedAt = (0, utils_js_3.getDefinedAtString)(definedAtInfo);
37
+ const definedAt = (0, utils_js_3.getDefinedAtString)(configValue);
39
38
  if (typeof route === 'string') {
40
39
  pageRoute = {
41
40
  pageId,
@@ -141,10 +140,10 @@ function getGlobalHooks(pageFilesAll, pageConfigs, pageConfigGlobal) {
141
140
  // V1 Design
142
141
  if (pageConfigs.length > 0) {
143
142
  if (pageConfigGlobal.configValues.onBeforeRoute?.value) {
144
- const { value: hookFn, definedAtInfo } = pageConfigGlobal.configValues.onBeforeRoute;
145
- // config.onBeforeRoute isn't a computed nor a cumulative config => definedAtInfo should always be defined
146
- (0, utils_js_1.assert)(definedAtInfo);
147
- const hookFilePath = definedAtInfo.filePath;
143
+ const configValue = pageConfigGlobal.configValues.onBeforeRoute;
144
+ const { value: hookFn } = configValue;
145
+ const hookFilePath = (0, utils_js_3.getHookFilePathToShowToUser)(configValue);
146
+ // TODO: use getConfigDefinedAtString()
148
147
  (0, utils_js_1.assertUsage)((0, utils_js_2.isCallable)(hookFn), `The hook onBeforeRoute() defined by ${hookFilePath} should be a function.`);
149
148
  const onBeforeRouteHook = {
150
149
  hookFilePath: hookFilePath,
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.projectInfo = void 0;
4
4
  const assertSingleInstance_js_1 = require("./assertSingleInstance.js");
5
- const PROJECT_VERSION = '0.4.143-commit-dc6fea0';
5
+ const PROJECT_VERSION = '0.4.143-commit-fa295e1';
6
6
  const projectInfo = {
7
7
  projectName: 'Vike',
8
8
  projectVersion: PROJECT_VERSION,
@@ -22,7 +22,7 @@ async function determineOptimizeDeps(config, configVike, isDev) {
22
22
  */
23
23
  config.optimizeDeps.include = [...include, ...normalizeInclude(config.optimizeDeps.include)];
24
24
  config.optimizeDeps.entries = [...entries, ...normalizeEntries(config.optimizeDeps.entries)];
25
- // console.log('config.optimizeDeps', config.optimizeDeps)
25
+ console.log('config.optimizeDeps', config.optimizeDeps);
26
26
  }
27
27
  async function getPageDeps(config, pageConfigs, isDev) {
28
28
  let entries = [];
@@ -32,37 +32,40 @@ async function getPageDeps(config, pageConfigs, isDev) {
32
32
  pageConfigs.forEach((pageConfig) => {
33
33
  const configValueSourcesRelevant = getConfigValueSourcesRelevant(pageConfig);
34
34
  configValueSourcesRelevant.forEach((configValueSource) => {
35
- const { valueIsImportedAtRuntime, configEnv, definedAtInfo } = configValueSource;
36
- if (!valueIsImportedAtRuntime)
35
+ if (!configValueSource.valueIsImportedAtRuntime)
37
36
  return;
38
- const { filePath } = definedAtInfo;
39
- assert(filePath);
40
- if (configEnv !== 'client-only' && configEnv !== 'server-and-client')
37
+ if (configValueSource.isComputed)
41
38
  return;
42
- if (filePath.startsWith('/')) {
43
- // Is getFilePathAbsolute() really needed? This contradicts the code below that doesn't need getFilePathAbsolute().
44
- entries.push(getFilePathAbsolute(filePath, config));
39
+ const { definedAtInfo, configEnv } = configValueSource;
40
+ if (configEnv !== 'client-only' && configEnv !== 'server-and-client')
45
41
  return;
46
- }
47
- // getVikeConfig() resolves relative import paths
48
- assert(!filePath.startsWith('.'));
49
- // We need to differentiate between npm package imports and path aliases.
50
- // There are path aliases that cannot be distinguished from npm package names.
51
- // We recommend users to use the '#' prefix convention for path aliases, see https://vike.dev/path-aliases#vite and assertResolveAlias()
52
- if (isNpmPackageImport(filePath)) {
53
- // isNpmPackageImport() returns false for a path alias like #root/renderer/onRenderClient
54
- assert(!filePath.startsWith('#'));
55
- include.push(filePath);
42
+ if (definedAtInfo.filePathRelativeToUserRootDir !== null) {
43
+ const { filePathAbsolute } = definedAtInfo;
44
+ assert(filePathAbsolute);
45
+ // Surpsingly Vite expects entries to be absolute paths
46
+ entries.push(filePathAbsolute);
56
47
  }
57
48
  else {
58
- /* Path aliases, e.g.:
59
- * ```js
60
- * // /renderer/+config.js
61
- * import onRenderClient from '#root/renderer/onRenderClient'
62
- * ```
63
- * Does Vite resolve the path aliases or is getFilePathAbsolute() needed?
64
- */
65
- entries.push(filePath);
49
+ // Adding definedAtInfo.filePathAbsolute doesn't work for npm packages, I guess because of Vite's config.server.fs.allow
50
+ const { importPathAbsolute } = definedAtInfo;
51
+ assert(importPathAbsolute);
52
+ // We need to differentiate between npm package imports and path aliases.
53
+ // There are path aliases that cannot be distinguished from npm package names.
54
+ // We recommend users to use the '#' prefix convention for path aliases, see https://vike.dev/path-aliases#vite and assertResolveAlias()
55
+ if (isNpmPackageImport(importPathAbsolute)) {
56
+ // isNpmPackageImport() returns false for a path alias like #root/renderer/onRenderClient
57
+ assert(!importPathAbsolute.startsWith('#'));
58
+ include.push(importPathAbsolute);
59
+ }
60
+ else {
61
+ /* Path aliases, e.g.:
62
+ * ```js
63
+ * // /renderer/+config.js
64
+ * import onRenderClient from '#root/renderer/onRenderClient'
65
+ * ```
66
+ */
67
+ entries.push(importPathAbsolute);
68
+ }
66
69
  }
67
70
  });
68
71
  });
@@ -340,7 +340,9 @@ function getGlobalConfigs(interfaceFilesByLocationId, userRootDir) {
340
340
  if (configName === 'prerender' && typeof configValueSource.value === 'boolean')
341
341
  return;
342
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 });
343
+ const sourceFilePath = getFilePathToShowToUser2(configValueSource.definedAtInfo);
344
+ assert(sourceFilePath);
345
+ 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
346
  globalVikeConfig[configName] = configValueSource.value;
345
347
  }
346
348
  });
@@ -423,48 +425,48 @@ function warnOverridenConfigValues(interfaceFileWinner, interfaceFilesOverriden,
423
425
  interfaceFilesOverriden.forEach((interfaceFileLoser) => {
424
426
  const configValueSourceWinner = getConfigValueSource(configName, interfaceFileWinner, configDef, userRootDir);
425
427
  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 });
428
+ assert(!configValueSourceLoser.isComputed);
429
+ assert(!configValueSourceWinner.isComputed);
430
+ assertWarning(false, `${getConfigSourceDefinedAtString(configName, configValueSourceLoser, undefined, true)} overriden by another ${getConfigSourceDefinedAtString(configName, configValueSourceWinner, undefined, false)}, remove one of the two`, { onlyOnce: false });
427
431
  });
428
432
  }
429
433
  function isInterfaceFileUserLand(interfaceFile) {
430
434
  return (interfaceFile.isConfigFile && !interfaceFile.isConfigExtend) || interfaceFile.isValueFile;
431
435
  }
432
436
  function getConfigValueSource(configName, interfaceFile, configDef, userRootDir) {
433
- // TODO: rethink file paths of ConfigElement
434
- const filePathToShowToUser = interfaceFile.filePath.filePathRelativeToUserRootDir ?? interfaceFile.filePath.filePathAbsolute;
435
437
  const conf = interfaceFile.configMap[configName];
436
438
  assert(conf);
437
439
  const configEnv = configDef.env;
438
- const definedAtInfoConfigFile = {
439
- filePath: filePathToShowToUser,
440
+ const definedAtConfigFile = {
441
+ ...interfaceFile.filePath,
440
442
  fileExportPath: ['default', configName]
441
443
  };
442
444
  if (configDef._valueIsFilePath) {
443
- let filePath;
445
+ let definedAtInfo;
446
+ let valueFilePath;
444
447
  if (interfaceFile.isConfigFile) {
445
448
  const { configValue } = conf;
446
449
  const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
447
- const configDefinedAt = getConfigDefinedAtString(configName, { definedAtInfo: definedAtInfoConfigFile }, true);
450
+ const configDefinedAt = getConfigSourceDefinedAtString(configName, { definedAtInfo: definedAtConfigFile });
448
451
  assertUsage(import_, `${configDefinedAt} should be an import`);
449
- filePath = import_.filePathToShowToUser;
452
+ valueFilePath = import_.filePathRelativeToUserRootDir ?? import_.importPathAbsolute;
453
+ definedAtInfo = import_;
450
454
  }
451
455
  else {
452
456
  assert(interfaceFile.isValueFile);
453
- filePath =
454
- interfaceFile.filePath.filePathRelativeToUserRootDir ??
455
- // Experimental: is this needed? Would it work?
456
- interfaceFile.filePath.filePathAbsolute;
457
+ valueFilePath = interfaceFile.filePath.filePathRelativeToUserRootDir;
458
+ definedAtInfo = {
459
+ ...interfaceFile.filePath,
460
+ fileExportPath: []
461
+ };
457
462
  }
458
463
  const configValueSource = {
459
- value: filePath,
464
+ value: valueFilePath,
460
465
  valueIsFilePath: true,
461
466
  configEnv,
462
467
  valueIsImportedAtRuntime: true,
463
468
  isComputed: false,
464
- definedAtInfo: {
465
- filePath,
466
- fileExportPath: []
467
- }
469
+ definedAtInfo
468
470
  };
469
471
  return configValueSource;
470
472
  }
@@ -473,15 +475,11 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
473
475
  const { configValue } = conf;
474
476
  const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
475
477
  if (import_) {
476
- const { filePathToShowToUser, fileExportName: exportName } = import_;
477
478
  const configValueSource = {
478
479
  configEnv,
479
480
  valueIsImportedAtRuntime: true,
480
481
  isComputed: false,
481
- definedAtInfo: {
482
- filePath: filePathToShowToUser,
483
- fileExportPath: [exportName]
484
- }
482
+ definedAtInfo: import_
485
483
  };
486
484
  return configValueSource;
487
485
  }
@@ -491,23 +489,21 @@ function getConfigValueSource(configName, interfaceFile, configDef, userRootDir)
491
489
  configEnv,
492
490
  valueIsImportedAtRuntime: false,
493
491
  isComputed: false,
494
- definedAtInfo: definedAtInfoConfigFile
492
+ definedAtInfo: definedAtConfigFile
495
493
  };
496
494
  return configValueSource;
497
495
  }
498
496
  }
499
497
  else if (interfaceFile.isValueFile) {
500
498
  // TODO: rethink file paths of ConfigElement
501
- const importPath = interfaceFile.filePath.filePathRelativeToUserRootDir ?? interfaceFile.filePath.filePathAbsolute;
502
- const exportName = configName === interfaceFile.configName ? 'default' : configName;
503
499
  const valueAlreadyLoaded = 'configValue' in conf;
504
500
  const configValueSource = {
505
501
  configEnv,
506
502
  valueIsImportedAtRuntime: !valueAlreadyLoaded,
507
503
  isComputed: false,
508
504
  definedAtInfo: {
509
- filePath: importPath,
510
- fileExportPath: [exportName]
505
+ ...interfaceFile.filePath,
506
+ fileExportPath: configName === interfaceFile.configName ? [] : [configName]
511
507
  }
512
508
  };
513
509
  if (valueAlreadyLoaded) {
@@ -556,7 +552,8 @@ function resolveImport(configValue, importerFilePath, userRootDir, configEnv, co
556
552
  return null;
557
553
  const { importPath, exportName } = importData;
558
554
  const filePathAbsolute = resolveImportPath(importData, importerFilePath);
559
- let filePathToShowToUser;
555
+ assertFileEnv(filePathAbsolute ?? importPath, configEnv, configName);
556
+ const fileExportPath = exportName === 'default' || exportName === configName ? [] : [exportName];
560
557
  if (importPath.startsWith('.')) {
561
558
  // We need to resolve relative paths into absolute paths. Because the import paths are included in virtual files:
562
559
  // ```
@@ -564,22 +561,26 @@ function resolveImport(configValue, importerFilePath, userRootDir, configEnv, co
564
561
  // ```
565
562
  assertImportPath(filePathAbsolute, importData, importerFilePath);
566
563
  const filePathRelativeToUserRootDir = resolveImportPath_relativeToUserRootDir(filePathAbsolute, importData, importerFilePath, userRootDir);
567
- filePathToShowToUser = filePathRelativeToUserRootDir;
564
+ return {
565
+ exportName,
566
+ fileExportPath,
567
+ filePathAbsolute,
568
+ filePathRelativeToUserRootDir,
569
+ importPathAbsolute: null
570
+ };
568
571
  }
569
572
  else {
570
573
  // importPath can be:
571
574
  // - an npm package import
572
575
  // - a path alias
573
- filePathToShowToUser = importPath;
574
- }
575
- {
576
- const filePathForEnvCheck = filePathAbsolute ?? importPath;
577
- assertFileEnv(filePathForEnvCheck, configEnv, configName);
576
+ return {
577
+ exportName,
578
+ fileExportPath,
579
+ filePathAbsolute,
580
+ filePathRelativeToUserRootDir: null,
581
+ importPathAbsolute: importPath
582
+ };
578
583
  }
579
- return {
580
- filePathToShowToUser,
581
- fileExportName: exportName
582
- };
583
584
  }
584
585
  function resolveImportPath_relativeToUserRootDir(filePathAbsolute, importData, configFilePath, userRootDir) {
585
586
  assertPosixPath(userRootDir);
@@ -672,24 +673,26 @@ function applyEffects(pageConfig, configDefinitionsRelevant) {
672
673
  `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)}).`,
673
674
  'Reach out to a maintainer if you want to use this in production.'
674
675
  ].join(' '), { onlyOnce: true });
675
- const configValue = pageConfig.configValueSources[configName]?.[0];
676
- if (!configValue)
676
+ const source = pageConfig.configValueSources[configName]?.[0];
677
+ if (!source)
677
678
  return;
679
+ assert(!source.isComputed);
678
680
  const configModFromEffect = configDef.effect({
679
- configValue: configValue.value,
680
- configDefinedAt: getConfigDefinedAtString(configName, configValue, true)
681
+ configValue: source.value,
682
+ configDefinedAt: getConfigSourceDefinedAtString(configName, source)
681
683
  });
682
684
  if (!configModFromEffect)
683
685
  return;
684
- assert(hasProp(configValue, 'value')); // We need to assume that the config value is loaded at build-time
685
- applyEffect(configModFromEffect, configValue, pageConfig.configValueSources);
686
+ assert(hasProp(source, 'value')); // We need to assume that the config value is loaded at build-time
687
+ applyEffect(configModFromEffect, source, pageConfig.configValueSources);
686
688
  });
687
689
  }
688
690
  function applyEffect(configModFromEffect, configValueEffectSource, configValueSources) {
689
691
  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.`;
690
692
  objectEntries(configModFromEffect).forEach(([configName, configValue]) => {
691
693
  if (configName === 'meta') {
692
- assertMetaValue(configValue, getConfigDefinedAtString(configName, configValueEffectSource, true, 'effect'));
694
+ assert(!configValueEffectSource.isComputed);
695
+ assertMetaValue(configValue, getConfigSourceDefinedAtString(configName, configValueEffectSource, true));
693
696
  objectEntries(configValue).forEach(([configTargetName, configTargetDef]) => {
694
697
  {
695
698
  const keys = Object.keys(configTargetDef);
@@ -1001,11 +1004,13 @@ function getFilesystemRoutingRootEffect(configFilesystemRoutingRoot, configName)
1001
1004
  // Eagerly loaded since it's config-only
1002
1005
  assert('value' in configFilesystemRoutingRoot);
1003
1006
  const { value } = configFilesystemRoutingRoot;
1004
- const configDefinedAt = getConfigDefinedAtString(configName, configFilesystemRoutingRoot, false);
1007
+ assert(!configFilesystemRoutingRoot.isComputed);
1008
+ const configDefinedAt = getConfigSourceDefinedAtString(configName, configFilesystemRoutingRoot);
1005
1009
  assertUsage(typeof value === 'string', `${configDefinedAt} should be a string`);
1006
1010
  assertUsage(value.startsWith('/'), `${configDefinedAt} is ${pc.cyan(value)} but it should start with a leading slash ${pc.cyan('/')}`);
1007
1011
  assert(!configFilesystemRoutingRoot.isComputed);
1008
- const before = getFilesystemRouteString(getLocationId(configFilesystemRoutingRoot.definedAtInfo.filePath));
1012
+ assert(configFilesystemRoutingRoot.definedAtInfo.filePathRelativeToUserRootDir);
1013
+ const before = getFilesystemRouteString(getLocationId(configFilesystemRoutingRoot.definedAtInfo.filePathRelativeToUserRootDir));
1009
1014
  const after = value;
1010
1015
  const filesystemRoutingRootEffect = { before, after };
1011
1016
  return { filesystemRoutingRootEffect, filesystemRoutingRootDefinedAt: configDefinedAt };
@@ -1050,10 +1055,11 @@ function getConfigValues(configValueSources, configDefinitionsRelevant) {
1050
1055
  if (!configDef.cumulative) {
1051
1056
  const configValueSource = sources[0];
1052
1057
  if ('value' in configValueSource) {
1053
- const { value, definedAtInfo } = configValueSource;
1058
+ const { value } = configValueSource;
1059
+ const definedAt = configValueSource.isComputed ? { isComputed: true } : getDefinedAt(configValueSource);
1054
1060
  configValues[configName] = {
1055
1061
  value,
1056
- definedAtInfo
1062
+ definedAt
1057
1063
  };
1058
1064
  }
1059
1065
  }
@@ -1061,7 +1067,10 @@ function getConfigValues(configValueSources, configDefinitionsRelevant) {
1061
1067
  const value = mergeCumulative(configName, sources);
1062
1068
  configValues[configName] = {
1063
1069
  value,
1064
- definedAtInfo: null
1070
+ definedAt: {
1071
+ isCumulative: true,
1072
+ sources: sources.map((source) => getSourceDefinedAt(source))
1073
+ }
1065
1074
  };
1066
1075
  }
1067
1076
  });
@@ -1073,7 +1082,7 @@ function mergeCumulative(configName, configValueSources) {
1073
1082
  let configValueSourcePrevious = null;
1074
1083
  configValueSources.forEach((configValueSource) => {
1075
1084
  assert(!configValueSource.isComputed);
1076
- const configDefinedAt = getConfigDefinedAtString(configName, configValueSource, true);
1085
+ const configDefinedAt = getConfigSourceDefinedAtString(configName, configValueSource);
1077
1086
  const configNameColored = pc.cyan(configName);
1078
1087
  // We could, in principle, also support cumulative values to be defined in +${configName}.js but it ins't completely trivial to implement
1079
1088
  assertUsage('value' in configValueSource, `${configDefinedAt} is only allowed to be defined in a +config.h.js file. (Because the values of ${configNameColored} are cumulative.)`);
@@ -1081,7 +1090,7 @@ function mergeCumulative(configName, configValueSources) {
1081
1090
  const explanation = `(Because the values of ${configNameColored} are cumulative and therefore merged together.)` as const
1082
1091
  */
1083
1092
  // Make sure configValueSource.value is serializable
1084
- getConfigValueSerialized(configValueSource.value, configName, configValueSource.definedAtInfo);
1093
+ getConfigValueSerialized(configValueSource.value, configName, getDefinedAt(configValueSource));
1085
1094
  const assertNoMixing = (isSet) => {
1086
1095
  const vals1 = isSet ? valuesSet : valuesArr;
1087
1096
  const t1 = isSet ? 'a Set' : 'an array';
@@ -1091,7 +1100,8 @@ function mergeCumulative(configName, configValueSources) {
1091
1100
  if (vals2.length === 0)
1092
1101
  return;
1093
1102
  assert(configValueSourcePrevious);
1094
- const configPreviousDefinedAt = getConfigDefinedAtString(configName, configValueSourcePrevious, false);
1103
+ assert(!configValueSourcePrevious.isComputed);
1104
+ const configPreviousDefinedAt = getConfigSourceDefinedAtString(configName, configValueSourcePrevious, undefined, true);
1095
1105
  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).`);
1096
1106
  };
1097
1107
  const { value } = configValueSource;
@@ -1122,3 +1132,46 @@ function mergeCumulative(configName, configValueSources) {
1122
1132
  }
1123
1133
  assert(false);
1124
1134
  }
1135
+ // TODO: rename
1136
+ // TODO: refactor
1137
+ function getConfigSourceDefinedAtString(configName, { definedAtInfo }, isEffect = undefined, sentenceBegin = true) {
1138
+ return getConfigDefinedAtString(configName, {
1139
+ definedAt: {
1140
+ isEffect,
1141
+ source: {
1142
+ filePathToShowToUser: getFilePathToShowToUser2(definedAtInfo),
1143
+ fileExportPath: definedAtInfo.fileExportPath
1144
+ }
1145
+ }
1146
+ }, sentenceBegin);
1147
+ }
1148
+ // TODO: rename
1149
+ function getFilePathToShowToUser2(definedAtInfo) {
1150
+ return definedAtInfo.filePathRelativeToUserRootDir ?? definedAtInfo.importPathAbsolute;
1151
+ /*
1152
+ if (definedAtInfo.filePathRelativeToUserRootDir !== null) {
1153
+ return definedAtInfo.filePathRelativeToUserRootDir
1154
+ }
1155
+ if (definedAtInfo.importPathAbsolute !== null) {
1156
+ return definedAtInfo.importPathAbsolute
1157
+ } else {
1158
+ const filePathToShowToUser = definedAtInfo.filePathAbsolute
1159
+ // TypeScript failes to infer that definedAtInfo.filePathAbsolute cannot be null
1160
+ assert(filePathToShowToUser)
1161
+ return filePathToShowToUser
1162
+ }
1163
+ */
1164
+ }
1165
+ // TODO: rename
1166
+ function getSourceDefinedAt(source) {
1167
+ assert(!source.isComputed);
1168
+ return {
1169
+ filePathToShowToUser: getFilePathToShowToUser2(source.definedAtInfo),
1170
+ fileExportPath: source.definedAtInfo.fileExportPath
1171
+ };
1172
+ }
1173
+ function getDefinedAt(configValueSource) {
1174
+ return {
1175
+ source: getSourceDefinedAt(configValueSource)
1176
+ };
1177
+ }