vike 0.4.249 → 0.4.250-commit-6161324
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/bin.js +3 -0
- package/dist/client/runtime-client-routing/createPageContextClientSide.d.ts +20 -2
- package/dist/client/runtime-client-routing/createPageContextClientSide.js +19 -11
- package/dist/client/runtime-client-routing/getPageContext.js +0 -2
- package/dist/client/runtime-client-routing/getPageContextFromHooks.d.ts +180 -60
- package/dist/client/runtime-client-routing/history.d.ts +1 -1
- package/dist/client/runtime-client-routing/history.js +4 -11
- package/dist/client/runtime-client-routing/prefetch.d.ts +2 -2
- package/dist/client/runtime-client-routing/renderPageClient.d.ts +628 -31
- package/dist/client/runtime-client-routing/utils.d.ts +0 -1
- package/dist/client/runtime-client-routing/utils.js +0 -1
- package/dist/client/runtime-server-routing/createPageContextClientSide.d.ts +15 -6
- package/dist/client/runtime-server-routing/createPageContextClientSide.js +11 -25
- package/dist/client/runtime-server-routing/entry.js +15 -1
- package/dist/client/shared/execHookOnRenderClient.d.ts +4 -1
- package/dist/node/prerender/runPrerender.d.ts +2 -5
- package/dist/node/prerender/runPrerender.js +2 -2
- package/dist/node/vite/index.js +5 -2
- package/dist/node/vite/plugins/non-runnable-dev/pluginReplaceConstantsNonRunnableDev.js +38 -13
- package/dist/node/vite/plugins/pluginAssertFileEnv.js +22 -13
- package/dist/node/vite/plugins/pluginExtractAssets.js +2 -0
- package/dist/node/vite/plugins/pluginExtractExportNames.js +2 -0
- package/dist/node/vite/plugins/pluginReplaceConstantsEnvVars.js +2 -0
- package/dist/node/vite/plugins/pluginReplaceConstantsGlobalThis.js +3 -1
- package/dist/node/vite/plugins/pluginReplaceConstantsPageContext.js +2 -0
- package/dist/node/vite/plugins/pluginStaticReplace/applyStaticReplace.d.ts +126 -0
- package/dist/node/vite/plugins/pluginStaticReplace/applyStaticReplace.js +421 -0
- package/dist/node/vite/plugins/pluginStaticReplace.d.ts +4 -0
- package/dist/node/vite/plugins/pluginStaticReplace.js +88 -0
- package/dist/node/vite/plugins/pluginVirtualFiles.js +73 -113
- package/dist/node/vite/plugins/pluginViteConfigVikeExtensions.d.ts +2 -1
- package/dist/node/vite/plugins/pluginViteConfigVikeExtensions.js +1 -3
- package/dist/node/vite/shared/importString.d.ts +50 -0
- package/dist/node/vite/shared/importString.js +63 -0
- package/dist/node/vite/shared/loggerDev.d.ts +3 -3
- package/dist/node/vite/shared/loggerDev.js +3 -3
- package/dist/node/vite/shared/resolveVikeConfigInternal/assertExtensions.d.ts +1 -1
- package/dist/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.js +15 -1
- package/dist/node/vite/shared/resolveVikeConfigInternal/{crawlPlusFiles.d.ts → crawlPlusFilePaths.d.ts} +2 -2
- package/dist/node/vite/shared/resolveVikeConfigInternal/{crawlPlusFiles.js → crawlPlusFilePaths.js} +4 -4
- package/dist/node/vite/shared/resolveVikeConfigInternal/{getPlusFilesAll.d.ts → getPlusFilesByLocationId.d.ts} +8 -6
- package/dist/node/vite/shared/resolveVikeConfigInternal/{getPlusFilesAll.js → getPlusFilesByLocationId.js} +47 -59
- package/dist/node/vite/shared/resolveVikeConfigInternal/loadFileAtConfigTime.d.ts +1 -1
- package/dist/node/vite/shared/resolveVikeConfigInternal/pointerImports.js +11 -18
- package/dist/node/vite/shared/resolveVikeConfigInternal.d.ts +1 -1
- package/dist/node/vite/shared/resolveVikeConfigInternal.js +66 -64
- package/dist/server/onLoad.js +2 -2
- package/dist/server/runtime/logErrorServer.d.ts +2 -2
- package/dist/server/runtime/logErrorServer.js +0 -2
- package/dist/server/runtime/loggerRuntime.d.ts +3 -2
- package/dist/server/runtime/renderPageServer/createHttpResponse.d.ts +4 -2
- package/dist/server/runtime/renderPageServer/createHttpResponse.js +16 -8
- package/dist/server/runtime/renderPageServer/createPageContextServerSide.d.ts +15 -10
- package/dist/server/runtime/renderPageServer/createPageContextServerSide.js +12 -11
- package/dist/server/runtime/renderPageServer/csp.js +2 -0
- package/dist/server/runtime/renderPageServer/execHookOnError.d.ts +2 -2
- package/dist/server/runtime/renderPageServer/execHookOnError.js +3 -1
- package/dist/server/runtime/renderPageServer/handleErrorWithoutErrorPage.d.ts +4 -4
- package/dist/server/runtime/renderPageServer/handleErrorWithoutErrorPage.js +3 -4
- package/dist/server/runtime/renderPageServer/html/serializeContext.d.ts +2 -2
- package/dist/server/runtime/renderPageServer/html/stream.js +12 -13
- package/dist/server/runtime/renderPageServer/loadPageConfigsLazyServerSide.d.ts +3 -6
- package/dist/server/runtime/renderPageServer/log404/index.d.ts +2 -2
- package/dist/server/runtime/renderPageServer/renderPageServerAfterRoute.d.ts +7 -19
- package/dist/server/runtime/renderPageServer/renderPageServerAfterRoute.js +2 -2
- package/dist/server/runtime/renderPageServer.d.ts +2 -9
- package/dist/server/runtime/renderPageServer.js +19 -19
- package/dist/shared-server-client/createGlobalContextShared.js +1 -1
- package/dist/shared-server-client/createPageContextShared.d.ts +12 -2
- package/dist/shared-server-client/createPageContextShared.js +1 -0
- package/dist/shared-server-client/getPageContextUrlComputed.d.ts +5 -2
- package/dist/shared-server-client/hooks/execHook.d.ts +6 -4
- package/dist/shared-server-client/hooks/execHook.js +77 -12
- package/dist/shared-server-client/prepareGlobalContextForPublicUsage.d.ts +2 -0
- package/dist/shared-server-client/preparePageContextForPublicUsage.d.ts +2 -3
- package/dist/types/Config/ConfigResolved.d.ts +3 -2
- package/dist/types/Config.d.ts +48 -32
- package/dist/types/Config.js +1 -0
- package/dist/types/PageConfig.d.ts +1 -1
- package/dist/types/PageContext.d.ts +33 -26
- package/dist/types/index.d.ts +2 -1
- package/dist/utils/PROJECT_VERSION.d.ts +1 -1
- package/dist/utils/PROJECT_VERSION.js +1 -1
- package/dist/utils/assert.d.ts +5 -5
- package/dist/utils/assert.js +8 -8
- package/dist/utils/debug.d.ts +1 -1
- package/dist/utils/debug.js +1 -0
- package/package.json +9 -7
- package/node/cli/bin.js +0 -3
- /package/dist/node/vite/shared/resolveVikeConfigInternal/{crawlPlusFiles → crawlPlusFilePaths}/ignorePatternsBuiltIn.d.ts +0 -0
- /package/dist/node/vite/shared/resolveVikeConfigInternal/{crawlPlusFiles → crawlPlusFilePaths}/ignorePatternsBuiltIn.js +0 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
export { applyStaticReplace };
|
|
2
|
+
import { transformAsync } from '@babel/core';
|
|
3
|
+
import * as t from '@babel/types';
|
|
4
|
+
import { parseImportString } from '../../shared/importString.js';
|
|
5
|
+
import { assert } from '../../utils.js';
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Main transformer
|
|
8
|
+
// ============================================================================
|
|
9
|
+
async function applyStaticReplace(code, staticReplaceList, id, env) {
|
|
10
|
+
assert(staticReplaceList.length > 0);
|
|
11
|
+
const SKIPPED = undefined;
|
|
12
|
+
const NO_CHANGE = null;
|
|
13
|
+
const staticReplaceListFiltered = staticReplaceList.filter((staticReplace) => {
|
|
14
|
+
if (staticReplace.env && staticReplace.env !== env)
|
|
15
|
+
return false;
|
|
16
|
+
if (!code.includes(staticReplace.filter))
|
|
17
|
+
return false;
|
|
18
|
+
return true;
|
|
19
|
+
});
|
|
20
|
+
if (staticReplaceListFiltered.length === 0) {
|
|
21
|
+
return SKIPPED;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const state = {
|
|
25
|
+
modified: false,
|
|
26
|
+
imports: new Map(),
|
|
27
|
+
alreadyUnreferenced: new Set(),
|
|
28
|
+
};
|
|
29
|
+
const result = await transformAsync(code, {
|
|
30
|
+
filename: id,
|
|
31
|
+
ast: true,
|
|
32
|
+
sourceMaps: true,
|
|
33
|
+
plugins: [
|
|
34
|
+
collectImportsPlugin(state),
|
|
35
|
+
applyRulesPlugin(state, staticReplaceListFiltered),
|
|
36
|
+
removeUnreferencedPlugin(state),
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
if (!result?.code || !state.modified) {
|
|
40
|
+
return NO_CHANGE;
|
|
41
|
+
}
|
|
42
|
+
return { code: result.code, map: result.map };
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error(`Error transforming ${id}:`, error);
|
|
46
|
+
return SKIPPED;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Helpers
|
|
51
|
+
// ============================================================================
|
|
52
|
+
function valueToAst(value) {
|
|
53
|
+
if (value === null)
|
|
54
|
+
return t.nullLiteral();
|
|
55
|
+
if (value === undefined)
|
|
56
|
+
return t.identifier('undefined');
|
|
57
|
+
if (typeof value === 'string')
|
|
58
|
+
return t.stringLiteral(value);
|
|
59
|
+
if (typeof value === 'number')
|
|
60
|
+
return t.numericLiteral(value);
|
|
61
|
+
if (typeof value === 'boolean')
|
|
62
|
+
return t.booleanLiteral(value);
|
|
63
|
+
if (Array.isArray(value)) {
|
|
64
|
+
return t.arrayExpression(value.map(valueToAst));
|
|
65
|
+
}
|
|
66
|
+
if (typeof value === 'object') {
|
|
67
|
+
const properties = Object.entries(value).map(([key, val]) => {
|
|
68
|
+
return t.objectProperty(t.identifier(key), valueToAst(val));
|
|
69
|
+
});
|
|
70
|
+
return t.objectExpression(properties);
|
|
71
|
+
}
|
|
72
|
+
return t.callExpression(t.memberExpression(t.identifier('JSON'), t.identifier('parse')), [
|
|
73
|
+
t.stringLiteral(JSON.stringify(value)),
|
|
74
|
+
]);
|
|
75
|
+
}
|
|
76
|
+
function getCalleeName(callee) {
|
|
77
|
+
if (t.isIdentifier(callee))
|
|
78
|
+
return callee.name;
|
|
79
|
+
if (t.isMemberExpression(callee) && t.isIdentifier(callee.property))
|
|
80
|
+
return callee.property.name;
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check if an identifier matches an import condition
|
|
85
|
+
*/
|
|
86
|
+
function matchesImport(arg, parsed, state) {
|
|
87
|
+
if (!t.isIdentifier(arg))
|
|
88
|
+
return false;
|
|
89
|
+
const imported = state.imports.get(arg.name);
|
|
90
|
+
if (!imported)
|
|
91
|
+
return false;
|
|
92
|
+
return imported.importPath === parsed.importPath && imported.exportName === parsed.exportName;
|
|
93
|
+
}
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Babel plugins
|
|
96
|
+
// ============================================================================
|
|
97
|
+
/**
|
|
98
|
+
* Collect all imports: localName -> { importPath, exportName }
|
|
99
|
+
*/
|
|
100
|
+
function collectImportsPlugin(state) {
|
|
101
|
+
return {
|
|
102
|
+
visitor: {
|
|
103
|
+
ImportDeclaration(path) {
|
|
104
|
+
const importPath = path.node.source.value;
|
|
105
|
+
for (const specifier of path.node.specifiers) {
|
|
106
|
+
let exportName;
|
|
107
|
+
if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) {
|
|
108
|
+
exportName = specifier.imported.name;
|
|
109
|
+
}
|
|
110
|
+
else if (t.isImportDefaultSpecifier(specifier)) {
|
|
111
|
+
exportName = 'default';
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
state.imports.set(specifier.local.name, { importPath, exportName });
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Apply replacement rules to matching call expressions
|
|
124
|
+
*/
|
|
125
|
+
function applyRulesPlugin(state, rules) {
|
|
126
|
+
return {
|
|
127
|
+
visitor: {
|
|
128
|
+
CallExpression(path) {
|
|
129
|
+
const calleeName = getCalleeName(path.node.callee);
|
|
130
|
+
if (!calleeName)
|
|
131
|
+
return;
|
|
132
|
+
for (const rule of rules) {
|
|
133
|
+
if (!matchesRule(path, rule, calleeName, state))
|
|
134
|
+
continue;
|
|
135
|
+
if (rule.replace) {
|
|
136
|
+
applyReplace(path, rule.replace, state);
|
|
137
|
+
}
|
|
138
|
+
else if (rule.remove) {
|
|
139
|
+
applyRemove(path, rule.remove, state);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Check if a call expression matches a rule
|
|
148
|
+
*/
|
|
149
|
+
function matchesRule(path, staticReplace, calleeName, state) {
|
|
150
|
+
const { match } = staticReplace;
|
|
151
|
+
// Check callee name
|
|
152
|
+
const functions = Array.isArray(match.function) ? match.function : [match.function];
|
|
153
|
+
if (!matchesCallee(path.node.callee, calleeName, functions, state))
|
|
154
|
+
return false;
|
|
155
|
+
// Check argument conditions
|
|
156
|
+
if (match.args) {
|
|
157
|
+
for (const [indexStr, condition] of Object.entries(match.args)) {
|
|
158
|
+
const index = Number(indexStr);
|
|
159
|
+
const arg = path.node.arguments[index];
|
|
160
|
+
if (!arg)
|
|
161
|
+
return false;
|
|
162
|
+
if (!matchesCondition(arg, condition, state))
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if callee matches any of the function patterns
|
|
170
|
+
*/
|
|
171
|
+
function matchesCallee(callee, calleeName, functions, state) {
|
|
172
|
+
for (const fn of functions) {
|
|
173
|
+
const parsed = parseImportString(fn);
|
|
174
|
+
if (parsed) {
|
|
175
|
+
// Import string: check if callee is an imported identifier
|
|
176
|
+
if (t.isIdentifier(callee)) {
|
|
177
|
+
const imported = state.imports.get(callee.name);
|
|
178
|
+
if (imported && imported.importPath === parsed.importPath && imported.exportName === parsed.exportName) {
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Import string: check member expression
|
|
183
|
+
if (t.isMemberExpression(callee) && t.isIdentifier(callee.object) && t.isIdentifier(callee.property)) {
|
|
184
|
+
const imported = state.imports.get(callee.object.name);
|
|
185
|
+
if (imported &&
|
|
186
|
+
imported.importPath === parsed.importPath &&
|
|
187
|
+
imported.exportName === 'default' &&
|
|
188
|
+
callee.property.name === parsed.exportName) {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// Plain string: match function name directly
|
|
195
|
+
if (calleeName === fn)
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Check if an argument matches a condition
|
|
203
|
+
*/
|
|
204
|
+
function matchesCondition(arg, condition, state) {
|
|
205
|
+
// String condition
|
|
206
|
+
if (typeof condition === 'string') {
|
|
207
|
+
// Import condition: 'import:importPath:exportName'
|
|
208
|
+
const parsed = parseImportString(condition);
|
|
209
|
+
if (parsed) {
|
|
210
|
+
return t.isExpression(arg) && matchesImport(arg, parsed, state);
|
|
211
|
+
}
|
|
212
|
+
// Plain string: match string literal or identifier name
|
|
213
|
+
if (t.isStringLiteral(arg))
|
|
214
|
+
return arg.value === condition;
|
|
215
|
+
if (t.isIdentifier(arg))
|
|
216
|
+
return arg.name === condition;
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
// Call expression condition: match call with specific arguments
|
|
220
|
+
if ('call' in condition) {
|
|
221
|
+
if (!t.isCallExpression(arg))
|
|
222
|
+
return false;
|
|
223
|
+
const calleeName = getCalleeName(arg.callee);
|
|
224
|
+
if (!calleeName)
|
|
225
|
+
return false;
|
|
226
|
+
// Check if callee matches
|
|
227
|
+
const parsed = parseImportString(condition.call);
|
|
228
|
+
if (parsed) {
|
|
229
|
+
// Import string: check if callee is an imported identifier
|
|
230
|
+
if (!t.isIdentifier(arg.callee))
|
|
231
|
+
return false;
|
|
232
|
+
const imported = state.imports.get(arg.callee.name);
|
|
233
|
+
if (!imported || imported.importPath !== parsed.importPath || imported.exportName !== parsed.exportName) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// Plain string: match function name directly
|
|
239
|
+
if (calleeName !== condition.call)
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
// Check argument conditions
|
|
243
|
+
if (condition.args) {
|
|
244
|
+
for (const [indexStr, argCondition] of Object.entries(condition.args)) {
|
|
245
|
+
const index = Number(indexStr);
|
|
246
|
+
const nestedArg = arg.arguments[index];
|
|
247
|
+
if (!nestedArg)
|
|
248
|
+
return false;
|
|
249
|
+
if (!matchesCondition(nestedArg, argCondition, state))
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
// Member expression condition: match $setup["ClientOnly"]
|
|
256
|
+
if ('member' in condition) {
|
|
257
|
+
if (!t.isMemberExpression(arg))
|
|
258
|
+
return false;
|
|
259
|
+
// Check object
|
|
260
|
+
if (!t.isIdentifier(arg.object) || arg.object.name !== condition.object)
|
|
261
|
+
return false;
|
|
262
|
+
// Check property
|
|
263
|
+
if (typeof condition.property === 'string') {
|
|
264
|
+
// Simple string property
|
|
265
|
+
if (t.isIdentifier(arg.property) && !arg.computed) {
|
|
266
|
+
return arg.property.name === condition.property;
|
|
267
|
+
}
|
|
268
|
+
if (t.isStringLiteral(arg.property) && arg.computed) {
|
|
269
|
+
return arg.property.value === condition.property;
|
|
270
|
+
}
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
// Nested condition on property (for future extensibility)
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Object condition: match prop value inside an object argument
|
|
279
|
+
if (!t.isObjectExpression(arg))
|
|
280
|
+
return false;
|
|
281
|
+
for (const prop of arg.properties) {
|
|
282
|
+
if (!t.isObjectProperty(prop))
|
|
283
|
+
continue;
|
|
284
|
+
if (!t.isIdentifier(prop.key) || prop.key.name !== condition.prop)
|
|
285
|
+
continue;
|
|
286
|
+
// Check value
|
|
287
|
+
if (condition.equals === null && t.isNullLiteral(prop.value))
|
|
288
|
+
return true;
|
|
289
|
+
if (condition.equals === true && t.isBooleanLiteral(prop.value) && prop.value.value === true)
|
|
290
|
+
return true;
|
|
291
|
+
if (condition.equals === false && t.isBooleanLiteral(prop.value) && prop.value.value === false)
|
|
292
|
+
return true;
|
|
293
|
+
if (typeof condition.equals === 'string' && t.isStringLiteral(prop.value) && prop.value.value === condition.equals)
|
|
294
|
+
return true;
|
|
295
|
+
if (typeof condition.equals === 'number' && t.isNumericLiteral(prop.value) && prop.value.value === condition.equals)
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Apply a replacement to a call expression
|
|
302
|
+
*/
|
|
303
|
+
function applyReplace(path, replace, state) {
|
|
304
|
+
// Replace the entire call expression
|
|
305
|
+
if (!('arg' in replace) && !('argsFrom' in replace)) {
|
|
306
|
+
path.replaceWith(valueToAst(replace.with));
|
|
307
|
+
state.modified = true;
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
// Replace a prop inside an object argument
|
|
311
|
+
if ('arg' in replace && 'prop' in replace) {
|
|
312
|
+
const arg = path.node.arguments[replace.arg];
|
|
313
|
+
if (!t.isObjectExpression(arg))
|
|
314
|
+
return;
|
|
315
|
+
for (const prop of arg.properties) {
|
|
316
|
+
if (!t.isObjectProperty(prop))
|
|
317
|
+
continue;
|
|
318
|
+
if (!t.isIdentifier(prop.key) || prop.key.name !== replace.prop)
|
|
319
|
+
continue;
|
|
320
|
+
prop.value = valueToAst(replace.with);
|
|
321
|
+
state.modified = true;
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// Replace entire argument
|
|
326
|
+
else if ('arg' in replace) {
|
|
327
|
+
if (path.node.arguments.length > replace.arg) {
|
|
328
|
+
path.node.arguments[replace.arg] = valueToAst(replace.with);
|
|
329
|
+
state.modified = true;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Replace all args from index onwards with a single value
|
|
333
|
+
else if ('argsFrom' in replace) {
|
|
334
|
+
if (path.node.arguments.length > replace.argsFrom) {
|
|
335
|
+
path.node.arguments = [...path.node.arguments.slice(0, replace.argsFrom), valueToAst(replace.with)];
|
|
336
|
+
state.modified = true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Apply a removal to a call expression
|
|
342
|
+
*/
|
|
343
|
+
function applyRemove(path, remove, state) {
|
|
344
|
+
// Remove a prop inside an object argument
|
|
345
|
+
if ('prop' in remove) {
|
|
346
|
+
const arg = path.node.arguments[remove.arg];
|
|
347
|
+
if (!t.isObjectExpression(arg))
|
|
348
|
+
return;
|
|
349
|
+
const index = arg.properties.findIndex((prop) => {
|
|
350
|
+
// Check ObjectProperty with Identifier key
|
|
351
|
+
if (t.isObjectProperty(prop) && t.isIdentifier(prop.key) && prop.key.name === remove.prop) {
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
// Check ObjectMethod (getter/setter)
|
|
355
|
+
if (t.isObjectMethod(prop) && t.isIdentifier(prop.key) && prop.key.name === remove.prop) {
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
return false;
|
|
359
|
+
});
|
|
360
|
+
if (index !== -1) {
|
|
361
|
+
arg.properties.splice(index, 1);
|
|
362
|
+
state.modified = true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Remove entire argument
|
|
366
|
+
else if ('arg' in remove) {
|
|
367
|
+
if (path.node.arguments.length > remove.arg) {
|
|
368
|
+
path.node.arguments.splice(remove.arg, 1);
|
|
369
|
+
state.modified = true;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// Remove all args from index onwards
|
|
373
|
+
else if ('argsFrom' in remove) {
|
|
374
|
+
if (path.node.arguments.length > remove.argsFrom) {
|
|
375
|
+
path.node.arguments = path.node.arguments.slice(0, remove.argsFrom);
|
|
376
|
+
state.modified = true;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Remove unreferenced bindings after modifications
|
|
382
|
+
*/
|
|
383
|
+
function removeUnreferencedPlugin(state) {
|
|
384
|
+
return {
|
|
385
|
+
visitor: {
|
|
386
|
+
Program: {
|
|
387
|
+
enter(program) {
|
|
388
|
+
for (const [name, binding] of Object.entries(program.scope.bindings)) {
|
|
389
|
+
if (!binding.referenced)
|
|
390
|
+
state.alreadyUnreferenced.add(name);
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
exit(program) {
|
|
394
|
+
if (!state.modified)
|
|
395
|
+
return;
|
|
396
|
+
removeUnreferenced(program, state.alreadyUnreferenced);
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function removeUnreferenced(program, alreadyUnreferenced) {
|
|
403
|
+
for (;;) {
|
|
404
|
+
program.scope.crawl();
|
|
405
|
+
let removed = false;
|
|
406
|
+
for (const [name, binding] of Object.entries(program.scope.bindings)) {
|
|
407
|
+
if (binding.referenced || alreadyUnreferenced.has(name))
|
|
408
|
+
continue;
|
|
409
|
+
const parent = binding.path.parentPath;
|
|
410
|
+
if (parent?.isImportDeclaration() && parent.node.specifiers.length === 1) {
|
|
411
|
+
parent.remove();
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
binding.path.remove();
|
|
415
|
+
}
|
|
416
|
+
removed = true;
|
|
417
|
+
}
|
|
418
|
+
if (!removed)
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export { pluginStaticReplace };
|
|
2
|
+
import { assert, assertUsage, createDebug } from '../utils.js';
|
|
3
|
+
import { isViteServerSide_extraSafe } from '../shared/isViteServerSide.js';
|
|
4
|
+
import { applyStaticReplace } from './pluginStaticReplace/applyStaticReplace.js';
|
|
5
|
+
const debug = createDebug('vike:staticReplace');
|
|
6
|
+
function pluginStaticReplace(vikeConfig) {
|
|
7
|
+
let config;
|
|
8
|
+
// staticReplaceList
|
|
9
|
+
const staticReplaceList = getStaticReplaceList(vikeConfig);
|
|
10
|
+
if (staticReplaceList.length === 0)
|
|
11
|
+
return [];
|
|
12
|
+
// === Rolldown filter
|
|
13
|
+
const skipNodeModules = '/node_modules/';
|
|
14
|
+
const include = getFilterRolldown(staticReplaceList);
|
|
15
|
+
assert(include);
|
|
16
|
+
const filterRolldown = {
|
|
17
|
+
id: {
|
|
18
|
+
exclude: `**${skipNodeModules}**`,
|
|
19
|
+
},
|
|
20
|
+
code: {
|
|
21
|
+
include,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
const filterFunction = (id, code) => {
|
|
25
|
+
if (id.includes(skipNodeModules))
|
|
26
|
+
return false;
|
|
27
|
+
if (!include.some((s) => code.includes(s)))
|
|
28
|
+
return false;
|
|
29
|
+
return true;
|
|
30
|
+
};
|
|
31
|
+
// ===
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
name: 'vike:pluginStaticReplace',
|
|
35
|
+
enforce: 'post',
|
|
36
|
+
configResolved: {
|
|
37
|
+
async handler(config_) {
|
|
38
|
+
config = config_;
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
transform: {
|
|
42
|
+
filter: filterRolldown,
|
|
43
|
+
async handler(code, id, options) {
|
|
44
|
+
assert(filterFunction(id, code));
|
|
45
|
+
debug('id', id);
|
|
46
|
+
const env = isViteServerSide_extraSafe(config, this.environment, options) ? 'server' : 'client';
|
|
47
|
+
debug('env', env);
|
|
48
|
+
const result = await applyStaticReplace(code, staticReplaceList, id, env);
|
|
49
|
+
if (debug.isActivated) {
|
|
50
|
+
if (result === undefined) {
|
|
51
|
+
debug('Skipped');
|
|
52
|
+
}
|
|
53
|
+
if (result === null) {
|
|
54
|
+
debug('AST parsed, but no modifications');
|
|
55
|
+
}
|
|
56
|
+
if (result) {
|
|
57
|
+
debug('Before:', code);
|
|
58
|
+
debug('After:', result.code);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Extract all staticReplaceList from vikeConfig
|
|
69
|
+
*/
|
|
70
|
+
function getStaticReplaceList(vikeConfig) {
|
|
71
|
+
const staticReplaceConfigs = vikeConfig._from.configsCumulative.staticReplace;
|
|
72
|
+
if (!staticReplaceConfigs)
|
|
73
|
+
return [];
|
|
74
|
+
const staticReplaceList = [];
|
|
75
|
+
for (const configValue of staticReplaceConfigs.values) {
|
|
76
|
+
const entries = configValue.value;
|
|
77
|
+
assert(Array.isArray(entries));
|
|
78
|
+
staticReplaceList.push(...entries);
|
|
79
|
+
}
|
|
80
|
+
return staticReplaceList;
|
|
81
|
+
}
|
|
82
|
+
function getFilterRolldown(staticReplaceList) {
|
|
83
|
+
return staticReplaceList.map((staticReplace) => {
|
|
84
|
+
const { filter } = staticReplace;
|
|
85
|
+
assertUsage(filter, '+staticReplace entry is missing rolldown filter');
|
|
86
|
+
return filter;
|
|
87
|
+
});
|
|
88
|
+
}
|