vike 0.4.159-commit-71760c7 → 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/{transformImportStatements.js → transformImports.js} +33 -17
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/transpileAndExecuteFile.js +43 -34
- 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/{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 +42 -33
- 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,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 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
|
+
});
|
|
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,57 @@ 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, fileImportsTransformed } = await transpileFile(filePath, isValueFile, userRootDir);
|
|
18
|
+
async function transpileAndExecuteFile(filePath, isValueFile, userRootDir, isConfigOfExtension = false) {
|
|
19
|
+
const { code, fileImportsTransformed } = await transpileFile(filePath, isValueFile, userRootDir, isConfigOfExtension);
|
|
20
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
|
+
const importsAreTransformed = !isConfigOfExtension && !isValueFile;
|
|
30
|
+
let code = await transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile);
|
|
29
31
|
let fileImportsTransformed = null;
|
|
30
|
-
{
|
|
31
|
-
const res =
|
|
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
|
}
|
|
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
|
+
}
|
|
51
|
+
}
|
|
37
52
|
return { code, fileImportsTransformed };
|
|
38
53
|
}
|
|
39
|
-
function
|
|
40
|
-
// Do we need to remove the imports?
|
|
54
|
+
function transformImports_(codeOriginal, filePath) {
|
|
41
55
|
const { filePathAbsoluteFilesystem } = filePath;
|
|
42
56
|
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);
|
|
57
|
+
// Replace import statements with import strings
|
|
58
|
+
const res = (0, transformImports_js_1.transformImports)(codeOriginal, filePathToShowToUser2);
|
|
52
59
|
if (res.noTransformation) {
|
|
53
60
|
return null;
|
|
54
61
|
}
|
|
55
62
|
const { code, fileImportsTransformed } = res;
|
|
56
|
-
if (!
|
|
63
|
+
if (!isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
57
64
|
const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser2);
|
|
58
65
|
(0, utils_js_1.assertWarning)(false, `Rename ${filePathToShowToUser2} to ${filePathCorrect}, see https://vike.dev/header-file`, {
|
|
59
66
|
onlyOnce: true
|
|
@@ -61,7 +68,8 @@ function transformImports(codeOriginal, filePath, isValueFile) {
|
|
|
61
68
|
}
|
|
62
69
|
return { code, fileImportsTransformed };
|
|
63
70
|
}
|
|
64
|
-
async function transpileWithEsbuild(filePath,
|
|
71
|
+
async function transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile) {
|
|
72
|
+
const isConfigFile = !isValueFile;
|
|
65
73
|
const entryFilePath = filePath.filePathAbsoluteFilesystem;
|
|
66
74
|
const entryFileDir = path_1.default.posix.dirname(entryFilePath);
|
|
67
75
|
const options = {
|
|
@@ -77,22 +85,26 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
77
85
|
'NEVER_EMITTED.js'),
|
|
78
86
|
logLevel: 'silent',
|
|
79
87
|
format: 'esm',
|
|
80
|
-
|
|
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,
|
|
81
92
|
minify: false,
|
|
82
|
-
metafile:
|
|
83
|
-
|
|
93
|
+
metafile: isConfigFile,
|
|
94
|
+
// We cannot bundle imports that are meant to be transformed
|
|
95
|
+
bundle: !importsAreTransformed
|
|
84
96
|
};
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
// Track dependencies
|
|
98
|
+
if (isConfigFile) {
|
|
87
99
|
options.packages = 'external';
|
|
88
100
|
options.plugins = [
|
|
89
101
|
{
|
|
90
|
-
name: 'vike:
|
|
102
|
+
name: 'vike:dependency-tracker',
|
|
91
103
|
setup(b) {
|
|
92
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)
|
|
93
106
|
let { path } = args;
|
|
94
107
|
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
108
|
getVikeConfig_js_1.vikeConfigDependencies.add(path);
|
|
97
109
|
return undefined;
|
|
98
110
|
});
|
|
@@ -109,11 +121,6 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
109
121
|
}
|
|
110
122
|
];
|
|
111
123
|
}
|
|
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
124
|
let result;
|
|
118
125
|
try {
|
|
119
126
|
result = await (0, esbuild_1.build)(options);
|
|
@@ -122,7 +129,8 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
122
129
|
await formatBuildErr(err, filePath);
|
|
123
130
|
throw err;
|
|
124
131
|
}
|
|
125
|
-
|
|
132
|
+
// Track dependencies
|
|
133
|
+
if (isConfigFile) {
|
|
126
134
|
(0, utils_js_1.assert)(result.metafile);
|
|
127
135
|
Object.keys(result.metafile.inputs).forEach((filePathRelative) => {
|
|
128
136
|
filePathRelative = (0, utils_js_1.toPosixPath)(filePathRelative);
|
|
@@ -218,7 +226,7 @@ function assertImportsAreReExported(fileImportsTransformed, fileExports, filePat
|
|
|
218
226
|
Object.values(exportedStrings).forEach((exportVal) => {
|
|
219
227
|
if (typeof exportVal !== 'string')
|
|
220
228
|
return;
|
|
221
|
-
if (!(0,
|
|
229
|
+
if (!(0, transformImports_js_1.isImportData)(exportVal))
|
|
222
230
|
return;
|
|
223
231
|
const importString = exportVal;
|
|
224
232
|
fileImportsTransformed.forEach((fileImport) => {
|
|
@@ -256,6 +264,7 @@ function getExportedStrings(obj) {
|
|
|
256
264
|
return exportedStrings;
|
|
257
265
|
}
|
|
258
266
|
function isHeaderFile(filePath) {
|
|
267
|
+
(0, utils_js_1.assertPosixPath)(filePath);
|
|
259
268
|
const basenameParts = path_1.default.posix.basename(filePath).split('.');
|
|
260
269
|
return basenameParts.includes('h');
|
|
261
270
|
}
|
|
@@ -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,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 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
|
+
});
|
|
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,56 @@ 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, fileImportsTransformed } = await transpileFile(filePath, isValueFile, userRootDir);
|
|
16
|
+
async function transpileAndExecuteFile(filePath, isValueFile, userRootDir, isConfigOfExtension = false) {
|
|
17
|
+
const { code, fileImportsTransformed } = await transpileFile(filePath, isValueFile, userRootDir, isConfigOfExtension);
|
|
18
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
|
+
const importsAreTransformed = !isConfigOfExtension && !isValueFile;
|
|
27
|
+
let code = await transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile);
|
|
26
28
|
let fileImportsTransformed = null;
|
|
27
|
-
{
|
|
28
|
-
const res =
|
|
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
|
}
|
|
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
|
+
}
|
|
48
|
+
}
|
|
34
49
|
return { code, fileImportsTransformed };
|
|
35
50
|
}
|
|
36
|
-
function
|
|
37
|
-
// Do we need to remove the imports?
|
|
51
|
+
function transformImports_(codeOriginal, filePath) {
|
|
38
52
|
const { filePathAbsoluteFilesystem } = filePath;
|
|
39
53
|
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);
|
|
54
|
+
// Replace import statements with import strings
|
|
55
|
+
const res = transformImports(codeOriginal, filePathToShowToUser2);
|
|
49
56
|
if (res.noTransformation) {
|
|
50
57
|
return null;
|
|
51
58
|
}
|
|
52
59
|
const { code, fileImportsTransformed } = res;
|
|
53
|
-
if (!
|
|
60
|
+
if (!isHeaderFile(filePathAbsoluteFilesystem)) {
|
|
54
61
|
const filePathCorrect = appendHeaderFileExtension(filePathToShowToUser2);
|
|
55
62
|
assertWarning(false, `Rename ${filePathToShowToUser2} to ${filePathCorrect}, see https://vike.dev/header-file`, {
|
|
56
63
|
onlyOnce: true
|
|
@@ -58,7 +65,8 @@ function transformImports(codeOriginal, filePath, isValueFile) {
|
|
|
58
65
|
}
|
|
59
66
|
return { code, fileImportsTransformed };
|
|
60
67
|
}
|
|
61
|
-
async function transpileWithEsbuild(filePath,
|
|
68
|
+
async function transpileWithEsbuild(filePath, userRootDir, importsAreTransformed, isValueFile) {
|
|
69
|
+
const isConfigFile = !isValueFile;
|
|
62
70
|
const entryFilePath = filePath.filePathAbsoluteFilesystem;
|
|
63
71
|
const entryFileDir = path.posix.dirname(entryFilePath);
|
|
64
72
|
const options = {
|
|
@@ -74,22 +82,26 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
74
82
|
'NEVER_EMITTED.js'),
|
|
75
83
|
logLevel: 'silent',
|
|
76
84
|
format: 'esm',
|
|
77
|
-
|
|
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,
|
|
78
89
|
minify: false,
|
|
79
|
-
metafile:
|
|
80
|
-
|
|
90
|
+
metafile: isConfigFile,
|
|
91
|
+
// We cannot bundle imports that are meant to be transformed
|
|
92
|
+
bundle: !importsAreTransformed
|
|
81
93
|
};
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
// Track dependencies
|
|
95
|
+
if (isConfigFile) {
|
|
84
96
|
options.packages = 'external';
|
|
85
97
|
options.plugins = [
|
|
86
98
|
{
|
|
87
|
-
name: 'vike:
|
|
99
|
+
name: 'vike:dependency-tracker',
|
|
88
100
|
setup(b) {
|
|
89
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)
|
|
90
103
|
let { path } = args;
|
|
91
104
|
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
105
|
vikeConfigDependencies.add(path);
|
|
94
106
|
return undefined;
|
|
95
107
|
});
|
|
@@ -106,11 +118,6 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
106
118
|
}
|
|
107
119
|
];
|
|
108
120
|
}
|
|
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
121
|
let result;
|
|
115
122
|
try {
|
|
116
123
|
result = await build(options);
|
|
@@ -119,7 +126,8 @@ async function transpileWithEsbuild(filePath, bundle, userRootDir) {
|
|
|
119
126
|
await formatBuildErr(err, filePath);
|
|
120
127
|
throw err;
|
|
121
128
|
}
|
|
122
|
-
|
|
129
|
+
// Track dependencies
|
|
130
|
+
if (isConfigFile) {
|
|
123
131
|
assert(result.metafile);
|
|
124
132
|
Object.keys(result.metafile.inputs).forEach((filePathRelative) => {
|
|
125
133
|
filePathRelative = toPosixPath(filePathRelative);
|
|
@@ -250,6 +258,7 @@ function getExportedStrings(obj) {
|
|
|
250
258
|
return exportedStrings;
|
|
251
259
|
}
|
|
252
260
|
function isHeaderFile(filePath) {
|
|
261
|
+
assertPosixPath(filePath);
|
|
253
262
|
const basenameParts = path.posix.basename(filePath).split('.');
|
|
254
263
|
return basenameParts.includes('h');
|
|
255
264
|
}
|
|
@@ -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
|