vike 0.4.159 → 0.4.160

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 (59) hide show
  1. package/dist/cjs/node/plugin/index.js +20 -1
  2. package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -1
  3. package/dist/cjs/node/plugin/plugins/importBuild/index.js +1 -1
  4. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.js +18 -0
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileConfigEnv.js +129 -0
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +139 -0
  7. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → getVikeConfig/transformImports.js} +44 -13
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.js → getVikeConfig/transpileAndExecuteFile.js} +110 -77
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +57 -278
  10. package/dist/cjs/node/plugin/plugins/previewConfig.js +1 -1
  11. package/dist/cjs/node/plugin/shared/getHttpRequestAsyncStore.js +1 -1
  12. package/dist/cjs/node/plugin/shared/loggerNotProd/log.js +3 -3
  13. package/dist/cjs/node/plugin/shared/loggerNotProd.js +1 -1
  14. package/dist/cjs/node/runtime/globalContext.js +4 -3
  15. package/dist/cjs/shared/page-configs/assertPlusFileExport.js +44 -0
  16. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +2 -2
  17. package/dist/cjs/shared/route/abort.js +1 -1
  18. package/dist/cjs/utils/assert.js +5 -6
  19. package/dist/cjs/utils/assertIsNotProductionRuntime.js +35 -17
  20. package/dist/cjs/utils/nodeEnv.js +11 -1
  21. package/dist/cjs/utils/projectInfo.js +2 -4
  22. package/dist/esm/node/plugin/index.js +21 -2
  23. package/dist/esm/node/plugin/plugins/devConfig/index.js +2 -2
  24. package/dist/esm/node/plugin/plugins/importBuild/index.js +2 -2
  25. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.d.ts +2 -0
  26. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.js +12 -0
  27. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +6 -1
  28. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileConfigEnv.d.ts +21 -0
  29. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileConfigEnv.js +123 -0
  30. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.d.ts +12 -0
  31. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +133 -0
  32. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.d.ts → getVikeConfig/transformImports.d.ts} +5 -5
  33. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → getVikeConfig/transformImports.js} +43 -12
  34. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.d.ts → getVikeConfig/transpileAndExecuteFile.d.ts} +3 -3
  35. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.js → getVikeConfig/transpileAndExecuteFile.js} +110 -77
  36. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +14 -1
  37. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +54 -275
  38. package/dist/esm/node/plugin/plugins/previewConfig.js +2 -2
  39. package/dist/esm/node/plugin/shared/getHttpRequestAsyncStore.js +1 -1
  40. package/dist/esm/node/plugin/shared/loggerNotProd/log.js +3 -3
  41. package/dist/esm/node/plugin/shared/loggerNotProd.js +1 -1
  42. package/dist/esm/node/runtime/globalContext.js +5 -4
  43. package/dist/esm/shared/page-configs/PageConfig.d.ts +4 -0
  44. package/dist/esm/shared/page-configs/assertPlusFileExport.d.ts +2 -0
  45. package/dist/esm/shared/page-configs/assertPlusFileExport.js +38 -0
  46. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +2 -2
  47. package/dist/esm/shared/route/abort.js +2 -2
  48. package/dist/esm/utils/assert.js +5 -6
  49. package/dist/esm/utils/assertIsNotProductionRuntime.d.ts +8 -6
  50. package/dist/esm/utils/assertIsNotProductionRuntime.js +35 -17
  51. package/dist/esm/utils/debug.d.ts +1 -1
  52. package/dist/esm/utils/nodeEnv.d.ts +2 -0
  53. package/dist/esm/utils/nodeEnv.js +10 -0
  54. package/dist/esm/utils/projectInfo.d.ts +2 -8
  55. package/dist/esm/utils/projectInfo.js +2 -4
  56. package/package.json +1 -1
  57. package/dist/cjs/shared/page-configs/assertExports.js +0 -67
  58. package/dist/esm/shared/page-configs/assertExports.d.ts +0 -6
  59. package/dist/esm/shared/page-configs/assertExports.js +0 -61
@@ -2,31 +2,31 @@ export { getVikeConfig };
2
2
  export { reloadVikeConfig };
3
3
  export { vikeConfigDependencies };
4
4
  export { isVikeConfigFile };
5
- import { assertPosixPath, assert, isObject, assertUsage, assertWarning, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar, isNpmPackageImport, joinEnglish, lowerFirst, mergeCumulativeValues, requireResolve, getOutDirs, deepEqual, assertKeys } from '../../../utils.js';
5
+ import { assertPosixPath, assert, isObject, assertUsage, assertWarning, objectEntries, hasProp, arrayIncludes, assertIsNotProductionRuntime, getMostSimilar, joinEnglish, lowerFirst, mergeCumulativeValues, getOutDirs, assertKeys } from '../../../utils.js';
6
6
  import path from 'path';
7
7
  import { configDefinitionsBuiltIn, configDefinitionsBuiltInGlobal } from './getVikeConfig/configDefinitionsBuiltIn.js';
8
8
  import { getLocationId, getFilesystemRouteString, getFilesystemRouteDefinedBy, isInherited, sortAfterInheritanceOrder, isGlobalLocation, applyFilesystemRoutingRootEffect } from './getVikeConfig/filesystemRouting.js';
