vike 0.4.159-commit-71760c7 → 0.4.159-commit-a6bc208
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.
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +10 -22
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{transformImportStatements.js → transformImports.js} +33 -17
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +76 -53
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +8 -20
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transformImportStatements.d.ts → transformImports.d.ts} +2 -4
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{transformImportStatements.js → transformImports.js} +32 -17
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.d.ts +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +75 -52
- package/dist/esm/utils/projectInfo.d.ts +2 -2
- package/dist/esm/utils/projectInfo.js +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const configDefinitionsBuiltIn_js_1 = require("./getVikeConfig/configDefinitionsBuiltIn.js");
|
|
10
10
|
const filesystemRouting_js_1 = require("./getVikeConfig/filesystemRouting.js");
|
|
11
11
|
const transpileAndExecuteFile_js_1 = require("./transpileAndExecuteFile.js");
|
|
12
|
-
const
|
|
12
|
+
const transformImports_js_1 = require("./transformImports.js");
|
|
13
13
|
const isConfigInvalid_js_1 = require("../../../../runtime/renderPage/isConfigInvalid.js");
|
|
14
14
|
const globalContext_js_1 = require("../../../../runtime/globalContext.js");
|
|
15
15
|
const loggerNotProd_js_1 = require("../../../shared/loggerNotProd.js");
|
|
@@ -90,7 +90,7 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
90
90
|
let interfaceFilesByLocationId = {};
|
|
91
91
|
// Config files
|
|
92
92
|
await Promise.all(configFiles.map(async (filePath) => {
|
|
93
|
-
const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, []);
|
|
93
|
+
const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, [], false);
|
|
94
94
|
const interfaceFile = getInterfaceFileFromConfigFile(configFile, false);
|
|
95
95
|
const locationId = (0, filesystemRouting_js_1.getLocationId)(filePath.filePathAbsoluteVite);
|
|
96
96
|
interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
|
|
@@ -582,7 +582,7 @@ function isDefiningPageConfig(configName) {
|
|
|
582
582
|
function resolveImport(configValue, importerFilePath, userRootDir, configEnv, configName) {
|
|
583
583
|
if (typeof configValue !== 'string')
|
|
584
584
|
return null;
|
|
585
|
-
const importData = (0,
|
|
585
|
+
const importData = (0, transformImports_js_1.parseImportData)(configValue);
|
|
586
586
|
if (!importData)
|
|
587
587
|
return null;
|
|
588
588
|
const { importPath, exportName } = importData;
|
|
@@ -845,10 +845,10 @@ function getConfigName(filePath) {
|
|
|
845
845
|
return configName;
|
|
846
846
|
}
|
|
847
847
|
}
|
|
848
|
-
async function loadConfigFile(configFilePath, userRootDir, visited) {
|
|
848
|
+
async function loadConfigFile(configFilePath, userRootDir, visited, isConfigOfExtension) {
|
|
849
849
|
const { filePathAbsoluteFilesystem } = configFilePath;
|
|
850
850
|
assertNoInfiniteLoop(visited, filePathAbsoluteFilesystem);
|
|
851
|
-
const { fileExports } = await (0, transpileAndExecuteFile_js_1.transpileAndExecuteFile)(configFilePath, false, userRootDir);
|
|
851
|
+
const { fileExports } = await (0, transpileAndExecuteFile_js_1.transpileAndExecuteFile)(configFilePath, false, userRootDir, isConfigOfExtension);
|
|
852
852
|
const { extendsConfigs, extendsFilePaths } = await loadExtendsConfigs(fileExports, configFilePath, userRootDir, [
|
|
853
853
|
...visited,
|
|
854
854
|
filePathAbsoluteFilesystem
|
|
@@ -875,7 +875,7 @@ async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir
|
|
|
875
875
|
const { importPath: importPath } = importData;
|
|
876
876
|
const filePathAbsoluteFilesystem = resolveImportPath(importData, configFilePath);
|
|
877
877
|
assertImportPath(filePathAbsoluteFilesystem, importData, configFilePath);
|
|
878
|
-
|
|
878
|
+
warnUserLandExtension(importPath, configFilePath);
|
|
879
879
|
// - filePathRelativeToUserRootDir has no functionality beyond nicer error messages for user
|
|
880
880
|
// - Using importPath would be visually nicer but it's ambigous => we rather pick filePathAbsoluteFilesystem for added clarity
|
|
881
881
|
const filePathRelativeToUserRootDir = determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir);
|
|
@@ -890,7 +890,7 @@ async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir
|
|
|
890
890
|
});
|
|
891
891
|
const extendsConfigs = [];
|
|
892
892
|
await Promise.all(extendsConfigFiles.map(async (configFilePath) => {
|
|
893
|
-
const result = await loadConfigFile(configFilePath, userRootDir, visited);
|
|
893
|
+
const result = await loadConfigFile(configFilePath, userRootDir, visited, true);
|
|
894
894
|
extendsConfigs.push(result.configFile);
|
|
895
895
|
extendsConfigs.push(...result.extendsConfigs);
|
|
896
896
|
}));
|
|
@@ -908,20 +908,8 @@ function determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRoot
|
|
|
908
908
|
filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir;
|
|
909
909
|
return filePathRelativeToUserRootDir;
|
|
910
910
|
}
|
|
911
|
-
function
|
|
912
|
-
|
|
913
|
-
const fileDir = path_1.default.posix.dirname(filePath) + '/';
|
|
914
|
-
const fileName = path_1.default.posix.basename(filePath);
|
|
915
|
-
const fileNameBaseCorrect = '+config';
|
|
916
|
-
const [fileNameBase, ...fileNameRest] = fileName.split('.');
|
|
917
|
-
const fileNameCorrect = [fileNameBaseCorrect, ...fileNameRest].join('.');
|
|
918
|
-
(0, utils_js_1.assertWarning)(fileNameBase === fileNameBaseCorrect, `Rename ${fileName} to ${fileNameCorrect} in ${fileDir}`, {
|
|
919
|
-
onlyOnce: true
|
|
920
|
-
});
|
|
921
|
-
}
|
|
922
|
-
else {
|
|
923
|
-
(0, utils_js_1.assertWarning)(false, `${configFilePath.filePathToShowToUser} uses ${picocolors_1.default.cyan('extends')} to inherit from ${picocolors_1.default.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 });
|
|
924
|
-
}
|
|
911
|
+
function warnUserLandExtension(importPath, configFilePath) {
|
|
912
|
+
(0, utils_js_1.assertWarning)((0, utils_js_1.isNpmPackageImport)(importPath), `${configFilePath.filePathToShowToUser} uses ${picocolors_1.default.cyan('extends')} to inherit from ${picocolors_1.default.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.`, { onlyOnce: true });
|
|
925
913
|
}
|
|
926
914
|
function getExtendsImportData(configFileExports, configFilePath) {
|
|
927
915
|
const { filePathToShowToUser } = configFilePath;
|
|
@@ -941,7 +929,7 @@ function getExtendsImportData(configFileExports, configFilePath) {
|
|
|
941
929
|
(0, utils_js_1.assertUsage)(false, wrongUsage);
|
|
942
930
|
}
|
|
943
931
|
const extendsImportData = extendList.map((importDataSerialized) => {
|
|
944
|
-
const importData = (0,
|
|
932
|
+
const importData = (0, transformImports_js_1.parseImportData)(importDataSerialized);
|
|
945
933
|
(0, utils_js_1.assertUsage)(importData, wrongUsage);
|
|
946
934
|
return importData;
|
|
947
935
|
});
|
|
@@ -3,14 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.isImportData = exports.parseImportData = exports.transformImports = void 0;
|
|
7
7
|
// Playground: https://github.com/brillout/acorn-playground
|
|
8
8
|
// Import attributes support: https://github.com/acornjs/acorn/issues/983
|
|
9
9
|
// - Isn't stage 4 yet: https://github.com/tc39/proposal-import-attributes
|
|
10
10
|
const acorn_1 = require("acorn");
|
|
11
11
|
const utils_js_1 = require("../../../utils.js");
|
|
12
12
|
const picocolors_1 = __importDefault(require("@brillout/picocolors"));
|
|
13
|
-
function
|
|
13
|
+
function transformImports(code, filePathToShowToUser2,
|
|
14
|
+
// For ./transformImports.spec.ts
|
|
15
|
+
skipWarnings) {
|
|
14
16
|
const spliceOperations = [];
|
|
15
17
|
const fileImportsTransformed = [];
|
|
16
18
|
// Performance trick
|
|
@@ -24,9 +26,29 @@ function transformImportStatements(code, filePathToShowToUser2) {
|
|
|
24
26
|
return;
|
|
25
27
|
const importPath = node.source.value;
|
|
26
28
|
(0, utils_js_1.assert)(typeof importPath === 'string');
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
// - This doesn't work. To make it work we would need to run esbuild twice: esbuild for TypeScript to JavaScript => transformImports() => esbuild for bundling.
|
|
30
|
+
// - Or we use an esbuild plugin to apply transformImports(). Maybe we can completely skip the need for acorn?
|
|
31
|
+
// - ?real breaks TypeScript, and TypeScript isn't working on supporting query params: https://github.com/microsoft/TypeScript/issues/10988#issuecomment-867135453
|
|
32
|
+
// - Import attributes would be the best.
|
|
33
|
+
// - But it only works with Node.js >=21: https://nodejs.org/api/esm.html#import-attributes
|
|
34
|
+
// - But it's probably ok to tell users "to use real imports you need Node.js 21 or above".
|
|
35
|
+
// - 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
|
|
36
|
+
// - Esbuid seems to support it: https://esbuild.github.io/plugins/#on-load-arguments:~:text=This%20contains%20a%20map%20of%20the%20import%20attributes%20that
|
|
37
|
+
// - acorn supports it over an acorn plugin: https://github.com/acornjs/acorn/issues/983
|
|
38
|
+
// - Maybe we can use an esbuild plugin instead of acorn to apply transformImports()?
|
|
39
|
+
// - Using a magic comment `// @vike-real-import` is tricky:
|
|
40
|
+
// - Esbuild removes comments: https://github.com/evanw/esbuild/issues/1439#issuecomment-877656182
|
|
41
|
+
// - Using source maps to track these magic comments is brittle (source maps can easily break)
|
|
42
|
+
if (importPath.endsWith('?real')) {
|
|
43
|
+
const { start, end } = node.source;
|
|
44
|
+
spliceOperations.push({
|
|
45
|
+
start,
|
|
46
|
+
end,
|
|
47
|
+
replacement: importPath.slice(0, -1 * '?real'.length)
|
|
48
|
+
});
|
|
29
49
|
return;
|
|
50
|
+
}
|
|
51
|
+
const { start, end } = node;
|
|
30
52
|
const importStatementCode = code.slice(start, end);
|
|
31
53
|
// No variable imported
|
|
32
54
|
if (node.specifiers.length === 0) {
|
|
@@ -42,10 +64,12 @@ function transformImportStatements(code, filePathToShowToUser2) {
|
|
|
42
64
|
`As explained in https://vike.dev/header-file the following import in ${filePathToShowToUser2} has no effect:`,
|
|
43
65
|
quote
|
|
44
66
|
].join('\n');
|
|
45
|
-
if (!
|
|
46
|
-
(
|
|
67
|
+
if (!skipWarnings) {
|
|
68
|
+
if (!isWarning) {
|
|
69
|
+
(0, utils_js_1.assertUsage)(false, errMsg);
|
|
70
|
+
}
|
|
71
|
+
(0, utils_js_1.assertWarning)(false, errMsg, { onlyOnce: true });
|
|
47
72
|
}
|
|
48
|
-
(0, utils_js_1.assertWarning)(false, errMsg, { onlyOnce: true });
|
|
49
73
|
}
|
|
50
74
|
let replacement = '';
|
|
51
75
|
node.specifiers.forEach((specifier) => {
|
|
@@ -82,7 +106,7 @@ function transformImportStatements(code, filePathToShowToUser2) {
|
|
|
82
106
|
const codeMod = spliceMany(code, spliceOperations);
|
|
83
107
|
return { code: codeMod, fileImportsTransformed, noTransformation: false };
|
|
84
108
|
}
|
|
85
|
-
exports.
|
|
109
|
+
exports.transformImports = transformImports;
|
|
86
110
|
function getImports(code) {
|
|
87
111
|
const { body } = (0, acorn_1.parse)(code, {
|
|
88
112
|
ecmaVersion: 'latest',
|
|
@@ -150,7 +174,7 @@ function spliceMany(str, operations) {
|
|
|
150
174
|
.join('');
|
|
151
175
|
endPrev = end;
|
|
152
176
|
});
|
|
153
|
-
strMod += str.slice(endPrev, str.length
|
|
177
|
+
strMod += str.slice(endPrev, str.length);
|
|
154
178
|
return strMod;
|
|
155
179
|
}
|
|
156
180
|
function indent(str) {
|
|
@@ -159,11 +183,3 @@ function indent(str) {
|
|
|
159
183
|
.map((s) => ` ${s}`)
|
|
160
184
|
.join('\n');
|
|
161
185
|
}
|
|
162
|
-
function isVikeRealImport(code, posStart) {
|
|
163
|
-
let posEnd = code.indexOf('\n', posStart);
|
|
164
|
-
if (posEnd === -1)
|
|
165
|
-
posEnd = code.length;
|
|
166
|
-
const lineEnd = code.slice(posStart, posEnd);
|
|
167
|
-
return lineEnd.includes('@vike-real-import');
|
|
168
|
-
}
|
|
169
|
-
exports.isVikeRealImport = isVikeRealImport;
|
|
@@ -10,50 +10,64 @@ const path_1 = __importDefault(require("path"));
|
|
|
10
10
|
const picocolors_1 = __importDefault(require("@brillout/picocolors"));
|
|
11
11
|
const import_1 = require("@brillout/import");
|
|
12
12
|
const utils_js_1 = require("../../../utils.js");
|
|
13
|
-
const
|
|
13
|
+
const transformImports_js_1 = require("./transformImports.js");
|
|
14
14
|
const getVikeConfig_js_1 = require("./getVikeConfig.js");
|
|
15
15
|
require("source-map-support/register.js");
|
|
16
16
|
const getConfigFileExport_js_1 = require("./getConfigFileExport.js");
|
|
17
17
|
(0, utils_js_1.assertIsNotProductionRuntime)();
|
|
18
|
-
async function transpileAndExecuteFile(filePath, isValueFile, userRootDir) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
async function transpileAndExecuteFile(filePath, isValueFile, userRootDir, isConfigOfExtension = false) {
|
|
19
|
+
if (isConfigOfExtension) {
|
|
20
|
+
const fileExports = await executeFile(filePath.filePathAbsoluteFilesystem, filePath);
|
|
21
|
+
if (isHeaderFile(filePath.filePathAbsoluteFilesystem)) {
|
|
22
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
23
|
+
(0, utils_js_1.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 });
|
|
24
|
+
}
|
|
25
|
+
return { fileExports };
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const { code, fileImportsTransformed } = await transpileFile(filePath, isValueFile, userRootDir);
|
|
29
|
+
const fileExports = await executeTranspiledFile(filePath, code, fileImportsTransformed, isValueFile);
|
|
30
|
+
return { fileExports };
|
|
31
|
+
}
|
|
22
32
|
}
|
|
23
33
|
exports.transpileAndExecuteFile = transpileAndExecuteFile;
|
|
24
34
|
async function transpileFile(filePath, isValueFile, userRootDir) {
|
|
25
35
|
const { filePathAbsoluteFilesystem } = filePath;
|
|
36
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
26
37
|
(0, utils_js_1.assertPosixPath)(filePathAbsoluteFilesystem);
|
|
27
38
|
getVikeConfig_js_1.vikeConfigDependencies.add(filePathAbsoluteFilesystem);
|
|
28
|
-
|
|
39
|
+
const importsAreTransformed = !isValueFile;
|
|
40
|
+
let code = await transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile);
|
|
29
41
|
let fileImportsTransformed = null;
|
|
30
|
-
{
|
|
31
|
-
const res =
|
|
42
|
+
if (importsAreTransformed) {
|
|
43
|
+
const res = transformImports_(code, filePath);
|
|
32
44
|
if (res) {
|
|
33
45
|
code = res.code;
|
|
34
46
|
fileImportsTransformed = res.fileImportsTransformed;
|
|
35
47
|
}
|
|
36
48
|
}
|
|
49
|
+
else {
|
|
50
|
+
if (isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
51
|
+
if (isValueFile) {
|
|
52
|
+
(0, utils_js_1.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 });
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
(0, utils_js_1.assert)(false);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
37
59
|
return { code, fileImportsTransformed };
|
|
38
60
|
}
|
|
39
|
-
function
|
|
40
|
-
// Do we need to remove the imports?
|
|
61
|
+
function transformImports_(codeOriginal, filePath) {
|
|
41
62
|
const { filePathAbsoluteFilesystem } = filePath;
|
|
42
63
|
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
const isPageConfigFile = !isValueFile;
|
|
46
|
-
if (!isHeader && !isPageConfigFile) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
(0, utils_js_1.assertWarning)(isPageConfigFile, `${filePathToShowToUser2} 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 });
|
|
50
|
-
// Remove the imports
|
|
51
|
-
const res = (0, transformImportStatements_js_1.transformImportStatements)(codeOriginal, filePathToShowToUser2);
|
|
64
|
+
// Replace import statements with import strings
|
|
65
|
+
const res = (0, transformImports_js_1.transformImports)(codeOriginal, filePathToShowToUser2);
|
|
52
66
|
if (res.noTransformation) {
|
|
53
67
|
return null;
|
|
54
68
|
}
|
|
55
69
|
const { code, fileImportsTransformed } = res;
|
|
56
|
-
if (!
|
|
70
|
+
if (!isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
57
71
|
const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser2);
|
|
58
72
|
(0, utils_js_1.assertWarning)(false, `Rename ${filePathToShowToUser2} to ${filePathCorrect}, see https://vike.dev/header-file`, {
|
|
59
73
|
onlyOnce: true
|
|
@@ -61,7 +75,8 @@ function transformImports(codeOriginal, filePath, isValueFile) {
|
|
|
61
75
|
}
|
|
62
76
|
return { code, fileImportsTransformed };
|
|
63
77
|
}
|
|
64
|
-
async function transpileWithEsbuild(filePath,
|
|
78
|
+
async function transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile) {
|
|
79
|
+
const isConfigFile = !isValueFile;
|
|
65
80
|
const entryFilePath = filePath.filePathAbsoluteFilesystem;
|
|
66
81
|
const entryFileDir = path_1.default.posix.dirname(entryFilePath);
|
|
67
82
|
const options = {
|
|
@@ -77,22 +92,26 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
77
92
|
'NEVER_EMITTED.js'),
|
|
78
93
|
logLevel: 'silent',
|
|
79
94
|
format: 'esm',
|
|
80
|
-
|
|
95
|
+
absWorkingDir: userRootDir,
|
|
96
|
+
// Disable tree-shaking to avoid dead-code elimination, so that unused imports aren't removed.
|
|
97
|
+
// Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
|
|
98
|
+
treeShaking: false,
|
|
81
99
|
minify: false,
|
|
82
|
-
metafile:
|
|
83
|
-
|
|
100
|
+
metafile: isConfigFile,
|
|
101
|
+
// We cannot bundle imports that are meant to be transformed
|
|
102
|
+
bundle: !importsAreTransformed
|
|
84
103
|
};
|
|
85
|
-
|
|
86
|
-
|
|
104
|
+
// Track dependencies
|
|
105
|
+
if (isConfigFile) {
|
|
87
106
|
options.packages = 'external';
|
|
88
107
|
options.plugins = [
|
|
89
108
|
{
|
|
90
|
-
name: 'vike:
|
|
109
|
+
name: 'vike:dependency-tracker',
|
|
91
110
|
setup(b) {
|
|
92
111
|
b.onLoad({ filter: /./ }, (args) => {
|
|
112
|
+
// We collect the dependency `args.path` in case the bulid fails (upon build error => error is thrown => no metafile)
|
|
93
113
|
let { path } = args;
|
|
94
114
|
path = (0, utils_js_1.toPosixPath)(path);
|
|
95
|
-
// We collect the dependency args.path in case it fails to build (upon build error => error is thrown => no metafile)
|
|
96
115
|
getVikeConfig_js_1.vikeConfigDependencies.add(path);
|
|
97
116
|
return undefined;
|
|
98
117
|
});
|
|
@@ -109,11 +128,6 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
109
128
|
}
|
|
110
129
|
];
|
|
111
130
|
}
|
|
112
|
-
else {
|
|
113
|
-
// Avoid dead-code elimination to ensure unused imports aren't removed.
|
|
114
|
-
// Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
|
|
115
|
-
options.treeShaking = false;
|
|
116
|
-
}
|
|
117
131
|
let result;
|
|
118
132
|
try {
|
|
119
133
|
result = await (0, esbuild_1.build)(options);
|
|
@@ -122,7 +136,8 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
122
136
|
await formatBuildErr(err, filePath);
|
|
123
137
|
throw err;
|
|
124
138
|
}
|
|
125
|
-
|
|
139
|
+
// Track dependencies
|
|
140
|
+
if (isConfigFile) {
|
|
126
141
|
(0, utils_js_1.assert)(result.metafile);
|
|
127
142
|
Object.keys(result.metafile.inputs).forEach((filePathRelative) => {
|
|
128
143
|
filePathRelative = (0, utils_js_1.toPosixPath)(filePathRelative);
|
|
@@ -135,7 +150,7 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
135
150
|
(0, utils_js_1.assert)(typeof code === 'string');
|
|
136
151
|
return code;
|
|
137
152
|
}
|
|
138
|
-
async function
|
|
153
|
+
async function executeTranspiledFile(filePath, code, fileImportsTransformed, isValueFile) {
|
|
139
154
|
const { filePathAbsoluteFilesystem, filePathRelativeToUserRootDir } = filePath;
|
|
140
155
|
// Alternative to using a temporary file: https://github.com/vitejs/vite/pull/13269
|
|
141
156
|
// - But seems to break source maps, so I don't think it's worth it
|
|
@@ -144,28 +159,35 @@ async function executeFile(filePath, code, fileImportsTransformed, isValueFile)
|
|
|
144
159
|
const clean = () => fs_1.default.unlinkSync(filePathTmp);
|
|
145
160
|
let fileExports = {};
|
|
146
161
|
try {
|
|
147
|
-
fileExports = await (
|
|
148
|
-
}
|
|
149
|
-
catch (err) {
|
|
150
|
-
triggerPrepareStackTrace(err);
|
|
151
|
-
const errIntroMsg = getErrIntroMsg('execute', filePath);
|
|
152
|
-
(0, utils_js_1.assert)((0, utils_js_1.isObject)(err));
|
|
153
|
-
execErrIntroMsg.set(err, errIntroMsg);
|
|
154
|
-
throw err;
|
|
162
|
+
fileExports = await executeFile(filePathTmp, filePath);
|
|
155
163
|
}
|
|
156
164
|
finally {
|
|
157
165
|
clean();
|
|
158
166
|
}
|
|
159
|
-
// Return a plain JavaScript object
|
|
160
|
-
// - import() returns `[Module: null prototype] { default: { onRenderClient: '...' }}`
|
|
161
|
-
// - We don't need this special object
|
|
162
|
-
fileExports = { ...fileExports };
|
|
163
167
|
if (fileImportsTransformed && !isValueFile) {
|
|
164
168
|
(0, utils_js_1.assert)(filePathRelativeToUserRootDir !== undefined);
|
|
165
169
|
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
166
170
|
assertImportsAreReExported(fileImportsTransformed, fileExports, filePathToShowToUser2);
|
|
167
171
|
}
|
|
168
|
-
return
|
|
172
|
+
return fileExports;
|
|
173
|
+
}
|
|
174
|
+
async function executeFile(filePathToExecuteAbsoluteFilesystem, filePathSourceFile) {
|
|
175
|
+
let fileExports = {};
|
|
176
|
+
try {
|
|
177
|
+
fileExports = await (0, import_1.import_)(filePathToExecuteAbsoluteFilesystem);
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
triggerPrepareStackTrace(err);
|
|
181
|
+
const errIntroMsg = getErrIntroMsg('execute', filePathSourceFile);
|
|
182
|
+
(0, utils_js_1.assert)((0, utils_js_1.isObject)(err));
|
|
183
|
+
execErrIntroMsg.set(err, errIntroMsg);
|
|
184
|
+
throw err;
|
|
185
|
+
}
|
|
186
|
+
// Return a plain JavaScript object:
|
|
187
|
+
// - import() returns `[Module: null prototype] { default: { onRenderClient: '...' }}`
|
|
188
|
+
// - We don't need this special object.
|
|
189
|
+
fileExports = { ...fileExports };
|
|
190
|
+
return fileExports;
|
|
169
191
|
}
|
|
170
192
|
const formatted = '_formatted';
|
|
171
193
|
function getConfigBuildErrorFormatted(err) {
|
|
@@ -197,10 +219,10 @@ function getConfigExecutionErrorIntroMsg(err) {
|
|
|
197
219
|
}
|
|
198
220
|
exports.getConfigExecutionErrorIntroMsg = getConfigExecutionErrorIntroMsg;
|
|
199
221
|
const tmpPrefix = `[build-`;
|
|
200
|
-
function getFilePathTmp(
|
|
201
|
-
(0, utils_js_1.assertPosixPath)(
|
|
202
|
-
const dirname = path_1.default.posix.dirname(
|
|
203
|
-
const filename = path_1.default.posix.basename(
|
|
222
|
+
function getFilePathTmp(filePathAbsoluteFilesystem) {
|
|
223
|
+
(0, utils_js_1.assertPosixPath)(filePathAbsoluteFilesystem);
|
|
224
|
+
const dirname = path_1.default.posix.dirname(filePathAbsoluteFilesystem);
|
|
225
|
+
const filename = path_1.default.posix.basename(filePathAbsoluteFilesystem);
|
|
204
226
|
// Syntax with semicolon `[build:${/*...*/}]` doesn't work on Windows: https://github.com/vikejs/vike/issues/800#issuecomment-1517329455
|
|
205
227
|
const tag = `${tmpPrefix}${(0, utils_js_1.getRandomId)(12)}]`;
|
|
206
228
|
const filePathTmp = path_1.default.posix.join(dirname, `${tag}${filename}.mjs`);
|
|
@@ -218,7 +240,7 @@ function assertImportsAreReExported(fileImportsTransformed, fileExports, filePat
|
|
|
218
240
|
Object.values(exportedStrings).forEach((exportVal) => {
|
|
219
241
|
if (typeof exportVal !== 'string')
|
|
220
242
|
return;
|
|
221
|
-
if (!(0,
|
|
243
|
+
if (!(0, transformImports_js_1.isImportData)(exportVal))
|
|
222
244
|
return;
|
|
223
245
|
const importString = exportVal;
|
|
224
246
|
fileImportsTransformed.forEach((fileImport) => {
|
|
@@ -256,6 +278,7 @@ function getExportedStrings(obj) {
|
|
|
256
278
|
return exportedStrings;
|
|
257
279
|
}
|
|
258
280
|
function isHeaderFile(filePath) {
|
|
281
|
+
(0, utils_js_1.assertPosixPath)(filePath);
|
|
259
282
|
const basenameParts = path_1.default.posix.basename(filePath).split('.');
|
|
260
283
|
return basenameParts.includes('h');
|
|
261
284
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PROJECT_VERSION = exports.projectInfo = void 0;
|
|
4
4
|
const assertSingleInstance_js_1 = require("./assertSingleInstance.js");
|
|
5
|
-
const PROJECT_VERSION = '0.4.159-commit-
|
|
5
|
+
const PROJECT_VERSION = '0.4.159-commit-a6bc208';
|
|
6
6
|
exports.PROJECT_VERSION = PROJECT_VERSION;
|
|
7
7
|
const projectInfo = {
|
|
8
8
|
projectName: 'Vike',
|
|
@@ -7,7 +7,7 @@ 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
9
|
import { isTmpFile, transpileAndExecuteFile } from './transpileAndExecuteFile.js';
|
|
10
|
-
import { parseImportData } from './
|
|
10
|
+
import { parseImportData } from './transformImports.js';
|
|
11
11
|
import { isConfigInvalid, isConfigInvalid_set } from '../../../../runtime/renderPage/isConfigInvalid.js';
|
|
12
12
|
import { getViteDevServer } from '../../../../runtime/globalContext.js';
|
|
13
13
|
import { logConfigError, logConfigErrorRecover } from '../../../shared/loggerNotProd.js';
|
|
@@ -85,7 +85,7 @@ async function loadInterfaceFiles(userRootDir, outDirRoot, isDev, extensions) {
|
|
|
85
85
|
let interfaceFilesByLocationId = {};
|
|
86
86
|
// Config files
|
|
87
87
|
await Promise.all(configFiles.map(async (filePath) => {
|
|
88
|
-
const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, []);
|
|
88
|
+
const { configFile, extendsConfigs } = await loadConfigFile(filePath, userRootDir, [], false);
|
|
89
89
|
const interfaceFile = getInterfaceFileFromConfigFile(configFile, false);
|
|
90
90
|
const locationId = getLocationId(filePath.filePathAbsoluteVite);
|
|
91
91
|
interfaceFilesByLocationId[locationId] = interfaceFilesByLocationId[locationId] ?? [];
|
|
@@ -840,10 +840,10 @@ function getConfigName(filePath) {
|
|
|
840
840
|
return configName;
|
|
841
841
|
}
|
|
842
842
|
}
|
|
843
|
-
async function loadConfigFile(configFilePath, userRootDir, visited) {
|
|
843
|
+
async function loadConfigFile(configFilePath, userRootDir, visited, isConfigOfExtension) {
|
|
844
844
|
const { filePathAbsoluteFilesystem } = configFilePath;
|
|
845
845
|
assertNoInfiniteLoop(visited, filePathAbsoluteFilesystem);
|
|
846
|
-
const { fileExports } = await transpileAndExecuteFile(configFilePath, false, userRootDir);
|
|
846
|
+
const { fileExports } = await transpileAndExecuteFile(configFilePath, false, userRootDir, isConfigOfExtension);
|
|
847
847
|
const { extendsConfigs, extendsFilePaths } = await loadExtendsConfigs(fileExports, configFilePath, userRootDir, [
|
|
848
848
|
...visited,
|
|
849
849
|
filePathAbsoluteFilesystem
|
|
@@ -870,7 +870,7 @@ async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir
|
|
|
870
870
|
const { importPath: importPath } = importData;
|
|
871
871
|
const filePathAbsoluteFilesystem = resolveImportPath(importData, configFilePath);
|
|
872
872
|
assertImportPath(filePathAbsoluteFilesystem, importData, configFilePath);
|
|
873
|
-
|
|
873
|
+
warnUserLandExtension(importPath, configFilePath);
|
|
874
874
|
// - filePathRelativeToUserRootDir has no functionality beyond nicer error messages for user
|
|
875
875
|
// - Using importPath would be visually nicer but it's ambigous => we rather pick filePathAbsoluteFilesystem for added clarity
|
|
876
876
|
const filePathRelativeToUserRootDir = determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRootDir);
|
|
@@ -885,7 +885,7 @@ async function loadExtendsConfigs(configFileExports, configFilePath, userRootDir
|
|
|
885
885
|
});
|
|
886
886
|
const extendsConfigs = [];
|
|
887
887
|
await Promise.all(extendsConfigFiles.map(async (configFilePath) => {
|
|
888
|
-
const result = await loadConfigFile(configFilePath, userRootDir, visited);
|
|
888
|
+
const result = await loadConfigFile(configFilePath, userRootDir, visited, true);
|
|
889
889
|
extendsConfigs.push(result.configFile);
|
|
890
890
|
extendsConfigs.push(...result.extendsConfigs);
|
|
891
891
|
}));
|
|
@@ -903,20 +903,8 @@ function determineFilePathRelativeToUserDir(filePathAbsoluteFilesystem, userRoot
|
|
|
903
903
|
filePathRelativeToUserRootDir = '/' + filePathRelativeToUserRootDir;
|
|
904
904
|
return filePathRelativeToUserRootDir;
|
|
905
905
|
}
|
|
906
|
-
function
|
|
907
|
-
|
|
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
|
-
}
|
|
906
|
+
function warnUserLandExtension(importPath, configFilePath) {
|
|
907
|
+
assertWarning(isNpmPackageImport(importPath), `${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.`, { onlyOnce: true });
|
|
920
908
|
}
|
|
921
909
|
function getExtendsImportData(configFileExports, configFilePath) {
|
|
922
910
|
const { filePathToShowToUser } = configFilePath;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { transformImports };
|
|
2
2
|
export { parseImportData };
|
|
3
3
|
export { isImportData };
|
|
4
4
|
export type { FileImport };
|
|
5
5
|
export type { ImportData };
|
|
6
|
-
export { isVikeRealImport };
|
|
7
6
|
type FileImport = {
|
|
8
7
|
importStatementCode: string;
|
|
9
8
|
importString: string;
|
|
10
9
|
importLocalName: string;
|
|
11
10
|
};
|
|
12
|
-
declare function
|
|
11
|
+
declare function transformImports(code: string, filePathToShowToUser2: string, skipWarnings?: true): {
|
|
13
12
|
noTransformation: true;
|
|
14
13
|
} | {
|
|
15
14
|
noTransformation: false;
|
|
@@ -42,4 +41,3 @@ declare module 'estree' {
|
|
|
42
41
|
end: number;
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
|
-
declare function isVikeRealImport(code: string, posStart: number): boolean;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { transformImports };
|
|
2
2
|
export { parseImportData };
|
|
3
3
|
export { isImportData };
|
|
4
|
-
// For ./transformImportStatements.spec.ts
|
|
5
|
-
export { isVikeRealImport };
|
|
6
4
|
// Playground: https://github.com/brillout/acorn-playground
|
|
7
5
|
// Import attributes support: https://github.com/acornjs/acorn/issues/983
|
|
8
6
|
// - Isn't stage 4 yet: https://github.com/tc39/proposal-import-attributes
|
|
9
7
|
import { parse } from 'acorn';
|
|
10
8
|
import { assert, assertUsage, assertWarning, styleFileRE } from '../../../utils.js';
|
|
11
9
|
import pc from '@brillout/picocolors';
|
|
12
|
-
function
|
|
10
|
+
function transformImports(code, filePathToShowToUser2,
|
|
11
|
+
// For ./transformImports.spec.ts
|
|
12
|
+
skipWarnings) {
|
|
13
13
|
const spliceOperations = [];
|
|
14
14
|
const fileImportsTransformed = [];
|
|
15
15
|
// Performance trick
|
|
@@ -23,9 +23,29 @@ function transformImportStatements(code, filePathToShowToUser2) {
|
|
|
23
23
|
return;
|
|
24
24
|
const importPath = node.source.value;
|
|
25
25
|
assert(typeof importPath === 'string');
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
// - This doesn't work. To make it work we would need to run esbuild twice: esbuild for TypeScript to JavaScript => transformImports() => esbuild for bundling.
|
|
27
|
+
// - Or we use an esbuild plugin to apply transformImports(). 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 transformImports()?
|
|
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
|
+
});
|
|
28
46
|
return;
|
|
47
|
+
}
|
|
48
|
+
const { start, end } = node;
|
|
29
49
|
const importStatementCode = code.slice(start, end);
|
|
30
50
|
// No variable imported
|
|
31
51
|
if (node.specifiers.length === 0) {
|
|
@@ -41,10 +61,12 @@ function transformImportStatements(code, filePathToShowToUser2) {
|
|
|
41
61
|
`As explained in https://vike.dev/header-file the following import in ${filePathToShowToUser2} has no effect:`,
|
|
42
62
|
quote
|
|
43
63
|
].join('\n');
|
|
44
|
-
if (!
|
|
45
|
-
|
|
64
|
+
if (!skipWarnings) {
|
|
65
|
+
if (!isWarning) {
|
|
66
|
+
assertUsage(false, errMsg);
|
|
67
|
+
}
|
|
68
|
+
assertWarning(false, errMsg, { onlyOnce: true });
|
|
46
69
|
}
|
|
47
|
-
assertWarning(false, errMsg, { onlyOnce: true });
|
|
48
70
|
}
|
|
49
71
|
let replacement = '';
|
|
50
72
|
node.specifiers.forEach((specifier) => {
|
|
@@ -146,7 +168,7 @@ function spliceMany(str, operations) {
|
|
|
146
168
|
.join('');
|
|
147
169
|
endPrev = end;
|
|
148
170
|
});
|
|
149
|
-
strMod += str.slice(endPrev, str.length
|
|
171
|
+
strMod += str.slice(endPrev, str.length);
|
|
150
172
|
return strMod;
|
|
151
173
|
}
|
|
152
174
|
function indent(str) {
|
|
@@ -155,10 +177,3 @@ function indent(str) {
|
|
|
155
177
|
.map((s) => ` ${s}`)
|
|
156
178
|
.join('\n');
|
|
157
179
|
}
|
|
158
|
-
function isVikeRealImport(code, posStart) {
|
|
159
|
-
let posEnd = code.indexOf('\n', posStart);
|
|
160
|
-
if (posEnd === -1)
|
|
161
|
-
posEnd = code.length;
|
|
162
|
-
const lineEnd = code.slice(posStart, posEnd);
|
|
163
|
-
return lineEnd.includes('@vike-real-import');
|
|
164
|
-
}
|
|
@@ -4,7 +4,7 @@ export { getConfigExecutionErrorIntroMsg as getConfigExecutionErrorIntroMsg };
|
|
|
4
4
|
export { isTmpFile };
|
|
5
5
|
import 'source-map-support/register.js';
|
|
6
6
|
import type { FilePathResolved } from '../../../../../shared/page-configs/PageConfig.js';
|
|
7
|
-
declare function transpileAndExecuteFile(filePath: FilePathResolved, isValueFile: boolean, userRootDir: string): Promise<{
|
|
7
|
+
declare function transpileAndExecuteFile(filePath: FilePathResolved, isValueFile: boolean, userRootDir: string, isConfigOfExtension?: boolean): Promise<{
|
|
8
8
|
fileExports: Record<string, unknown>;
|
|
9
9
|
}>;
|
|
10
10
|
declare function getConfigBuildErrorFormatted(err: unknown): null | string;
|
|
@@ -8,49 +8,63 @@ import path from 'path';
|
|
|
8
8
|
import pc from '@brillout/picocolors';
|
|
9
9
|
import { import_ } from '@brillout/import';
|
|
10
10
|
import { assertPosixPath, getRandomId, assertIsNotProductionRuntime, assert, unique, assertWarning, isObject, toPosixPath } from '../../../utils.js';
|
|
11
|
-
import { isImportData,
|
|
11
|
+
import { isImportData, transformImports } from './transformImports.js';
|
|
12
12
|
import { vikeConfigDependencies } from './getVikeConfig.js';
|
|
13
13
|
import 'source-map-support/register.js';
|
|
14
14
|
import { getConfigFileExport } from './getConfigFileExport.js';
|
|
15
15
|
assertIsNotProductionRuntime();
|
|
16
|
-
async function transpileAndExecuteFile(filePath, isValueFile, userRootDir) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
async function transpileAndExecuteFile(filePath, isValueFile, userRootDir, isConfigOfExtension = false) {
|
|
17
|
+
if (isConfigOfExtension) {
|
|
18
|
+
const fileExports = await executeFile(filePath.filePathAbsoluteFilesystem, filePath);
|
|
19
|
+
if (isHeaderFile(filePath.filePathAbsoluteFilesystem)) {
|
|
20
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
21
|
+
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 });
|
|
22
|
+
}
|
|
23
|
+
return { fileExports };
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const { code, fileImportsTransformed } = await transpileFile(filePath, isValueFile, userRootDir);
|
|
27
|
+
const fileExports = await executeTranspiledFile(filePath, code, fileImportsTransformed, isValueFile);
|
|
28
|
+
return { fileExports };
|
|
29
|
+
}
|
|
20
30
|
}
|
|
21
31
|
async function transpileFile(filePath, isValueFile, userRootDir) {
|
|
22
32
|
const { filePathAbsoluteFilesystem } = filePath;
|
|
33
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
23
34
|
assertPosixPath(filePathAbsoluteFilesystem);
|
|
24
35
|
vikeConfigDependencies.add(filePathAbsoluteFilesystem);
|
|
25
|
-
|
|
36
|
+
const importsAreTransformed = !isValueFile;
|
|
37
|
+
let code = await transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile);
|
|
26
38
|
let fileImportsTransformed = null;
|
|
27
|
-
{
|
|
28
|
-
const res =
|
|
39
|
+
if (importsAreTransformed) {
|
|
40
|
+
const res = transformImports_(code, filePath);
|
|
29
41
|
if (res) {
|
|
30
42
|
code = res.code;
|
|
31
43
|
fileImportsTransformed = res.fileImportsTransformed;
|
|
32
44
|
}
|
|
33
45
|
}
|
|
46
|
+
else {
|
|
47
|
+
if (isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
48
|
+
if (isValueFile) {
|
|
49
|
+
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 });
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
assert(false);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
34
56
|
return { code, fileImportsTransformed };
|
|
35
57
|
}
|
|
36
|
-
function
|
|
37
|
-
// Do we need to remove the imports?
|
|
58
|
+
function transformImports_(codeOriginal, filePath) {
|
|
38
59
|
const { filePathAbsoluteFilesystem } = filePath;
|
|
39
60
|
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const isPageConfigFile = !isValueFile;
|
|
43
|
-
if (!isHeader && !isPageConfigFile) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
assertWarning(isPageConfigFile, `${filePathToShowToUser2} 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 });
|
|
47
|
-
// Remove the imports
|
|
48
|
-
const res = transformImportStatements(codeOriginal, filePathToShowToUser2);
|
|
61
|
+
// Replace import statements with import strings
|
|
62
|
+
const res = transformImports(codeOriginal, filePathToShowToUser2);
|
|
49
63
|
if (res.noTransformation) {
|
|
50
64
|
return null;
|
|
51
65
|
}
|
|
52
66
|
const { code, fileImportsTransformed } = res;
|
|
53
|
-
if (!
|
|
67
|
+
if (!isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
54
68
|
const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser2);
|
|
55
69
|
assertWarning(false, `Rename ${filePathToShowToUser2} to ${filePathCorrect}, see https://vike.dev/header-file`, {
|
|
56
70
|
onlyOnce: true
|
|
@@ -58,7 +72,8 @@ function transformImports(codeOriginal, filePath, isValueFile) {
|
|
|
58
72
|
}
|
|
59
73
|
return { code, fileImportsTransformed };
|
|
60
74
|
}
|
|
61
|
-
async function transpileWithEsbuild(filePath,
|
|
75
|
+
async function transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile) {
|
|
76
|
+
const isConfigFile = !isValueFile;
|
|
62
77
|
const entryFilePath = filePath.filePathAbsoluteFilesystem;
|
|
63
78
|
const entryFileDir = path.posix.dirname(entryFilePath);
|
|
64
79
|
const options = {
|
|
@@ -74,22 +89,26 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
74
89
|
'NEVER_EMITTED.js'),
|
|
75
90
|
logLevel: 'silent',
|
|
76
91
|
format: 'esm',
|
|
77
|
-
|
|
92
|
+
absWorkingDir: userRootDir,
|
|
93
|
+
// Disable tree-shaking to avoid dead-code elimination, so that unused imports aren't removed.
|
|
94
|
+
// Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
|
|
95
|
+
treeShaking: false,
|
|
78
96
|
minify: false,
|
|
79
|
-
metafile:
|
|
80
|
-
|
|
97
|
+
metafile: isConfigFile,
|
|
98
|
+
// We cannot bundle imports that are meant to be transformed
|
|
99
|
+
bundle: !importsAreTransformed
|
|
81
100
|
};
|
|
82
|
-
|
|
83
|
-
|
|
101
|
+
// Track dependencies
|
|
102
|
+
if (isConfigFile) {
|
|
84
103
|
options.packages = 'external';
|
|
85
104
|
options.plugins = [
|
|
86
105
|
{
|
|
87
|
-
name: 'vike:
|
|
106
|
+
name: 'vike:dependency-tracker',
|
|
88
107
|
setup(b) {
|
|
89
108
|
b.onLoad({ filter: /./ }, (args) => {
|
|
109
|
+
// We collect the dependency `args.path` in case the bulid fails (upon build error => error is thrown => no metafile)
|
|
90
110
|
let { path } = args;
|
|
91
111
|
path = toPosixPath(path);
|
|
92
|
-
// We collect the dependency args.path in case it fails to build (upon build error => error is thrown => no metafile)
|
|
93
112
|
vikeConfigDependencies.add(path);
|
|
94
113
|
return undefined;
|
|
95
114
|
});
|
|
@@ -106,11 +125,6 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
106
125
|
}
|
|
107
126
|
];
|
|
108
127
|
}
|
|
109
|
-
else {
|
|
110
|
-
// Avoid dead-code elimination to ensure unused imports aren't removed.
|
|
111
|
-
// Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
|
|
112
|
-
options.treeShaking = false;
|
|
113
|
-
}
|
|
114
128
|
let result;
|
|
115
129
|
try {
|
|
116
130
|
result = await build(options);
|
|
@@ -119,7 +133,8 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
119
133
|
await formatBuildErr(err, filePath);
|
|
120
134
|
throw err;
|
|
121
135
|
}
|
|
122
|
-
|
|
136
|
+
// Track dependencies
|
|
137
|
+
if (isConfigFile) {
|
|
123
138
|
assert(result.metafile);
|
|
124
139
|
Object.keys(result.metafile.inputs).forEach((filePathRelative) => {
|
|
125
140
|
filePathRelative = toPosixPath(filePathRelative);
|
|
@@ -132,7 +147,7 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
132
147
|
assert(typeof code === 'string');
|
|
133
148
|
return code;
|
|
134
149
|
}
|
|
135
|
-
async function
|
|
150
|
+
async function executeTranspiledFile(filePath, code, fileImportsTransformed, isValueFile) {
|
|
136
151
|
const { filePathAbsoluteFilesystem, filePathRelativeToUserRootDir } = filePath;
|
|
137
152
|
// Alternative to using a temporary file: https://github.com/vitejs/vite/pull/13269
|
|
138
153
|
// - But seems to break source maps, so I don't think it's worth it
|
|
@@ -141,28 +156,35 @@ async function executeFile(filePath, code, fileImportsTransformed, isValueFile)
|
|
|
141
156
|
const clean = () => fs.unlinkSync(filePathTmp);
|
|
142
157
|
let fileExports = {};
|
|
143
158
|
try {
|
|
144
|
-
fileExports = await
|
|
145
|
-
}
|
|
146
|
-
catch (err) {
|
|
147
|
-
triggerPrepareStackTrace(err);
|
|
148
|
-
const errIntroMsg = getErrIntroMsg('execute', filePath);
|
|
149
|
-
assert(isObject(err));
|
|
150
|
-
execErrIntroMsg.set(err, errIntroMsg);
|
|
151
|
-
throw err;
|
|
159
|
+
fileExports = await executeFile(filePathTmp, filePath);
|
|
152
160
|
}
|
|
153
161
|
finally {
|
|
154
162
|
clean();
|
|
155
163
|
}
|
|
156
|
-
// Return a plain JavaScript object
|
|
157
|
-
// - import() returns `[Module: null prototype] { default: { onRenderClient: '...' }}`
|
|
158
|
-
// - We don't need this special object
|
|
159
|
-
fileExports = { ...fileExports };
|
|
160
164
|
if (fileImportsTransformed && !isValueFile) {
|
|
161
165
|
assert(filePathRelativeToUserRootDir !== undefined);
|
|
162
166
|
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
163
167
|
assertImportsAreReExported(fileImportsTransformed, fileExports, filePathToShowToUser2);
|
|
164
168
|
}
|
|
165
|
-
return
|
|
169
|
+
return fileExports;
|
|
170
|
+
}
|
|
171
|
+
async function executeFile(filePathToExecuteAbsoluteFilesystem, filePathSourceFile) {
|
|
172
|
+
let fileExports = {};
|
|
173
|
+
try {
|
|
174
|
+
fileExports = await import_(filePathToExecuteAbsoluteFilesystem);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
triggerPrepareStackTrace(err);
|
|
178
|
+
const errIntroMsg = getErrIntroMsg('execute', filePathSourceFile);
|
|
179
|
+
assert(isObject(err));
|
|
180
|
+
execErrIntroMsg.set(err, errIntroMsg);
|
|
181
|
+
throw err;
|
|
182
|
+
}
|
|
183
|
+
// Return a plain JavaScript object:
|
|
184
|
+
// - import() returns `[Module: null prototype] { default: { onRenderClient: '...' }}`
|
|
185
|
+
// - We don't need this special object.
|
|
186
|
+
fileExports = { ...fileExports };
|
|
187
|
+
return fileExports;
|
|
166
188
|
}
|
|
167
189
|
const formatted = '_formatted';
|
|
168
190
|
function getConfigBuildErrorFormatted(err) {
|
|
@@ -192,10 +214,10 @@ function getConfigExecutionErrorIntroMsg(err) {
|
|
|
192
214
|
return errIntroMsg ?? null;
|
|
193
215
|
}
|
|
194
216
|
const tmpPrefix = `[build-`;
|
|
195
|
-
function getFilePathTmp(
|
|
196
|
-
assertPosixPath(
|
|
197
|
-
const dirname = path.posix.dirname(
|
|
198
|
-
const filename = path.posix.basename(
|
|
217
|
+
function getFilePathTmp(filePathAbsoluteFilesystem) {
|
|
218
|
+
assertPosixPath(filePathAbsoluteFilesystem);
|
|
219
|
+
const dirname = path.posix.dirname(filePathAbsoluteFilesystem);
|
|
220
|
+
const filename = path.posix.basename(filePathAbsoluteFilesystem);
|
|
199
221
|
// Syntax with semicolon `[build:${/*...*/}]` doesn't work on Windows: https://github.com/vikejs/vike/issues/800#issuecomment-1517329455
|
|
200
222
|
const tag = `${tmpPrefix}${getRandomId(12)}]`;
|
|
201
223
|
const filePathTmp = path.posix.join(dirname, `${tag}${filename}.mjs`);
|
|
@@ -250,6 +272,7 @@ function getExportedStrings(obj) {
|
|
|
250
272
|
return exportedStrings;
|
|
251
273
|
}
|
|
252
274
|
function isHeaderFile(filePath) {
|
|
275
|
+
assertPosixPath(filePath);
|
|
253
276
|
const basenameParts = path.posix.basename(filePath).split('.');
|
|
254
277
|
return basenameParts.includes('h');
|
|
255
278
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { projectInfo };
|
|
2
2
|
export { PROJECT_VERSION };
|
|
3
|
-
declare const PROJECT_VERSION: "0.4.159-commit-
|
|
3
|
+
declare const PROJECT_VERSION: "0.4.159-commit-a6bc208";
|
|
4
4
|
declare const projectInfo: {
|
|
5
5
|
projectName: "Vike";
|
|
6
|
-
projectVersion: "0.4.159-commit-
|
|
6
|
+
projectVersion: "0.4.159-commit-a6bc208";
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { projectInfo };
|
|
2
2
|
export { PROJECT_VERSION };
|
|
3
3
|
import { onProjectInfo } from './assertSingleInstance.js';
|
|
4
|
-
const PROJECT_VERSION = '0.4.159-commit-
|
|
4
|
+
const PROJECT_VERSION = '0.4.159-commit-a6bc208';
|
|
5
5
|
const projectInfo = {
|
|
6
6
|
projectName: 'Vike',
|
|
7
7
|
projectVersion: PROJECT_VERSION
|