vike 0.4.159 → 0.4.160-commit-30d535e

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 (125) hide show
  1. package/dist/cjs/node/plugin/index.js +20 -1
  2. package/dist/cjs/node/plugin/plugins/autoFullBuild.js +2 -2
  3. package/dist/cjs/node/plugin/plugins/buildConfig.js +9 -0
  4. package/dist/cjs/node/plugin/plugins/commonConfig.js +1 -1
  5. package/dist/cjs/node/plugin/plugins/config/stemUtils.js +1 -1
  6. package/dist/cjs/node/plugin/plugins/devConfig/index.js +1 -1
  7. package/dist/cjs/node/plugin/plugins/importBuild/index.js +1 -1
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.js +18 -0
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +1 -5
  10. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +28 -46
  11. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +129 -0
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.js +33 -0
  13. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +139 -0
  14. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → getVikeConfig/transformFileImports.js} +44 -13
  15. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.js → getVikeConfig/transpileAndExecuteFile.js} +105 -78
  16. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +201 -382
  17. package/dist/cjs/node/plugin/plugins/previewConfig.js +1 -1
  18. package/dist/cjs/node/plugin/shared/getHttpRequestAsyncStore.js +1 -1
  19. package/dist/cjs/node/plugin/shared/loggerNotProd/log.js +3 -3
  20. package/dist/cjs/node/plugin/shared/loggerNotProd.js +1 -1
  21. package/dist/cjs/node/plugin/utils.js +1 -2
  22. package/dist/cjs/node/prerender/runPrerender.js +12 -5
  23. package/dist/cjs/node/runtime/globalContext.js +7 -3
  24. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +2 -2
  25. package/dist/cjs/node/runtime/html/renderHtml.js +1 -1
  26. package/dist/cjs/node/runtime/html/stream.js +2 -2
  27. package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +2 -2
  28. package/dist/cjs/node/runtime/renderPage/getHttpResponseBody.js +1 -1
  29. package/dist/cjs/node/runtime/renderPage/loadUserFilesServerSide.js +1 -1
  30. package/dist/cjs/node/runtime/renderPage/{logHintForCjsEsmError.js → logErrorHint.js} +81 -43
  31. package/dist/cjs/node/runtime/renderPage/loggerProd.js +3 -3
  32. package/dist/cjs/node/runtime/utils.js +1 -1
  33. package/dist/cjs/shared/page-configs/assertPlusFileExport.js +44 -0
  34. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +54 -27
  35. package/dist/cjs/shared/route/abort.js +1 -1
  36. package/dist/cjs/shared/route/executeGuardHook.js +3 -2
  37. package/dist/cjs/shared/utils.js +0 -1
  38. package/dist/cjs/utils/assert.js +5 -6
  39. package/dist/cjs/utils/assertIsNotProductionRuntime.js +35 -17
  40. package/dist/cjs/utils/{findUserPackageJsonPath.js → findFile.js} +11 -8
  41. package/dist/cjs/utils/nodeEnv.js +33 -1
  42. package/dist/cjs/utils/objectKeys.js +19 -3
  43. package/dist/cjs/utils/projectInfo.js +2 -4
  44. package/dist/cjs/utils/sorter.js +62 -1
  45. package/dist/esm/node/plugin/index.js +21 -2
  46. package/dist/esm/node/plugin/plugins/autoFullBuild.js +2 -2
  47. package/dist/esm/node/plugin/plugins/buildConfig.js +10 -1
  48. package/dist/esm/node/plugin/plugins/commonConfig.js +2 -2
  49. package/dist/esm/node/plugin/plugins/config/stemUtils.js +2 -2
  50. package/dist/esm/node/plugin/plugins/devConfig/index.js +2 -2
  51. package/dist/esm/node/plugin/plugins/importBuild/index.js +2 -2
  52. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.d.ts +2 -0
  53. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigFileExport.js +12 -0
  54. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.d.ts +8 -1
  55. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.d.ts +0 -1
  56. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +1 -5
  57. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.d.ts +39 -12
  58. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/filesystemRouting.js +29 -47
  59. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.d.ts +21 -0
  60. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/loadFileAtConfigTime.js +123 -0
  61. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.d.ts +5 -0
  62. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveFilePath.js +27 -0
  63. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.d.ts +12 -0
  64. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolveImportPath.js +133 -0
  65. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.d.ts → getVikeConfig/transformFileImports.d.ts} +5 -5
  66. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → getVikeConfig/transformFileImports.js} +43 -12
  67. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.d.ts → getVikeConfig/transpileAndExecuteFile.d.ts} +3 -3
  68. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transpileAndExecuteFile.js → getVikeConfig/transpileAndExecuteFile.js} +105 -78
  69. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.d.ts +16 -1
  70. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +199 -380
  71. package/dist/esm/node/plugin/plugins/previewConfig.js +2 -2
  72. package/dist/esm/node/plugin/shared/getHttpRequestAsyncStore.js +1 -1
  73. package/dist/esm/node/plugin/shared/loggerNotProd/log.js +3 -3
  74. package/dist/esm/node/plugin/shared/loggerNotProd.js +1 -1
  75. package/dist/esm/node/plugin/utils.d.ts +1 -2
  76. package/dist/esm/node/plugin/utils.js +1 -2
  77. package/dist/esm/node/prerender/runPrerender.js +13 -6
  78. package/dist/esm/node/runtime/globalContext.js +8 -4
  79. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +2 -2
  80. package/dist/esm/node/runtime/html/renderHtml.js +1 -1
  81. package/dist/esm/node/runtime/html/stream.js +2 -2
  82. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +2 -2
  83. package/dist/esm/node/runtime/renderPage/getHttpResponseBody.js +1 -1
  84. package/dist/esm/node/runtime/renderPage/loadUserFilesServerSide.js +1 -1
  85. package/dist/esm/node/runtime/renderPage/logErrorHint.d.ts +8 -0
  86. package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError.js → logErrorHint.js} +80 -42
  87. package/dist/esm/node/runtime/renderPage/loggerProd.js +3 -3
  88. package/dist/esm/node/runtime/utils.d.ts +1 -1
  89. package/dist/esm/node/runtime/utils.js +1 -1
  90. package/dist/esm/shared/page-configs/Config.d.ts +1 -1
  91. package/dist/esm/shared/page-configs/PageConfig.d.ts +6 -0
  92. package/dist/esm/shared/page-configs/assertPlusFileExport.d.ts +2 -0
  93. package/dist/esm/shared/page-configs/assertPlusFileExport.js +38 -0
  94. package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +54 -27
  95. package/dist/esm/shared/route/abort.js +2 -2
  96. package/dist/esm/shared/route/executeGuardHook.js +3 -2
  97. package/dist/esm/shared/utils.d.ts +0 -1
  98. package/dist/esm/shared/utils.js +0 -1
  99. package/dist/esm/utils/assert.js +5 -6
  100. package/dist/esm/utils/assertIsNotProductionRuntime.d.ts +8 -6
  101. package/dist/esm/utils/assertIsNotProductionRuntime.js +35 -17
  102. package/dist/esm/utils/debug.d.ts +1 -1
  103. package/dist/esm/utils/findFile.d.ts +3 -0
  104. package/dist/esm/utils/findFile.js +21 -0
  105. package/dist/esm/utils/nodeEnv.d.ts +6 -0
  106. package/dist/esm/utils/nodeEnv.js +29 -0
  107. package/dist/esm/utils/objectKeys.d.ts +10 -1
  108. package/dist/esm/utils/objectKeys.js +20 -3
  109. package/dist/esm/utils/projectInfo.d.ts +2 -8
  110. package/dist/esm/utils/projectInfo.js +2 -4
  111. package/dist/esm/utils/sorter.d.ts +59 -0
  112. package/dist/esm/utils/sorter.js +61 -0
  113. package/package.json +1 -1
  114. package/dist/cjs/shared/page-configs/assertExports.js +0 -67
  115. package/dist/cjs/utils/objectEntries.js +0 -8
  116. package/dist/esm/node/runtime/renderPage/logHintForCjsEsmError.d.ts +0 -13
  117. package/dist/esm/shared/page-configs/assertExports.d.ts +0 -6
  118. package/dist/esm/shared/page-configs/assertExports.js +0 -61
  119. package/dist/esm/utils/findUserPackageJsonPath.d.ts +0 -2
  120. package/dist/esm/utils/findUserPackageJsonPath.js +0 -18
  121. package/dist/esm/utils/objectEntries.d.ts +0 -4
  122. package/dist/esm/utils/objectEntries.js +0 -5
  123. /package/dist/cjs/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.js +0 -0
  124. /package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.d.ts +0 -0
  125. /package/dist/esm/node/runtime/renderPage/{logHintForCjsEsmError → logErrorHint}/errors.js +0 -0