9
- import { isTmpFile, transpileAndExecuteFile } from './transpileAndExecuteFile.js';
10
- import { parseImportData } from './replaceImportStatements.js';
9
+ import { isTmpFile } from './getVikeConfig/transpileAndExecuteFile.js';
11
10
  import { isConfigInvalid, isConfigInvalid_set } from '../../../../runtime/renderPage/isConfigInvalid.js';
12
11
  import { getViteDevServer } from '../../../../runtime/globalContext.js';
13
12
  import { logConfigError, logConfigErrorRecover } from '../../../shared/loggerNotProd.js';
14
13
  import { removeSuperfluousViteLog_enable, removeSuperfluousViteLog_disable } from '../../../shared/loggerVite/removeSuperfluousViteLog.js';
15
14
  import pc from '@brillout/picocolors';
16
15
  import { getConfigDefinedAtString } from '../../../../../shared/page-configs/helpers.js';
17
- import { assertExportsOfConfigFile, assertExportsOfValueFile } from '../../../../../shared/page-configs/assertExports.js';
18
16
  import { getConfigVike } from '../../../../shared/getConfigVike.js';
19
17
  import { assertConfigValueIsSerializable } from './getConfigValuesSerialized.js';
20
18
  import { crawlPlusFiles } from './getVikeConfig/crawlPlusFiles.js';
19
+ import { getConfigFileExport } from './getConfigFileExport.js';
20
+ import { loadConfigFile, loadImportedFile, loadValueFile } from './getVikeConfig/loadFileConfigEnv.js';
21
+ import { clearFilesEnvMap, resolveImport } from './getVikeConfig/resolveImportPath.js';
21
22
  assertIsNotProductionRuntime();
22
23
  let devServerIsCorrupt = false;
23
24
  let wasConfigInvalid = null;
24
25
  let vikeConfigPromise = null;
25
26
  const vikeConfigDependencies = new Set();
26
- const filesEnv = new Map();
27
27
  function reloadVikeConfig(userRootDir, outDirRoot, extensions) {
28
28
  vikeConfigDependencies.clear();
29
- filesEnv.clear();
29
+ clearFilesEnvMap();
30
30
  vikeConfigPromise = loadVikeConfig_withErrorHandling(userRootDir, outDirRoot, true, extensions, true);
31
31
  handleReloadSideEffects();
32
32
  }
@@ -84,7 +84,7 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
84
84
  let interfaceFilesByLocationId = {};
85
85
  // Config files
