@tanstack/start-plugin-core 1.166.11 → 1.166.13
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/build-sitemap.js +94 -123
- package/dist/esm/build-sitemap.js.map +1 -1
- package/dist/esm/constants.js +15 -20
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/dev-server-plugin/dev-styles.js +137 -150
- package/dist/esm/dev-server-plugin/dev-styles.js.map +1 -1
- package/dist/esm/dev-server-plugin/extract-html-scripts.js +16 -15
- package/dist/esm/dev-server-plugin/extract-html-scripts.js.map +1 -1
- package/dist/esm/dev-server-plugin/plugin.js +125 -195
- package/dist/esm/dev-server-plugin/plugin.js.map +1 -1
- package/dist/esm/import-protection-plugin/ast.js +6 -5
- package/dist/esm/import-protection-plugin/ast.js.map +1 -1
- package/dist/esm/import-protection-plugin/constants.js +20 -22
- package/dist/esm/import-protection-plugin/constants.js.map +1 -1
- package/dist/esm/import-protection-plugin/defaults.js +35 -25
- package/dist/esm/import-protection-plugin/defaults.js.map +1 -1
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js +93 -92
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +1 -1
- package/dist/esm/import-protection-plugin/matchers.js +23 -24
- package/dist/esm/import-protection-plugin/matchers.js.map +1 -1
- package/dist/esm/import-protection-plugin/plugin.js +1045 -1361
- package/dist/esm/import-protection-plugin/plugin.js.map +1 -1
- package/dist/esm/import-protection-plugin/postCompileUsage.js +58 -55
- package/dist/esm/import-protection-plugin/postCompileUsage.js.map +1 -1
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +187 -259
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +1 -1
- package/dist/esm/import-protection-plugin/sourceLocation.js +238 -248
- package/dist/esm/import-protection-plugin/sourceLocation.js.map +1 -1
- package/dist/esm/import-protection-plugin/trace.js +173 -184
- package/dist/esm/import-protection-plugin/trace.js.map +1 -1
- package/dist/esm/import-protection-plugin/utils.js +132 -111
- package/dist/esm/import-protection-plugin/utils.js.map +1 -1
- package/dist/esm/import-protection-plugin/virtualModules.js +214 -194
- package/dist/esm/import-protection-plugin/virtualModules.js.map +1 -1
- package/dist/esm/index.js +2 -7
- package/dist/esm/load-env-plugin/plugin.js +12 -11
- package/dist/esm/load-env-plugin/plugin.js.map +1 -1
- package/dist/esm/output-directory.js +10 -10
- package/dist/esm/output-directory.js.map +1 -1
- package/dist/esm/plugin.js +275 -355
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/post-server-build.js +39 -53
- package/dist/esm/post-server-build.js.map +1 -1
- package/dist/esm/prerender.js +177 -239
- package/dist/esm/prerender.js.map +1 -1
- package/dist/esm/preview-server-plugin/plugin.js +41 -44
- package/dist/esm/preview-server-plugin/plugin.js.map +1 -1
- package/dist/esm/queue.js +115 -126
- package/dist/esm/queue.js.map +1 -1
- package/dist/esm/resolve-entries.js +31 -32
- package/dist/esm/resolve-entries.js.map +1 -1
- package/dist/esm/schema.js +156 -179
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/start-compiler-plugin/compiler.js +655 -812
- package/dist/esm/start-compiler-plugin/compiler.js.map +1 -1
- package/dist/esm/start-compiler-plugin/handleClientOnlyJSX.js +25 -8
- package/dist/esm/start-compiler-plugin/handleClientOnlyJSX.js.map +1 -1
- package/dist/esm/start-compiler-plugin/handleCreateIsomorphicFn.js +22 -19
- package/dist/esm/start-compiler-plugin/handleCreateIsomorphicFn.js.map +1 -1
- package/dist/esm/start-compiler-plugin/handleCreateMiddleware.js +20 -22
- package/dist/esm/start-compiler-plugin/handleCreateMiddleware.js.map +1 -1
- package/dist/esm/start-compiler-plugin/handleCreateServerFn.js +187 -255
- package/dist/esm/start-compiler-plugin/handleCreateServerFn.js.map +1 -1
- package/dist/esm/start-compiler-plugin/handleEnvOnly.js +23 -33
- package/dist/esm/start-compiler-plugin/handleEnvOnly.js.map +1 -1
- package/dist/esm/start-compiler-plugin/plugin.js +247 -291
- package/dist/esm/start-compiler-plugin/plugin.js.map +1 -1
- package/dist/esm/start-compiler-plugin/utils.js +27 -27
- package/dist/esm/start-compiler-plugin/utils.js.map +1 -1
- package/dist/esm/start-manifest-plugin/manifestBuilder.js +272 -378
- package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -1
- package/dist/esm/start-manifest-plugin/plugin.js +35 -44
- package/dist/esm/start-manifest-plugin/plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/constants.js +6 -5
- package/dist/esm/start-router-plugin/constants.js.map +1 -1
- package/dist/esm/start-router-plugin/generator-plugins/prerender-routes-plugin.js +24 -19
- package/dist/esm/start-router-plugin/generator-plugins/prerender-routes-plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js +28 -29
- package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/plugin.js +146 -199
- package/dist/esm/start-router-plugin/plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js +32 -31
- package/dist/esm/start-router-plugin/pruneServerOnlySubtrees.js.map +1 -1
- package/dist/esm/utils.js +14 -14
- package/dist/esm/utils.js.map +1 -1
- package/package.json +7 -7
- package/dist/esm/index.js.map +0 -1
|
@@ -1,137 +1,158 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IMPORT_PROTECTION_DEBUG, IMPORT_PROTECTION_DEBUG_FILTER, KNOWN_SOURCE_EXTENSIONS } from "./constants.js";
|
|
2
2
|
import { normalizePath } from "vite";
|
|
3
|
-
import {
|
|
3
|
+
import { extname, isAbsolute, relative, resolve } from "node:path";
|
|
4
|
+
//#region src/import-protection-plugin/utils.ts
|
|
4
5
|
function dedupePatterns(patterns) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
6
|
+
const out = [];
|
|
7
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8
|
+
for (const p of patterns) {
|
|
9
|
+
const key = typeof p === "string" ? `s:${p}` : `r:${p.toString()}`;
|
|
10
|
+
if (seen.has(key)) continue;
|
|
11
|
+
seen.add(key);
|
|
12
|
+
out.push(p);
|
|
13
|
+
}
|
|
14
|
+
return out;
|
|
15
|
+
}
|
|
16
|
+
/** Strip both `?query` and `#hash` from a module ID. */
|
|
15
17
|
function stripQueryAndHash(id) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
18
|
+
const q = id.indexOf("?");
|
|
19
|
+
const h = id.indexOf("#");
|
|
20
|
+
if (q === -1 && h === -1) return id;
|
|
21
|
+
if (q === -1) return id.slice(0, h);
|
|
22
|
+
if (h === -1) return id.slice(0, q);
|
|
23
|
+
return id.slice(0, Math.min(q, h));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Strip Vite query/hash parameters and normalize the path in one step.
|
|
27
|
+
*
|
|
28
|
+
* Results are memoized because the same module IDs are processed many
|
|
29
|
+
* times across resolveId, transform, and trace-building hooks.
|
|
30
|
+
*/
|
|
31
|
+
var normalizeFilePathCache = /* @__PURE__ */ new Map();
|
|
24
32
|
function normalizeFilePath(id) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
33
|
+
let result = normalizeFilePathCache.get(id);
|
|
34
|
+
if (result === void 0) {
|
|
35
|
+
result = normalizePath(stripQueryAndHash(id));
|
|
36
|
+
normalizeFilePathCache.set(id, result);
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
/** Clear the memoization cache (call from buildStart to bound growth). */
|
|
32
41
|
function clearNormalizeFilePathCache() {
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
42
|
+
normalizeFilePathCache.clear();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Lightweight regex to extract all import/re-export source strings from
|
|
46
|
+
* post-transform code. Matches:
|
|
47
|
+
* - `from "..."` / `from '...'` (static import/export)
|
|
48
|
+
* - `import("...")` / `import('...')` (dynamic import)
|
|
49
|
+
*/
|
|
50
|
+
var importSourceRe = /\bfrom\s+(?:"([^"]+)"|'([^']+)')|import\s*\(\s*(?:"([^"]+)"|'([^']+)')\s*\)/g;
|
|
36
51
|
function escapeRegExp(s) {
|
|
37
|
-
|
|
52
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
38
53
|
}
|
|
54
|
+
/** Get a value from a Map, creating it with `factory` if absent. */
|
|
39
55
|
function getOrCreate(map, key, factory) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
56
|
+
let value = map.get(key);
|
|
57
|
+
if (value === void 0) {
|
|
58
|
+
value = factory();
|
|
59
|
+
map.set(key, value);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
/** Make a path relative to `root`, keeping non-rooted paths as-is. */
|
|
47
64
|
function relativizePath(p, root) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
if (!p.startsWith(root)) return p;
|
|
66
|
+
const ch = p.charCodeAt(root.length);
|
|
67
|
+
if (ch !== 47 && !Number.isNaN(ch)) return p;
|
|
68
|
+
return ch === 47 ? p.slice(root.length + 1) : p.slice(root.length);
|
|
52
69
|
}
|
|
53
70
|
function extractImportSources(code) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
71
|
+
const sources = [];
|
|
72
|
+
let m;
|
|
73
|
+
importSourceRe.lastIndex = 0;
|
|
74
|
+
while ((m = importSourceRe.exec(code)) !== null) {
|
|
75
|
+
const src = m[1] ?? m[2] ?? m[3] ?? m[4];
|
|
76
|
+
if (src) sources.push(src);
|
|
77
|
+
}
|
|
78
|
+
return sources;
|
|
79
|
+
}
|
|
80
|
+
/** Log import-protection debug output when debug mode is enabled. */
|
|
63
81
|
function debugLog(...args) {
|
|
64
|
-
|
|
65
|
-
|
|
82
|
+
if (!IMPORT_PROTECTION_DEBUG) return;
|
|
83
|
+
console.warn("[import-protection:debug]", ...args);
|
|
66
84
|
}
|
|
85
|
+
/** Check if any value matches the configured debug filter (if present). */
|
|
67
86
|
function matchesDebugFilter(...values) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
87
|
+
const debugFilter = IMPORT_PROTECTION_DEBUG_FILTER;
|
|
88
|
+
if (!debugFilter) return true;
|
|
89
|
+
return values.some((v) => v.includes(debugFilter));
|
|
71
90
|
}
|
|
91
|
+
/** Strip `?query` (but not `#hash`) from a module ID. */
|
|
72
92
|
function stripQuery(id) {
|
|
73
|
-
|
|
74
|
-
|
|
93
|
+
const queryIndex = id.indexOf("?");
|
|
94
|
+
return queryIndex === -1 ? id : id.slice(0, queryIndex);
|
|
75
95
|
}
|
|
76
96
|
function withoutKnownExtension(id) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
97
|
+
const ext = extname(id);
|
|
98
|
+
return KNOWN_SOURCE_EXTENSIONS.has(ext) ? id.slice(0, -ext.length) : id;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Check whether `filePath` is contained inside `directory` using a
|
|
102
|
+
* boundary-safe comparison. A naïve `filePath.startsWith(directory)`
|
|
103
|
+
* would incorrectly treat `/app/src2/foo.ts` as inside `/app/src`.
|
|
104
|
+
*/
|
|
80
105
|
function isInsideDirectory(filePath, directory) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
106
|
+
const rel = relative(resolve(directory), resolve(filePath));
|
|
107
|
+
return rel.length > 0 && !rel.startsWith("..") && !isAbsolute(rel);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Decide whether a violation should be deferred for later verification
|
|
111
|
+
* rather than reported immediately.
|
|
112
|
+
*
|
|
113
|
+
* Build mode: always defer — generateBundle checks tree-shaking.
|
|
114
|
+
* Dev mock mode: always defer — edge-survival verifies whether the Start
|
|
115
|
+
* compiler strips the import (factory-safe pattern). All violation
|
|
116
|
+
* types and specifier formats are handled uniformly by the
|
|
117
|
+
* edge-survival mechanism in processPendingViolations.
|
|
118
|
+
* Dev error mode: never defer — throw immediately (no mock fallback).
|
|
119
|
+
*/
|
|
84
120
|
function shouldDeferViolation(opts) {
|
|
85
|
-
|
|
121
|
+
return opts.isBuild || opts.isDevMock;
|
|
86
122
|
}
|
|
87
123
|
function buildSourceCandidates(source, resolved, root) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
125
|
+
const push = (value) => {
|
|
126
|
+
if (!value) return;
|
|
127
|
+
candidates.add(value);
|
|
128
|
+
candidates.add(stripQuery(value));
|
|
129
|
+
candidates.add(withoutKnownExtension(stripQuery(value)));
|
|
130
|
+
};
|
|
131
|
+
push(source);
|
|
132
|
+
if (resolved) {
|
|
133
|
+
push(resolved);
|
|
134
|
+
const relativeResolved = relativizePath(resolved, root);
|
|
135
|
+
push(relativeResolved);
|
|
136
|
+
push(`./${relativeResolved}`);
|
|
137
|
+
push(`/${relativeResolved}`);
|
|
138
|
+
}
|
|
139
|
+
return candidates;
|
|
104
140
|
}
|
|
105
141
|
function buildResolutionCandidates(id) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
142
|
+
const normalized = normalizeFilePath(id);
|
|
143
|
+
const stripped = stripQuery(normalized);
|
|
144
|
+
return [...new Set([
|
|
145
|
+
id,
|
|
146
|
+
normalized,
|
|
147
|
+
stripped
|
|
148
|
+
])];
|
|
109
149
|
}
|
|
110
150
|
function canonicalizeResolvedId(id, root, resolveExtensionlessAbsoluteId) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
buildResolutionCandidates,
|
|
120
|
-
buildSourceCandidates,
|
|
121
|
-
canonicalizeResolvedId,
|
|
122
|
-
clearNormalizeFilePathCache,
|
|
123
|
-
debugLog,
|
|
124
|
-
dedupePatterns,
|
|
125
|
-
escapeRegExp,
|
|
126
|
-
extractImportSources,
|
|
127
|
-
getOrCreate,
|
|
128
|
-
isInsideDirectory,
|
|
129
|
-
matchesDebugFilter,
|
|
130
|
-
normalizeFilePath,
|
|
131
|
-
relativizePath,
|
|
132
|
-
shouldDeferViolation,
|
|
133
|
-
stripQuery,
|
|
134
|
-
stripQueryAndHash,
|
|
135
|
-
withoutKnownExtension
|
|
136
|
-
};
|
|
137
|
-
//# sourceMappingURL=utils.js.map
|
|
151
|
+
let normalized = normalizeFilePath(stripQuery(id));
|
|
152
|
+
if (!isAbsolute(normalized) && !normalized.startsWith(".") && !normalized.startsWith("\0") && !/^[a-zA-Z]+:/.test(normalized)) normalized = normalizeFilePath(resolve(root, normalized));
|
|
153
|
+
return resolveExtensionlessAbsoluteId(normalized);
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
export { buildResolutionCandidates, buildSourceCandidates, canonicalizeResolvedId, clearNormalizeFilePathCache, debugLog, dedupePatterns, escapeRegExp, extractImportSources, getOrCreate, isInsideDirectory, matchesDebugFilter, normalizeFilePath, relativizePath, shouldDeferViolation };
|
|
157
|
+
|
|
158
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/import-protection-plugin/utils.ts"],"sourcesContent":["import {\n extname,\n isAbsolute,\n relative,\n resolve as resolvePath,\n} from 'node:path'\nimport { normalizePath } from 'vite'\n\nimport {\n IMPORT_PROTECTION_DEBUG,\n IMPORT_PROTECTION_DEBUG_FILTER,\n KNOWN_SOURCE_EXTENSIONS,\n} from './constants'\n\nexport type Pattern = string | RegExp\n\nexport function dedupePatterns(patterns: Array<Pattern>): Array<Pattern> {\n const out: Array<Pattern> = []\n const seen = new Set<string>()\n for (const p of patterns) {\n const key = typeof p === 'string' ? `s:${p}` : `r:${p.toString()}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push(p)\n }\n return out\n}\n\n/** Strip both `?query` and `#hash` from a module ID. */\nexport function stripQueryAndHash(id: string): string {\n const q = id.indexOf('?')\n const h = id.indexOf('#')\n if (q === -1 && h === -1) return id\n if (q === -1) return id.slice(0, h)\n if (h === -1) return id.slice(0, q)\n return id.slice(0, Math.min(q, h))\n}\n\n/**\n * Strip Vite query/hash parameters and normalize the path in one step.\n *\n * Results are memoized because the same module IDs are processed many\n * times across resolveId, transform, and trace-building hooks.\n */\nconst normalizeFilePathCache = new Map<string, string>()\nexport function normalizeFilePath(id: string): string {\n let result = normalizeFilePathCache.get(id)\n if (result === undefined) {\n result = normalizePath(stripQueryAndHash(id))\n normalizeFilePathCache.set(id, result)\n }\n return result\n}\n\n/** Clear the memoization cache (call from buildStart to bound growth). */\nexport function clearNormalizeFilePathCache(): void {\n normalizeFilePathCache.clear()\n}\n\n/**\n * Lightweight regex to extract all import/re-export source strings from\n * post-transform code. Matches:\n * - `from \"...\"` / `from '...'` (static import/export)\n * - `import(\"...\")` / `import('...')` (dynamic import)\n */\nconst importSourceRe =\n /\\bfrom\\s+(?:\"([^\"]+)\"|'([^']+)')|import\\s*\\(\\s*(?:\"([^\"]+)\"|'([^']+)')\\s*\\)/g\n\nexport function escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/** Get a value from a Map, creating it with `factory` if absent. */\nexport function getOrCreate<TKey, TValue>(\n map: Map<TKey, TValue>,\n key: TKey,\n factory: () => TValue,\n): TValue {\n let value = map.get(key)\n if (value === undefined) {\n value = factory()\n map.set(key, value)\n }\n return value\n}\n\n/** Make a path relative to `root`, keeping non-rooted paths as-is. */\nexport function relativizePath(p: string, root: string): string {\n if (!p.startsWith(root)) return p\n const ch = p.charCodeAt(root.length)\n // Must be followed by a separator or end-of-string to be a true child\n if (ch !== 47 && !Number.isNaN(ch)) return p\n return ch === 47 ? p.slice(root.length + 1) : p.slice(root.length)\n}\n\nexport function extractImportSources(code: string): Array<string> {\n const sources: Array<string> = []\n let m: RegExpExecArray | null\n importSourceRe.lastIndex = 0\n while ((m = importSourceRe.exec(code)) !== null) {\n const src = m[1] ?? m[2] ?? m[3] ?? m[4]\n if (src) sources.push(src)\n }\n return sources\n}\n\n/** Log import-protection debug output when debug mode is enabled. */\nexport function debugLog(...args: Array<unknown>): void {\n if (!IMPORT_PROTECTION_DEBUG) return\n console.warn('[import-protection:debug]', ...args)\n}\n\n/** Check if any value matches the configured debug filter (if present). */\nexport function matchesDebugFilter(...values: Array<string>): boolean {\n const debugFilter = IMPORT_PROTECTION_DEBUG_FILTER\n if (!debugFilter) return true\n return values.some((v) => v.includes(debugFilter))\n}\n\n/** Strip `?query` (but not `#hash`) from a module ID. */\nexport function stripQuery(id: string): string {\n const queryIndex = id.indexOf('?')\n return queryIndex === -1 ? id : id.slice(0, queryIndex)\n}\n\nexport function withoutKnownExtension(id: string): string {\n const ext = extname(id)\n return KNOWN_SOURCE_EXTENSIONS.has(ext) ? id.slice(0, -ext.length) : id\n}\n\n/**\n * Check whether `filePath` is contained inside `directory` using a\n * boundary-safe comparison. A naïve `filePath.startsWith(directory)`\n * would incorrectly treat `/app/src2/foo.ts` as inside `/app/src`.\n */\nexport function isInsideDirectory(\n filePath: string,\n directory: string,\n): boolean {\n const rel = relative(resolvePath(directory), resolvePath(filePath))\n return rel.length > 0 && !rel.startsWith('..') && !isAbsolute(rel)\n}\n\n/**\n * Decide whether a violation should be deferred for later verification\n * rather than reported immediately.\n *\n * Build mode: always defer — generateBundle checks tree-shaking.\n * Dev mock mode: always defer — edge-survival verifies whether the Start\n * compiler strips the import (factory-safe pattern). All violation\n * types and specifier formats are handled uniformly by the\n * edge-survival mechanism in processPendingViolations.\n * Dev error mode: never defer — throw immediately (no mock fallback).\n */\nexport function shouldDeferViolation(opts: {\n isBuild: boolean\n isDevMock: boolean\n}): boolean {\n return opts.isBuild || opts.isDevMock\n}\n\nexport function buildSourceCandidates(\n source: string,\n resolved: string | undefined,\n root: string,\n): Set<string> {\n const candidates = new Set<string>()\n const push = (value: string | undefined) => {\n if (!value) return\n candidates.add(value)\n candidates.add(stripQuery(value))\n candidates.add(withoutKnownExtension(stripQuery(value)))\n }\n\n push(source)\n if (resolved) {\n push(resolved)\n const relativeResolved = relativizePath(resolved, root)\n push(relativeResolved)\n push(`./${relativeResolved}`)\n push(`/${relativeResolved}`)\n }\n\n return candidates\n}\n\nexport function buildResolutionCandidates(id: string): Array<string> {\n const normalized = normalizeFilePath(id)\n const stripped = stripQuery(normalized)\n\n return [...new Set([id, normalized, stripped])]\n}\n\nexport function canonicalizeResolvedId(\n id: string,\n root: string,\n resolveExtensionlessAbsoluteId: (value: string) => string,\n): string {\n const stripped = stripQuery(id)\n let normalized = normalizeFilePath(stripped)\n\n if (\n !isAbsolute(normalized) &&\n !normalized.startsWith('.') &&\n !normalized.startsWith('\\0') &&\n !/^[a-zA-Z]+:/.test(normalized)\n ) {\n normalized = normalizeFilePath(resolvePath(root, normalized))\n }\n\n return resolveExtensionlessAbsoluteId(normalized)\n}\n"],"
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../src/import-protection-plugin/utils.ts"],"sourcesContent":["import {\n extname,\n isAbsolute,\n relative,\n resolve as resolvePath,\n} from 'node:path'\nimport { normalizePath } from 'vite'\n\nimport {\n IMPORT_PROTECTION_DEBUG,\n IMPORT_PROTECTION_DEBUG_FILTER,\n KNOWN_SOURCE_EXTENSIONS,\n} from './constants'\n\nexport type Pattern = string | RegExp\n\nexport function dedupePatterns(patterns: Array<Pattern>): Array<Pattern> {\n const out: Array<Pattern> = []\n const seen = new Set<string>()\n for (const p of patterns) {\n const key = typeof p === 'string' ? `s:${p}` : `r:${p.toString()}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push(p)\n }\n return out\n}\n\n/** Strip both `?query` and `#hash` from a module ID. */\nexport function stripQueryAndHash(id: string): string {\n const q = id.indexOf('?')\n const h = id.indexOf('#')\n if (q === -1 && h === -1) return id\n if (q === -1) return id.slice(0, h)\n if (h === -1) return id.slice(0, q)\n return id.slice(0, Math.min(q, h))\n}\n\n/**\n * Strip Vite query/hash parameters and normalize the path in one step.\n *\n * Results are memoized because the same module IDs are processed many\n * times across resolveId, transform, and trace-building hooks.\n */\nconst normalizeFilePathCache = new Map<string, string>()\nexport function normalizeFilePath(id: string): string {\n let result = normalizeFilePathCache.get(id)\n if (result === undefined) {\n result = normalizePath(stripQueryAndHash(id))\n normalizeFilePathCache.set(id, result)\n }\n return result\n}\n\n/** Clear the memoization cache (call from buildStart to bound growth). */\nexport function clearNormalizeFilePathCache(): void {\n normalizeFilePathCache.clear()\n}\n\n/**\n * Lightweight regex to extract all import/re-export source strings from\n * post-transform code. Matches:\n * - `from \"...\"` / `from '...'` (static import/export)\n * - `import(\"...\")` / `import('...')` (dynamic import)\n */\nconst importSourceRe =\n /\\bfrom\\s+(?:\"([^\"]+)\"|'([^']+)')|import\\s*\\(\\s*(?:\"([^\"]+)\"|'([^']+)')\\s*\\)/g\n\nexport function escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/** Get a value from a Map, creating it with `factory` if absent. */\nexport function getOrCreate<TKey, TValue>(\n map: Map<TKey, TValue>,\n key: TKey,\n factory: () => TValue,\n): TValue {\n let value = map.get(key)\n if (value === undefined) {\n value = factory()\n map.set(key, value)\n }\n return value\n}\n\n/** Make a path relative to `root`, keeping non-rooted paths as-is. */\nexport function relativizePath(p: string, root: string): string {\n if (!p.startsWith(root)) return p\n const ch = p.charCodeAt(root.length)\n // Must be followed by a separator or end-of-string to be a true child\n if (ch !== 47 && !Number.isNaN(ch)) return p\n return ch === 47 ? p.slice(root.length + 1) : p.slice(root.length)\n}\n\nexport function extractImportSources(code: string): Array<string> {\n const sources: Array<string> = []\n let m: RegExpExecArray | null\n importSourceRe.lastIndex = 0\n while ((m = importSourceRe.exec(code)) !== null) {\n const src = m[1] ?? m[2] ?? m[3] ?? m[4]\n if (src) sources.push(src)\n }\n return sources\n}\n\n/** Log import-protection debug output when debug mode is enabled. */\nexport function debugLog(...args: Array<unknown>): void {\n if (!IMPORT_PROTECTION_DEBUG) return\n console.warn('[import-protection:debug]', ...args)\n}\n\n/** Check if any value matches the configured debug filter (if present). */\nexport function matchesDebugFilter(...values: Array<string>): boolean {\n const debugFilter = IMPORT_PROTECTION_DEBUG_FILTER\n if (!debugFilter) return true\n return values.some((v) => v.includes(debugFilter))\n}\n\n/** Strip `?query` (but not `#hash`) from a module ID. */\nexport function stripQuery(id: string): string {\n const queryIndex = id.indexOf('?')\n return queryIndex === -1 ? id : id.slice(0, queryIndex)\n}\n\nexport function withoutKnownExtension(id: string): string {\n const ext = extname(id)\n return KNOWN_SOURCE_EXTENSIONS.has(ext) ? id.slice(0, -ext.length) : id\n}\n\n/**\n * Check whether `filePath` is contained inside `directory` using a\n * boundary-safe comparison. A naïve `filePath.startsWith(directory)`\n * would incorrectly treat `/app/src2/foo.ts` as inside `/app/src`.\n */\nexport function isInsideDirectory(\n filePath: string,\n directory: string,\n): boolean {\n const rel = relative(resolvePath(directory), resolvePath(filePath))\n return rel.length > 0 && !rel.startsWith('..') && !isAbsolute(rel)\n}\n\n/**\n * Decide whether a violation should be deferred for later verification\n * rather than reported immediately.\n *\n * Build mode: always defer — generateBundle checks tree-shaking.\n * Dev mock mode: always defer — edge-survival verifies whether the Start\n * compiler strips the import (factory-safe pattern). All violation\n * types and specifier formats are handled uniformly by the\n * edge-survival mechanism in processPendingViolations.\n * Dev error mode: never defer — throw immediately (no mock fallback).\n */\nexport function shouldDeferViolation(opts: {\n isBuild: boolean\n isDevMock: boolean\n}): boolean {\n return opts.isBuild || opts.isDevMock\n}\n\nexport function buildSourceCandidates(\n source: string,\n resolved: string | undefined,\n root: string,\n): Set<string> {\n const candidates = new Set<string>()\n const push = (value: string | undefined) => {\n if (!value) return\n candidates.add(value)\n candidates.add(stripQuery(value))\n candidates.add(withoutKnownExtension(stripQuery(value)))\n }\n\n push(source)\n if (resolved) {\n push(resolved)\n const relativeResolved = relativizePath(resolved, root)\n push(relativeResolved)\n push(`./${relativeResolved}`)\n push(`/${relativeResolved}`)\n }\n\n return candidates\n}\n\nexport function buildResolutionCandidates(id: string): Array<string> {\n const normalized = normalizeFilePath(id)\n const stripped = stripQuery(normalized)\n\n return [...new Set([id, normalized, stripped])]\n}\n\nexport function canonicalizeResolvedId(\n id: string,\n root: string,\n resolveExtensionlessAbsoluteId: (value: string) => string,\n): string {\n const stripped = stripQuery(id)\n let normalized = normalizeFilePath(stripped)\n\n if (\n !isAbsolute(normalized) &&\n !normalized.startsWith('.') &&\n !normalized.startsWith('\\0') &&\n !/^[a-zA-Z]+:/.test(normalized)\n ) {\n normalized = normalizeFilePath(resolvePath(root, normalized))\n }\n\n return resolveExtensionlessAbsoluteId(normalized)\n}\n"],"mappings":"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"}
|