@@ -1,21 +1,50 @@
1
- export { replaceImportStatements };
1
+ export { transformFileImports };
2
2
  export { parseImportData };
3
3
  export { isImportData };
4
4
  // Playground: https://github.com/brillout/acorn-playground
5
+ // Import attributes support: https://github.com/acornjs/acorn/issues/983
6
+ // - Isn't stage 4 yet: https://github.com/tc39/proposal-import-attributes
5
7
  import { parse } from 'acorn';
6
- import { assert, assertUsage, assertWarning, styleFileRE } from '../../../utils.js';
8
+ import { assert, assertUsage, assertWarning, styleFileRE } from '../../../../utils.js';
7
9
  import pc from '@brillout/picocolors';
8
- function replaceImportStatements(code, filePathToShowToUser) {
10
+ function transformFileImports(code, filePathToShowToUser2,
11
+ // For ./transformFileImports.spec.ts
12
+ skipWarnings) {
9
13
  const spliceOperations = [];
10
- const fileImports = [];
14
+ const fileImportsTransformed = [];
15
+ // Performance trick
16
+ if (!code.includes('import'))
17
+ return { noTransformation: true };
11
18
  const imports = getImports(code);
12
19
  if (imports.length === 0)
13
- return { noImportStatement: true };
20
+ return { noTransformation: true };
14
21
  imports.forEach((node) => {
15
22
  if (node.type !== 'ImportDeclaration')
16
23
  return;
17
24
  const importPath = node.source.value;
18
25
  assert(typeof importPath === 'string');
26
+ // - This doesn't work. To make it work we would need to run esbuild twice: esbuild for TypeScript to JavaScript => transformFileImports() => esbuild for bundling.
27
+ // - Or we use an esbuild plugin to apply transformFileImports(). Maybe we can completely skip the need for acorn?
28
+ // - ?real breaks TypeScript, and TypeScript isn't working on supporting query params: https://github.com/microsoft/TypeScript/issues/10988#issuecomment-867135453
29
+ // - Import attributes would be the best.
30
+ // - But it only works with Node.js >=21: https://nodejs.org/api/esm.html#import-attributes
31
+ // - But it's probably ok to tell users "to use real imports you need Node.js 21 or above".
32
+ // - It works well with TypeScript: it doesn't complain upon `with { type: 'unknown-to-typescript' }` and go-to-definition & types are preserved: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html#import-attributes
33
+ // - Esbuid seems to support it: https://esbuild.github.io/plugins/#on-load-arguments:~:text=This%20contains%20a%20map%20of%20the%20import%20attributes%20that
34
+ // - acorn supports it over an acorn plugin: https://github.com/acornjs/acorn/issues/983
35
+ // - Maybe we can use an esbuild plugin instead of acorn to apply transformFileImports()?
36
+ // - Using a magic comment `// @vike-real-import` is tricky:
37
+ // - Esbuild removes comments: https://github.com/evanw/esbuild/issues/1439#issuecomment-877656182
38
+ // - Using source maps to track these magic comments is brittle (source maps can easily break)
39
+ if (importPath.endsWith('?real')) {
40
+ const { start, end } = node.source;
41
+ spliceOperations.push({
42
+ start,
43
+ end,
44
+ replacement: importPath.slice(0, -1 * '?real'.length)
45
+ });
46
+ return;
47
+ }
19
48
  const { start, end } = node;
20
49
  const importStatementCode = code.slice(start, end);
21
50
  // No variable imported
@@ -29,13 +58,15 @@ function replaceImportStatements(code, filePathToShowToUser) {
29
58
  quote = pc.bold(pc.red(quote));
30
59
  }
31
60
  const errMsg = [
32
- `As explained in https://vike.dev/header-file the following import in ${filePathToShowToUser} has no effect:`,
61
+ `As explained in https://vike.dev/header-file the following import in ${filePathToShowToUser2} has no effect:`,
33
62
  quote
34
63
  ].join('\n');
35
- if (!isWarning) {
36
- assertUsage(false, errMsg);
64
+ if (!skipWarnings) {
65
+ if (!isWarning) {
66
+ assertUsage(false, errMsg);
67
+ }
68
+ assertWarning(false, errMsg, { onlyOnce: true });
37
69
  }
38
- assertWarning(false, errMsg, { onlyOnce: true });
39
70
  }
40
71
  let replacement = '';
41
72
  node.specifiers.forEach((specifier) => {
@@ -57,7 +88,7 @@ function replaceImportStatements(code, filePathToShowToUser) {
57
88
  })();
58
89
  const importString = serializeImportData({ importPath, exportName, importStringWasGenerated: true });
59
90
  replacement += `const ${importLocalName} = '${importString}';`;
60
- fileImports.push({
91
+ fileImportsTransformed.push({
61
92
  importStatementCode,
62
93
  importString,
63
94
  importLocalName
@@ -70,7 +101,7 @@ function replaceImportStatements(code, filePathToShowToUser) {
70
101
  });
71
102
  });
72
103
  const codeMod = spliceMany(code, spliceOperations);
73
- return { code: codeMod, fileImports, noImportStatement: false };
104
+ return { code: codeMod, fileImportsTransformed, noTransformation: false };
74
105
  }
75
106
  function getImports(code) {
76
107
  const { body } = parse(code, {
@@ -137,7 +168,7 @@ function spliceMany(str, operations) {
137
168
  .join('');
138
169
  endPrev = end;
139
170
  });
140
- strMod += str.slice(endPrev, str.length - 1);
171
+ strMod += str.slice(endPrev, str.length);
141
172
  return strMod;
142
173
  }
143
174
  function indent(str) {
@@ -1,10 +1,10 @@
1
1
  export { transpileAndExecuteFile };
2
2
  export { getConfigBuildErrorFormatted };
3
- export { getConfigExecutionErrorIntroMsg as getConfigExecutionErrorIntroMsg };
3
+ export { getConfigExecutionErrorIntroMsg };
4
4
  export { isTmpFile };
5
5
  import 'source-map-support/register.js';
6
- import type { FilePathResolved } from '../../../../../shared/page-configs/PageConfig.js';
7
- declare function transpileAndExecuteFile(filePath: FilePathResolved, isValueFile: boolean, userRootDir: string): Promise<{
6
+ import type { FilePathResolved } from '../../../../../../shared/page-configs/PageConfig.js';
7
+ declare function transpileAndExecuteFile(filePath: FilePathResolved, transformImports: boolean, userRootDir: string, doNotTranspile?: boolean): Promise<{
8
8
  fileExports: Record<string, unknown>;
9
9
  }>;
10
10
  declare function getConfigBuildErrorFormatted(err: unknown): null | string;
@@ -1,63 +1,73 @@
1
1
  export { transpileAndExecuteFile };
2
2
  export { getConfigBuildErrorFormatted };
3
- export { getConfigExecutionErrorIntroMsg as getConfigExecutionErrorIntroMsg };
3
+ export { getConfigExecutionErrorIntroMsg };
4
4
  export { isTmpFile };
5
5
  import { build, formatMessages } from 'esbuild';
6
6
  import fs from 'fs';
7
7
  import path from 'path';
8
8
  import pc from '@brillout/picocolors';
9
9
  import { import_ } from '@brillout/import';
10
- import { assertPosixPath, getRandomId, assertIsNotProductionRuntime, assert, unique, assertWarning, isObject, toPosixPath } from '../../../utils.js';
11
- import { isImportData, replaceImportStatements } from './replaceImportStatements.js';
12
- import { vikeConfigDependencies } from './getVikeConfig.js';
10
+ import { assertPosixPath, getRandomId, assertIsNotProductionRuntime, assert, unique, assertWarning, isObject, toPosixPath } from '../../../../utils.js';
11
+ import { isImportData, transformFileImports } from './transformFileImports.js';
12
+ import { vikeConfigDependencies } from '../getVikeConfig.js';
13
13
  import 'source-map-support/register.js';
14
- import { assertExportsOfConfigFile } from '../../../../../shared/page-configs/assertExports.js';
14
+ import { getConfigFileExport } from '../getConfigFileExport.js';
15
15
  assertIsNotProductionRuntime();
16
- async function transpileAndExecuteFile(filePath, isValueFile, userRootDir) {
17
- const { code, fileImports } = await transpileFile(filePath, isValueFile, userRootDir);
18
- const { fileExports } = await executeFile(filePath, code, fileImports, isValueFile);
19
- return { fileExports };
16
+ async function transpileAndExecuteFile(filePath, transformImports, userRootDir, doNotTranspile = false) {
17
+ if (doNotTranspile) {
18
+ assert(!transformImports);
19
+ const fileExports = await executeFile(filePath.filePathAbsoluteFilesystem, filePath);
20
+ if (isHeaderFile(filePath.filePathAbsoluteFilesystem)) {
21
+ const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
22
+ assertWarning(false, `${filePathToShowToUser2} is a JavaScript header file (.h.js), but JavaScript header files don't apply to the config files of extensions`, { onlyOnce: true });
23
+ }
24
+ return { fileExports };
25
+ }
26
+ else {
27
+ const { code, fileImportsTransformed } = await transpileFile(filePath, transformImports, userRootDir);
28
+ const fileExports = await executeTranspiledFile(filePath, code, fileImportsTransformed);
29
+ return { fileExports };
30
+ }
20
31
  }
21
- async function transpileFile(filePath, isValueFile, userRootDir) {
32
+ async function transpileFile(filePath, transformImports, userRootDir) {
22
33
  const { filePathAbsoluteFilesystem } = filePath;
34
+ const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
23
35
  assertPosixPath(filePathAbsoluteFilesystem);
24
36
  vikeConfigDependencies.add(filePathAbsoluteFilesystem);
25
- let code = await transpileWithEsbuild(filePath, isValueFile, userRootDir);
26
- let fileImports = null;
27
- {
28
- const res = transpileImports(code, filePath, isValueFile);
37
+ let code = await transpileWithEsbuild(filePath, userRootDir, transformImports);
38
+ let fileImportsTransformed = null;
39
+ if (transformImports) {
40
+ const res = transformFileImports_(code, filePath);
29
41
  if (res) {
30
42
  code = res.code;
31
- fileImports = res.fileImports;
43
+ fileImportsTransformed = res.fileImportsTransformed;
32
44
  }
33
45
  }
34
- return { code, fileImports };
35
- }
36
- function transpileImports(codeOriginal, filePath, isValueFile) {
37
- // Do we need to remove the imports?
38
- const { filePathAbsoluteFilesystem, filePathToShowToUser } = filePath;
39
- assertPosixPath(filePathAbsoluteFilesystem);
40
- const isHeader = isHeaderFile(filePathAbsoluteFilesystem);
41
- const isPageConfigFile = !isValueFile;
42
- if (!isHeader && !isPageConfigFile) {
43
- return null;
46
+ else {
47
+ if (isHeaderFile(filePathAbsoluteFilesystem)) {
48
+ assertWarning(false, `${filePathToShowToUser2} is a JavaScript header file (.h.js), but JavaScript header files only apply to +config.h.js, see https://vike.dev/header-file`, { onlyOnce: true });
49
+ }
44
50
  }
45
- assertWarning(isPageConfigFile, `${filePathToShowToUser} is a JavaScript header file (.h.js), but JavaScript header files should only be used for +config.h.js, see https://vike.dev/header-file`, { onlyOnce: true });
46
- // Remove the imports
47
- const res = replaceImportStatements(codeOriginal, filePathToShowToUser);
48
- if (res.noImportStatement) {
51
+ return { code, fileImportsTransformed };
52
+ }
53
+ function transformFileImports_(codeOriginal, filePath) {
54
+ const { filePathAbsoluteFilesystem } = filePath;
55
+ const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
56
+ // Replace import statements with import strings
57
+ const res = transformFileImports(codeOriginal, filePathToShowToUser2);
58
+ if (res.noTransformation) {
49
59
  return null;
50
60
  }
51
- const { code, fileImports } = res;
52
- if (!isHeader) {
53
- const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser);
54
- assertWarning(false, `Rename ${filePathToShowToUser} to ${filePathCorrect}, see https://vike.dev/header-file`, {
61
+ const { code, fileImportsTransformed } = res;
62
+ if (!isHeaderFile(filePathAbsoluteFilesystem)) {
63
+ const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser2);
64
+ assertWarning(false, `Rename ${filePathToShowToUser2} to ${filePathCorrect}, see https://vike.dev/header-file`, {
55
65
  onlyOnce: true
56
66
  });
57
67
  }
58
- return { code, fileImports };
68
+ return { code, fileImportsTransformed };
59
69
  }
60
- async function transpileWithEsbuild(filePath, bundle, userRootDir) {
70
+ async function transpileWithEsbuild(filePath, userRootDir, transformImports) {
61
71
  const entryFilePath = filePath.filePathAbsoluteFilesystem;
62
72
  const entryFileDir = path.posix.dirname(entryFilePath);
63
73
  const options = {
@@ -73,22 +83,26 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
73
83
  'NEVER_EMITTED.js'),
74
84
  logLevel: 'silent',
75
85
  format: 'esm',
76
- bundle,
86
+ absWorkingDir: userRootDir,
87
+ // Disable tree-shaking to avoid dead-code elimination, so that unused imports aren't removed.
88
+ // Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
89
+ treeShaking: false,
77
90
  minify: false,
78
- metafile: bundle,
79
- absWorkingDir: userRootDir
91
+ metafile: !transformImports,
92
+ // We cannot bundle imports that are meant to be transformed
93
+ bundle: !transformImports
80
94
  };
81
- if (bundle) {
82
- options.bundle = true;
95
+ // Track dependencies
96
+ if (!transformImports) {
83
97
  options.packages = 'external';
84
98
  options.plugins = [
85
99
  {
86
- name: 'vike:import-hook',
100
+ name: 'vike:dependency-tracker',
87
101
  setup(b) {
88
102
  b.onLoad({ filter: /./ }, (args) => {
103
+ // We collect the dependency `args.path` in case the bulid fails (upon build error => error is thrown => no metafile)
89
104
  let { path } = args;
90
105
  path = toPosixPath(path);
91
- // We collect the dependency args.path in case it fails to build (upon build error => error is thrown => no metafile)
92
106
  vikeConfigDependencies.add(path);
93
107
  return undefined;
94
108
  });
@@ -105,11 +119,6 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
105
119
  }
106
120
  ];
107
121
  }
108
- else {
109
- // Avoid dead-code elimination to ensure unused imports aren't removed.
110
- // Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
111
- options.treeShaking = false;
112
- }
113
122
  let result;
114
123
  try {
115
124
  result = await build(options);
@@ -118,7 +127,8 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
118
127
  await formatBuildErr(err, filePath);
119
128
  throw err;
120
129
  }
121
- if (bundle) {
130
+ // Track dependencies
131
+ if (!transformImports) {
122
132
  assert(result.metafile);
123
133
  Object.keys(result.metafile.inputs).forEach((filePathRelative) => {
124
134
  filePathRelative = toPosixPath(filePathRelative);
@@ -131,7 +141,7 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
131
141
  assert(typeof code === 'string');
132
142
  return code;
133
143
  }
134
- async function executeFile(filePath, code, fileImports, isValueFile) {
144
+ async function executeTranspiledFile(filePath, code, fileImportsTransformed) {
135
145
  const { filePathAbsoluteFilesystem, filePathRelativeToUserRootDir } = filePath;
136
146
  // Alternative to using a temporary file: https://github.com/vitejs/vite/pull/13269
137
147
  // - But seems to break source maps, so I don't think it's worth it
@@ -140,28 +150,35 @@ async function executeFile(filePath, code, fileImports, isValueFile) {
140
150
  const clean = () => fs.unlinkSync(filePathTmp);
141
151
  let fileExports = {};
142
152
  try {
143
- fileExports = await import_(filePathTmp);
153
+ fileExports = await executeFile(filePathTmp, filePath);
154
+ }
155
+ finally {
156
+ clean();
157
+ }
158
+ if (fileImportsTransformed) {
159
+ assert(filePathRelativeToUserRootDir !== undefined);
160
+ const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
161
+ assertImportsAreReExported(fileImportsTransformed, fileExports, filePathToShowToUser2);
162
+ }
163
+ return fileExports;
164
+ }
165
+ async function executeFile(filePathToExecuteAbsoluteFilesystem, filePathSourceFile) {
166
+ let fileExports = {};
167
+ try {
168
+ fileExports = await import_(filePathToExecuteAbsoluteFilesystem);
144
169
  }
145
170
  catch (err) {
146
171
  triggerPrepareStackTrace(err);
147
- const errIntroMsg = getErrIntroMsg('execute', filePath);
172
+ const errIntroMsg = getErrIntroMsg('execute', filePathSourceFile);
148
173
  assert(isObject(err));
149
174
  execErrIntroMsg.set(err, errIntroMsg);
150
175
  throw err;
151
176
  }
152
- finally {
153
- clean();
154
- }
155
- // Return a plain JavaScript object
177
+ // Return a plain JavaScript object:
156
178
  // - import() returns `[Module: null prototype] { default: { onRenderClient: '...' }}`
157
- // - We don't need this special object
179
+ // - We don't need this special object.
158
180
  fileExports = { ...fileExports };
159
- if (fileImports && !isValueFile) {
160
- assert(filePathRelativeToUserRootDir !== undefined);
161
- const filePathToShowToUser = filePathRelativeToUserRootDir ?? filePathAbsoluteFilesystem;
162
- assertImportsAreReExported(fileImports, fileExports, filePathToShowToUser);
163
- }
164
- return { fileExports };
181
+ return fileExports;
165
182
  }
166
183
  const formatted = '_formatted';
167
184
  function getConfigBuildErrorFormatted(err) {
@@ -191,10 +208,10 @@ function getConfigExecutionErrorIntroMsg(err) {
191
208
  return errIntroMsg ?? null;
192
209
  }
193
210
  const tmpPrefix = `[build-`;
194
- function getFilePathTmp(filePath) {
195
- assertPosixPath(filePath);
196
- const dirname = path.posix.dirname(filePath);
197
- const filename = path.posix.basename(filePath);
211
+ function getFilePathTmp(filePathAbsoluteFilesystem) {
212
+ assertPosixPath(filePathAbsoluteFilesystem);
213
+ const dirname = path.posix.dirname(filePathAbsoluteFilesystem);
214
+ const filename = path.posix.basename(filePathAbsoluteFilesystem);
198
215
  // Syntax with semicolon `[build:${/*...*/}]` doesn't work on Windows: https://github.com/vikejs/vike/issues/800#issuecomment-1517329455
199
216
  const tag = `${tmpPrefix}${getRandomId(12)}]`;
200
217
  const filePathTmp = path.posix.join(dirname, `${tag}${filename}.mjs`);
@@ -205,29 +222,29 @@ function isTmpFile(filePath) {
205
222
  const fileName = path.posix.basename(filePath);
206
223
  return fileName.startsWith(tmpPrefix);
207
224
  }
208
- function assertImportsAreReExported(fileImports, fileExports, filePathToShowToUser) {
209
- assertExportsOfConfigFile(fileExports, filePathToShowToUser);
210
- const exportedStrings = getExportedStrings(fileExports.default);
225
+ function assertImportsAreReExported(fileImportsTransformed, fileExports, filePathToShowToUser2) {
226
+ const fileExport = getConfigFileExport(fileExports, filePathToShowToUser2);
227
+ const exportedStrings = getExportedStrings(fileExport);
211
228
  Object.values(exportedStrings).forEach((exportVal) => {
212
229
  if (typeof exportVal !== 'string')
213
230
  return;
214
231
  if (!isImportData(exportVal))
215
232
  return;
216
233
  const importString = exportVal;
217
- fileImports.forEach((fileImport) => {
234
+ fileImportsTransformed.forEach((fileImport) => {
218
235
  if (fileImport.importString === importString) {
219
236
  fileImport.isReExported = true;
220
237
  }
221
238
  });
222
239
  });
223
- const fileImportsUnused = fileImports.filter((fi) => !fi.isReExported);
224
- if (fileImportsUnused.length === 0)
240
+ const fileImportsTransformedUnused = fileImportsTransformed.filter((fi) => !fi.isReExported);
241
+ if (fileImportsTransformedUnused.length === 0)
225
242
  return;
226
- const importStatements = unique(fileImportsUnused.map((fi) => fi.importStatementCode));
227
- const importNamesUnused = fileImportsUnused.map((fi) => pc.cyan(fi.importLocalName)).join(', ');
228
- const singular = fileImportsUnused.length === 1;
229
- assertWarning(fileImportsUnused.length === 0, [
230
- `${filePathToShowToUser} imports the following:`,
243
+ const importStatements = unique(fileImportsTransformedUnused.map((fi) => fi.importStatementCode));
244
+ const importNamesUnused = fileImportsTransformedUnused.map((fi) => pc.cyan(fi.importLocalName)).join(', ');
245
+ const singular = fileImportsTransformedUnused.length === 1;
246
+ assertWarning(fileImportsTransformedUnused.length === 0, [
247
+ `${filePathToShowToUser2} imports the following:`,
231
248
  ...importStatements.map((s) => pc.cyan(` ${s}`)),
232
249
  `But the import${singular ? '' : 's'} ${importNamesUnused} ${singular ? "isn't" : "aren't"} re-exported at ${pc.cyan('export default { ... }')} and therefore ${singular ? 'has' : 'have'} no effect, see explanation at https://vike.dev/header-file`
233
250
  ].join('\n'), { onlyOnce: true });
@@ -249,6 +266,7 @@ function getExportedStrings(obj) {
249
266
  return exportedStrings;
250
267
  }
251
268
  function isHeaderFile(filePath) {
269
+ assertPosixPath(filePath);
252
270
  const basenameParts = path.posix.basename(filePath).split('.');
253
271
  return basenameParts.includes('h');
254
272
  }
@@ -269,10 +287,19 @@ function triggerPrepareStackTrace(err) {
269
287
  }
270
288
  }
271
289
  function getErrIntroMsg(operation, filePath) {
290
+ const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
272
291
  const msg = [
292
+ // prettier ignore
273
293
  pc.red(`Failed to ${operation}`),
274
- pc.bold(pc.red(filePath.filePathToShowToUser)),
294
+ pc.bold(pc.red(filePathToShowToUser2)),
275
295
  pc.red(`because:`)
276
296
  ].join(' ');
277
297
  return msg;
278
298
  }
299
+ /** `filePath.filePathToShowToUser` may show the import path of a package, use `filePathToShowToUser2` instead always show a file path instead. */
300
+ function getFilePathToShowToUser2(filePath) {
301
+ const { filePathAbsoluteFilesystem, filePathRelativeToUserRootDir } = filePath;
302
+ const filePathToShowToUser2 = filePathRelativeToUserRootDir || filePathAbsoluteFilesystem;
303
+ assert(filePathToShowToUser2);
304
+ return filePathToShowToUser2;
305
+ }
@@ -2,9 +2,24 @@ export { getVikeConfig };
2
2
  export { reloadVikeConfig };
3
3
  export { vikeConfigDependencies };
4
4
  export { isVikeConfigFile };
5
- import type { PageConfigGlobalBuildTime, PageConfigBuildTime } from '../../../../../shared/page-configs/PageConfig.js';
5
+ export type { InterfaceValueFile };
6
+ import type { PageConfigGlobalBuildTime, PageConfigBuildTime, FilePathResolved } from '../../../../../shared/page-configs/PageConfig.js';
6
7
  import type { ExtensionResolved } from '../../../../../shared/ConfigVike.js';
8
+ import { type LocationId } from './getVikeConfig/filesystemRouting.js';
7
9
  import type { ResolvedConfig } from 'vite';
10
+ type InterfaceFileCommons = {
11
+ locationId: LocationId;
12
+ filePath: FilePathResolved;
13
+ fileExportsByConfigName: Record<ConfigName, {
14
+ configValue?: unknown;
15
+ }>;
16
+ };
17
+ type InterfaceValueFile = InterfaceFileCommons & {
18
+ isConfigFile: false;
19
+ isValueFile: true;
20
+ configName: string;
21
+ };
22
+ type ConfigName = string;
8
23
  type VikeConfig = {
9
24
  pageConfigs: PageConfigBuildTime[];
10
25
  pageConfigGlobal: PageConfigGlobalBuildTime;