vike 0.4.248 → 0.4.249-commit-55681da

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 (45) hide show
  1. package/bin.js +3 -0
  2. package/dist/client/runtime-client-routing/getPageContext.js +0 -2
  3. package/dist/client/runtime-client-routing/getPageContextFromHooks.d.ts +8 -8
  4. package/dist/client/runtime-client-routing/renderPageClient.d.ts +4 -4
  5. package/dist/node/api/utils.d.ts +2 -2
  6. package/dist/node/api/utils.js +2 -2
  7. package/dist/node/vite/plugins/build/pluginBuildConfig.js +2 -2
  8. package/dist/node/vite/plugins/pluginVirtualFiles.js +71 -113
  9. package/dist/node/vite/shared/loggerDev.d.ts +3 -0
  10. package/dist/node/vite/shared/loggerDev.js +29 -13
  11. package/dist/node/vite/shared/loggerVite.js +3 -3
  12. package/dist/node/vite/shared/resolveVikeConfigInternal/assertExtensions.d.ts +1 -1
  13. package/dist/node/vite/shared/resolveVikeConfigInternal/{crawlPlusFiles.d.ts → crawlPlusFilePaths.d.ts} +2 -2
  14. package/dist/node/vite/shared/resolveVikeConfigInternal/{crawlPlusFiles.js → crawlPlusFilePaths.js} +4 -4
  15. package/dist/node/vite/shared/resolveVikeConfigInternal/{getPlusFilesAll.d.ts → getPlusFilesByLocationId.d.ts} +8 -6
  16. package/dist/node/vite/shared/resolveVikeConfigInternal/{getPlusFilesAll.js → getPlusFilesByLocationId.js} +47 -59
  17. package/dist/node/vite/shared/resolveVikeConfigInternal/loadFileAtConfigTime.d.ts +1 -1
  18. package/dist/node/vite/shared/resolveVikeConfigInternal.d.ts +1 -1
  19. package/dist/node/vite/shared/resolveVikeConfigInternal.js +66 -64
  20. package/dist/server/runtime/asyncHook.d.ts +2 -2
  21. package/dist/server/runtime/asyncHook.js +2 -2
  22. package/dist/server/runtime/renderPageServer/html/stream.js +12 -13
  23. package/dist/server/utils.d.ts +2 -2
  24. package/dist/server/utils.js +2 -2
  25. package/dist/types/Config.d.ts +3 -2
  26. package/dist/types/PageConfig.d.ts +1 -1
  27. package/dist/utils/PROJECT_VERSION.d.ts +1 -1
  28. package/dist/utils/PROJECT_VERSION.js +1 -1
  29. package/dist/utils/assert.d.ts +7 -4
  30. package/dist/utils/assert.js +65 -50
  31. package/dist/utils/colorsClient.d.ts +6 -0
  32. package/dist/utils/colorsClient.js +16 -0
  33. package/dist/utils/{colors.js → colorsServer.js} +2 -0
  34. package/dist/utils/formatHintLog.js +1 -1
  35. package/dist/utils/getBetterError.js +11 -7
  36. package/dist/utils/shallowClone.d.ts +2 -0
  37. package/dist/utils/shallowClone.js +11 -0
  38. package/dist/utils/trimWithAnsi.js +1 -1
  39. package/package.json +6 -6
  40. package/dist/utils/colorVike.d.ts +0 -2
  41. package/dist/utils/colorVike.js +0 -5
  42. package/node/cli/bin.js +0 -3
  43. /package/dist/node/vite/shared/resolveVikeConfigInternal/{crawlPlusFiles → crawlPlusFilePaths}/ignorePatternsBuiltIn.d.ts +0 -0
  44. /package/dist/node/vite/shared/resolveVikeConfigInternal/{crawlPlusFiles → crawlPlusFilePaths}/ignorePatternsBuiltIn.js +0 -0
  45. /package/dist/utils/{colors.d.ts → colorsServer.d.ts} +0 -0
@@ -1,61 +1,51 @@
1
- export { getPlusFilesAll };
1
+ export { getPlusFilesByLocationId };
2
2
  import { assert } from '../../utils.js';
3
3
  import { configDefinitionsBuiltIn } from './configDefinitionsBuiltIn.js';
4
4
  import { getLocationId } from './filesystemRouting.js';
5
- import { crawlPlusFiles, getPlusFileValueConfigName } from './crawlPlusFiles.js';
5
+ import { crawlPlusFilePaths, getPlusFileValueConfigName } from './crawlPlusFilePaths.js';
6
6
  import { getConfigFileExport } from './getConfigFileExport.js';
7
7
  import { loadConfigFile, loadValueFile } from './loadFileAtConfigTime.js';
8
8
  import { resolvePointerImport } from './resolvePointerImport.js';
9
9
  import { getFilePathResolved } from '../getFilePath.js';
10
10
  import { assertExtensionsConventions, assertExtensionsRequire } from './assertExtensions.js';
