@tanstack/start-plugin-core 1.163.3 → 1.163.5
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/esm/constants.d.ts +1 -0
- package/dist/esm/constants.js +2 -0
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/import-protection-plugin/ast.d.ts +3 -0
- package/dist/esm/import-protection-plugin/ast.js +8 -0
- package/dist/esm/import-protection-plugin/ast.js.map +1 -0
- package/dist/esm/import-protection-plugin/constants.d.ts +6 -0
- package/dist/esm/import-protection-plugin/constants.js +24 -0
- package/dist/esm/import-protection-plugin/constants.js.map +1 -0
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.d.ts +22 -0
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js +95 -0
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +1 -0
- package/dist/esm/import-protection-plugin/plugin.d.ts +2 -13
- package/dist/esm/import-protection-plugin/plugin.js +684 -299
- package/dist/esm/import-protection-plugin/plugin.js.map +1 -1
- package/dist/esm/import-protection-plugin/postCompileUsage.js +4 -2
- package/dist/esm/import-protection-plugin/postCompileUsage.js.map +1 -1
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.d.ts +4 -5
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +225 -3
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +1 -1
- package/dist/esm/import-protection-plugin/sourceLocation.d.ts +4 -7
- package/dist/esm/import-protection-plugin/sourceLocation.js +18 -73
- package/dist/esm/import-protection-plugin/sourceLocation.js.map +1 -1
- package/dist/esm/import-protection-plugin/types.d.ts +94 -0
- package/dist/esm/import-protection-plugin/utils.d.ts +33 -1
- package/dist/esm/import-protection-plugin/utils.js +69 -3
- package/dist/esm/import-protection-plugin/utils.js.map +1 -1
- package/dist/esm/import-protection-plugin/virtualModules.d.ts +30 -2
- package/dist/esm/import-protection-plugin/virtualModules.js +66 -23
- package/dist/esm/import-protection-plugin/virtualModules.js.map +1 -1
- package/dist/esm/start-compiler-plugin/plugin.d.ts +2 -1
- package/dist/esm/start-compiler-plugin/plugin.js +1 -2
- package/dist/esm/start-compiler-plugin/plugin.js.map +1 -1
- package/package.json +4 -4
- package/src/constants.ts +2 -0
- package/src/import-protection-plugin/INTERNALS.md +462 -60
- package/src/import-protection-plugin/ast.ts +7 -0
- package/src/import-protection-plugin/constants.ts +25 -0
- package/src/import-protection-plugin/extensionlessAbsoluteIdResolver.ts +121 -0
- package/src/import-protection-plugin/plugin.ts +1080 -597
- package/src/import-protection-plugin/postCompileUsage.ts +8 -2
- package/src/import-protection-plugin/rewriteDeniedImports.ts +141 -9
- package/src/import-protection-plugin/sourceLocation.ts +19 -89
- package/src/import-protection-plugin/types.ts +103 -0
- package/src/import-protection-plugin/utils.ts +123 -4
- package/src/import-protection-plugin/virtualModules.ts +117 -31
- package/src/start-compiler-plugin/plugin.ts +7 -2
|
@@ -1,28 +1,41 @@
|
|
|
1
1
|
import { normalizePath } from "vite";
|
|
2
2
|
import { resolveViteId } from "../utils.js";
|
|
3
3
|
import { VITE_ENVIRONMENT_NAMES } from "../constants.js";
|
|
4
|
-
import { SERVER_FN_LOOKUP } from "../start-compiler-plugin/plugin.js";
|
|
5
4
|
import { formatViolation, ImportGraph, buildTrace } from "./trace.js";
|
|
6
5
|
import { getDefaultImportProtectionRules, getMarkerSpecifiers } from "./defaults.js";
|
|
7
|
-
import { findPostCompileUsagePos } from "./postCompileUsage.js";
|
|
8
6
|
import { matchesAny, compileMatchers } from "./matchers.js";
|
|
9
|
-
import {
|
|
10
|
-
import { collectMockExportNamesBySource } from "./rewriteDeniedImports.js";
|
|
11
|
-
import { loadResolvedVirtualModule, getResolvedVirtualModuleMatchers, resolveInternalVirtualModuleId, resolvedMarkerVirtualModuleId, mockRuntimeModuleIdFromViolation,
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const IMPORT_PROTECTION_DEBUG_FILTER = process.env.TSR_IMPORT_PROTECTION_DEBUG_FILTER;
|
|
16
|
-
function debugLog(...args) {
|
|
17
|
-
if (!IMPORT_PROTECTION_DEBUG) return;
|
|
18
|
-
console.warn("[import-protection:debug]", ...args);
|
|
19
|
-
}
|
|
20
|
-
function matchesDebugFilter(...values) {
|
|
21
|
-
if (!IMPORT_PROTECTION_DEBUG_FILTER) return true;
|
|
22
|
-
return values.some((v) => v.includes(IMPORT_PROTECTION_DEBUG_FILTER));
|
|
23
|
-
}
|
|
7
|
+
import { normalizeFilePath, matchesDebugFilter, debugLog, escapeRegExp, getOrCreate, clearNormalizeFilePathCache, shouldDeferViolation, dedupePatterns, relativizePath, extractImportSources, canonicalizeResolvedId, isInsideDirectory, buildSourceCandidates, buildResolutionCandidates } from "./utils.js";
|
|
8
|
+
import { collectNamedExports, rewriteDeniedImports, collectMockExportNamesBySource } from "./rewriteDeniedImports.js";
|
|
9
|
+
import { loadResolvedVirtualModule, getResolvedVirtualModuleMatchers, resolveInternalVirtualModuleId, resolvedMarkerVirtualModuleId, generateSelfContainedMockModule, mockRuntimeModuleIdFromViolation, generateDevSelfDenialModule, MOCK_BUILD_PREFIX, makeMockEdgeModuleId } from "./virtualModules.js";
|
|
10
|
+
import { ExtensionlessAbsoluteIdResolver } from "./extensionlessAbsoluteIdResolver.js";
|
|
11
|
+
import { IMPORT_PROTECTION_DEBUG, SERVER_FN_LOOKUP_QUERY, VITE_BROWSER_VIRTUAL_PREFIX } from "./constants.js";
|
|
12
|
+
import { pickOriginalCodeFromSourcesContent, buildLineIndex, ImportLocCache, buildCodeSnippet, findPostCompileUsageLocation, findImportStatementLocationFromTransformed, addTraceImportLocations } from "./sourceLocation.js";
|
|
24
13
|
function importProtectionPlugin(opts) {
|
|
25
14
|
let devServer = null;
|
|
15
|
+
const extensionlessIdResolver = new ExtensionlessAbsoluteIdResolver();
|
|
16
|
+
const resolveExtensionlessAbsoluteId = (id) => extensionlessIdResolver.resolve(id);
|
|
17
|
+
const importPatternCache = /* @__PURE__ */ new Map();
|
|
18
|
+
function findFirstImportSpecifierIndex(code, source) {
|
|
19
|
+
let patterns = importPatternCache.get(source);
|
|
20
|
+
if (!patterns) {
|
|
21
|
+
const escaped = escapeRegExp(source);
|
|
22
|
+
patterns = [
|
|
23
|
+
new RegExp(`\\bimport\\s+(['"])${escaped}\\1`),
|
|
24
|
+
new RegExp(`\\bfrom\\s+(['"])${escaped}\\1`),
|
|
25
|
+
new RegExp(`\\bimport\\s*\\(\\s*(['"])${escaped}\\1\\s*\\)`)
|
|
26
|
+
];
|
|
27
|
+
importPatternCache.set(source, patterns);
|
|
28
|
+
}
|
|
29
|
+
let best = -1;
|
|
30
|
+
for (const re of patterns) {
|
|
31
|
+
const m = re.exec(code);
|
|
32
|
+
if (!m) continue;
|
|
33
|
+
const idx = m.index + m[0].indexOf(source);
|
|
34
|
+
if (idx === -1) continue;
|
|
35
|
+
if (best === -1 || idx < best) best = idx;
|
|
36
|
+
}
|
|
37
|
+
return best;
|
|
38
|
+
}
|
|
26
39
|
function buildTraceFromModuleGraph(envName, env, targetFile) {
|
|
27
40
|
if (!devServer) return null;
|
|
28
41
|
const environment = devServer.environments[envName];
|
|
@@ -94,7 +107,6 @@ function importProtectionPlugin(opts) {
|
|
|
94
107
|
command: "build",
|
|
95
108
|
srcDirectory: "",
|
|
96
109
|
framework: opts.framework,
|
|
97
|
-
entryFiles: [],
|
|
98
110
|
effectiveBehavior: "error",
|
|
99
111
|
mockAccess: "error",
|
|
100
112
|
logMode: "once",
|
|
@@ -112,10 +124,6 @@ function importProtectionPlugin(opts) {
|
|
|
112
124
|
};
|
|
113
125
|
const envStates = /* @__PURE__ */ new Map();
|
|
114
126
|
const shared = { fileMarkerKind: /* @__PURE__ */ new Map() };
|
|
115
|
-
function getMarkerKindForFile(fileId) {
|
|
116
|
-
const file = normalizeFilePath(fileId);
|
|
117
|
-
return shared.fileMarkerKind.get(file);
|
|
118
|
-
}
|
|
119
127
|
async function rebuildAndAnnotateTrace(provider, env, envName, normalizedImporter, specifier, importerLoc, traceOverride) {
|
|
120
128
|
let trace = traceOverride ?? buildTrace(env.graph, normalizedImporter, config.maxTraceDepth);
|
|
121
129
|
if (config.command === "serve") {
|
|
@@ -128,7 +136,12 @@ function importProtectionPlugin(opts) {
|
|
|
128
136
|
trace = mgTrace;
|
|
129
137
|
}
|
|
130
138
|
}
|
|
131
|
-
await addTraceImportLocations(
|
|
139
|
+
await addTraceImportLocations(
|
|
140
|
+
provider,
|
|
141
|
+
trace,
|
|
142
|
+
env.importLocCache,
|
|
143
|
+
findFirstImportSpecifierIndex
|
|
144
|
+
);
|
|
132
145
|
if (trace.length > 0) {
|
|
133
146
|
const last = trace[trace.length - 1];
|
|
134
147
|
if (!last.specifier) last.specifier = specifier;
|
|
@@ -140,16 +153,16 @@ function importProtectionPlugin(opts) {
|
|
|
140
153
|
return trace;
|
|
141
154
|
}
|
|
142
155
|
async function buildViolationInfo(provider, env, envName, envType, importer, normalizedImporter, source, overrides, traceOverride) {
|
|
143
|
-
const
|
|
144
|
-
provider,
|
|
145
|
-
importer,
|
|
156
|
+
const sourceCandidates = buildSourceCandidates(
|
|
146
157
|
source,
|
|
147
|
-
|
|
148
|
-
|
|
158
|
+
"resolved" in overrides && typeof overrides.resolved === "string" ? overrides.resolved : void 0,
|
|
159
|
+
config.root
|
|
160
|
+
);
|
|
161
|
+
const loc = await resolveImporterLocation(
|
|
149
162
|
provider,
|
|
163
|
+
env,
|
|
150
164
|
importer,
|
|
151
|
-
|
|
152
|
-
env.importLocCache
|
|
165
|
+
sourceCandidates
|
|
153
166
|
);
|
|
154
167
|
const trace = await rebuildAndAnnotateTrace(
|
|
155
168
|
provider,
|
|
@@ -173,8 +186,22 @@ function importProtectionPlugin(opts) {
|
|
|
173
186
|
...overrides
|
|
174
187
|
};
|
|
175
188
|
}
|
|
189
|
+
async function resolveImporterLocation(provider, env, importer, sourceCandidates) {
|
|
190
|
+
for (const candidate of sourceCandidates) {
|
|
191
|
+
const loc = await findPostCompileUsageLocation(provider, importer, candidate) || await findImportStatementLocationFromTransformed(
|
|
192
|
+
provider,
|
|
193
|
+
importer,
|
|
194
|
+
candidate,
|
|
195
|
+
env.importLocCache,
|
|
196
|
+
findFirstImportSpecifierIndex
|
|
197
|
+
);
|
|
198
|
+
if (loc) return loc;
|
|
199
|
+
}
|
|
200
|
+
return void 0;
|
|
201
|
+
}
|
|
176
202
|
async function buildMarkerViolationFromResolvedImport(provider, env, envName, envType, importer, source, resolvedId, relativePath, traceOverride) {
|
|
177
|
-
const
|
|
203
|
+
const normalizedResolvedId = normalizeFilePath(resolvedId);
|
|
204
|
+
const markerKind = shared.fileMarkerKind.get(normalizedResolvedId);
|
|
178
205
|
const violates = envType === "client" && markerKind === "server" || envType === "server" && markerKind === "client";
|
|
179
206
|
if (!violates) return void 0;
|
|
180
207
|
const normalizedImporter = normalizeFilePath(importer);
|
|
@@ -188,8 +215,30 @@ function importProtectionPlugin(opts) {
|
|
|
188
215
|
source,
|
|
189
216
|
{
|
|
190
217
|
type: "marker",
|
|
191
|
-
resolved:
|
|
192
|
-
message:
|
|
218
|
+
resolved: normalizedResolvedId,
|
|
219
|
+
message: buildMarkerViolationMessage(relativePath, markerKind)
|
|
220
|
+
},
|
|
221
|
+
traceOverride
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
function buildMarkerViolationMessage(relativePath, markerKind) {
|
|
225
|
+
return markerKind === "server" ? `Module "${relativePath}" is marked server-only but is imported in the client environment` : `Module "${relativePath}" is marked client-only but is imported in the server environment`;
|
|
226
|
+
}
|
|
227
|
+
async function buildFileViolationInfo(provider, env, envName, envType, importer, normalizedImporter, source, resolvedPath, pattern, traceOverride) {
|
|
228
|
+
const relativePath = getRelativePath(resolvedPath);
|
|
229
|
+
return buildViolationInfo(
|
|
230
|
+
provider,
|
|
231
|
+
env,
|
|
232
|
+
envName,
|
|
233
|
+
envType,
|
|
234
|
+
importer,
|
|
235
|
+
normalizedImporter,
|
|
236
|
+
source,
|
|
237
|
+
{
|
|
238
|
+
type: "file",
|
|
239
|
+
pattern,
|
|
240
|
+
resolved: resolvedPath,
|
|
241
|
+
message: `Import "${source}" (resolved to "${relativePath}") is denied in the ${envType} environment`
|
|
193
242
|
},
|
|
194
243
|
traceOverride
|
|
195
244
|
);
|
|
@@ -201,6 +250,12 @@ function importProtectionPlugin(opts) {
|
|
|
201
250
|
const type = getEnvType(envName);
|
|
202
251
|
return type === "client" ? config.compiledRules.client : config.compiledRules.server;
|
|
203
252
|
}
|
|
253
|
+
function checkFileDenial(relativePath, matchers) {
|
|
254
|
+
if (matchers.excludeFiles.length > 0 && matchesAny(relativePath, matchers.excludeFiles)) {
|
|
255
|
+
return void 0;
|
|
256
|
+
}
|
|
257
|
+
return matchers.files.length > 0 ? matchesAny(relativePath, matchers.files) : void 0;
|
|
258
|
+
}
|
|
204
259
|
const environmentNames = /* @__PURE__ */ new Set([
|
|
205
260
|
VITE_ENVIRONMENT_NAMES.client,
|
|
206
261
|
VITE_ENVIRONMENT_NAMES.server
|
|
@@ -214,8 +269,6 @@ function importProtectionPlugin(opts) {
|
|
|
214
269
|
const transformResultCache = /* @__PURE__ */ new Map();
|
|
215
270
|
envState = {
|
|
216
271
|
graph: new ImportGraph(),
|
|
217
|
-
deniedSources: /* @__PURE__ */ new Set(),
|
|
218
|
-
deniedEdges: /* @__PURE__ */ new Map(),
|
|
219
272
|
mockExportsByImporter: /* @__PURE__ */ new Map(),
|
|
220
273
|
resolveCache: /* @__PURE__ */ new Map(),
|
|
221
274
|
resolveCacheByFile: /* @__PURE__ */ new Map(),
|
|
@@ -241,27 +294,137 @@ function importProtectionPlugin(opts) {
|
|
|
241
294
|
}
|
|
242
295
|
return envState;
|
|
243
296
|
}
|
|
297
|
+
function findExportsInMap(exportMap, candidates) {
|
|
298
|
+
for (const candidate of candidates) {
|
|
299
|
+
const hit = exportMap.get(candidate);
|
|
300
|
+
if (hit && hit.length > 0) return hit;
|
|
301
|
+
}
|
|
302
|
+
return [];
|
|
303
|
+
}
|
|
304
|
+
function buildIdCandidates(id, extra) {
|
|
305
|
+
const set = new Set(buildResolutionCandidates(id));
|
|
306
|
+
if (extra) {
|
|
307
|
+
for (const c of buildResolutionCandidates(extra)) set.add(c);
|
|
308
|
+
set.add(resolveExtensionlessAbsoluteId(extra));
|
|
309
|
+
}
|
|
310
|
+
return Array.from(set);
|
|
311
|
+
}
|
|
312
|
+
async function resolveExportsForDeniedSpecifier(env, ctx, info, importerIdHint) {
|
|
313
|
+
const importerFile = normalizeFilePath(info.importer);
|
|
314
|
+
const specifierCandidates = buildIdCandidates(info.specifier, info.resolved);
|
|
315
|
+
let parsedBySource = env.mockExportsByImporter.get(importerFile);
|
|
316
|
+
if (!parsedBySource) {
|
|
317
|
+
const importerCode = env.transformResultProvider.getTransformResult(importerFile)?.code ?? (importerIdHint && ctx.getModuleInfo ? ctx.getModuleInfo(importerIdHint)?.code ?? void 0 : void 0);
|
|
318
|
+
if (typeof importerCode !== "string" || importerCode.length === 0)
|
|
319
|
+
return [];
|
|
320
|
+
try {
|
|
321
|
+
parsedBySource = collectMockExportNamesBySource(importerCode);
|
|
322
|
+
await recordMockExportsForImporter(
|
|
323
|
+
env,
|
|
324
|
+
importerFile,
|
|
325
|
+
parsedBySource,
|
|
326
|
+
async (src) => {
|
|
327
|
+
const cacheKey = `${importerFile}:${src}`;
|
|
328
|
+
if (env.resolveCache.has(cacheKey)) {
|
|
329
|
+
return env.resolveCache.get(cacheKey) ?? void 0;
|
|
330
|
+
}
|
|
331
|
+
if (!ctx.resolve) return void 0;
|
|
332
|
+
const resolved = await ctx.resolve(src, info.importer, {
|
|
333
|
+
skipSelf: true
|
|
334
|
+
});
|
|
335
|
+
if (!resolved || resolved.external) return void 0;
|
|
336
|
+
return resolved.id;
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
parsedBySource = env.mockExportsByImporter.get(importerFile) ?? parsedBySource;
|
|
340
|
+
} catch {
|
|
341
|
+
return [];
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const direct = findExportsInMap(parsedBySource, specifierCandidates);
|
|
345
|
+
if (direct.length > 0) return direct;
|
|
346
|
+
const candidateSet = new Set(specifierCandidates);
|
|
347
|
+
for (const [sourceKey, names] of parsedBySource) {
|
|
348
|
+
if (!names.length) continue;
|
|
349
|
+
const resolvedId = await resolveSourceKey(
|
|
350
|
+
env,
|
|
351
|
+
ctx,
|
|
352
|
+
importerFile,
|
|
353
|
+
sourceKey,
|
|
354
|
+
info.importer
|
|
355
|
+
);
|
|
356
|
+
if (!resolvedId) continue;
|
|
357
|
+
const resolvedCandidates = buildIdCandidates(resolvedId);
|
|
358
|
+
resolvedCandidates.push(resolveExtensionlessAbsoluteId(resolvedId));
|
|
359
|
+
if (resolvedCandidates.some((v) => candidateSet.has(v))) {
|
|
360
|
+
return names;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return [];
|
|
364
|
+
}
|
|
365
|
+
async function resolveSourceKey(env, ctx, importerFile, sourceKey, importerId) {
|
|
366
|
+
const cacheKey = `${importerFile}:${sourceKey}`;
|
|
367
|
+
if (env.resolveCache.has(cacheKey)) {
|
|
368
|
+
return env.resolveCache.get(cacheKey) ?? void 0;
|
|
369
|
+
}
|
|
370
|
+
if (!ctx.resolve) return void 0;
|
|
371
|
+
try {
|
|
372
|
+
const resolved = await ctx.resolve(sourceKey, importerId, {
|
|
373
|
+
skipSelf: true
|
|
374
|
+
});
|
|
375
|
+
if (!resolved || resolved.external) return void 0;
|
|
376
|
+
return resolved.id;
|
|
377
|
+
} catch {
|
|
378
|
+
return void 0;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
async function recordMockExportsForImporter(env, importerId, namesBySource, resolveSource) {
|
|
382
|
+
const importerFile = normalizeFilePath(importerId);
|
|
383
|
+
if (namesBySource.size === 0) return;
|
|
384
|
+
for (const [source, names] of namesBySource) {
|
|
385
|
+
try {
|
|
386
|
+
const resolvedId = await resolveSource(source);
|
|
387
|
+
if (!resolvedId) continue;
|
|
388
|
+
namesBySource.set(normalizeFilePath(resolvedId), names);
|
|
389
|
+
namesBySource.set(resolveExtensionlessAbsoluteId(resolvedId), names);
|
|
390
|
+
} catch {
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
const existing = env.mockExportsByImporter.get(importerFile);
|
|
394
|
+
if (!existing) {
|
|
395
|
+
env.mockExportsByImporter.set(importerFile, namesBySource);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
for (const [source, names] of namesBySource) {
|
|
399
|
+
const prev = existing.get(source);
|
|
400
|
+
if (!prev) {
|
|
401
|
+
existing.set(source, names);
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
const union = /* @__PURE__ */ new Set([...prev, ...names]);
|
|
405
|
+
existing.set(source, Array.from(union).sort());
|
|
406
|
+
}
|
|
407
|
+
}
|
|
244
408
|
const shouldCheckImporterCache = /* @__PURE__ */ new Map();
|
|
245
409
|
function shouldCheckImporter(importer) {
|
|
246
410
|
let result = shouldCheckImporterCache.get(importer);
|
|
247
411
|
if (result !== void 0) return result;
|
|
248
412
|
const relativePath = relativizePath(importer, config.root);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
} else if (config.ignoreImporterMatchers.length > 0 && matchesAny(relativePath, config.ignoreImporterMatchers)) {
|
|
413
|
+
const excluded = config.excludeMatchers.length > 0 && matchesAny(relativePath, config.excludeMatchers) || config.ignoreImporterMatchers.length > 0 && matchesAny(relativePath, config.ignoreImporterMatchers);
|
|
414
|
+
if (excluded) {
|
|
252
415
|
result = false;
|
|
253
416
|
} else if (config.includeMatchers.length > 0) {
|
|
254
417
|
result = !!matchesAny(relativePath, config.includeMatchers);
|
|
255
418
|
} else if (config.srcDirectory) {
|
|
256
|
-
result = importer
|
|
419
|
+
result = isInsideDirectory(importer, config.srcDirectory);
|
|
257
420
|
} else {
|
|
258
421
|
result = true;
|
|
259
422
|
}
|
|
260
423
|
shouldCheckImporterCache.set(importer, result);
|
|
261
424
|
return result;
|
|
262
425
|
}
|
|
263
|
-
function dedupeKey(
|
|
264
|
-
return `${type}:${importer}:${specifier}:${resolved ?? ""}`;
|
|
426
|
+
function dedupeKey(info) {
|
|
427
|
+
return `${info.type}:${info.importer}:${info.specifier}:${info.resolved ?? ""}`;
|
|
265
428
|
}
|
|
266
429
|
function hasSeen(env, key) {
|
|
267
430
|
if (config.logMode === "always") return false;
|
|
@@ -272,6 +435,56 @@ function importProtectionPlugin(opts) {
|
|
|
272
435
|
function getRelativePath(absolutePath) {
|
|
273
436
|
return relativizePath(normalizePath(absolutePath), config.root);
|
|
274
437
|
}
|
|
438
|
+
function clearEnvState(envState) {
|
|
439
|
+
envState.resolveCache.clear();
|
|
440
|
+
envState.resolveCacheByFile.clear();
|
|
441
|
+
envState.importLocCache.clear();
|
|
442
|
+
envState.seenViolations.clear();
|
|
443
|
+
envState.transformResultCache.clear();
|
|
444
|
+
envState.transformResultKeysByFile.clear();
|
|
445
|
+
envState.postTransformImports.clear();
|
|
446
|
+
envState.serverFnLookupModules.clear();
|
|
447
|
+
envState.pendingViolations.clear();
|
|
448
|
+
envState.deferredBuildViolations.length = 0;
|
|
449
|
+
envState.graph.clear();
|
|
450
|
+
envState.mockExportsByImporter.clear();
|
|
451
|
+
}
|
|
452
|
+
function invalidateFileFromEnv(envState, file) {
|
|
453
|
+
envState.importLocCache.deleteByFile(file);
|
|
454
|
+
const resolveKeys = envState.resolveCacheByFile.get(file);
|
|
455
|
+
if (resolveKeys) {
|
|
456
|
+
for (const key of resolveKeys) envState.resolveCache.delete(key);
|
|
457
|
+
envState.resolveCacheByFile.delete(file);
|
|
458
|
+
}
|
|
459
|
+
envState.graph.invalidate(file);
|
|
460
|
+
envState.mockExportsByImporter.delete(file);
|
|
461
|
+
envState.serverFnLookupModules.delete(file);
|
|
462
|
+
envState.pendingViolations.delete(file);
|
|
463
|
+
const transformKeys = envState.transformResultKeysByFile.get(file);
|
|
464
|
+
if (transformKeys) {
|
|
465
|
+
for (const key of transformKeys) {
|
|
466
|
+
envState.transformResultCache.delete(key);
|
|
467
|
+
envState.postTransformImports.delete(key);
|
|
468
|
+
}
|
|
469
|
+
envState.transformResultKeysByFile.delete(file);
|
|
470
|
+
} else {
|
|
471
|
+
envState.transformResultCache.delete(file);
|
|
472
|
+
envState.postTransformImports.delete(file);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
function cacheTransformResult(envState, file, cacheKey, result) {
|
|
476
|
+
envState.transformResultCache.set(cacheKey, result);
|
|
477
|
+
const keySet = getOrCreate(
|
|
478
|
+
envState.transformResultKeysByFile,
|
|
479
|
+
file,
|
|
480
|
+
() => /* @__PURE__ */ new Set()
|
|
481
|
+
);
|
|
482
|
+
keySet.add(cacheKey);
|
|
483
|
+
if (cacheKey !== file) {
|
|
484
|
+
envState.transformResultCache.set(file, result);
|
|
485
|
+
keySet.add(file);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
275
488
|
function registerEntries() {
|
|
276
489
|
const { resolvedStartConfig } = opts.getConfig();
|
|
277
490
|
for (const envDef of opts.environments) {
|
|
@@ -288,6 +501,46 @@ function importProtectionPlugin(opts) {
|
|
|
288
501
|
}
|
|
289
502
|
}
|
|
290
503
|
}
|
|
504
|
+
function getPostTransformImports(env, file) {
|
|
505
|
+
const keySet = env.transformResultKeysByFile.get(file);
|
|
506
|
+
let merged = null;
|
|
507
|
+
if (keySet) {
|
|
508
|
+
for (const k of keySet) {
|
|
509
|
+
if (k.includes(SERVER_FN_LOOKUP_QUERY)) continue;
|
|
510
|
+
const imports = env.postTransformImports.get(k);
|
|
511
|
+
if (imports) {
|
|
512
|
+
if (!merged) merged = new Set(imports);
|
|
513
|
+
else for (const v of imports) merged.add(v);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
if (!merged) {
|
|
518
|
+
const imports = env.postTransformImports.get(file);
|
|
519
|
+
if (imports) merged = new Set(imports);
|
|
520
|
+
}
|
|
521
|
+
return merged;
|
|
522
|
+
}
|
|
523
|
+
function checkEdgeLiveness(env, parent, target) {
|
|
524
|
+
const keySet = env.transformResultKeysByFile.get(parent);
|
|
525
|
+
let anyVariantCached = false;
|
|
526
|
+
if (keySet) {
|
|
527
|
+
for (const k of keySet) {
|
|
528
|
+
if (k.includes(SERVER_FN_LOOKUP_QUERY)) continue;
|
|
529
|
+
const imports = env.postTransformImports.get(k);
|
|
530
|
+
if (imports) {
|
|
531
|
+
anyVariantCached = true;
|
|
532
|
+
if (imports.has(target)) return "live";
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (!anyVariantCached) {
|
|
537
|
+
const imports = env.postTransformImports.get(parent);
|
|
538
|
+
if (imports) return imports.has(target) ? "live" : "dead";
|
|
539
|
+
const hasTransformResult = env.transformResultCache.has(parent) || (keySet ? keySet.size > 0 : false);
|
|
540
|
+
return hasTransformResult ? "pending" : "no-data";
|
|
541
|
+
}
|
|
542
|
+
return "dead";
|
|
543
|
+
}
|
|
291
544
|
function checkPostTransformReachability(env, file) {
|
|
292
545
|
const visited = /* @__PURE__ */ new Set();
|
|
293
546
|
const queue = [file];
|
|
@@ -304,147 +557,148 @@ function importProtectionPlugin(opts) {
|
|
|
304
557
|
if (!importers) continue;
|
|
305
558
|
for (const [parent] of importers) {
|
|
306
559
|
if (visited.has(parent)) continue;
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
let edgeLive = false;
|
|
310
|
-
if (keySet) {
|
|
311
|
-
for (const k of keySet) {
|
|
312
|
-
if (k.includes(SERVER_FN_LOOKUP_QUERY)) continue;
|
|
313
|
-
const resolvedImports = env.postTransformImports.get(k);
|
|
314
|
-
if (resolvedImports) {
|
|
315
|
-
anyVariantCached = true;
|
|
316
|
-
if (resolvedImports.has(current)) {
|
|
317
|
-
edgeLive = true;
|
|
318
|
-
break;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if (!anyVariantCached) {
|
|
324
|
-
const resolvedImports = env.postTransformImports.get(parent);
|
|
325
|
-
if (resolvedImports) {
|
|
326
|
-
anyVariantCached = true;
|
|
327
|
-
if (resolvedImports.has(current)) {
|
|
328
|
-
edgeLive = true;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
if (!anyVariantCached) {
|
|
333
|
-
const hasTransformResult = env.transformResultCache.has(parent) || (keySet ? keySet.size > 0 : false);
|
|
334
|
-
if (hasTransformResult) {
|
|
335
|
-
hasUnknownEdge = true;
|
|
336
|
-
continue;
|
|
337
|
-
}
|
|
338
|
-
queue.push(parent);
|
|
339
|
-
continue;
|
|
340
|
-
}
|
|
341
|
-
if (edgeLive) {
|
|
560
|
+
const liveness = checkEdgeLiveness(env, parent, current);
|
|
561
|
+
if (liveness === "live" || liveness === "no-data") {
|
|
342
562
|
queue.push(parent);
|
|
563
|
+
} else if (liveness === "pending") {
|
|
564
|
+
hasUnknownEdge = true;
|
|
343
565
|
}
|
|
344
566
|
}
|
|
345
567
|
}
|
|
346
568
|
return hasUnknownEdge ? "unknown" : "unreachable";
|
|
347
569
|
}
|
|
570
|
+
function filterEdgeSurvival(env, file, violations) {
|
|
571
|
+
const postTransform = getPostTransformImports(env, file);
|
|
572
|
+
if (postTransform) {
|
|
573
|
+
const surviving = violations.filter(
|
|
574
|
+
(pv) => !pv.info.resolved || postTransform.has(pv.info.resolved)
|
|
575
|
+
);
|
|
576
|
+
if (surviving.length === 0) return "all-stripped";
|
|
577
|
+
env.pendingViolations.set(file, surviving);
|
|
578
|
+
return { active: surviving, edgeSurvivalApplied: true };
|
|
579
|
+
}
|
|
580
|
+
if (violations.some((pv) => pv.fromPreTransformResolve)) {
|
|
581
|
+
return "await-transform";
|
|
582
|
+
}
|
|
583
|
+
return { active: violations, edgeSurvivalApplied: false };
|
|
584
|
+
}
|
|
348
585
|
async function processPendingViolations(env, warnFn) {
|
|
349
586
|
if (env.pendingViolations.size === 0) return;
|
|
350
587
|
const toDelete = [];
|
|
351
588
|
for (const [file, violations] of env.pendingViolations) {
|
|
589
|
+
const filtered = filterEdgeSurvival(env, file, violations);
|
|
590
|
+
if (filtered === "all-stripped") {
|
|
591
|
+
toDelete.push(file);
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
if (filtered === "await-transform") continue;
|
|
595
|
+
const { active, edgeSurvivalApplied } = filtered;
|
|
352
596
|
const status = env.graph.entries.size > 0 ? checkPostTransformReachability(env, file) : "unknown";
|
|
353
597
|
if (status === "reachable") {
|
|
354
|
-
for (const pv of
|
|
355
|
-
|
|
356
|
-
pv.info.type,
|
|
357
|
-
pv.info.importer,
|
|
358
|
-
pv.info.specifier,
|
|
359
|
-
pv.info.resolved
|
|
360
|
-
);
|
|
361
|
-
if (!hasSeen(env, key)) {
|
|
362
|
-
const freshTrace = await rebuildAndAnnotateTrace(
|
|
363
|
-
env.transformResultProvider,
|
|
364
|
-
env,
|
|
365
|
-
pv.info.env,
|
|
366
|
-
pv.info.importer,
|
|
367
|
-
pv.info.specifier,
|
|
368
|
-
pv.info.importerLoc
|
|
369
|
-
);
|
|
370
|
-
if (freshTrace.length > pv.info.trace.length) {
|
|
371
|
-
pv.info.trace = freshTrace;
|
|
372
|
-
}
|
|
373
|
-
if (config.onViolation) {
|
|
374
|
-
const result = await config.onViolation(pv.info);
|
|
375
|
-
if (result === false) continue;
|
|
376
|
-
}
|
|
377
|
-
warnFn(formatViolation(pv.info, config.root));
|
|
378
|
-
}
|
|
598
|
+
for (const pv of active) {
|
|
599
|
+
await emitPendingViolation(env, warnFn, pv);
|
|
379
600
|
}
|
|
380
601
|
toDelete.push(file);
|
|
381
602
|
} else if (status === "unreachable") {
|
|
382
603
|
toDelete.push(file);
|
|
604
|
+
} else if (config.command === "serve") {
|
|
605
|
+
let emittedAny = false;
|
|
606
|
+
for (const pv of active) {
|
|
607
|
+
if (pv.fromPreTransformResolve) continue;
|
|
608
|
+
const shouldEmit = edgeSurvivalApplied || pv.info.type === "file" && !!pv.info.resolved && isInsideDirectory(pv.info.resolved, config.srcDirectory);
|
|
609
|
+
if (shouldEmit) {
|
|
610
|
+
emittedAny = await emitPendingViolation(env, warnFn, pv) || emittedAny;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (emittedAny) {
|
|
614
|
+
toDelete.push(file);
|
|
615
|
+
}
|
|
383
616
|
}
|
|
384
617
|
}
|
|
385
618
|
for (const file of toDelete) {
|
|
386
619
|
env.pendingViolations.delete(file);
|
|
387
620
|
}
|
|
388
621
|
}
|
|
389
|
-
function
|
|
622
|
+
async function emitPendingViolation(env, warnFn, pv) {
|
|
623
|
+
if (!pv.info.importerLoc) {
|
|
624
|
+
const sourceCandidates = buildSourceCandidates(
|
|
625
|
+
pv.info.specifier,
|
|
626
|
+
pv.info.resolved,
|
|
627
|
+
config.root
|
|
628
|
+
);
|
|
629
|
+
const loc = await resolveImporterLocation(
|
|
630
|
+
env.transformResultProvider,
|
|
631
|
+
env,
|
|
632
|
+
pv.info.importer,
|
|
633
|
+
sourceCandidates
|
|
634
|
+
);
|
|
635
|
+
if (loc) {
|
|
636
|
+
pv.info.importerLoc = loc;
|
|
637
|
+
pv.info.snippet = buildCodeSnippet(
|
|
638
|
+
env.transformResultProvider,
|
|
639
|
+
pv.info.importer,
|
|
640
|
+
loc
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if (hasSeen(env, dedupeKey(pv.info))) {
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
const freshTrace = await rebuildAndAnnotateTrace(
|
|
648
|
+
env.transformResultProvider,
|
|
649
|
+
env,
|
|
650
|
+
pv.info.env,
|
|
651
|
+
pv.info.importer,
|
|
652
|
+
pv.info.specifier,
|
|
653
|
+
pv.info.importerLoc
|
|
654
|
+
);
|
|
655
|
+
if (freshTrace.length > pv.info.trace.length) {
|
|
656
|
+
pv.info.trace = freshTrace;
|
|
657
|
+
}
|
|
658
|
+
if (config.onViolation) {
|
|
659
|
+
const result = await config.onViolation(pv.info);
|
|
660
|
+
if (result === false) return false;
|
|
661
|
+
}
|
|
662
|
+
warnFn(formatViolation(pv.info, config.root));
|
|
663
|
+
return true;
|
|
664
|
+
}
|
|
665
|
+
function deferViolation(env, importerFile, info, isPreTransformResolve) {
|
|
390
666
|
getOrCreate(env.pendingViolations, importerFile, () => []).push({
|
|
391
667
|
info,
|
|
392
|
-
|
|
668
|
+
fromPreTransformResolve: isPreTransformResolve
|
|
393
669
|
});
|
|
394
670
|
}
|
|
395
671
|
let buildViolationCounter = 0;
|
|
396
|
-
async function handleViolation(ctx, env, info, violationOpts) {
|
|
397
|
-
const key = dedupeKey(
|
|
398
|
-
info.type,
|
|
399
|
-
info.importer,
|
|
400
|
-
info.specifier,
|
|
401
|
-
info.resolved
|
|
402
|
-
);
|
|
672
|
+
async function handleViolation(ctx, env, info, importerIdHint, violationOpts) {
|
|
403
673
|
if (!violationOpts?.silent) {
|
|
404
674
|
if (config.onViolation) {
|
|
405
675
|
const result = await config.onViolation(info);
|
|
406
|
-
if (result === false)
|
|
407
|
-
return void 0;
|
|
408
|
-
}
|
|
676
|
+
if (result === false) return void 0;
|
|
409
677
|
}
|
|
410
678
|
if (config.effectiveBehavior === "error") {
|
|
411
679
|
return ctx.error(formatViolation(info, config.root));
|
|
412
680
|
}
|
|
413
|
-
|
|
414
|
-
if (!seen) {
|
|
681
|
+
if (!hasSeen(env, dedupeKey(info))) {
|
|
415
682
|
ctx.warn(formatViolation(info, config.root));
|
|
416
683
|
}
|
|
417
|
-
} else {
|
|
418
|
-
|
|
419
|
-
return void 0;
|
|
420
|
-
}
|
|
684
|
+
} else if (config.effectiveBehavior === "error" && config.command !== "build") {
|
|
685
|
+
return void 0;
|
|
421
686
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
info,
|
|
429
|
-
config.mockAccess,
|
|
430
|
-
config.root
|
|
431
|
-
);
|
|
432
|
-
const importerFile2 = normalizeFilePath(info.importer);
|
|
433
|
-
const exports2 = env.mockExportsByImporter.get(importerFile2)?.get(info.specifier) ?? [];
|
|
434
|
-
return resolveViteId(
|
|
435
|
-
makeMockEdgeModuleId(exports2, info.specifier, runtimeId)
|
|
436
|
-
);
|
|
437
|
-
}
|
|
438
|
-
const baseMockId = `${MOCK_BUILD_PREFIX}${buildViolationCounter++}`;
|
|
439
|
-
const importerFile = normalizeFilePath(info.importer);
|
|
440
|
-
const exports = env.mockExportsByImporter.get(importerFile)?.get(info.specifier) ?? [];
|
|
441
|
-
return resolveViteId(
|
|
442
|
-
makeMockEdgeModuleId(exports, info.specifier, baseMockId)
|
|
687
|
+
if (info.type === "file") return info.resolved;
|
|
688
|
+
const exports = await resolveExportsForDeniedSpecifier(
|
|
689
|
+
env,
|
|
690
|
+
ctx,
|
|
691
|
+
info,
|
|
692
|
+
importerIdHint
|
|
443
693
|
);
|
|
694
|
+
const baseMockId = config.command === "serve" ? mockRuntimeModuleIdFromViolation(info, config.mockAccess, config.root) : `${MOCK_BUILD_PREFIX}${buildViolationCounter++}`;
|
|
695
|
+
return resolveViteId(makeMockEdgeModuleId(exports, baseMockId));
|
|
444
696
|
}
|
|
445
|
-
async function reportOrDeferViolation(ctx, env, importerFile, info, shouldDefer, isPreTransformResolve) {
|
|
697
|
+
async function reportOrDeferViolation(ctx, env, importerFile, importerIdHint, info, shouldDefer, isPreTransformResolve) {
|
|
446
698
|
if (shouldDefer) {
|
|
447
|
-
const result = await handleViolation(ctx, env, info, {
|
|
699
|
+
const result = await handleViolation(ctx, env, info, importerIdHint, {
|
|
700
|
+
silent: true
|
|
701
|
+
});
|
|
448
702
|
if (config.command === "build") {
|
|
449
703
|
const mockId = result ?? "";
|
|
450
704
|
env.deferredBuildViolations.push({
|
|
@@ -454,12 +708,12 @@ function importProtectionPlugin(opts) {
|
|
|
454
708
|
checkModuleId: info.type === "marker" ? info.importer : void 0
|
|
455
709
|
});
|
|
456
710
|
} else {
|
|
457
|
-
deferViolation(env, importerFile, info,
|
|
711
|
+
deferViolation(env, importerFile, info, isPreTransformResolve);
|
|
458
712
|
await processPendingViolations(env, ctx.warn.bind(ctx));
|
|
459
713
|
}
|
|
460
714
|
return result;
|
|
461
715
|
}
|
|
462
|
-
return
|
|
716
|
+
return handleViolation(ctx, env, info, importerIdHint, {
|
|
463
717
|
silent: isPreTransformResolve
|
|
464
718
|
});
|
|
465
719
|
}
|
|
@@ -476,24 +730,17 @@ function importProtectionPlugin(opts) {
|
|
|
476
730
|
config.command = viteConfig.command;
|
|
477
731
|
const { startConfig, resolvedStartConfig } = opts.getConfig();
|
|
478
732
|
config.srcDirectory = resolvedStartConfig.srcDirectory;
|
|
479
|
-
config.entryFiles = [
|
|
480
|
-
resolvedStartConfig.routerFilePath,
|
|
481
|
-
resolvedStartConfig.startFilePath
|
|
482
|
-
].filter((f) => Boolean(f));
|
|
483
733
|
const userOpts = startConfig.importProtection;
|
|
484
734
|
if (userOpts?.enabled === false) {
|
|
485
735
|
config.enabled = false;
|
|
486
736
|
return;
|
|
487
737
|
}
|
|
488
738
|
config.enabled = true;
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
} else {
|
|
493
|
-
config.effectiveBehavior = viteConfig.command === "serve" ? userOpts.behavior.dev ?? "mock" : userOpts.behavior.build ?? "error";
|
|
494
|
-
}
|
|
739
|
+
const behavior = userOpts?.behavior;
|
|
740
|
+
if (typeof behavior === "string") {
|
|
741
|
+
config.effectiveBehavior = behavior;
|
|
495
742
|
} else {
|
|
496
|
-
config.effectiveBehavior = viteConfig.command === "serve" ? "mock" : "error";
|
|
743
|
+
config.effectiveBehavior = viteConfig.command === "serve" ? behavior?.dev ?? "mock" : behavior?.build ?? "error";
|
|
497
744
|
}
|
|
498
745
|
config.logMode = userOpts?.log ?? "once";
|
|
499
746
|
config.mockAccess = userOpts?.mockAccess ?? "error";
|
|
@@ -503,36 +750,38 @@ function importProtectionPlugin(opts) {
|
|
|
503
750
|
config.onViolation = (info) => fn(info);
|
|
504
751
|
}
|
|
505
752
|
const defaults = getDefaultImportProtectionRules();
|
|
753
|
+
const pick = (user, fallback) => user ? [...user] : [...fallback];
|
|
506
754
|
const clientSpecifiers = dedupePatterns([
|
|
507
755
|
...defaults.client.specifiers,
|
|
508
756
|
...userOpts?.client?.specifiers ?? []
|
|
509
757
|
]);
|
|
510
|
-
const clientFiles = userOpts?.client?.files ? [...userOpts.client.files] : [...defaults.client.files];
|
|
511
|
-
const clientExcludeFiles = userOpts?.client?.excludeFiles ? [...userOpts.client.excludeFiles] : [...defaults.client.excludeFiles];
|
|
512
|
-
const serverSpecifiers = userOpts?.server?.specifiers ? dedupePatterns([...userOpts.server.specifiers]) : dedupePatterns([...defaults.server.specifiers]);
|
|
513
|
-
const serverFiles = userOpts?.server?.files ? [...userOpts.server.files] : [...defaults.server.files];
|
|
514
|
-
const serverExcludeFiles = userOpts?.server?.excludeFiles ? [...userOpts.server.excludeFiles] : [...defaults.server.excludeFiles];
|
|
515
758
|
config.compiledRules.client = {
|
|
516
759
|
specifiers: compileMatchers(clientSpecifiers),
|
|
517
|
-
files: compileMatchers(
|
|
518
|
-
|
|
760
|
+
files: compileMatchers(
|
|
761
|
+
pick(userOpts?.client?.files, defaults.client.files)
|
|
762
|
+
),
|
|
763
|
+
excludeFiles: compileMatchers(
|
|
764
|
+
pick(userOpts?.client?.excludeFiles, defaults.client.excludeFiles)
|
|
765
|
+
)
|
|
519
766
|
};
|
|
520
767
|
config.compiledRules.server = {
|
|
521
|
-
specifiers: compileMatchers(
|
|
522
|
-
|
|
523
|
-
|
|
768
|
+
specifiers: compileMatchers(
|
|
769
|
+
dedupePatterns(
|
|
770
|
+
pick(userOpts?.server?.specifiers, defaults.server.specifiers)
|
|
771
|
+
)
|
|
772
|
+
),
|
|
773
|
+
files: compileMatchers(
|
|
774
|
+
pick(userOpts?.server?.files, defaults.server.files)
|
|
775
|
+
),
|
|
776
|
+
excludeFiles: compileMatchers(
|
|
777
|
+
pick(userOpts?.server?.excludeFiles, defaults.server.excludeFiles)
|
|
778
|
+
)
|
|
524
779
|
};
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
}
|
|
531
|
-
if (userOpts?.ignoreImporters) {
|
|
532
|
-
config.ignoreImporterMatchers = compileMatchers(
|
|
533
|
-
userOpts.ignoreImporters
|
|
534
|
-
);
|
|
535
|
-
}
|
|
780
|
+
config.includeMatchers = compileMatchers(userOpts?.include ?? []);
|
|
781
|
+
config.excludeMatchers = compileMatchers(userOpts?.exclude ?? []);
|
|
782
|
+
config.ignoreImporterMatchers = compileMatchers(
|
|
783
|
+
userOpts?.ignoreImporters ?? []
|
|
784
|
+
);
|
|
536
785
|
const markers = getMarkerSpecifiers();
|
|
537
786
|
config.markerSpecifiers = {
|
|
538
787
|
serverOnly: new Set(markers.serverOnly),
|
|
@@ -545,23 +794,11 @@ function importProtectionPlugin(opts) {
|
|
|
545
794
|
buildStart() {
|
|
546
795
|
if (!config.enabled) return;
|
|
547
796
|
clearNormalizeFilePathCache();
|
|
548
|
-
|
|
797
|
+
extensionlessIdResolver.clear();
|
|
798
|
+
importPatternCache.clear();
|
|
549
799
|
shouldCheckImporterCache.clear();
|
|
550
800
|
for (const envState of envStates.values()) {
|
|
551
|
-
envState
|
|
552
|
-
envState.resolveCacheByFile.clear();
|
|
553
|
-
envState.importLocCache.clear();
|
|
554
|
-
envState.seenViolations.clear();
|
|
555
|
-
envState.transformResultCache.clear();
|
|
556
|
-
envState.transformResultKeysByFile.clear();
|
|
557
|
-
envState.postTransformImports.clear();
|
|
558
|
-
envState.serverFnLookupModules.clear();
|
|
559
|
-
envState.pendingViolations.clear();
|
|
560
|
-
envState.deferredBuildViolations.length = 0;
|
|
561
|
-
envState.graph.clear();
|
|
562
|
-
envState.deniedSources.clear();
|
|
563
|
-
envState.deniedEdges.clear();
|
|
564
|
-
envState.mockExportsByImporter.clear();
|
|
801
|
+
clearEnvState(envState);
|
|
565
802
|
}
|
|
566
803
|
shared.fileMarkerKind.clear();
|
|
567
804
|
registerEntries();
|
|
@@ -572,32 +809,10 @@ function importProtectionPlugin(opts) {
|
|
|
572
809
|
if (mod.id) {
|
|
573
810
|
const id = mod.id;
|
|
574
811
|
const importerFile = normalizeFilePath(id);
|
|
812
|
+
extensionlessIdResolver.invalidateByFile(importerFile);
|
|
575
813
|
shared.fileMarkerKind.delete(importerFile);
|
|
576
814
|
for (const envState of envStates.values()) {
|
|
577
|
-
envState
|
|
578
|
-
const resolveKeys = envState.resolveCacheByFile.get(importerFile);
|
|
579
|
-
if (resolveKeys) {
|
|
580
|
-
for (const key of resolveKeys) {
|
|
581
|
-
envState.resolveCache.delete(key);
|
|
582
|
-
}
|
|
583
|
-
envState.resolveCacheByFile.delete(importerFile);
|
|
584
|
-
}
|
|
585
|
-
envState.graph.invalidate(importerFile);
|
|
586
|
-
envState.deniedEdges.delete(importerFile);
|
|
587
|
-
envState.mockExportsByImporter.delete(importerFile);
|
|
588
|
-
envState.serverFnLookupModules.delete(importerFile);
|
|
589
|
-
envState.pendingViolations.delete(importerFile);
|
|
590
|
-
const transformKeys = envState.transformResultKeysByFile.get(importerFile);
|
|
591
|
-
if (transformKeys) {
|
|
592
|
-
for (const key of transformKeys) {
|
|
593
|
-
envState.transformResultCache.delete(key);
|
|
594
|
-
envState.postTransformImports.delete(key);
|
|
595
|
-
}
|
|
596
|
-
envState.transformResultKeysByFile.delete(importerFile);
|
|
597
|
-
} else {
|
|
598
|
-
envState.transformResultCache.delete(importerFile);
|
|
599
|
-
envState.postTransformImports.delete(importerFile);
|
|
600
|
-
}
|
|
815
|
+
invalidateFileFromEnv(envState, importerFile);
|
|
601
816
|
}
|
|
602
817
|
}
|
|
603
818
|
}
|
|
@@ -611,7 +826,7 @@ function importProtectionPlugin(opts) {
|
|
|
611
826
|
if (IMPORT_PROTECTION_DEBUG) {
|
|
612
827
|
const importerPath = importer ? normalizeFilePath(importer) : "(entry)";
|
|
613
828
|
const isEntryResolve = !importer;
|
|
614
|
-
const filtered =
|
|
829
|
+
const filtered = process.env.TSR_IMPORT_PROTECTION_DEBUG_FILTER === "entry" ? isEntryResolve : matchesDebugFilter(source, importerPath);
|
|
615
830
|
if (filtered) {
|
|
616
831
|
debugLog("resolveId", {
|
|
617
832
|
env: envName,
|
|
@@ -619,8 +834,7 @@ function importProtectionPlugin(opts) {
|
|
|
619
834
|
source,
|
|
620
835
|
importer: importerPath,
|
|
621
836
|
isEntryResolve,
|
|
622
|
-
command: config.command
|
|
623
|
-
behavior: config.effectiveBehavior
|
|
837
|
+
command: config.command
|
|
624
838
|
});
|
|
625
839
|
}
|
|
626
840
|
}
|
|
@@ -642,7 +856,20 @@ function importProtectionPlugin(opts) {
|
|
|
642
856
|
const isPreTransformResolve = isDirectLookup || env.serverFnLookupModules.has(normalizedImporter) || isScanResolve;
|
|
643
857
|
const isDevMock = config.command === "serve" && config.effectiveBehavior === "mock";
|
|
644
858
|
const isBuild = config.command === "build";
|
|
645
|
-
const shouldDefer =
|
|
859
|
+
const shouldDefer = shouldDeferViolation({ isBuild, isDevMock });
|
|
860
|
+
const resolveAgainstImporter = async () => {
|
|
861
|
+
const primary = await this.resolve(source, importer, {
|
|
862
|
+
skipSelf: true
|
|
863
|
+
});
|
|
864
|
+
if (primary) {
|
|
865
|
+
return canonicalizeResolvedId(
|
|
866
|
+
primary.id,
|
|
867
|
+
config.root,
|
|
868
|
+
resolveExtensionlessAbsoluteId
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
return null;
|
|
872
|
+
};
|
|
646
873
|
const markerKind = config.markerSpecifiers.serverOnly.has(source) ? "server" : config.markerSpecifiers.clientOnly.has(source) ? "client" : void 0;
|
|
647
874
|
if (markerKind) {
|
|
648
875
|
const existing = shared.fileMarkerKind.get(normalizedImporter);
|
|
@@ -664,13 +891,17 @@ function importProtectionPlugin(opts) {
|
|
|
664
891
|
source,
|
|
665
892
|
{
|
|
666
893
|
type: "marker",
|
|
667
|
-
message:
|
|
894
|
+
message: buildMarkerViolationMessage(
|
|
895
|
+
getRelativePath(normalizedImporter),
|
|
896
|
+
markerKind
|
|
897
|
+
)
|
|
668
898
|
}
|
|
669
899
|
);
|
|
670
900
|
const markerResult = await reportOrDeferViolation(
|
|
671
901
|
this,
|
|
672
902
|
env,
|
|
673
903
|
normalizedImporter,
|
|
904
|
+
importer,
|
|
674
905
|
info,
|
|
675
906
|
shouldDefer,
|
|
676
907
|
isPreTransformResolve
|
|
@@ -679,6 +910,40 @@ function importProtectionPlugin(opts) {
|
|
|
679
910
|
return markerResult;
|
|
680
911
|
}
|
|
681
912
|
}
|
|
913
|
+
const envRetroKey = `retro-marker:${normalizedImporter}`;
|
|
914
|
+
if (violatesEnv && !env.seenViolations.has(envRetroKey)) {
|
|
915
|
+
env.seenViolations.add(envRetroKey);
|
|
916
|
+
let retroDeferred = false;
|
|
917
|
+
const importersMap = env.graph.reverseEdges.get(normalizedImporter);
|
|
918
|
+
if (importersMap && importersMap.size > 0) {
|
|
919
|
+
for (const [importerFile, specifier] of importersMap) {
|
|
920
|
+
if (!specifier) continue;
|
|
921
|
+
if (!shouldCheckImporter(importerFile)) continue;
|
|
922
|
+
const markerInfo = await buildMarkerViolationFromResolvedImport(
|
|
923
|
+
provider,
|
|
924
|
+
env,
|
|
925
|
+
envName,
|
|
926
|
+
envType,
|
|
927
|
+
importerFile,
|
|
928
|
+
specifier,
|
|
929
|
+
normalizedImporter,
|
|
930
|
+
getRelativePath(normalizedImporter)
|
|
931
|
+
);
|
|
932
|
+
if (markerInfo) {
|
|
933
|
+
deferViolation(
|
|
934
|
+
env,
|
|
935
|
+
importerFile,
|
|
936
|
+
markerInfo,
|
|
937
|
+
isPreTransformResolve
|
|
938
|
+
);
|
|
939
|
+
retroDeferred = true;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
if (retroDeferred) {
|
|
944
|
+
await processPendingViolations(env, this.warn.bind(this));
|
|
945
|
+
}
|
|
946
|
+
}
|
|
682
947
|
return markerKind === "server" ? resolvedMarkerVirtualModuleId("server") : resolvedMarkerVirtualModuleId("client");
|
|
683
948
|
}
|
|
684
949
|
if (!shouldCheckImporter(normalizedImporter)) {
|
|
@@ -687,7 +952,9 @@ function importProtectionPlugin(opts) {
|
|
|
687
952
|
const matchers = getRulesForEnvironment(envName);
|
|
688
953
|
const specifierMatch = matchesAny(source, matchers.specifiers);
|
|
689
954
|
if (specifierMatch) {
|
|
690
|
-
|
|
955
|
+
if (!isPreTransformResolve) {
|
|
956
|
+
env.graph.addEdge(source, normalizedImporter, source);
|
|
957
|
+
}
|
|
691
958
|
const info = await buildViolationInfo(
|
|
692
959
|
provider,
|
|
693
960
|
env,
|
|
@@ -702,10 +969,18 @@ function importProtectionPlugin(opts) {
|
|
|
702
969
|
message: `Import "${source}" is denied in the ${envType} environment`
|
|
703
970
|
}
|
|
704
971
|
);
|
|
972
|
+
if (shouldDefer && !info.resolved) {
|
|
973
|
+
try {
|
|
974
|
+
const resolvedForInfo = await resolveAgainstImporter();
|
|
975
|
+
if (resolvedForInfo) info.resolved = resolvedForInfo;
|
|
976
|
+
} catch {
|
|
977
|
+
}
|
|
978
|
+
}
|
|
705
979
|
return reportOrDeferViolation(
|
|
706
980
|
this,
|
|
707
981
|
env,
|
|
708
982
|
normalizedImporter,
|
|
983
|
+
importer,
|
|
709
984
|
info,
|
|
710
985
|
shouldDefer,
|
|
711
986
|
isPreTransformResolve
|
|
@@ -716,28 +991,29 @@ function importProtectionPlugin(opts) {
|
|
|
716
991
|
if (env.resolveCache.has(cacheKey)) {
|
|
717
992
|
resolved = env.resolveCache.get(cacheKey) ?? null;
|
|
718
993
|
} else {
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
).add(cacheKey);
|
|
994
|
+
resolved = await resolveAgainstImporter();
|
|
995
|
+
if (resolved !== null) {
|
|
996
|
+
env.resolveCache.set(cacheKey, resolved);
|
|
997
|
+
getOrCreate(
|
|
998
|
+
env.resolveCacheByFile,
|
|
999
|
+
normalizedImporter,
|
|
1000
|
+
() => /* @__PURE__ */ new Set()
|
|
1001
|
+
).add(cacheKey);
|
|
1002
|
+
}
|
|
729
1003
|
}
|
|
730
1004
|
if (resolved) {
|
|
731
1005
|
const relativePath = getRelativePath(resolved);
|
|
732
1006
|
if (isPreTransformResolve && !isScanResolve) {
|
|
733
1007
|
env.serverFnLookupModules.add(resolved);
|
|
734
1008
|
}
|
|
735
|
-
|
|
1009
|
+
if (!isPreTransformResolve) {
|
|
1010
|
+
env.graph.addEdge(resolved, normalizedImporter, source);
|
|
1011
|
+
}
|
|
736
1012
|
const isExcludedFile = matchers.excludeFiles.length > 0 && matchesAny(relativePath, matchers.excludeFiles);
|
|
737
1013
|
if (!isExcludedFile) {
|
|
738
1014
|
const fileMatch = matchers.files.length > 0 ? matchesAny(relativePath, matchers.files) : void 0;
|
|
739
1015
|
if (fileMatch) {
|
|
740
|
-
const info = await
|
|
1016
|
+
const info = await buildFileViolationInfo(
|
|
741
1017
|
provider,
|
|
742
1018
|
env,
|
|
743
1019
|
envName,
|
|
@@ -745,17 +1021,14 @@ function importProtectionPlugin(opts) {
|
|
|
745
1021
|
importer,
|
|
746
1022
|
normalizedImporter,
|
|
747
1023
|
source,
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
pattern: fileMatch.pattern,
|
|
751
|
-
resolved,
|
|
752
|
-
message: `Import "${source}" (resolved to "${relativePath}") is denied in the ${envType} environment`
|
|
753
|
-
}
|
|
1024
|
+
resolved,
|
|
1025
|
+
fileMatch.pattern
|
|
754
1026
|
);
|
|
755
1027
|
return reportOrDeferViolation(
|
|
756
1028
|
this,
|
|
757
1029
|
env,
|
|
758
1030
|
normalizedImporter,
|
|
1031
|
+
importer,
|
|
759
1032
|
info,
|
|
760
1033
|
shouldDefer,
|
|
761
1034
|
isPreTransformResolve
|
|
@@ -776,6 +1049,7 @@ function importProtectionPlugin(opts) {
|
|
|
776
1049
|
this,
|
|
777
1050
|
env,
|
|
778
1051
|
normalizedImporter,
|
|
1052
|
+
importer,
|
|
779
1053
|
markerInfo,
|
|
780
1054
|
shouldDefer,
|
|
781
1055
|
isPreTransformResolve
|
|
@@ -807,22 +1081,70 @@ function importProtectionPlugin(opts) {
|
|
|
807
1081
|
const envName = this.environment.name;
|
|
808
1082
|
const env = envStates.get(envName);
|
|
809
1083
|
if (!env || env.deferredBuildViolations.length === 0) return;
|
|
1084
|
+
const candidateCache = /* @__PURE__ */ new Map();
|
|
1085
|
+
const toModuleIdCandidates = (id) => {
|
|
1086
|
+
let cached = candidateCache.get(id);
|
|
1087
|
+
if (cached) return cached;
|
|
1088
|
+
const out = /* @__PURE__ */ new Set();
|
|
1089
|
+
const normalized = normalizeFilePath(id);
|
|
1090
|
+
out.add(id);
|
|
1091
|
+
out.add(normalized);
|
|
1092
|
+
out.add(relativizePath(normalized, config.root));
|
|
1093
|
+
if (normalized.startsWith(VITE_BROWSER_VIRTUAL_PREFIX)) {
|
|
1094
|
+
const internal = `\0${normalized.slice(VITE_BROWSER_VIRTUAL_PREFIX.length)}`;
|
|
1095
|
+
out.add(internal);
|
|
1096
|
+
out.add(relativizePath(normalizeFilePath(internal), config.root));
|
|
1097
|
+
}
|
|
1098
|
+
if (normalized.startsWith("\0")) {
|
|
1099
|
+
const browser = `${VITE_BROWSER_VIRTUAL_PREFIX}${normalized.slice(1)}`;
|
|
1100
|
+
out.add(browser);
|
|
1101
|
+
out.add(relativizePath(normalizeFilePath(browser), config.root));
|
|
1102
|
+
}
|
|
1103
|
+
cached = Array.from(out);
|
|
1104
|
+
candidateCache.set(id, cached);
|
|
1105
|
+
return cached;
|
|
1106
|
+
};
|
|
810
1107
|
const survivingModules = /* @__PURE__ */ new Set();
|
|
811
1108
|
for (const chunk of Object.values(bundle)) {
|
|
812
1109
|
if (chunk.type === "chunk") {
|
|
813
1110
|
for (const moduleId of Object.keys(chunk.modules)) {
|
|
814
|
-
|
|
1111
|
+
for (const candidate of toModuleIdCandidates(moduleId)) {
|
|
1112
|
+
survivingModules.add(candidate);
|
|
1113
|
+
}
|
|
815
1114
|
}
|
|
816
1115
|
}
|
|
817
1116
|
}
|
|
1117
|
+
const didModuleSurvive = (moduleId) => toModuleIdCandidates(moduleId).some(
|
|
1118
|
+
(candidate) => survivingModules.has(candidate)
|
|
1119
|
+
);
|
|
818
1120
|
const realViolations = [];
|
|
819
1121
|
for (const {
|
|
820
1122
|
info,
|
|
821
1123
|
mockModuleId,
|
|
822
1124
|
checkModuleId
|
|
823
1125
|
} of env.deferredBuildViolations) {
|
|
824
|
-
|
|
825
|
-
if (
|
|
1126
|
+
let survived;
|
|
1127
|
+
if (checkModuleId != null) {
|
|
1128
|
+
const importerVariantIds = /* @__PURE__ */ new Set([info.importer]);
|
|
1129
|
+
const importerKeys = env.transformResultKeysByFile.get(
|
|
1130
|
+
normalizeFilePath(info.importer)
|
|
1131
|
+
);
|
|
1132
|
+
if (importerKeys) {
|
|
1133
|
+
for (const key of importerKeys) {
|
|
1134
|
+
importerVariantIds.add(key);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
survived = false;
|
|
1138
|
+
for (const importerId of importerVariantIds) {
|
|
1139
|
+
if (didModuleSurvive(importerId)) {
|
|
1140
|
+
survived = true;
|
|
1141
|
+
break;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
} else {
|
|
1145
|
+
survived = didModuleSurvive(mockModuleId);
|
|
1146
|
+
}
|
|
1147
|
+
if (!survived) continue;
|
|
826
1148
|
if (config.onViolation) {
|
|
827
1149
|
const result = await config.onViolation(info);
|
|
828
1150
|
if (result === false) continue;
|
|
@@ -835,12 +1157,7 @@ function importProtectionPlugin(opts) {
|
|
|
835
1157
|
} else {
|
|
836
1158
|
const seen = /* @__PURE__ */ new Set();
|
|
837
1159
|
for (const info of realViolations) {
|
|
838
|
-
const key = dedupeKey(
|
|
839
|
-
info.type,
|
|
840
|
-
info.importer,
|
|
841
|
-
info.specifier,
|
|
842
|
-
info.resolved
|
|
843
|
-
);
|
|
1160
|
+
const key = dedupeKey(info);
|
|
844
1161
|
if (!seen.has(key)) {
|
|
845
1162
|
seen.add(key);
|
|
846
1163
|
this.warn(formatViolation(info, config.root));
|
|
@@ -867,6 +1184,9 @@ function importProtectionPlugin(opts) {
|
|
|
867
1184
|
async handler(code, id) {
|
|
868
1185
|
const envName = this.environment.name;
|
|
869
1186
|
const file = normalizeFilePath(id);
|
|
1187
|
+
const envType = getEnvType(envName);
|
|
1188
|
+
const matchers = getRulesForEnvironment(envName);
|
|
1189
|
+
const isBuild = config.command === "build";
|
|
870
1190
|
if (IMPORT_PROTECTION_DEBUG) {
|
|
871
1191
|
if (matchesDebugFilter(file)) {
|
|
872
1192
|
debugLog("transform-cache", {
|
|
@@ -879,6 +1199,31 @@ function importProtectionPlugin(opts) {
|
|
|
879
1199
|
if (!shouldCheckImporter(file)) {
|
|
880
1200
|
return void 0;
|
|
881
1201
|
}
|
|
1202
|
+
const selfFileMatch = checkFileDenial(getRelativePath(file), matchers);
|
|
1203
|
+
if (selfFileMatch) {
|
|
1204
|
+
let exportNames = [];
|
|
1205
|
+
try {
|
|
1206
|
+
exportNames = collectNamedExports(code);
|
|
1207
|
+
} catch {
|
|
1208
|
+
}
|
|
1209
|
+
if (isBuild) {
|
|
1210
|
+
return generateSelfContainedMockModule(exportNames);
|
|
1211
|
+
}
|
|
1212
|
+
const runtimeId = mockRuntimeModuleIdFromViolation(
|
|
1213
|
+
{
|
|
1214
|
+
env: envType,
|
|
1215
|
+
behavior: config.effectiveBehavior === "error" ? "error" : "mock",
|
|
1216
|
+
importer: file,
|
|
1217
|
+
specifier: relativizePath(file, config.root),
|
|
1218
|
+
pattern: selfFileMatch.pattern,
|
|
1219
|
+
message: `File "${relativizePath(file, config.root)}" is denied in the ${envType} environment`,
|
|
1220
|
+
trace: []
|
|
1221
|
+
},
|
|
1222
|
+
config.mockAccess,
|
|
1223
|
+
config.root
|
|
1224
|
+
);
|
|
1225
|
+
return generateDevSelfDenialModule(exportNames, runtimeId);
|
|
1226
|
+
}
|
|
882
1227
|
let map;
|
|
883
1228
|
try {
|
|
884
1229
|
map = this.getCombinedSourcemap();
|
|
@@ -896,77 +1241,119 @@ function importProtectionPlugin(opts) {
|
|
|
896
1241
|
const lineIndex = buildLineIndex(code);
|
|
897
1242
|
const cacheKey = normalizePath(id);
|
|
898
1243
|
const envState = getEnv(envName);
|
|
899
|
-
|
|
1244
|
+
const isServerFnLookup = id.includes(SERVER_FN_LOOKUP_QUERY);
|
|
1245
|
+
if (isServerFnLookup) {
|
|
900
1246
|
envState.serverFnLookupModules.add(file);
|
|
901
1247
|
}
|
|
902
|
-
|
|
1248
|
+
const result = {
|
|
903
1249
|
code,
|
|
904
1250
|
map,
|
|
905
1251
|
originalCode,
|
|
906
1252
|
lineIndex
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
() => /* @__PURE__ */ new Set()
|
|
912
|
-
);
|
|
913
|
-
keySet.add(cacheKey);
|
|
914
|
-
if (cacheKey !== file) {
|
|
915
|
-
envState.transformResultCache.set(file, {
|
|
916
|
-
code,
|
|
917
|
-
map,
|
|
918
|
-
originalCode,
|
|
919
|
-
lineIndex
|
|
920
|
-
});
|
|
921
|
-
keySet.add(file);
|
|
922
|
-
}
|
|
1253
|
+
};
|
|
1254
|
+
cacheTransformResult(envState, file, cacheKey, result);
|
|
1255
|
+
if (isBuild) return void 0;
|
|
1256
|
+
const isDevMock = config.effectiveBehavior === "mock";
|
|
923
1257
|
const importSources = extractImportSources(code);
|
|
924
1258
|
const resolvedChildren = /* @__PURE__ */ new Set();
|
|
1259
|
+
const deniedSourceReplacements = /* @__PURE__ */ new Map();
|
|
925
1260
|
for (const src of importSources) {
|
|
926
1261
|
try {
|
|
927
1262
|
const resolved = await this.resolve(src, id, { skipSelf: true });
|
|
928
1263
|
if (resolved && !resolved.external) {
|
|
929
|
-
const resolvedPath =
|
|
1264
|
+
const resolvedPath = canonicalizeResolvedId(
|
|
1265
|
+
resolved.id,
|
|
1266
|
+
config.root,
|
|
1267
|
+
resolveExtensionlessAbsoluteId
|
|
1268
|
+
);
|
|
930
1269
|
resolvedChildren.add(resolvedPath);
|
|
1270
|
+
if (resolved.id.includes("tanstack-start-import-protection:")) {
|
|
1271
|
+
let physicalPath;
|
|
1272
|
+
const pending = envState.pendingViolations.get(file);
|
|
1273
|
+
if (pending) {
|
|
1274
|
+
const match = pending.find(
|
|
1275
|
+
(pv) => pv.info.specifier === src && pv.info.resolved
|
|
1276
|
+
);
|
|
1277
|
+
if (match) physicalPath = match.info.resolved;
|
|
1278
|
+
}
|
|
1279
|
+
if (physicalPath && physicalPath !== resolvedPath) {
|
|
1280
|
+
resolvedChildren.add(physicalPath);
|
|
1281
|
+
envState.graph.addEdge(physicalPath, file, src);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
931
1284
|
envState.graph.addEdge(resolvedPath, file, src);
|
|
1285
|
+
if (isDevMock) {
|
|
1286
|
+
const relativePath = getRelativePath(resolvedPath);
|
|
1287
|
+
const fileMatch = checkFileDenial(relativePath, matchers);
|
|
1288
|
+
if (fileMatch) {
|
|
1289
|
+
const info = await buildFileViolationInfo(
|
|
1290
|
+
envState.transformResultProvider,
|
|
1291
|
+
envState,
|
|
1292
|
+
envName,
|
|
1293
|
+
envType,
|
|
1294
|
+
id,
|
|
1295
|
+
file,
|
|
1296
|
+
src,
|
|
1297
|
+
resolvedPath,
|
|
1298
|
+
fileMatch.pattern
|
|
1299
|
+
);
|
|
1300
|
+
const replacement = await reportOrDeferViolation(
|
|
1301
|
+
this,
|
|
1302
|
+
envState,
|
|
1303
|
+
file,
|
|
1304
|
+
id,
|
|
1305
|
+
info,
|
|
1306
|
+
isDevMock,
|
|
1307
|
+
isServerFnLookup
|
|
1308
|
+
);
|
|
1309
|
+
if (replacement) {
|
|
1310
|
+
deniedSourceReplacements.set(
|
|
1311
|
+
src,
|
|
1312
|
+
replacement.startsWith("\0") ? VITE_BROWSER_VIRTUAL_PREFIX + replacement.slice(1) : replacement
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
932
1317
|
}
|
|
933
1318
|
} catch {
|
|
934
1319
|
}
|
|
935
1320
|
}
|
|
936
1321
|
envState.postTransformImports.set(cacheKey, resolvedChildren);
|
|
937
|
-
if (cacheKey !== file) {
|
|
1322
|
+
if (cacheKey !== file && !isServerFnLookup) {
|
|
938
1323
|
envState.postTransformImports.set(file, resolvedChildren);
|
|
939
1324
|
}
|
|
940
1325
|
await processPendingViolations(envState, this.warn.bind(this));
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1326
|
+
if (deniedSourceReplacements.size > 0) {
|
|
1327
|
+
try {
|
|
1328
|
+
const rewritten = rewriteDeniedImports(
|
|
1329
|
+
code,
|
|
1330
|
+
id,
|
|
1331
|
+
new Set(deniedSourceReplacements.keys()),
|
|
1332
|
+
(source) => deniedSourceReplacements.get(source) ?? source
|
|
1333
|
+
);
|
|
1334
|
+
if (!rewritten) {
|
|
1335
|
+
return void 0;
|
|
1336
|
+
}
|
|
1337
|
+
const normalizedMap = rewritten.map ? {
|
|
1338
|
+
...rewritten.map,
|
|
1339
|
+
version: Number(rewritten.map.version),
|
|
1340
|
+
sourcesContent: rewritten.map.sourcesContent?.map(
|
|
1341
|
+
(s) => s ?? ""
|
|
1342
|
+
) ?? []
|
|
1343
|
+
} : {
|
|
1344
|
+
version: 3,
|
|
1345
|
+
file: id,
|
|
1346
|
+
names: [],
|
|
1347
|
+
sources: [id],
|
|
1348
|
+
sourcesContent: [code],
|
|
1349
|
+
mappings: ""
|
|
1350
|
+
};
|
|
1351
|
+
return {
|
|
1352
|
+
code: rewritten.code,
|
|
1353
|
+
map: normalizedMap
|
|
1354
|
+
};
|
|
1355
|
+
} catch {
|
|
1356
|
+
}
|
|
970
1357
|
}
|
|
971
1358
|
return void 0;
|
|
972
1359
|
}
|
|
@@ -975,8 +1362,6 @@ function importProtectionPlugin(opts) {
|
|
|
975
1362
|
];
|
|
976
1363
|
}
|
|
977
1364
|
export {
|
|
978
|
-
dedupePatterns,
|
|
979
|
-
extractImportSources,
|
|
980
1365
|
importProtectionPlugin
|
|
981
1366
|
};
|
|
982
1367
|
//# sourceMappingURL=plugin.js.map
|