86
86
  await Promise.all(configFiles.map(async (filePath) => {
87
- const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, []);
87
+ const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, [], false);
88
88
  const interfaceFile = getInterfaceFileFromConfigFile(configFile, false);
89
89
  const locationId = getLocationId(filePath.filePathAbsoluteVite);
90
90
  interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
@@ -100,7 +100,7 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
100
100
  assert(configName);
101
101
  const interfaceFile = {
102
102
  filePath,
103
- configMap: {
103
+ fileExportsByConfigName: {
104
104
  [configName]: {}
105
105
  },
106
106
  isConfigFile: false,
@@ -134,23 +134,6 @@ function getConfigDefinition(configDefinitionsRelevant, configName, filePathToSh
134
134
  function getConfigDefinitionOptional(configDefinitions, configName) {
135
135
  return configDefinitions[configName] ?? null;
136
136
  }
137
- async function loadValueFile(interfaceValueFile, configName, userRootDir) {
138
- const { fileExports } = await transpileAndExecuteFile(interfaceValueFile.filePath, true, userRootDir);
139
- const { filePathToShowToUser } = interfaceValueFile.filePath;
140
- assertExportsOfValueFile(fileExports, filePathToShowToUser, configName);
141
- Object.entries(fileExports).forEach(([exportName, configValue]) => {
142
- const configName_ = exportName === 'default' ? configName : exportName;
143
- interfaceValueFile.configMap[configName_] = { configValue };
144
- });
145
- }
146
- async function loadImportedFile(filePath, userRootDir, importedFilesLoaded) {
147
- const f = filePath.filePathAbsoluteFilesystem;
148
- if (!importedFilesLoaded[f]) {
149
- importedFilesLoaded[f] = transpileAndExecuteFile(filePath, true, userRootDir).then((r) => r.fileExports);
150
- }
151
- const fileExports = await importedFilesLoaded[f];
152
- return fileExports;
153
- }
154
137
  function isConfigEnv(configDef, configName) {
155
138
  const configEnv = configDef.env;
156
139
  if (configDef.cumulative) {
@@ -163,16 +146,15 @@ function getInterfaceFileFromConfigFile(configFile, isConfigExtend) {
163
146
  const { fileExports, filePath, extendsFilePaths } = configFile;
164
147
  const interfaceFile = {
165
148
  filePath,
166
- configMap: {},
149
+ fileExportsByConfigName: {},
167
150
  isConfigFile: true,
168
151
  isValueFile: false,
169
152
  isConfigExtend,
170
153
  extendsFilePaths
171
154
  };
172
- const { filePathToShowToUser } = filePath;
173
- assertExportsOfConfigFile(fileExports, filePathToShowToUser);
174
- Object.entries(fileExports.default).forEach(([configName, configValue]) => {
175
- interfaceFile.configMap[configName] = { configValue };
155
+ const fileExport = getConfigFileExport(fileExports, filePath.filePathToShowToUser);
156
+ Object.entries(fileExport).forEach(([configName, configValue]) => {
157
+ interfaceFile.fileExportsByConfigName[configName] = { configValue };
176
158
  });
177
159
  return interfaceFile;
178
160
  }
@@ -182,7 +164,7 @@ function assertAllConfigsAreKnown(interfaceFilesByLocationId) {
182
164
  const interfaceFilesRelevant = getInterfaceFilesRelevant(interfaceFilesByLocationId, locationId);
183
165
  const configDefinitionsRelevant = getConfigDefinitions(interfaceFilesRelevant);
184
166
  interfaceFiles.forEach((interfaceFile) => {
185
- Object.keys(interfaceFile.configMap).forEach((configName) => {
167
+ Object.keys(interfaceFile.fileExportsByConfigName).forEach((configName) => {
186
168
  assertConfigExists(configName, Object.keys(configDefinitionsRelevant), interfaceFile.filePath.filePathToShowToUser);
187
169
  });
188
170
  });
@@ -296,7 +278,7 @@ function assertOnBeforeRenderEnv(pageConfig) {
296
278
  assertUsage(!(onBeforeRenderEnv.client && !isClientRouting), `Page ${pageConfig.pageId} has an onBeforeRender() hook with env ${pc.cyan(JSON.stringify(onBeforeRenderEnv))} which doesn't make sense because the page is using Server Routing: onBeforeRender() can be run in the client only when using Client Routing.`);
297
279
  }
298
280
  function interfacefileIsAlreaydLoaded(interfaceFile) {
299
- const configMapValues = Object.values(interfaceFile.configMap);
281
+ const configMapValues = Object.values(interfaceFile.fileExportsByConfigName);
300
282
  const isAlreadyLoaded = configMapValues.some((conf) => 'configValue' in conf);
301
283
  if (isAlreadyLoaded) {
302
284
  assert(configMapValues.every((conf) => 'configValue' in conf));
@@ -337,7 +319,7 @@ async function getGlobalConfigs(interfaceFilesByLocationId, userRootDir, importe
337
319
  const globalPaths = Array.from(new Set(interfaceFilesGlobalPaths.map((p) => path.posix.dirname(p))));
338
320
  Object.entries(interfaceFilesByLocationId).forEach(([locationId, interfaceFiles]) => {
339
321
  interfaceFiles.forEach((interfaceFile) => {
340
- Object.keys(interfaceFile.configMap).forEach((configName) => {
322
+ Object.keys(interfaceFile.fileExportsByConfigName).forEach((configName) => {
341
323
  if (!isGlobalLocation(locationId, locationIds) && isGlobalConfig(configName)) {
342
324
  assertUsage(false, [
343
325
  `${interfaceFile.filePath.filePathToShowToUser} defines the config ${pc.cyan(configName)} which is global:`,
@@ -378,7 +360,7 @@ async function resolveConfigValueSources(configName, configDef, interfaceFilesRe
378
360
  const sourcesInfo = [];
379
361
  // interfaceFilesRelevant is sorted by sortAfterInheritanceOrder()
380
362
  for (const interfaceFiles of Object.values(interfaceFilesRelevant)) {
381
- const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.configMap[configName]);
363
+ const interfaceFilesDefiningConfig = interfaceFiles.filter((interfaceFile) => interfaceFile.fileExportsByConfigName[configName]);
382
364
  if (interfaceFilesDefiningConfig.length === 0)
383
365
  continue;
384
366
  const visited = new WeakSet();
@@ -456,13 +438,14 @@ function isInterfaceFileUserLand(interfaceFile) {
456
438
  return (interfaceFile.isConfigFile && !interfaceFile.isConfigExtend) || interfaceFile.isValueFile;
457
439
  }
458
440
  async function getConfigValueSource(configName, interfaceFile, configDef, userRootDir, importedFilesLoaded) {
459
- const conf = interfaceFile.configMap[configName];
441
+ const conf = interfaceFile.fileExportsByConfigName[configName];
460
442
  assert(conf);
461
443
  const configEnv = configDef.env;
462
444
  const definedAtConfigFile = {
463
445
  ...interfaceFile.filePath,
464
446
  fileExportPathToShowToUser: ['default', configName]
465
447
  };
448
+ // +client.js
466
449
  if (configDef._valueIsFilePath) {
467
450
  let definedAt;
468
451
  let valueFilePath;
@@ -491,9 +474,11 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
491
474
  };
492
475
  return configValueSource;
493
476
  }
477
+ // +config.js
494
478
  if (interfaceFile.isConfigFile) {
495
479
  assert('configValue' in conf);
496
480
  const { configValue } = conf;
481
+ // fake import
497
482
  const import_ = resolveImport(configValue, interfaceFile.filePath, userRootDir, configEnv, configName);
498
483
  if (import_) {
499
484
  const configValueSource = {
@@ -501,12 +486,14 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
501
486
  valueIsImportedAtRuntime: true,
502
487
  definedAt: import_
503
488
  };
504
- // Load config value
505
- if (isConfigEnv(configDef, configName)) {
489
+ // Load fake import
490
+ if (isConfigEnv(configDef, configName) &&
491
+ // The value of `extends` was already loaded and already used: we don't need the value of `extends` anymore
492
+ configName !== 'extends') {
506
493
  if (import_.filePathAbsoluteFilesystem) {
507
494
  assert(hasProp(import_, 'filePathAbsoluteFilesystem', 'string')); // Help TS
508
- const fileExports = await loadImportedFile(import_, userRootDir, importedFilesLoaded);
509
- configValueSource.value = fileExports[import_.fileExportName];
495
+ const fileExport = await loadImportedFile(import_, userRootDir, importedFilesLoaded);
496
+ configValueSource.value = fileExport;
510
497
  }
511
498
  else {
512
499
  const configDefinedAt = getConfigDefinedAtString('Config', configName, configValueSource);
@@ -515,17 +502,17 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
515
502
  }
516
503
  return configValueSource;
517
504
  }
518
- else {
519
- const configValueSource = {
520
- value: configValue,
521
- configEnv,
522
- valueIsImportedAtRuntime: false,
523
- definedAt: definedAtConfigFile
524
- };
525
- return configValueSource;
526
- }
505
+ // Defined by config file, i.e. +config.js file
506
+ const configValueSource = {
507
+ value: configValue,
508
+ configEnv,
509
+ valueIsImportedAtRuntime: false,
510
+ definedAt: definedAtConfigFile
511
+ };
512
+ return configValueSource;
527
513
  }
528
- else if (interfaceFile.isValueFile) {
514
+ // Defined by value file, i.e. +{configName}.js
515
+ if (interfaceFile.isValueFile) {
529
516
  const valueAlreadyLoaded = 'configValue' in conf;
530
517
  assert(valueAlreadyLoaded === !!configEnv.config);
531
518
  const configValueSource = {
@@ -546,25 +533,9 @@ async function getConfigValueSource(configName, interfaceFile, configDef, userRo
546
533
  }
547
534
  assert(false);
548
535
  }
549
- function assertFileEnv(filePathForEnvCheck, configEnv, configName) {
550
- assertPosixPath(filePathForEnvCheck);
551
- if (!filesEnv.has(filePathForEnvCheck)) {
552
- filesEnv.set(filePathForEnvCheck, []);
553
- }
554
- const fileEnv = filesEnv.get(filePathForEnvCheck);
555
- fileEnv.push({ configEnv, configName });
556
- const configDifferentEnv = fileEnv.filter((c) => !deepEqual(c.configEnv, configEnv))[0];
557
- if (configDifferentEnv) {
558
- assertUsage(false, [
559
- `${filePathForEnvCheck} defines the value of configs living in different environments:`,
560
- ...[configDifferentEnv, { configName, configEnv }].map((c) => ` - config ${pc.cyan(c.configName)} which value lives in environment ${pc.cyan(JSON.stringify(c.configEnv))}`),
561
- 'Defining config values in the same file is allowed only if they live in the same environment, see https://vike.dev/header-file'
562
- ].join('\n'));
563
- }
564
- }
565
536
  function isDefiningPage(interfaceFiles) {
566
537
  for (const interfaceFile of interfaceFiles) {
567
- const configNames = Object.keys(interfaceFile.configMap);
538
+ const configNames = Object.keys(interfaceFile.fileExportsByConfigName);
568
539
  if (configNames.some((configName) => isDefiningPageConfig(configName))) {
569
540
  return true;
570
541
  }
@@ -574,90 +545,11 @@ function isDefiningPage(interfaceFiles) {
574
545
  function isDefiningPageConfig(configName) {
575
546
  return ['Page', 'route'].includes(configName);
576
547
  }
577
- function resolveImport(configValue, importerFilePath, userRootDir, configEnv, configName) {
578
- if (typeof configValue !== 'string')
579
- return null;
580
- const importData = parseImportData(configValue);
581
- if (!importData)
582
- return null;
583
- const { importPath, exportName } = importData;
584
- const filePathAbsoluteFilesystem = resolveImportPath(importData, importerFilePath);
585
- assertFileEnv(filePathAbsoluteFilesystem ?? importPath, configEnv, configName);
586
- const fileExportPathToShowToUser = exportName === 'default' || exportName === configName ? [] : [exportName];
587
- if (importPath.startsWith('.')) {
588
- // We need to resolve relative paths into absolute paths. Because the import paths are included in virtual files:
589
- // ```
590
- // [vite] Internal server error: Failed to resolve import "./onPageTransitionHooks" from "virtual:vike:pageConfigValuesAll:client:/pages/index". Does the file exist?
591
- // ```
592
- assertImportPath(filePathAbsoluteFilesystem, importData, importerFilePath);
593
- const filePathRelativeToUserRootDir = resolveImportPath_relativeToUserRootDir(filePathAbsoluteFilesystem, importData, importerFilePath, userRootDir);
594
- const filePath = {
595
- filePathAbsoluteFilesystem,
596
- filePathRelativeToUserRootDir,
597
- filePathAbsoluteVite: filePathRelativeToUserRootDir,
598
- filePathToShowToUser: filePathRelativeToUserRootDir,
599
- importPathAbsolute: null
600
- };
601
- return {
602
- ...filePath,
603
- fileExportName: exportName,
604
- fileExportPathToShowToUser
605
- };
606
- }
607
- else {
608
- // importPath can be:
609
- // - an npm package import
610
- // - a path alias
611
- const filePath = {
612
- filePathAbsoluteFilesystem,
613
- filePathRelativeToUserRootDir: null,
614
- filePathAbsoluteVite: importPath,
615
- filePathToShowToUser: importPath,
616
- importPathAbsolute: importPath
617
- };
618
- return {
619
- ...filePath,
620
- fileExportName: exportName,
621
- fileExportPathToShowToUser
622
- };
623
- }
624
- }
625
- function resolveImportPath_relativeToUserRootDir(filePathAbsoluteFilesystem, importData, configFilePath, userRootDir) {
626
- assertPosixPath(userRootDir);
627
- let filePathRelativeToUserRootDir;
628
- if (filePathAbsoluteFilesystem.startsWith(userRootDir)) {
629
- filePathRelativeToUserRootDir = getVitePathFromAbsolutePath(filePathAbsoluteFilesystem, userRootDir);
630
- }
631
- else {
632
- 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`);
633
- // None of the following works. Seems to be a Vite bug?
634
- // /*
635
- // assert(filePathAbsoluteFilesystem.startsWith('/'))
636
- // filePath = `/@fs${filePathAbsoluteFilesystem}`
637
- // /*/
638
- // filePathRelativeToUserRootDir = path.posix.relative(userRootDir, filePathAbsoluteFilesystem)
639
- // assert(filePathRelativeToUserRootDir.startsWith('../'))
640
- // filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir
641
- // //*/
642
- }
643
- assertPosixPath(filePathRelativeToUserRootDir);
644
- assert(filePathRelativeToUserRootDir.startsWith('/'));
645
- return filePathRelativeToUserRootDir;
646
- }
647
- function getVitePathFromAbsolutePath(filePathAbsoluteFilesystem, root) {
648
- assertPosixPath(filePathAbsoluteFilesystem);
649
- assertPosixPath(root);
650
- assert(filePathAbsoluteFilesystem.startsWith(root));
651
- let vitePath = path.posix.relative(root, filePathAbsoluteFilesystem);
652
- assert(!vitePath.startsWith('/') && !vitePath.startsWith('.'));
653
- vitePath = '/' + vitePath;
654
- return vitePath;
655
- }
656
548
  function getConfigDefinitions(interfaceFilesRelevant) {
657
549
  const configDefinitions = { ...configDefinitionsBuiltIn };
658
550
  Object.entries(interfaceFilesRelevant).forEach(([_locationId, interfaceFiles]) => {
659
551
  interfaceFiles.forEach((interfaceFile) => {
660
- const configMeta = interfaceFile.configMap['meta'];
552
+ const configMeta = interfaceFile.fileExportsByConfigName['meta'];
661
553
  if (!configMeta)
662
554
  return;
663
555
  const meta = configMeta.configValue;
@@ -840,109 +732,22 @@ function getConfigName(filePath) {
840
732
  return configName;
841
733
  }
842
734
  }
843
- async function loadConfigFile(configFilePath, userRootDir, visited) {
844
- const { filePathAbsoluteFilesystem } = configFilePath;
845
- assertNoInfiniteLoop(visited, filePathAbsoluteFilesystem);
846
- const { fileExports } = await transpileAndExecuteFile(configFilePath, false, userRootDir);
847
- const { extendsConfigs, extendsFilePaths } = await loadExtendsConfigs(fileExports, configFilePath, userRootDir, [
848
- ...visited,
849
- filePathAbsoluteFilesystem
850
- ]);
851
- const configFile = {
852
- fileExports,
853
- filePath: configFilePath,
854
- extendsFilePaths
855
- };
856
- return { configFile, extendsConfigs };
857
- }
858
- function assertNoInfiniteLoop(visited, filePathAbsoluteFilesystem) {
859
- const idx = visited.indexOf(filePathAbsoluteFilesystem);
860
- if (idx === -1)
861
- return;
862
- const loop = visited.slice(idx);
863
- assert(loop[0] === filePathAbsoluteFilesystem);
864
- assertUsage(idx === -1, `Infinite extends loop ${[...loop, filePathAbsoluteFilesystem].join('>')}`);
865
- }
866
- async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir, visited) {
867
- const extendsImportData = getExtendsImportData(configFileExports, configFilePath);
868
- const extendsConfigFiles = [];
869
- extendsImportData.map((importData) => {
870
- const { importPath: importPath } = importData;
871
- const filePathAbsoluteFilesystem = resolveImportPath(importData, configFilePath);
872
- assertImportPath(filePathAbsoluteFilesystem, importData, configFilePath);
873
- assertExtendsImportPath(importPath, filePathAbsoluteFilesystem, configFilePath);
874
- // - filePathRelativeToUserRootDir has no functionality beyond nicer error messages for user
875
- // - Using importPath would be visually nicer but it's ambigous => we rather pick filePathAbsoluteFilesystem for added clarity
876
- const filePathRelativeToUserRootDir = determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir);
877
- const filePathAbsoluteVite = filePathRelativeToUserRootDir ?? importPath;
878
- extendsConfigFiles.push({
879
- filePathAbsoluteFilesystem,
880
- filePathAbsoluteVite,
881
- filePathRelativeToUserRootDir,
882
- filePathToShowToUser: filePathAbsoluteVite,
883
- importPathAbsolute: importPath
884
- });
885
- });
886
- const extendsConfigs = [];
887
- await Promise.all(extendsConfigFiles.map(async (configFilePath) => {
888
- const result = await loadConfigFile(configFilePath, userRootDir, visited);
889
- extendsConfigs.push(result.configFile);
890
- extendsConfigs.push(...result.extendsConfigs);
891
- }));
892
- const extendsFilePaths = extendsConfigFiles.map((f) => f.filePathAbsoluteFilesystem);
893
- return { extendsConfigs, extendsFilePaths };
894
- }
895
- function determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir) {
896
- assertPosixPath(filePathAbsoluteFilesystem);
897
- assertPosixPath(userRootDir);
898
- if (!filePathAbsoluteFilesystem.startsWith(userRootDir)) {
899
- return null;
900
- }
901
- let filePathRelativeToUserRootDir = filePathAbsoluteFilesystem.slice(userRootDir.length);
902
- if (!filePathRelativeToUserRootDir.startsWith('/'))
903
- filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir;
904
- return filePathRelativeToUserRootDir;
905
- }
906
- function assertExtendsImportPath(importPath, filePath, configFilePath) {
907
- if (isNpmPackageImport(importPath)) {
908
- const fileDir = path.posix.dirname(filePath) + '/';
909
- const fileName = path.posix.basename(filePath);
910
- const fileNameBaseCorrect = '+config';
911
- const [fileNameBase, ...fileNameRest] = fileName.split('.');
912
- const fileNameCorrect = [fileNameBaseCorrect, ...fileNameRest].join('.');
913
- assertWarning(fileNameBase === fileNameBaseCorrect, `Rename ${fileName} to ${fileNameCorrect} in ${fileDir}`, {
914
- onlyOnce: true
915
- });
916
- }
917
- else {
918
- 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 });
919
- }
920
- }
921
- function getExtendsImportData(configFileExports, configFilePath) {
922
- const { filePathToShowToUser } = configFilePath;
923
- assertExportsOfConfigFile(configFileExports, filePathToShowToUser);
924
- const defaultExports = configFileExports.default;
925
- const wrongUsage = `${filePathToShowToUser} sets the config ${pc.cyan('extends')} to an invalid value, see https://vike.dev/extends`;
926
- let extendList;
927
- if (!('extends' in defaultExports)) {
928
- return [];
929
- }
930
- else if (hasProp(defaultExports, 'extends', 'string')) {
931
- extendList = [defaultExports.extends];
932
- }
933
- else if (hasProp(defaultExports, 'extends', 'string[]')) {
934
- extendList = defaultExports.extends;
935
- }
936
- else {
937
- assertUsage(false, wrongUsage);
938
- }
939
- const extendsImportData = extendList.map((importDataSerialized) => {
940
- const importData = parseImportData(importDataSerialized);
941
- assertUsage(importData, wrongUsage);
942
- return importData;
943
- });
944
- return extendsImportData;
945
- }
735
+ /* https://github.com/vikejs/vike/issues/1407
736
+ function assertNoUnexpectedPlusSign(filePath: string, fileName: string) {
737
+ const dirs = path.posix.dirname(filePath).split('/')
738
+ dirs.forEach((dir, i) => {
739
+ const dirPath = dirs.slice(0, i + 1).join('/')
740
+ assertUsage(
741
+ !dir.includes('+'),
742
+ `Character '+' is a reserved character: remove '+' from the directory name ${dirPath}/`
743
+ )
744
+ })
745
+ assertUsage(
746
+ !fileName.slice(1).includes('+'),
747
+ `Character '+' is only allowed at the beginning of filenames: make sure ${filePath} doesn't contain any '+' in its filename other than its first letter`
748
+ )
749
+ }
750
+ */
946
751
  function isGlobalConfig(configName) {
947
752
  if (configName === 'prerender')
948
753
  return false;
@@ -1025,32 +830,6 @@ function determineIsErrorPage(routeFilesystem) {
1025
830
  assertPosixPath(routeFilesystem);
1026
831
  return routeFilesystem.split('/').includes('_error');
1027
832
  }
1028
- function resolveImportPath(importData, importerFilePath) {
1029
- const importerFilePathAbsolute = importerFilePath.filePathAbsoluteFilesystem;
1030
- assertPosixPath(importerFilePathAbsolute);
1031
- const cwd = path.posix.dirname(importerFilePathAbsolute);
1032
- // We can't use import.meta.resolve() as of Junary 2023 (and probably for a lot longer): https://stackoverflow.com/questions/54977743/do-require-resolve-for-es-modules#comment137174954_62272600:~:text=But%20the%20argument%20parent%20(aka%20cwd)%20still%20requires%20a%20flag
1033
- // filePathAbsoluteFilesystem is expected to be null when importData.importPath is a Vite path alias
1034
- const filePathAbsoluteFilesystem = requireResolve(importData.importPath, cwd);
1035
- return filePathAbsoluteFilesystem;
1036
- }
1037
- function assertImportPath(filePathAbsoluteFilesystem, importData, importerFilePath) {
1038
- const { importPath: importPath, importStringWasGenerated, importString } = importData;
1039
- const { filePathToShowToUser } = importerFilePath;
1040
- if (!filePathAbsoluteFilesystem) {
1041
- const importPathString = pc.cyan(`'${importPath}'`);
1042
- const errIntro = importStringWasGenerated
1043
- ? `The import path ${importPathString} in ${filePathToShowToUser}`
1044
- : `The import ${pc.cyan(importString)} defined in ${filePathToShowToUser}`;
1045
- const errIntro2 = `${errIntro} couldn't be resolved: does ${importPathString}`;
1046
- if (importPath.startsWith('.')) {
1047
- assertUsage(false, `${errIntro2} point to an existing file?`);
1048
- }
1049
- else {
1050
- assertUsage(false, `${errIntro2} exist?`);
1051
- }
1052
- }
1053
- }
1054
833
  function isVikeConfigFile(filePath) {
1055
834
  return !!getConfigName(filePath);
1056
835
  }
@@ -1,5 +1,5 @@
1
1
  export { previewConfig };
2
- import { assertUsage, getOutDirs, resolveOutDir, markEnvAsPreview } from '../utils.js';
2
+ import { assertUsage, getOutDirs, resolveOutDir, markEnvAsVitePreview } from '../utils.js';
3
3
  import { getConfigVike } from '../../shared/getConfigVike.js';
4
4
  import fs from 'fs';
5
5
  import path from 'path';
@@ -28,7 +28,7 @@ function previewConfig() {
28
28
  - This ugly hack to set appType for preview won't be need once https://github.com/vitejs/vite/pull/14855 is merged.
29
29
  config.appType = 'mpa'
30
30
  */
31
- markEnvAsPreview();
31
+ markEnvAsVitePreview();
32
32
  return () => {
33
33
  assertDist();
34
34
  /* We don't use this condition (we wrongfully always use the SSR middleware) because of the regression introduced by https://github.com/vitejs/vite/pull/14756 which stops servering .html files when `appType: 'custom'`.
@@ -12,7 +12,7 @@ export { getHttpRequestAsyncStore };
12
12
  export { installHttpRequestAsyncStore };
13
13
  import { renderPage_addWrapper } from '../../runtime/renderPage.js';
14
14
  import { assert, assertIsNotProductionRuntime, isObject } from '../utils.js';
15
- import { getConfigBuildErrorFormatted } from '../plugins/importUserCode/v1-design/transpileAndExecuteFile.js';
15
+ import { getConfigBuildErrorFormatted } from '../plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js';
16
16
  import { logErrorDebugNote } from './loggerNotProd.js';
17
17
  import { isEquivalentErrorWithCodeSnippet } from './loggerNotProd/errorWithCodeSnippet.js';
18
18
  assertIsNotProductionRuntime();
@@ -20,10 +20,10 @@ function logWithVikeTag(msg, logType, category, showVikeVersion = false) {
20
20
  function getProjectTag(showVikeVersion) {
21
21
  let projectTag;
22
22
  if (showVikeVersion) {
23
- projectTag = `[${projectInfo.npmPackageName}@${projectInfo.projectVersion}]`;
23
+ projectTag = `[vike@${projectInfo.projectVersion}]`;
24
24
  }
25
25
  else {
26
- projectTag = `[${projectInfo.npmPackageName}]`;
26
+ projectTag = `[vike]`;
27
27
  }
28
28
  return projectTag;
29
29
  }
@@ -83,7 +83,7 @@ function prependTags(msg, projectTag, category, logType) {
83
83
  return pc.yellow(s);
84
84
  if (projectTag === '[vite]')
85
85
  return pc.bold(pc.cyan(s));
86
- if (projectTag.startsWith(`[${projectInfo.npmPackageName}`))
86
+ if (projectTag.startsWith(`[vike`))
87
87
  return pc.bold(pc.cyan(s));
88
88
  assert(false);
89
89
  };
@@ -18,7 +18,7 @@ import { assert, assertIsNotProductionRuntime, formatHintLog, getAssertErrMsg, i
18
18
  import { getHttpRequestAsyncStore } from './getHttpRequestAsyncStore.js';
19
19
  import { isErrorDebug } from './isErrorDebug.js';
20
20
  import { isErrorWithCodeSnippet, getPrettyErrorWithCodeSnippet } from './loggerNotProd/errorWithCodeSnippet.js';
21
- import { getConfigExecutionErrorIntroMsg, getConfigBuildErrorFormatted } from '../plugins/importUserCode/v1-design/transpileAndExecuteFile.js';
21
+ import { getConfigExecutionErrorIntroMsg, getConfigBuildErrorFormatted } from '../plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js';
22
22
  import { logWithVikeTag, logWithViteTag, logDirectly, isFirstLog, screenHasErrors, clearScreen, applyViteSourceMapToStackTrace } from './loggerNotProd/log.js';
23
23
  import pc from '@brillout/picocolors';
24
24
  import { setAlreadyLogged } from '../../runtime/renderPage/isNewError.js';
@@ -6,7 +6,7 @@ export { setGlobalContext_viteDevServer };
6
6
  export { setGlobalContext_vitePreviewServer };
7
7
  export { setGlobalContext_viteConfig };
8
8
  export { getRuntimeManifest };
9
- import { assert, assertUsage, assertWarning, getGlobalObject, getNodeEnv, isPlainObject, objectAssign } from './utils.js';
9
+ import { assert, assertUsage, getGlobalObject, getNodeEnv, isNodeEnvDev, isPlainObject, objectAssign } from './utils.js';
10
10
  import { loadImportBuild } from './globalContext/loadImportBuild.js';
11
11
  import { setPageFiles } from '../../shared/getPageFiles.js';
12
12
  import { assertPluginManifest } from '../shared/assertPluginManifest.js';
@@ -151,7 +151,8 @@ function assertNodeEnv(hasViteDevServer) {
151
151
  const nodeEnv = getNodeEnv();
152
152
  if (nodeEnv === null || nodeEnv === 'test')
153
153
  return;
154
- const isDevNodeEnv = [undefined, '', 'dev', 'development'].includes(nodeEnv);
155
- // calling Vite's createServer() is enough for hasViteDevServer to be true, even without actually adding Vite's development middleware to the server: https://github.com/vikejs/vike/issues/792#issuecomment-1516830759
156
- assertWarning(hasViteDevServer === isDevNodeEnv, `Vite's development server was${hasViteDevServer ? '' : "n't"} instantiated while the environment is set to be a ${isDevNodeEnv ? 'development' : 'production'} environment by ${pc.cyan(`process.env.NODE_ENV === ${JSON.stringify(nodeEnv)}`)} which is contradictory, see https://vike.dev/NODE_ENV`, { onlyOnce: true });
154
+ const isDevNodeEnv = isNodeEnvDev();
155
+ // - Calling Vite's createServer() is enough for hasViteDevServer to be true, even without actually adding Vite's development middleware to the server: https://github.com/vikejs/vike/issues/792#issuecomment-1516830759
156
+ // - We should change this to be a warning if it blocks users (e.g. if a bad-citizen tool sets a wrong process.env.NODE_ENV value).
157
+ assertUsage(hasViteDevServer === isDevNodeEnv, `Vite's development server was${hasViteDevServer ? '' : "n't"} instantiated while the environment is set to be a ${isDevNodeEnv ? 'development' : 'production'} environment by ${pc.cyan(`process.env.NODE_ENV === ${JSON.stringify(nodeEnv)}`)} which is contradictory, see https://vike.dev/NODE_ENV`);
157
158
  }
@@ -53,6 +53,10 @@ type PageConfigGlobalRuntime = {
53
53
  type PageConfigGlobalBuildTime = {
54
54
  configValueSources: ConfigValueSources;
55
55
  };
56
+ /** In what environment(s) the config value is loaded.
57
+ *
58
+ * https://vike.dev/meta
59
+ */
56
60
  type ConfigEnv = {
57
61
  client?: boolean;
58
62
  server?: boolean;
@@ -0,0 +1,2 @@
1
+ export { assertPlusFileExport };
2
+ declare function assertPlusFileExport(fileExports: Record<string, unknown>, filePathToShowToUser: string, configName: string): void;
@@ -0,0 +1,38 @@
1
+ export { assertPlusFileExport };
2
+ import { assert, assertUsage, assertWarning } from '../utils.js';
3
+ import pc from '@brillout/picocolors';
4
+ const EXPORTS_IGNORE = [
5
+ // vite-plugin-solid adds `export { $$registrations }`
6
+ '$$registrations',
7
+ // @vitejs/plugin-vue adds `export { _rerender_only }`
8
+ '_rerender_only'
9
+ ];
10
+ // Tolerate `export { frontmatter }` in .mdx files
11
+ const TOLERATE_SIDE_EXPORTS = ['.md', '.mdx'];
12
+ function assertPlusFileExport(fileExports, filePathToShowToUser, configName) {
13
+ const exportsAll = Object.keys(fileExports).filter((exportName) => !EXPORTS_IGNORE.includes(exportName));
14
+ const exportsInvalid = exportsAll.filter((e) => e !== 'default' && e !== configName);
15
+ if (exportsInvalid.length === 0) {
16
+ if (exportsAll.length === 1) {
17
+ return;
18
+ }
19
+ const exportDefault = pc.cyan('export default');
20
+ const exportNamed = pc.cyan(`export { ${configName} }`);
21
+ if (exportsAll.length === 0) {
22
+ assertUsage(false, `${filePathToShowToUser} doesn't export any value, but it should have a ${exportNamed} or ${exportDefault}`);
23
+ }
24
+ else {
25
+ assert(exportsAll.length === 2); // because `exportsInvalid.length === 0`
26
+ assertWarning(false, `${filePathToShowToUser} remove ${exportNamed} or ${exportDefault}`, {
27
+ onlyOnce: true
28
+ });
29
+ }
30
+ }
31
+ else {
32
+ if (TOLERATE_SIDE_EXPORTS.some((ext) => filePathToShowToUser.endsWith(ext)))
33
+ return;
34
+ exportsInvalid.forEach((exportInvalid) => {
35
+ assertWarning(false, `${filePathToShowToUser} should have only one export: move ${pc.cyan(`export { ${exportInvalid} }`)} to its own +${exportsInvalid}.js file`, { onlyOnce: true });
36
+ });
37
+ }
38
+ }
@@ -1,6 +1,6 @@
1
1
  export { parseConfigValuesImported };
2
2
  import { assert } from '../../utils.js';
3
- import { assertExportsOfValueFile } from '../assertExports.js';
3
+ import { assertPlusFileExport } from '../assertPlusFileExport.js';
4
4
  function parseConfigValuesImported(configValuesImported) {
5
5
  const configValues = {};
6
6
  const addConfigValue = (configName, value, importPath, exportName) => {
@@ -21,7 +21,7 @@ function parseConfigValuesImported(configValuesImported) {
21
21
  if (configValueLoaded.isValueFile) {
22
22
  const { exportValues, importPath, configName } = configValueLoaded;
23
23
  if (configName !== 'client') {
24
- assertExportsOfValueFile(exportValues, importPath, configName);
24
+ assertPlusFileExport(exportValues, importPath, configName);
25
25
  }
26
26
  Object.entries(exportValues).forEach(([exportName, exportValue]) => {
27
27
  const isSideExport = exportName !== 'default'; // .md files may have "side-exports" such as `export { frontmatter }`