11
- async function getPlusFilesAll(userRootDir, esbuildCache) {
12
- const plusFiles = await findPlusFiles(userRootDir);
13
- const configFiles = [];
14
- const valueFiles = [];
15
- plusFiles.forEach((f) => {
16
- if (getPlusFileValueConfigName(f.filePathAbsoluteFilesystem) === 'config') {
17
- configFiles.push(f);
18
- }
19
- else {
20
- valueFiles.push(f);
21
- }
22
- });
23
- let plusFilesAll = {};
24
- await Promise.all([
25
- // Config files
26
- ...configFiles.map(async (filePath) => {
11
+ async function getPlusFilesByLocationId(userRootDir, esbuildCache) {
12
+ const plusFilePaths = (await crawlPlusFilePaths(userRootDir)).map(({ filePathAbsoluteUserRootDir }) => getFilePathResolved({ filePathAbsoluteUserRootDir, userRootDir }));
13
+ const plusFilesByLocationId = {};
14
+ await Promise.all(plusFilePaths.map(async (filePath) => {
15
+ if (getPlusFileValueConfigName(filePath.filePathAbsoluteFilesystem) === 'config') {
16
+ // +config.js files
27
17
  const { filePathAbsoluteUserRootDir } = filePath;
28
18
  assert(filePathAbsoluteUserRootDir);
29
19
  const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, [], false, esbuildCache);
30
20
  assert(filePath.filePathAbsoluteUserRootDir);
31
21
  const locationId = getLocationId(filePathAbsoluteUserRootDir);
32
22
  const plusFile = getPlusFileFromConfigFile(configFile, false, locationId, userRootDir);
33
- plusFilesAll[locationId] = plusFilesAll[locationId] ?? [];
34
- plusFilesAll[locationId].push(plusFile);
23
+ plusFilesByLocationId[locationId] = plusFilesByLocationId[locationId] ?? [];
24
+ plusFilesByLocationId[locationId].push(plusFile);
35
25
  extendsConfigs.forEach((extendsConfig) => {
36
26
  /* We purposely use the same locationId because the Vike extension's config should only apply to where it's being extended from, for example:
37
- ```js
38
- // /pages/admin/+config.js
39
-
40
- import vikeVue from 'vike-vue/config'
41
- // Should only apply to /pages/admin/**
42
- export default { extends: [vikeVue] }
43
- ```
44
- ```js
45
- // /pages/marketing/+config.js
46
-
47
- import vikeReact from 'vike-react/config'
48
- // Should only apply to /pages/marketing/**
49
- export default { extends: [vikeReact] }
50
- ```
51
- */
27
+ ```js
28
+ // /pages/admin/+config.js
29
+
30
+ import vikeVue from 'vike-vue/config'
31
+ // Should only apply to /pages/admin/**
32
+ export default { extends: [vikeVue] }
33
+ ```
34
+ ```js
35
+ // /pages/marketing/+config.js
36
+
37
+ import vikeReact from 'vike-react/config'
38
+ // Should only apply to /pages/marketing/**
39
+ export default { extends: [vikeReact] }
40
+ ```
41
+ */
52
42
  const plusFile = getPlusFileFromConfigFile(extendsConfig, true, locationId, userRootDir);
53
43
  assertExtensionsConventions(plusFile);
54
- plusFilesAll[locationId].push(plusFile);
44
+ plusFilesByLocationId[locationId].push(plusFile);
55
45
  });
56
- }),
57
- // Value files
58
- ...valueFiles.map(async (filePath) => {
46
+ }
47
+ else {
48
+ // +{configName}.js files
59
49
  const { filePathAbsoluteUserRootDir } = filePath;
60
50
  assert(filePathAbsoluteUserRootDir);
61
51
  const configName = getPlusFileValueConfigName(filePathAbsoluteUserRootDir);
@@ -68,23 +58,23 @@ async function getPlusFilesAll(userRootDir, esbuildCache) {
68
58
  isNotLoaded: true,
69
59
  configName,
70
60
  };
71
- plusFilesAll[locationId] = plusFilesAll[locationId] ?? [];
72
- plusFilesAll[locationId].push(plusFile);
61
+ plusFilesByLocationId[locationId] = plusFilesByLocationId[locationId] ?? [];
62
+ plusFilesByLocationId[locationId].push(plusFile);
73
63
  // We don't have access to the custom config definitions defined by the user yet.
74
64
  // - If `configDef` is `undefined` => we load the file +{configName}.js later.
75
65
  // - We already need to load +meta.js here (to get the custom config definitions defined by the user)
76
66
  await loadValueFile(plusFile, configDefinitionsBuiltIn, userRootDir, esbuildCache);
77
- }),
78
- ]);
67
+ }
68
+ }));
79
69
  // Make lists element order deterministic
80
- Object.entries(plusFilesAll).forEach(([_locationId, plusFiles]) => {
70
+ Object.entries(plusFilesByLocationId).forEach(([_locationId, plusFiles]) => {
81
71
  plusFiles.sort(sortMakeDeterministic);
82
72
  });
83
- assertPlusFiles(plusFilesAll);
84
- return plusFilesAll;
73
+ assertPlusFiles(plusFilesByLocationId);
74
+ return plusFilesByLocationId;
85
75
  }
86
- function assertPlusFiles(plusFilesAll) {
87
- const plusFiles = Object.values(plusFilesAll).flat();
76
+ function assertPlusFiles(plusFilesByLocationId) {
77
+ const plusFiles = Object.values(plusFilesByLocationId).flat();
88
78
  // The earlier we call it the better, so that +require can be used by Vike extensions to depend on new Vike features
89
79
  assertExtensionsRequire(plusFiles);
90
80
  }
@@ -95,12 +85,14 @@ function getPlusFileFromConfigFile(configFile, isExtensionConfig, locationId, us
95
85
  const fileExport = getConfigFileExport(fileExports, filePath.filePathToShowToUser);
96
86
  Object.entries(fileExport).forEach(([configName, configValue]) => {
97
87
  fileExportsByConfigName[configName] = configValue;
98
- const pointerImport = resolvePointerImport(configValue, configFile.filePath, userRootDir, configName);
99
- if (pointerImport) {
100
- pointerImportsByConfigName[configName] = {
101
- ...pointerImport,
102
- fileExportValueLoaded: false,
103
- };
88
+ // Pointer imports
89
+ const values = Array.isArray(configValue) ? configValue : [configValue];
90
+ const pointerImports = values
91
+ .map((value) => resolvePointerImport(value, configFile.filePath, userRootDir, configName))
92
+ .filter((pointerImport) => pointerImport !== null)
93
+ .map((pointerImport) => ({ ...pointerImport, fileExportValueLoaded: false }));
94
+ if (pointerImports.length > 0) {
95
+ pointerImportsByConfigName[configName] = pointerImports;
104
96
  }
105
97
  });
106
98
  const plusFile = {
@@ -116,10 +108,6 @@ function getPlusFileFromConfigFile(configFile, isExtensionConfig, locationId, us
116
108
  }
117
109
  // Make order deterministic (no other purpose)
118
110
  function sortMakeDeterministic(plusFile1, plusFile2) {
111
+ // Sort by file path
119
112
  return plusFile1.filePath.filePathAbsoluteVite < plusFile2.filePath.filePathAbsoluteVite ? -1 : 1;
120
113
  }
121
- async function findPlusFiles(userRootDir) {
122
- const files = await crawlPlusFiles(userRootDir);
123
- const plusFiles = files.map(({ filePathAbsoluteUserRootDir }) => getFilePathResolved({ filePathAbsoluteUserRootDir, userRootDir }));
124
- return plusFiles;
125
- }
@@ -5,7 +5,7 @@ export type { ConfigFile };
5
5
  export type { PointerImportLoaded };
6
6
  import type { FilePathResolved } from '../../../../types/FilePath.js';
7
7
  import { type EsbuildCache } from './transpileAndExecuteFile.js';
8
- import type { PlusFileValue } from './getPlusFilesAll.js';
8
+ import type { PlusFileValue } from './getPlusFilesByLocationId.js';
9
9
  import { PointerImport } from './resolvePointerImport.js';
10
10
  import type { ConfigDefinitionsInternal } from './configDefinitionsBuiltIn.js';
11
11
  type ConfigFile = {
@@ -14,7 +14,7 @@ export type { PageConfigBuildTimeBeforeComputed };
14
14
  import type { PageConfigGlobalBuildTime, PageConfigBuildTime } from '../../../types/PageConfig.js';
15
15
  import { type ConfigDefinitionsInternal, type ConfigDefinitionInternal } from './resolveVikeConfigInternal/configDefinitionsBuiltIn.js';
16
16
  import { type GlobalConfigPublic } from '../../../shared-server-client/page-configs/resolveVikeConfigPublic.js';
17
- import { type PlusFile } from './resolveVikeConfigInternal/getPlusFilesAll.js';
17
+ import { type PlusFile } from './resolveVikeConfigInternal/getPlusFilesByLocationId.js';
18
18
  import type { PrerenderContextPublic } from '../../prerender/runPrerender.js';
19
19
  import type { ResolvedConfig, UserConfig } from 'vite';
20
20
  import { type DangerouslyUseInternals } from '../../../shared-server-client/getProxyForPublicUsage.js';
@@ -25,7 +25,7 @@ import { getFilePathResolved } from './getFilePath.js';
25
25
  import { getConfigValueBuildTime } from '../../../shared-server-client/page-configs/getConfigValueBuildTime.js';
26
26
  import { resolveGlobalConfigPublic, } from '../../../shared-server-client/page-configs/resolveVikeConfigPublic.js';
27
27
  import { getConfigValuesBase, isJsonValue, } from '../../../shared-server-client/page-configs/serialize/serializeConfigValues.js';
28
- import { getPlusFilesAll, } from './resolveVikeConfigInternal/getPlusFilesAll.js';
28
+ import { getPlusFilesByLocationId, } from './resolveVikeConfigInternal/getPlusFilesByLocationId.js';
29
29
  import { getEnvVarObject } from './getEnvVarObject.js';
30
30
  import { getVikeApiOperation } from '../../../shared-server-node/api-context.js';
31
31
  import { getCliOptions } from '../../cli/context.js';
@@ -169,9 +169,9 @@ async function resolveVikeConfigInternal_withErrorHandling(userRootDir, isDev, v
169
169
  }
170
170
  }
171
171
  async function resolveVikeConfigInternal(userRootDir, vikeVitePluginOptions, esbuildCache) {
172
- const plusFilesAll = await getPlusFilesAll(userRootDir, esbuildCache);
173
- const configDefinitionsResolved = await resolveConfigDefinitions(plusFilesAll, userRootDir, esbuildCache);
174
- const { pageConfigGlobal, pageConfigs } = getPageConfigsBuildTime(configDefinitionsResolved, plusFilesAll, userRootDir);
172
+ const plusFilesByLocationId = await getPlusFilesByLocationId(userRootDir, esbuildCache);
173
+ const configDefinitionsResolved = await resolveConfigDefinitions(plusFilesByLocationId, userRootDir, esbuildCache);
174
+ const { pageConfigGlobal, pageConfigs } = getPageConfigsBuildTime(configDefinitionsResolved, plusFilesByLocationId, userRootDir);
175
175
  if (!globalObject.isV1Design_)
176
176
  globalObject.isV1Design_ = pageConfigs.length > 0;
177
177
  // Backwards compatibility for vike(options) in vite.config.js
@@ -197,21 +197,21 @@ function resolveGlobalConfig(pageConfigGlobal, pageConfigs) {
197
197
  const globalConfigPublic = resolveGlobalConfigPublic(pageConfigs, pageConfigGlobal, getConfigValues);
198
198
  return globalConfigPublic;
199
199
  }
200
- async function resolveConfigDefinitions(plusFilesAll, userRootDir, esbuildCache) {
201
- const plusFilesAllOrdered = Object.values(plusFilesAll)
200
+ async function resolveConfigDefinitions(plusFilesByLocationId, userRootDir, esbuildCache) {
201
+ const plusFilesByLocationIdOrdered = Object.values(plusFilesByLocationId)
202
202
  .flat()
203
- .sort((plusFile1, plusFile2) => sortAfterInheritanceOrderGlobal(plusFile1, plusFile2, plusFilesAll, null));
203
+ .sort((plusFile1, plusFile2) => sortAfterInheritanceOrderGlobal(plusFile1, plusFile2, plusFilesByLocationId, null));
204
204
  const configDefinitionsGlobal = getConfigDefinitions(
205
- // We use `plusFilesAll` in order to allow local Vike extensions to create global configs, and to set the value of global configs such as `+vite` (enabling Vike extensions to add Vite plugins).
206
- plusFilesAllOrdered, (configDef) => !!configDef.global);
207
- await loadCustomConfigBuildTimeFiles(plusFilesAll, configDefinitionsGlobal, userRootDir, esbuildCache);
208
- const configDefinitionsAll = getConfigDefinitions(Object.values(plusFilesAll).flat());
205
+ // We use `plusFilesByLocationId` in order to allow local Vike extensions to create global configs, and to set the value of global configs such as `+vite` (enabling Vike extensions to add Vite plugins).
206
+ plusFilesByLocationIdOrdered, (configDef) => !!configDef.global);
207
+ await loadCustomConfigBuildTimeFiles(plusFilesByLocationId, configDefinitionsGlobal, userRootDir, esbuildCache);
208
+ const configDefinitionsAll = getConfigDefinitions(Object.values(plusFilesByLocationId).flat());
209
209
  const configNamesKnownAll = Object.keys(configDefinitionsAll);
210
210
  const configNamesKnownGlobal = Object.keys(configDefinitionsGlobal);
211
211
  assert(configNamesKnownGlobal.every((configName) => configNamesKnownAll.includes(configName)));
212
212
  const configDefinitionsLocal = {};
213
- await Promise.all(objectEntries(plusFilesAll).map(async ([locationIdPage, plusFiles]) => {
214
- const plusFilesRelevant = objectEntries(plusFilesAll)
213
+ await Promise.all(objectEntries(plusFilesByLocationId).map(async ([locationIdPage, plusFiles]) => {
214
+ const plusFilesRelevant = objectEntries(plusFilesByLocationId)
215
215
  .filter(([locationId]) => isInherited(locationId, locationIdPage))
216
216
  .map(([, plusFiles]) => plusFiles)
217
217
  .flat()
@@ -238,7 +238,7 @@ async function resolveConfigDefinitions(plusFilesAll, userRootDir, esbuildCache)
238
238
  return configDefinitionsResolved;
239
239
  }
240
240
  // Load value files (with `env.config===true`) of *custom* configs.
241
- // - The value files of *built-in* configs are already loaded at `getPlusFilesAll()`.
241
+ // - The value files of *built-in* configs are already loaded at `getPlusFilesByLocationId()`.
242
242
  async function loadCustomConfigBuildTimeFiles(plusFiles, configDefinitions, userRootDir, esbuildCache) {
243
243
  const plusFileList = Object.values(plusFiles).flat(1);
244
244
  await Promise.all(plusFileList.map(async (plusFile) => {
@@ -246,28 +246,28 @@ async function loadCustomConfigBuildTimeFiles(plusFiles, configDefinitions, user
246
246
  await loadValueFile(plusFile, configDefinitions, userRootDir, esbuildCache);
247
247
  }
248
248
  else {
249
- await Promise.all(Object.entries(plusFile.pointerImportsByConfigName).map(async ([configName, pointerImport]) => {
250
- await loadPointerImport(pointerImport, userRootDir, configName, configDefinitions, esbuildCache);
249
+ await Promise.all(Object.entries(plusFile.pointerImportsByConfigName).map(async ([configName, pointerImports]) => {
250
+ await Promise.all(pointerImports.map((pointerImport) => loadPointerImport(pointerImport, userRootDir, configName, configDefinitions, esbuildCache)));
251
251
  }));
252
252
  }
253
253
  }));
254
254
  }
255
- function getPageConfigsBuildTime(configDefinitionsResolved, plusFilesAll, userRootDir) {
255
+ function getPageConfigsBuildTime(configDefinitionsResolved, plusFilesByLocationId, userRootDir) {
256
256
  const pageConfigGlobal = {
257
257
  configDefinitions: configDefinitionsResolved.configDefinitionsGlobal,
258
258
  configValueSources: {},
259
259
  };
260
260
  objectEntries(configDefinitionsResolved.configDefinitionsGlobal).forEach(([configName, configDef]) => {
261
261
  const sources = resolveConfigValueSources(configName, configDef,
262
- // We use `plusFilesAll` in order to allow local Vike extensions to create global configs, and to set the value of global configs such as `+vite` (enabling Vike extensions to add Vite plugins).
263
- Object.values(plusFilesAll).flat(), userRootDir, true, plusFilesAll);
262
+ // We use `plusFilesByLocationId` in order to allow local Vike extensions to create global configs, and to set the value of global configs such as `+vite` (enabling Vike extensions to add Vite plugins).
263
+ Object.values(plusFilesByLocationId).flat(), userRootDir, true, plusFilesByLocationId);
264
264
  if (sources.length === 0)
265
265
  return;
266
266
  pageConfigGlobal.configValueSources[configName] = sources;
267
267
  });
268
- applyEffects(pageConfigGlobal.configValueSources, configDefinitionsResolved.configDefinitionsGlobal, plusFilesAll);
268
+ applyEffects(pageConfigGlobal.configValueSources, configDefinitionsResolved.configDefinitionsGlobal, plusFilesByLocationId);
269
269
  sortConfigValueSources(pageConfigGlobal.configValueSources, null);
270
- assertPageConfigGlobal(pageConfigGlobal, plusFilesAll);
270
+ assertPageConfigGlobal(pageConfigGlobal, plusFilesByLocationId);
271
271
  const pageConfigs = objectEntries(configDefinitionsResolved.configDefinitionsLocal)
272
272
  .filter(([_locationId, { plusFiles }]) => isDefiningPage(plusFiles))
273
273
  .map(([locationId, { configDefinitions, plusFilesRelevant }]) => {
@@ -276,13 +276,13 @@ function getPageConfigsBuildTime(configDefinitionsResolved, plusFilesAll, userRo
276
276
  objectEntries(configDefinitionsLocal)
277
277
  .filter(([_configName, configDef]) => configDef.global !== true)
278
278
  .forEach(([configName, configDef]) => {
279
- const sources = resolveConfigValueSources(configName, configDef, plusFilesRelevant, userRootDir, false, plusFilesAll);
279
+ const sources = resolveConfigValueSources(configName, configDef, plusFilesRelevant, userRootDir, false, plusFilesByLocationId);
280
280
  if (sources.length === 0)
281
281
  return;
282
282
  configValueSources[configName] = sources;
283
283
  });
284
284
  const pageConfigRoute = determineRouteFilesystem(locationId, configValueSources);
285
- applyEffects(configValueSources, configDefinitionsLocal, plusFilesAll);
285
+ applyEffects(configValueSources, configDefinitionsLocal, plusFilesByLocationId);
286
286
  sortConfigValueSources(configValueSources, locationId);
287
287
  const pageConfig = {
288
288
  pageId: locationId,
@@ -299,15 +299,15 @@ function getPageConfigsBuildTime(configDefinitionsResolved, plusFilesAll, userRo
299
299
  assertPageConfigs(pageConfigs);
300
300
  return { pageConfigs, pageConfigGlobal };
301
301
  }
302
- function assertPageConfigGlobal(pageConfigGlobal, plusFilesAll) {
302
+ function assertPageConfigGlobal(pageConfigGlobal, plusFilesByLocationId) {
303
303
  Object.entries(pageConfigGlobal.configValueSources).forEach(([configName, sources]) => {
304
- assertGlobalConfigLocation(configName, sources, plusFilesAll, pageConfigGlobal.configDefinitions);
304
+ assertGlobalConfigLocation(configName, sources, plusFilesByLocationId, pageConfigGlobal.configDefinitions);
305
305
  });
306
306
  }
307
- function assertGlobalConfigLocation(configName, sources, plusFilesAll, configDefinitionsGlobal) {
307
+ function assertGlobalConfigLocation(configName, sources, plusFilesByLocationId, configDefinitionsGlobal) {
308
308
  // Determine existing global +config.js files
309
309
  const configFilePathsGlobal = [];
310
- const plusFilesGlobal = Object.values(objectFromEntries(objectEntries(plusFilesAll).filter(([locationId]) => isGlobalLocation(locationId, plusFilesAll)))).flat();
310
+ const plusFilesGlobal = Object.values(objectFromEntries(objectEntries(plusFilesByLocationId).filter(([locationId]) => isGlobalLocation(locationId, plusFilesByLocationId)))).flat();
311
311
  plusFilesGlobal
312
312
  .filter((i) => i.isConfigFile)
313
313
  .forEach((plusFile) => {
@@ -326,7 +326,7 @@ function assertGlobalConfigLocation(configName, sources, plusFilesAll, configDef
326
326
  if (!filePathAbsoluteUserRootDir)
327
327
  return;
328
328
  assert(!plusFile.isExtensionConfig);
329
- if (!isGlobalLocation(source.locationId, plusFilesAll)) {
329
+ if (!isGlobalLocation(source.locationId, plusFilesByLocationId)) {
330
330
  const configDef = configDefinitionsGlobal[configName];
331
331
  assert(configDef);
332
332
  const isConditionallyGlobal = isCallable(configDef.global);
@@ -502,9 +502,9 @@ function sortAfterInheritanceOrderPage(plusFile1, plusFile2, locationIdPage, con
502
502
  }
503
503
  return 0;
504
504
  }
505
- function sortAfterInheritanceOrderGlobal(plusFile1, plusFile2, plusFilesAll, configName) {
506
- if (plusFilesAll) {
507
- const ret = makeFirst((plusFile) => isGlobalLocation(plusFile.locationId, plusFilesAll))(plusFile1, plusFile2);
505
+ function sortAfterInheritanceOrderGlobal(plusFile1, plusFile2, plusFilesByLocationId, configName) {
506
+ if (plusFilesByLocationId) {
507
+ const ret = makeFirst((plusFile) => isGlobalLocation(plusFile.locationId, plusFilesByLocationId))(plusFile1, plusFile2);
508
508
  if (ret !== 0)
509
509
  return ret;
510
510
  }
@@ -552,13 +552,13 @@ function sortPlusFilesSameLocationId(plusFile1, plusFile2, configName) {
552
552
  return ret;
553
553
  }
554
554
  // Config set by +{configName}.js (highest precedence)
555
- // No need to make it deterministic: the overall order is already deterministic, see sortMakeDeterministic() at getPlusFilesAll()
555
+ // No need to make it deterministic: the overall order is already deterministic, see sortMakeDeterministic() at getPlusFilesByLocationId()
556
556
  return 0;
557
557
  }
558
- function resolveConfigValueSources(configName, configDef, plusFilesRelevant, userRootDir, isGlobal, plusFilesAll) {
558
+ function resolveConfigValueSources(configName, configDef, plusFilesRelevant, userRootDir, isGlobal, plusFilesByLocationId) {
559
559
  let sources = plusFilesRelevant
560
560
  .filter((plusFile) => isDefiningConfig(plusFile, configName))
561
- .map((plusFile) => getConfigValueSource(configName, plusFile, configDef, userRootDir));
561
+ .flatMap((plusFile) => getConfigValueSources(configName, plusFile, configDef, userRootDir));
562
562
  // Filter hydrid global-local configs
563
563
  if (!isCallable(configDef.global)) {
564
564
  // Already filtered
@@ -570,7 +570,7 @@ function resolveConfigValueSources(configName, configDef, plusFilesRelevant, use
570
570
  sources = sources.filter((source) => {
571
571
  assert(source.configEnv.config);
572
572
  assert(source.valueIsLoaded);
573
- const valueIsGlobal = resolveIsGlobalValue(configDef.global, source, plusFilesAll);
573
+ const valueIsGlobal = resolveIsGlobalValue(configDef.global, source, plusFilesByLocationId);
574
574
  return isGlobal ? valueIsGlobal : !valueIsGlobal;
575
575
  });
576
576
  }
@@ -579,7 +579,7 @@ function resolveConfigValueSources(configName, configDef, plusFilesRelevant, use
579
579
  function isDefiningConfig(plusFile, configName) {
580
580
  return getConfigNamesSetByPlusFile(plusFile).includes(configName);
581
581
  }
582
- function getConfigValueSource(configName, plusFile, configDef, userRootDir) {
582
+ function getConfigValueSources(configName, plusFile, configDef, userRootDir) {
583
583
  const confVal = getConfVal(plusFile, configName);
584
584
  assert(confVal);
585
585
  const configValueSourceCommon = {
@@ -622,7 +622,7 @@ function getConfigValueSource(configName, plusFile, configDef, userRootDir) {
622
622
  valueIsDefinedByPlusValueFile: false,
623
623
  definedAt: definedAtFilePath,
624
624
  };
625
- return configValueSource;
625
+ return [configValueSource];
626
626
  }
627
627
  // +config.js
628
628
  if (plusFile.isConfigFile) {
@@ -630,23 +630,25 @@ function getConfigValueSource(configName, plusFile, configDef, userRootDir) {
630
630
  // Defined over pointer import
631
631
  const pointerImport = plusFile.pointerImportsByConfigName[configName];
632
632
  if (pointerImport) {
633
- const value = pointerImport.fileExportValueLoaded
634
- ? {
635
- valueIsLoaded: true,
636
- value: pointerImport.fileExportValue,
637
- }
638
- : {
639
- valueIsLoaded: false,
633
+ return pointerImport.map((pointerImport) => {
634
+ const value = pointerImport.fileExportValueLoaded
635
+ ? {
636
+ valueIsLoaded: true,
637
+ value: pointerImport.fileExportValue,
638
+ }
639
+ : {
640
+ valueIsLoaded: false,
641
+ };
642
+ const configValueSource = {
643
+ ...configValueSourceCommon,
644
+ ...value,
645
+ configEnv: resolveConfigEnv(configDef.env, pointerImport.fileExportPath),
646
+ valueIsLoadedWithImport: true,
647
+ valueIsDefinedByPlusValueFile: false,
648
+ definedAt: pointerImport.fileExportPath,
640
649
  };
641
- const configValueSource = {
642
- ...configValueSourceCommon,
643
- ...value,
644
- configEnv: resolveConfigEnv(configDef.env, pointerImport.fileExportPath),
645
- valueIsLoadedWithImport: true,
646
- valueIsDefinedByPlusValueFile: false,
647
- definedAt: pointerImport.fileExportPath,
648
- };
649
- return configValueSource;
650
+ return configValueSource;
651
+ });
650
652
  }
651
653
  // Defined inside +config.js
652
654
  const configValueSource = {
@@ -658,7 +660,7 @@ function getConfigValueSource(configName, plusFile, configDef, userRootDir) {
658
660
  valueIsDefinedByPlusValueFile: false,
659
661
  definedAt: definedAtFilePath_,
660
662
  };
661
- return configValueSource;
663
+ return [configValueSource];
662
664
  }
663
665
  // Defined by value file, i.e. +{configName}.js
664
666
  if (!plusFile.isConfigFile) {
@@ -678,7 +680,7 @@ function getConfigValueSource(configName, plusFile, configDef, userRootDir) {
678
680
  [configName],
679
681
  },
680
682
  };
681
- return configValueSource;
683
+ return [configValueSource];
682
684
  }
683
685
  assert(false);
684
686
  }
@@ -694,12 +696,12 @@ function isDefiningPage(plusFiles) {
694
696
  function isDefiningPageConfig(configName) {
695
697
  return ['Page', 'route'].includes(configName);
696
698
  }
697
- function resolveIsGlobalValue(configDefGlobal, source, plusFilesAll) {
699
+ function resolveIsGlobalValue(configDefGlobal, source, plusFilesByLocationId) {
698
700
  assert(source.valueIsLoaded);
699
701
  let isGlobal;
700
702
  if (isCallable(configDefGlobal))
701
703
  isGlobal = configDefGlobal(source.value, {
702
- isGlobalLocation: isGlobalLocation(source.locationId, plusFilesAll),
704
+ isGlobalLocation: isGlobalLocation(source.locationId, plusFilesByLocationId),
703
705
  });
704
706
  else
705
707
  isGlobal = configDefGlobal ?? false;
@@ -802,7 +804,7 @@ function assertMetaUsage(metaVal, metaConfigDefinedAt) {
802
804
  });
803
805
  }
804
806
  // Test: https://github.com/vikejs/vike/blob/871a111a77d637bbd156b07be5ae728c3d595501/test/playground/pages/config-meta/effect/e2e-test.ts
805
- function applyEffects(configValueSources, configDefinitions, plusFilesAll) {
807
+ function applyEffects(configValueSources, configDefinitions, plusFilesByLocationId) {
806
808
  objectEntries(configDefinitions).forEach(([configNameEffect, configDefEffect]) => {
807
809
  const sourceEffect = configValueSources[configNameEffect]?.[0];
808
810
  if (!sourceEffect)
@@ -812,7 +814,7 @@ function applyEffects(configValueSources, configDefinitions, plusFilesAll) {
812
814
  return;
813
815
  const configModFromEffect = effect;
814
816
  // Apply config value changes first to create sources, then meta.env changes to modify their env
815
- applyEffectConfVal(configModFromEffect, sourceEffect, configValueSources, configNameEffect, configDefEffect, configDefinitions, plusFilesAll);
817
+ applyEffectConfVal(configModFromEffect, sourceEffect, configValueSources, configNameEffect, configDefEffect, configDefinitions, plusFilesByLocationId);
816
818
  applyEffectMetaEnv(configModFromEffect, configValueSources, configDefEffect);
817
819
  });
818
820
  }
@@ -833,7 +835,7 @@ function runEffect(configName, configDef, source) {
833
835
  return null;
834
836
  return configModFromEffect;
835
837
  }
836
- function applyEffectConfVal(configModFromEffect, sourceEffect, configValueSources, configNameEffect, configDefEffect, configDefinitions, plusFilesAll) {
838
+ function applyEffectConfVal(configModFromEffect, sourceEffect, configValueSources, configNameEffect, configDefEffect, configDefinitions, plusFilesByLocationId) {
837
839
  objectEntries(configModFromEffect).forEach(([configNameTarget, configValue]) => {
838
840
  if (configNameTarget === 'meta')
839
841
  return;
@@ -851,8 +853,8 @@ function applyEffectConfVal(configModFromEffect, sourceEffect, configValueSource
851
853
  value: configValue,
852
854
  };
853
855
  assert(sourceEffect.valueIsLoaded);
854
- const isValueGlobalSource = resolveIsGlobalValue(configDefEffect.global, sourceEffect, plusFilesAll);
855
- const isValueGlobalTarget = resolveIsGlobalValue(configDef.global, configValueSource, plusFilesAll);
856
+ const isValueGlobalSource = resolveIsGlobalValue(configDefEffect.global, sourceEffect, plusFilesByLocationId);
857
+ const isValueGlobalTarget = resolveIsGlobalValue(configDef.global, configValueSource, plusFilesByLocationId);
856
858
  const isGlobalHumanReadable = (isGlobal) => `${isGlobal ? 'non-' : ''}global`;
857
859
  // The error message make it sound like it's an inherent limitation, it actually isn't (both ways can make senses).
858
860
  assertUsage(isValueGlobalSource === isValueGlobalTarget, `The configuration ${pc.cyan(configNameEffect)} is set to ${pc.cyan(JSON.stringify(sourceEffect.value))} which is considered ${isGlobalHumanReadable(isValueGlobalSource)}. However, it has a meta.effect that sets the configuration ${pc.cyan(configNameTarget)} to ${pc.cyan(JSON.stringify(configValue))} which is considered ${isGlobalHumanReadable(isValueGlobalTarget)}. This is contradictory: make sure the values are either both non-global or both global.`);
@@ -1084,8 +1086,8 @@ function resolveConfigEnv(configEnv, filePath) {
1084
1086
  return configEnvResolved;
1085
1087
  }
1086
1088
  /** Whether configs defined in `locationId` apply to every page */
1087
- function isGlobalLocation(locationId, plusFilesAll) {
1088
- const locationIdsPage = objectEntries(plusFilesAll)
1089
+ function isGlobalLocation(locationId, plusFilesByLocationId) {
1090
+ const locationIdsPage = objectEntries(plusFilesByLocationId)
1089
1091
  .filter(([_locationId, plusFiles]) => isDefiningPage(plusFiles))
1090
1092
  .map(([locationId]) => locationId);
1091
1093
  return locationIdsPage.every((locId) => isInherited(locationId, locId));
@@ -1,5 +1,5 @@
1
1
  export { getPageContext_withAsyncHook };
2
- export { getHttpRequestId_withAsyncHook };
2
+ export { getRequestId_withAsyncHook };
3
3
  export { getAsyncLocalStorage };
4
4
  export type { AsyncStore };
5
5
  import type { AsyncLocalStorage as AsyncLocalStorageType } from 'node:async_hooks';
@@ -8,5 +8,5 @@ type AsyncStore = null | {
8
8
  pageContext?: Record<string, unknown>;
9
9
  };
10
10
  declare function getAsyncLocalStorage(): Promise<AsyncLocalStorageType<AsyncStore> | null>;
11
- declare function getHttpRequestId_withAsyncHook(): number | null;
11
+ declare function getRequestId_withAsyncHook(): number | null;
12
12
  declare function getPageContext_withAsyncHook(): any;
@@ -1,5 +1,5 @@
1
1
  export { getPageContext_withAsyncHook };
2
- export { getHttpRequestId_withAsyncHook };
2
+ export { getRequestId_withAsyncHook };
3
3
  export { getAsyncLocalStorage };
4
4
  import { preparePageContextForPublicUsageServer } from './renderPageServer/preparePageContextForPublicUsageServer.js';
5
5
  import { assert, assertIsNotBrowser, getGlobalObject, isObject } from '../utils.js';
@@ -30,7 +30,7 @@ function getAsyncStore() {
30
30
  assert(asyncStore === undefined || isObject(asyncStore));
31
31
  return asyncStore ?? null;
32
32
  }
33
- function getHttpRequestId_withAsyncHook() {
33
+ function getRequestId_withAsyncHook() {
34
34
  const asyncStore = getAsyncStore();
35
35
  return asyncStore?.requestId ?? null;
36
36
  }
@@ -242,7 +242,7 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
242
242
  writeStream(injectedChunk); // Adds injectedChunk to buffer
243
243
  flushStream(); // Sets shouldFlushStream to true
244
244
  }
245
- // We call onStreamEvent() also when the stream ends in order to properly handle the situation when the stream didn't emit any data
245
+ // We call onStreamDataOrEnd() also when the stream ends in order to properly handle the situation when the stream didn't emit any data
246
246
  const onStreamDataOrEnd = (cb) => {
247
247
  assert(streamOriginalEnded === false);
248
248
  streamOriginalHasStartedEmitting = true;
@@ -277,26 +277,23 @@ async function processStream(streamOriginal, { injectStringAtBegin, injectString
277
277
  }
278
278
  });
279
279
  },
280
- async onEnd(
281
- /* Should we use this `isCancel`? Maybe we can skip `injectStringAtEnd()`?
282
- isCancel,
283
- //*/
284
- ) {
280
+ async onEnd(isCancel) {
285
281
  try {
286
282
  assert(!onEndWasCalled);
287
283
  onEndWasCalled = true;
288
284
  debug('stream end');
289
- // We call onStreamEvent() also here in case the stream didn't emit any data
285
+ // We call onStreamDataOrEnd() also here in case the stream didn't emit any data
290
286
  onStreamDataOrEnd(() => {
291
287
  streamOriginalEnded = true;
292
288
  });
293
- if (injectStringAtEnd) {
289
+ if (injectStringAtEnd && !isCancel) {
294
290
  const injectedChunk = await injectStringAtEnd();
295
291
  writeStream(injectedChunk);
296
292
  }
297
293
  await promiseReadyToWrite; // E.g. if the user calls the pipe wrapper after the original writable has ended
298
294
  assert(isReady());
299
- flushBuffer();
295
+ if (!isCancel)
296
+ flushBuffer();
300
297
  streamClosed = true;
301
298
  debug('stream ended');
302
299
  }
@@ -526,7 +523,8 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
526
523
  return;
527
524
  await onEnd(isCancel);
528
525
  isClosed = true;
529
- controllerProxy.close();
526
+ if (!isCancel)
527
+ controllerProxy.close();
530
528
  };
531
529
  let controllerProxy;
532
530
  assertReadableStreamConstructor();
@@ -546,6 +544,7 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
546
544
  });
547
545
  },
548
546
  async cancel(...args) {
547
+ debug('stream cancelled');
549
548
  isCancel = true;
550
549
  await readableOriginal.cancel(...args);
551
550
  // If readableOriginal has implemented readableOriginal.cancel() then the onEnd() callback and therefore closeStream() may already have been called at this point
@@ -553,9 +552,9 @@ async function createStreamWrapper({ streamOriginal, onError, onData, onEnd, onF
553
552
  },
554
553
  });
555
554
  const writeChunk = (chunk) => {
556
- if (
557
- // If readableOriginal doesn't implement readableOriginal.cancel() then it may still emit data after we close the stream. We therefore need to check whether the steam is closed.
558
- !isClosed) {
555
+ if (!isCancel &&
556
+ // If readableOriginal doesn't implement readableOriginal.cancel() then it may still emit data after we close the stream. We therefore need to check whether the steam is closed.
557
+ !isClosed) {
559
558
  controllerProxy.enqueue(encodeForWebStream(chunk));
560
559
  debugWithChunk('data written (Web Readable)', chunk);
561
560
  }
@@ -42,8 +42,8 @@ export * from '../utils/assertSetup.js';
42
42
  export * from '../utils/path.js';
43
43
  export * from '../utils/isHtml.js';
44
44
  export * from '../utils/virtualFileId.js';
45
- export * from '../utils/colors.js';
46
- export * from '../utils/colorVike.js';
45
+ export * from '../utils/colorsServer.js';
46
+ export * from '../utils/colorsClient.js';
47
47
  export * from '../utils/getTerminalWidth.js';
48
48
  export * from '../utils/truncateString.js';
49
49
  export * from '../utils/formatHintLog.js';
@@ -46,8 +46,8 @@ export * from '../utils/assertSetup.js';
46
46
  export * from '../utils/path.js';
47
47
  export * from '../utils/isHtml.js';
48
48
  export * from '../utils/virtualFileId.js';
49
- export * from '../utils/colors.js';
50
- export * from '../utils/colorVike.js';
49
+ export * from '../utils/colorsServer.js';
50
+ export * from '../utils/colorsClient.js';
51
51
  export * from '../utils/getTerminalWidth.js';
52
52
  export * from '../utils/truncateString.js';
53
53
  export * from '../utils/formatHintLog.js';
@@ -339,7 +339,7 @@ type ConfigBuiltIn = {
339
339
  *
340
340
  * https://vike.dev/extends
341
341
  */
342
- extends?: Config | ImportString | (Config | ImportString)[];
342
+ extends?: Config | Config[] | ImportString;
343
343
  /** Hook called before the page is rendered.
344
344
  *
345
345
  * https://vike.dev/onBeforeRender
@@ -596,4 +596,5 @@ type ConfigBuiltInResolved = {
596
596
  headersResponse?: Exclude<Config['headersResponse'], ImportString | undefined>[];
597
597
  };
598
598
  type ConfigMeta = Record<string, ConfigDefinition>;
599
- type ImportString = `import:${string}`;
599
+ type ImportString = ImportStringVal | ImportStringVal[];
600
+ type ImportStringVal = `import:${string}`;