vike 0.4.159-commit-6bcb2fd → 0.4.159-commit-0424983
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 +7 -7
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → transformImports.js} +43 -12
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +78 -59
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +5 -5
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.d.ts → transformImports.d.ts} +5 -5
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/{replaceImportStatements.js → transformImports.js} +42 -11
- 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 +77 -58
- 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
|
|
@@ -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
|
}));
|
|
@@ -941,7 +941,7 @@ function getExtendsImportData(configFileExports, configFilePath) {
|
|
|
941
941
|
(0, utils_js_1.assertUsage)(false, wrongUsage);
|
|
942
942
|
}
|
|
943
943
|
const extendsImportData = extendList.map((importDataSerialized) => {
|
|
944
|
-
const importData = (0,
|
|
944
|
+
const importData = (0, transformImports_js_1.parseImportData)(importDataSerialized);
|
|
945
945
|
(0, utils_js_1.assertUsage)(importData, wrongUsage);
|
|
946
946
|
return importData;
|
|
947
947
|
});
|
|
@@ -3,22 +3,51 @@ 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.isImportData = exports.parseImportData = exports.
|
|
6
|
+
exports.isImportData = exports.parseImportData = exports.transformImports = void 0;
|
|
7
7
|
// Playground: https://github.com/brillout/acorn-playground
|
|
8
|
+
// Import attributes support: https://github.com/acornjs/acorn/issues/983
|
|
9
|
+
// - Isn't stage 4 yet: https://github.com/tc39/proposal-import-attributes
|
|
8
10
|
const acorn_1 = require("acorn");
|
|
9
11
|
const utils_js_1 = require("../../../utils.js");
|
|
10
12
|
const picocolors_1 = __importDefault(require("@brillout/picocolors"));
|
|
11
|
-
function
|
|
13
|
+
function transformImports(code, filePathToShowToUser2,
|
|
14
|
+
// For ./transformImports.spec.ts
|
|
15
|
+
skipWarnings) {
|
|
12
16
|
const spliceOperations = [];
|
|
13
|
-
const
|
|
17
|
+
const fileImportsTransformed = [];
|
|
18
|
+
// Performance trick
|
|
19
|
+
if (!code.includes('import'))
|
|
20
|
+
return { noTransformation: true };
|
|
14
21
|
const imports = getImports(code);
|
|
15
22
|
if (imports.length === 0)
|
|
16
|
-
return {
|
|
23
|
+
return { noTransformation: true };
|
|
17
24
|
imports.forEach((node) => {
|
|
18
25
|
if (node.type !== 'ImportDeclaration')
|
|
19
26
|
return;
|
|
20
27
|
const importPath = node.source.value;
|
|
21
28
|
(0, utils_js_1.assert)(typeof importPath === 'string');
|
|
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 seems to work well with the latest TypeScript versions: TypeScript doesn't complain upon `with { type: 'unknown-to-typescript' }` and go-to-definition & types are preserved.
|
|
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
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
22
51
|
const { start, end } = node;
|
|
23
52
|
const importStatementCode = code.slice(start, end);
|
|
24
53
|
// No variable imported
|
|
@@ -32,13 +61,15 @@ function replaceImportStatements(code, filePathToShowToUser) {
|
|
|
32
61
|
quote = picocolors_1.default.bold(picocolors_1.default.red(quote));
|
|
33
62
|
}
|
|
34
63
|
const errMsg = [
|
|
35
|
-
`As explained in https://vike.dev/header-file the following import in ${
|
|
64
|
+
`As explained in https://vike.dev/header-file the following import in ${filePathToShowToUser2} has no effect:`,
|
|
36
65
|
quote
|
|
37
66
|
].join('\n');
|
|
38
|
-
if (!
|
|
39
|
-
(
|
|
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 });
|
|
40
72
|
}
|
|
41
|
-
(0, utils_js_1.assertWarning)(false, errMsg, { onlyOnce: true });
|
|
42
73
|
}
|
|
43
74
|
let replacement = '';
|
|
44
75
|
node.specifiers.forEach((specifier) => {
|
|
@@ -60,7 +91,7 @@ function replaceImportStatements(code, filePathToShowToUser) {
|
|
|
60
91
|
})();
|
|
61
92
|
const importString = serializeImportData({ importPath, exportName, importStringWasGenerated: true });
|
|
62
93
|
replacement += `const ${importLocalName} = '${importString}';`;
|
|
63
|
-
|
|
94
|
+
fileImportsTransformed.push({
|
|
64
95
|
importStatementCode,
|
|
65
96
|
importString,
|
|
66
97
|
importLocalName
|
|
@@ -73,9 +104,9 @@ function replaceImportStatements(code, filePathToShowToUser) {
|
|
|
73
104
|
});
|
|
74
105
|
});
|
|
75
106
|
const codeMod = spliceMany(code, spliceOperations);
|
|
76
|
-
return { code: codeMod,
|
|
107
|
+
return { code: codeMod, fileImportsTransformed, noTransformation: false };
|
|
77
108
|
}
|
|
78
|
-
exports.
|
|
109
|
+
exports.transformImports = transformImports;
|
|
79
110
|
function getImports(code) {
|
|
80
111
|
const { body } = (0, acorn_1.parse)(code, {
|
|
81
112
|
ecmaVersion: 'latest',
|
|
@@ -143,7 +174,7 @@ function spliceMany(str, operations) {
|
|
|
143
174
|
.join('');
|
|
144
175
|
endPrev = end;
|
|
145
176
|
});
|
|
146
|
-
strMod += str.slice(endPrev, str.length
|
|
177
|
+
strMod += str.slice(endPrev, str.length);
|
|
147
178
|
return strMod;
|
|
148
179
|
}
|
|
149
180
|
function indent(str) {
|
|
@@ -10,57 +10,66 @@ 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
|
-
const { code,
|
|
20
|
-
const { fileExports } = await executeFile(filePath, code,
|
|
18
|
+
async function transpileAndExecuteFile(filePath, isValueFile, userRootDir, isConfigOfExtension = false) {
|
|
19
|
+
const { code, fileImportsTransformed } = await transpileFile(filePath, isValueFile, userRootDir, isConfigOfExtension);
|
|
20
|
+
const { fileExports } = await executeFile(filePath, code, fileImportsTransformed, isValueFile);
|
|
21
21
|
return { fileExports };
|
|
22
22
|
}
|
|
23
23
|
exports.transpileAndExecuteFile = transpileAndExecuteFile;
|
|
24
|
-
async function transpileFile(filePath, isValueFile, userRootDir) {
|
|
24
|
+
async function transpileFile(filePath, isValueFile, userRootDir, isConfigOfExtension) {
|
|
25
25
|
const { filePathAbsoluteFilesystem } = filePath;
|
|
26
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
26
27
|
(0, utils_js_1.assertPosixPath)(filePathAbsoluteFilesystem);
|
|
27
28
|
getVikeConfig_js_1.vikeConfigDependencies.add(filePathAbsoluteFilesystem);
|
|
28
|
-
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
const importsAreTransformed = !isConfigOfExtension && !isValueFile;
|
|
30
|
+
let code = await transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile);
|
|
31
|
+
let fileImportsTransformed = null;
|
|
32
|
+
if (importsAreTransformed) {
|
|
33
|
+
const res = transformImports_(code, filePath);
|
|
32
34
|
if (res) {
|
|
33
35
|
code = res.code;
|
|
34
|
-
|
|
36
|
+
fileImportsTransformed = res.fileImportsTransformed;
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
else {
|
|
40
|
+
if (isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
41
|
+
if (isValueFile) {
|
|
42
|
+
(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 });
|
|
43
|
+
}
|
|
44
|
+
else if (isConfigOfExtension) {
|
|
45
|
+
(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 });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
(0, utils_js_1.assert)(false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
return { code, fileImportsTransformed };
|
|
53
|
+
}
|
|
54
|
+
function transformImports_(codeOriginal, filePath) {
|
|
55
|
+
const { filePathAbsoluteFilesystem } = filePath;
|
|
56
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
57
|
+
// Replace import statements with import strings
|
|
58
|
+
const res = (0, transformImports_js_1.transformImports)(codeOriginal, filePathToShowToUser2);
|
|
59
|
+
if (res.noTransformation) {
|
|
52
60
|
return null;
|
|
53
61
|
}
|
|
54
|
-
const { code,
|
|
55
|
-
if (!
|
|
56
|
-
const filePathCorrect = appendHeaderFileExtension(
|
|
57
|
-
(0, utils_js_1.assertWarning)(false, `Rename ${
|
|
62
|
+
const { code, fileImportsTransformed } = res;
|
|
63
|
+
if (!isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
64
|
+
const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser2);
|
|
65
|
+
(0, utils_js_1.assertWarning)(false, `Rename ${filePathToShowToUser2} to ${filePathCorrect}, see https://vike.dev/header-file`, {
|
|
58
66
|
onlyOnce: true
|
|
59
67
|
});
|
|
60
68
|
}
|
|
61
|
-
return { code,
|
|
69
|
+
return { code, fileImportsTransformed };
|
|
62
70
|
}
|
|
63
|
-
async function transpileWithEsbuild(filePath,
|
|
71
|
+
async function transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile) {
|
|
72
|
+
const isConfigFile = !isValueFile;
|
|
64
73
|
const entryFilePath = filePath.filePathAbsoluteFilesystem;
|
|
65
74
|
const entryFileDir = path_1.default.posix.dirname(entryFilePath);
|
|
66
75
|
const options = {
|
|
@@ -76,22 +85,26 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
76
85
|
'NEVER_EMITTED.js'),
|
|
77
86
|
logLevel: 'silent',
|
|
78
87
|
format: 'esm',
|
|
79
|
-
|
|
88
|
+
absWorkingDir: userRootDir,
|
|
89
|
+
// Disable tree-shaking to avoid dead-code elimination, so that unused imports aren't removed.
|
|
90
|
+
// Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
|
|
91
|
+
treeShaking: false,
|
|
80
92
|
minify: false,
|
|
81
|
-
metafile:
|
|
82
|
-
|
|
93
|
+
metafile: isConfigFile,
|
|
94
|
+
// We cannot bundle imports that are meant to be transformed
|
|
95
|
+
bundle: !importsAreTransformed
|
|
83
96
|
};
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
// Track dependencies
|
|
98
|
+
if (isConfigFile) {
|
|
86
99
|
options.packages = 'external';
|
|
87
100
|
options.plugins = [
|
|
88
101
|
{
|
|
89
|
-
name: 'vike:
|
|
102
|
+
name: 'vike:dependency-tracker',
|
|
90
103
|
setup(b) {
|
|
91
104
|
b.onLoad({ filter: /./ }, (args) => {
|
|
105
|
+
// We collect the dependency `args.path` in case the bulid fails (upon build error => error is thrown => no metafile)
|
|
92
106
|
let { path } = args;
|
|
93
107
|
path = (0, utils_js_1.toPosixPath)(path);
|
|
94
|
-
// We collect the dependency args.path in case it fails to build (upon build error => error is thrown => no metafile)
|
|
95
108
|
getVikeConfig_js_1.vikeConfigDependencies.add(path);
|
|
96
109
|
return undefined;
|
|
97
110
|
});
|
|
@@ -108,11 +121,6 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
108
121
|
}
|
|
109
122
|
];
|
|
110
123
|
}
|
|
111
|
-
else {
|
|
112
|
-
// Avoid dead-code elimination to ensure unused imports aren't removed.
|
|
113
|
-
// Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
|
|
114
|
-
options.treeShaking = false;
|
|
115
|
-
}
|
|
116
124
|
let result;
|
|
117
125
|
try {
|
|
118
126
|
result = await (0, esbuild_1.build)(options);
|
|
@@ -121,7 +129,8 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
121
129
|
await formatBuildErr(err, filePath);
|
|
122
130
|
throw err;
|
|
123
131
|
}
|
|
124
|
-
|
|
132
|
+
// Track dependencies
|
|
133
|
+
if (isConfigFile) {
|
|
125
134
|
(0, utils_js_1.assert)(result.metafile);
|
|
126
135
|
Object.keys(result.metafile.inputs).forEach((filePathRelative) => {
|
|
127
136
|
filePathRelative = (0, utils_js_1.toPosixPath)(filePathRelative);
|
|
@@ -134,7 +143,7 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
134
143
|
(0, utils_js_1.assert)(typeof code === 'string');
|
|
135
144
|
return code;
|
|
136
145
|
}
|
|
137
|
-
async function executeFile(filePath, code,
|
|
146
|
+
async function executeFile(filePath, code, fileImportsTransformed, isValueFile) {
|
|
138
147
|
const { filePathAbsoluteFilesystem, filePathRelativeToUserRootDir } = filePath;
|
|
139
148
|
// Alternative to using a temporary file: https://github.com/vitejs/vite/pull/13269
|
|
140
149
|
// - But seems to break source maps, so I don't think it's worth it
|
|
@@ -159,10 +168,10 @@ async function executeFile(filePath, code, fileImports, isValueFile) {
|
|
|
159
168
|
// - import() returns `[Module: null prototype] { default: { onRenderClient: '...' }}`
|
|
160
169
|
// - We don't need this special object
|
|
161
170
|
fileExports = { ...fileExports };
|
|
162
|
-
if (
|
|
171
|
+
if (fileImportsTransformed && !isValueFile) {
|
|
163
172
|
(0, utils_js_1.assert)(filePathRelativeToUserRootDir !== undefined);
|
|
164
|
-
const
|
|
165
|
-
assertImportsAreReExported(
|
|
173
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
174
|
+
assertImportsAreReExported(fileImportsTransformed, fileExports, filePathToShowToUser2);
|
|
166
175
|
}
|
|
167
176
|
return { fileExports };
|
|
168
177
|
}
|
|
@@ -211,29 +220,29 @@ function isTmpFile(filePath) {
|
|
|
211
220
|
return fileName.startsWith(tmpPrefix);
|
|
212
221
|
}
|
|
213
222
|
exports.isTmpFile = isTmpFile;
|
|
214
|
-
function assertImportsAreReExported(
|
|
215
|
-
const fileExport = (0, getConfigFileExport_js_1.getConfigFileExport)(fileExports,
|
|
223
|
+
function assertImportsAreReExported(fileImportsTransformed, fileExports, filePathToShowToUser2) {
|
|
224
|
+
const fileExport = (0, getConfigFileExport_js_1.getConfigFileExport)(fileExports, filePathToShowToUser2);
|
|
216
225
|
const exportedStrings = getExportedStrings(fileExport);
|
|
217
226
|
Object.values(exportedStrings).forEach((exportVal) => {
|
|
218
227
|
if (typeof exportVal !== 'string')
|
|
219
228
|
return;
|
|
220
|
-
if (!(0,
|
|
229
|
+
if (!(0, transformImports_js_1.isImportData)(exportVal))
|
|
221
230
|
return;
|
|
222
231
|
const importString = exportVal;
|
|
223
|
-
|
|
232
|
+
fileImportsTransformed.forEach((fileImport) => {
|
|
224
233
|
if (fileImport.importString === importString) {
|
|
225
234
|
fileImport.isReExported = true;
|
|
226
235
|
}
|
|
227
236
|
});
|
|
228
237
|
});
|
|
229
|
-
const
|
|
230
|
-
if (
|
|
238
|
+
const fileImportsTransformedUnused = fileImportsTransformed.filter((fi) => !fi.isReExported);
|
|
239
|
+
if (fileImportsTransformedUnused.length === 0)
|
|
231
240
|
return;
|
|
232
|
-
const importStatements = (0, utils_js_1.unique)(
|
|
233
|
-
const importNamesUnused =
|
|
234
|
-
const singular =
|
|
235
|
-
(0, utils_js_1.assertWarning)(
|
|
236
|
-
`${
|
|
241
|
+
const importStatements = (0, utils_js_1.unique)(fileImportsTransformedUnused.map((fi) => fi.importStatementCode));
|
|
242
|
+
const importNamesUnused = fileImportsTransformedUnused.map((fi) => picocolors_1.default.cyan(fi.importLocalName)).join(', ');
|
|
243
|
+
const singular = fileImportsTransformedUnused.length === 1;
|
|
244
|
+
(0, utils_js_1.assertWarning)(fileImportsTransformedUnused.length === 0, [
|
|
245
|
+
`${filePathToShowToUser2} imports the following:`,
|
|
237
246
|
...importStatements.map((s) => picocolors_1.default.cyan(` ${s}`)),
|
|
238
247
|
`But the import${singular ? '' : 's'} ${importNamesUnused} ${singular ? "isn't" : "aren't"} re-exported at ${picocolors_1.default.cyan('export default { ... }')} and therefore ${singular ? 'has' : 'have'} no effect, see explanation at https://vike.dev/header-file`
|
|
239
248
|
].join('\n'), { onlyOnce: true });
|
|
@@ -255,6 +264,7 @@ function getExportedStrings(obj) {
|
|
|
255
264
|
return exportedStrings;
|
|
256
265
|
}
|
|
257
266
|
function isHeaderFile(filePath) {
|
|
267
|
+
(0, utils_js_1.assertPosixPath)(filePath);
|
|
258
268
|
const basenameParts = path_1.default.posix.basename(filePath).split('.');
|
|
259
269
|
return basenameParts.includes('h');
|
|
260
270
|
}
|
|
@@ -275,10 +285,19 @@ function triggerPrepareStackTrace(err) {
|
|
|
275
285
|
}
|
|
276
286
|
}
|
|
277
287
|
function getErrIntroMsg(operation, filePath) {
|
|
288
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
278
289
|
const msg = [
|
|
290
|
+
// prettier ignore
|
|
279
291
|
picocolors_1.default.red(`Failed to ${operation}`),
|
|
280
|
-
picocolors_1.default.bold(picocolors_1.default.red(
|
|
292
|
+
picocolors_1.default.bold(picocolors_1.default.red(filePathToShowToUser2)),
|
|
281
293
|
picocolors_1.default.red(`because:`)
|
|
282
294
|
].join(' ');
|
|
283
295
|
return msg;
|
|
284
296
|
}
|
|
297
|
+
/** `filePath.filePathToShowToUser` may show the import path of a package, use `filePathToShowToUser2` instead always show a file path instead. */
|
|
298
|
+
function getFilePathToShowToUser2(filePath) {
|
|
299
|
+
const { filePathAbsoluteFilesystem, filePathRelativeToUserRootDir } = filePath;
|
|
300
|
+
const filePathToShowToUser2 = filePathRelativeToUserRootDir || filePathAbsoluteFilesystem;
|
|
301
|
+
(0, utils_js_1.assert)(filePathToShowToUser2);
|
|
302
|
+
return filePathToShowToUser2;
|
|
303
|
+
}
|
|
@@ -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-0424983';
|
|
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
|
|
@@ -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
|
}));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { transformImports };
|
|
2
2
|
export { parseImportData };
|
|
3
3
|
export { isImportData };
|
|
4
4
|
export type { FileImport };
|
|
@@ -8,12 +8,12 @@ type FileImport = {
|
|
|
8
8
|
importString: string;
|
|
9
9
|
importLocalName: string;
|
|
10
10
|
};
|
|
11
|
-
declare function
|
|
12
|
-
|
|
11
|
+
declare function transformImports(code: string, filePathToShowToUser2: string, skipWarnings?: true): {
|
|
12
|
+
noTransformation: true;
|
|
13
13
|
} | {
|
|
14
|
-
|
|
14
|
+
noTransformation: false;
|
|
15
15
|
code: string;
|
|
16
|
-
|
|
16
|
+
fileImportsTransformed: FileImport[];
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
19
|
* Data Structure holding info about import statement:
|
|
@@ -1,21 +1,50 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { transformImports };
|
|
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
8
|
import { assert, assertUsage, assertWarning, styleFileRE } from '../../../utils.js';
|
|
7
9
|
import pc from '@brillout/picocolors';
|
|
8
|
-
function
|
|
10
|
+
function transformImports(code, filePathToShowToUser2,
|
|
11
|
+
// For ./transformImports.spec.ts
|
|
12
|
+
skipWarnings) {
|
|
9
13
|
const spliceOperations = [];
|
|
10
|
-
const
|
|
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 {
|
|
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 => 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 seems to work well with the latest TypeScript versions: TypeScript doesn't complain upon `with { type: 'unknown-to-typescript' }` and go-to-definition & types are preserved.
|
|
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
|
+
});
|
|
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 ${
|
|
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 (!
|
|
36
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
171
|
+
strMod += str.slice(endPrev, str.length);
|
|
141
172
|
return strMod;
|
|
142
173
|
}
|
|
143
174
|
function indent(str) {
|
|
@@ -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,56 +8,65 @@ 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
|
-
const { code,
|
|
18
|
-
const { fileExports } = await executeFile(filePath, code,
|
|
16
|
+
async function transpileAndExecuteFile(filePath, isValueFile, userRootDir, isConfigOfExtension = false) {
|
|
17
|
+
const { code, fileImportsTransformed } = await transpileFile(filePath, isValueFile, userRootDir, isConfigOfExtension);
|
|
18
|
+
const { fileExports } = await executeFile(filePath, code, fileImportsTransformed, isValueFile);
|
|
19
19
|
return { fileExports };
|
|
20
20
|
}
|
|
21
|
-
async function transpileFile(filePath, isValueFile, userRootDir) {
|
|
21
|
+
async function transpileFile(filePath, isValueFile, userRootDir, isConfigOfExtension) {
|
|
22
22
|
const { filePathAbsoluteFilesystem } = filePath;
|
|
23
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
23
24
|
assertPosixPath(filePathAbsoluteFilesystem);
|
|
24
25
|
vikeConfigDependencies.add(filePathAbsoluteFilesystem);
|
|
25
|
-
|
|
26
|
-
let
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const importsAreTransformed = !isConfigOfExtension && !isValueFile;
|
|
27
|
+
let code = await transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile);
|
|
28
|
+
let fileImportsTransformed = null;
|
|
29
|
+
if (importsAreTransformed) {
|
|
30
|
+
const res = transformImports_(code, filePath);
|
|
29
31
|
if (res) {
|
|
30
32
|
code = res.code;
|
|
31
|
-
|
|
33
|
+
fileImportsTransformed = res.fileImportsTransformed;
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
else {
|
|
37
|
+
if (isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
38
|
+
if (isValueFile) {
|
|
39
|
+
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 });
|
|
40
|
+
}
|
|
41
|
+
else if (isConfigOfExtension) {
|
|
42
|
+
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 });
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
assert(false);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
return { code, fileImportsTransformed };
|
|
50
|
+
}
|
|
51
|
+
function transformImports_(codeOriginal, filePath) {
|
|
52
|
+
const { filePathAbsoluteFilesystem } = filePath;
|
|
53
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
54
|
+
// Replace import statements with import strings
|
|
55
|
+
const res = transformImports(codeOriginal, filePathToShowToUser2);
|
|
56
|
+
if (res.noTransformation) {
|
|
49
57
|
return null;
|
|
50
58
|
}
|
|
51
|
-
const { code,
|
|
52
|
-
if (!
|
|
53
|
-
const filePathCorrect = appendHeaderFileExtension(
|
|
54
|
-
assertWarning(false, `Rename ${
|
|
59
|
+
const { code, fileImportsTransformed } = res;
|
|
60
|
+
if (!isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
61
|
+
const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser2);
|
|
62
|
+
assertWarning(false, `Rename ${filePathToShowToUser2} to ${filePathCorrect}, see https://vike.dev/header-file`, {
|
|
55
63
|
onlyOnce: true
|
|
56
64
|
});
|
|
57
65
|
}
|
|
58
|
-
return { code,
|
|
66
|
+
return { code, fileImportsTransformed };
|
|
59
67
|
}
|
|
60
|
-
async function transpileWithEsbuild(filePath,
|
|
68
|
+
async function transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile) {
|
|
69
|
+
const isConfigFile = !isValueFile;
|
|
61
70
|
const entryFilePath = filePath.filePathAbsoluteFilesystem;
|
|
62
71
|
const entryFileDir = path.posix.dirname(entryFilePath);
|
|
63
72
|
const options = {
|
|
@@ -73,22 +82,26 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
73
82
|
'NEVER_EMITTED.js'),
|
|
74
83
|
logLevel: 'silent',
|
|
75
84
|
format: 'esm',
|
|
76
|
-
|
|
85
|
+
absWorkingDir: userRootDir,
|
|
86
|
+
// Disable tree-shaking to avoid dead-code elimination, so that unused imports aren't removed.
|
|
87
|
+
// Esbuild still sometimes removes unused imports because of TypeScript: https://github.com/evanw/esbuild/issues/3034
|
|
88
|
+
treeShaking: false,
|
|
77
89
|
minify: false,
|
|
78
|
-
metafile:
|
|
79
|
-
|
|
90
|
+
metafile: isConfigFile,
|
|
91
|
+
// We cannot bundle imports that are meant to be transformed
|
|
92
|
+
bundle: !importsAreTransformed
|
|
80
93
|
};
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
// Track dependencies
|
|
95
|
+
if (isConfigFile) {
|
|
83
96
|
options.packages = 'external';
|
|
84
97
|
options.plugins = [
|
|
85
98
|
{
|
|
86
|
-
name: 'vike:
|
|
99
|
+
name: 'vike:dependency-tracker',
|
|
87
100
|
setup(b) {
|
|
88
101
|
b.onLoad({ filter: /./ }, (args) => {
|
|
102
|
+
// We collect the dependency `args.path` in case the bulid fails (upon build error => error is thrown => no metafile)
|
|
89
103
|
let { path } = args;
|
|
90
104
|
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
105
|
vikeConfigDependencies.add(path);
|
|
93
106
|
return undefined;
|
|
94
107
|
});
|
|
@@ -105,11 +118,6 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
105
118
|
}
|
|
106
119
|
];
|
|
107
120
|
}
|
|
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
121
|
let result;
|
|
114
122
|
try {
|
|
115
123
|
result = await build(options);
|
|
@@ -118,7 +126,8 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
118
126
|
await formatBuildErr(err, filePath);
|
|
119
127
|
throw err;
|
|
120
128
|
}
|
|
121
|
-
|
|
129
|
+
// Track dependencies
|
|
130
|
+
if (isConfigFile) {
|
|
122
131
|
assert(result.metafile);
|
|
123
132
|
Object.keys(result.metafile.inputs).forEach((filePathRelative) => {
|
|
124
133
|
filePathRelative = toPosixPath(filePathRelative);
|
|
@@ -131,7 +140,7 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
131
140
|
assert(typeof code === 'string');
|
|
132
141
|
return code;
|
|
133
142
|
}
|
|
134
|
-
async function executeFile(filePath, code,
|
|
143
|
+
async function executeFile(filePath, code, fileImportsTransformed, isValueFile) {
|
|
135
144
|
const { filePathAbsoluteFilesystem, filePathRelativeToUserRootDir } = filePath;
|
|
136
145
|
// Alternative to using a temporary file: https://github.com/vitejs/vite/pull/13269
|
|
137
146
|
// - But seems to break source maps, so I don't think it's worth it
|
|
@@ -156,10 +165,10 @@ async function executeFile(filePath, code, fileImports, isValueFile) {
|
|
|
156
165
|
// - import() returns `[Module: null prototype] { default: { onRenderClient: '...' }}`
|
|
157
166
|
// - We don't need this special object
|
|
158
167
|
fileExports = { ...fileExports };
|
|
159
|
-
if (
|
|
168
|
+
if (fileImportsTransformed && !isValueFile) {
|
|
160
169
|
assert(filePathRelativeToUserRootDir !== undefined);
|
|
161
|
-
const
|
|
162
|
-
assertImportsAreReExported(
|
|
170
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
171
|
+
assertImportsAreReExported(fileImportsTransformed, fileExports, filePathToShowToUser2);
|
|
163
172
|
}
|
|
164
173
|
return { fileExports };
|
|
165
174
|
}
|
|
@@ -205,8 +214,8 @@ function isTmpFile(filePath) {
|
|
|
205
214
|
const fileName = path.posix.basename(filePath);
|
|
206
215
|
return fileName.startsWith(tmpPrefix);
|
|
207
216
|
}
|
|
208
|
-
function assertImportsAreReExported(
|
|
209
|
-
const fileExport = getConfigFileExport(fileExports,
|
|
217
|
+
function assertImportsAreReExported(fileImportsTransformed, fileExports, filePathToShowToUser2) {
|
|
218
|
+
const fileExport = getConfigFileExport(fileExports, filePathToShowToUser2);
|
|
210
219
|
const exportedStrings = getExportedStrings(fileExport);
|
|
211
220
|
Object.values(exportedStrings).forEach((exportVal) => {
|
|
212
221
|
if (typeof exportVal !== 'string')
|
|
@@ -214,20 +223,20 @@ function assertImportsAreReExported(fileImports, fileExports, filePathToShowToUs
|
|
|
214
223
|
if (!isImportData(exportVal))
|
|
215
224
|
return;
|
|
216
225
|
const importString = exportVal;
|
|
217
|
-
|
|
226
|
+
fileImportsTransformed.forEach((fileImport) => {
|
|
218
227
|
if (fileImport.importString === importString) {
|
|
219
228
|
fileImport.isReExported = true;
|
|
220
229
|
}
|
|
221
230
|
});
|
|
222
231
|
});
|
|
223
|
-
const
|
|
224
|
-
if (
|
|
232
|
+
const fileImportsTransformedUnused = fileImportsTransformed.filter((fi) => !fi.isReExported);
|
|
233
|
+
if (fileImportsTransformedUnused.length === 0)
|
|
225
234
|
return;
|
|
226
|
-
const importStatements = unique(
|
|
227
|
-
const importNamesUnused =
|
|
228
|
-
const singular =
|
|
229
|
-
assertWarning(
|
|
230
|
-
`${
|
|
235
|
+
const importStatements = unique(fileImportsTransformedUnused.map((fi) => fi.importStatementCode));
|
|
236
|
+
const importNamesUnused = fileImportsTransformedUnused.map((fi) => pc.cyan(fi.importLocalName)).join(', ');
|
|
237
|
+
const singular = fileImportsTransformedUnused.length === 1;
|
|
238
|
+
assertWarning(fileImportsTransformedUnused.length === 0, [
|
|
239
|
+
`${filePathToShowToUser2} imports the following:`,
|
|
231
240
|
...importStatements.map((s) => pc.cyan(` ${s}`)),
|
|
232
241
|
`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
242
|
].join('\n'), { onlyOnce: true });
|
|
@@ -249,6 +258,7 @@ function getExportedStrings(obj) {
|
|
|
249
258
|
return exportedStrings;
|
|
250
259
|
}
|
|
251
260
|
function isHeaderFile(filePath) {
|
|
261
|
+
assertPosixPath(filePath);
|
|
252
262
|
const basenameParts = path.posix.basename(filePath).split('.');
|
|
253
263
|
return basenameParts.includes('h');
|
|
254
264
|
}
|
|
@@ -269,10 +279,19 @@ function triggerPrepareStackTrace(err) {
|
|
|
269
279
|
}
|
|
270
280
|
}
|
|
271
281
|
function getErrIntroMsg(operation, filePath) {
|
|
282
|
+
const filePathToShowToUser2 = getFilePathToShowToUser2(filePath);
|
|
272
283
|
const msg = [
|
|
284
|
+
// prettier ignore
|
|
273
285
|
pc.red(`Failed to ${operation}`),
|
|
274
|
-
pc.bold(pc.red(
|
|
286
|
+
pc.bold(pc.red(filePathToShowToUser2)),
|
|
275
287
|
pc.red(`because:`)
|
|
276
288
|
].join(' ');
|
|
277
289
|
return msg;
|
|
278
290
|
}
|
|
291
|
+
/** `filePath.filePathToShowToUser` may show the import path of a package, use `filePathToShowToUser2` instead always show a file path instead. */
|
|
292
|
+
function getFilePathToShowToUser2(filePath) {
|
|
293
|
+
const { filePathAbsoluteFilesystem, filePathRelativeToUserRootDir } = filePath;
|
|
294
|
+
const filePathToShowToUser2 = filePathRelativeToUserRootDir || filePathAbsoluteFilesystem;
|
|
295
|
+
assert(filePathToShowToUser2);
|
|
296
|
+
return filePathToShowToUser2;
|
|
297
|
+
}
|
|
@@ -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-0424983";
|
|
4
4
|
declare const projectInfo: {
|
|
5
5
|
projectName: "Vike";
|
|
6
|
-
projectVersion: "0.4.159-commit-
|
|
6
|
+
projectVersion: "0.4.159-commit-0424983";
|
|
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-0424983';
|
|
5
5
|
const projectInfo = {
|
|
6
6
|
projectName: 'Vike',
|
|
7
7
|
projectVersion: PROJECT_VERSION
|