@tanstack/start-plugin-core 1.161.4 → 1.162.1
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/import-protection-plugin/defaults.d.ts +6 -4
- package/dist/esm/import-protection-plugin/defaults.js +3 -12
- package/dist/esm/import-protection-plugin/defaults.js.map +1 -1
- package/dist/esm/import-protection-plugin/plugin.d.ts +1 -1
- package/dist/esm/import-protection-plugin/plugin.js +488 -257
- package/dist/esm/import-protection-plugin/plugin.js.map +1 -1
- package/dist/esm/import-protection-plugin/postCompileUsage.d.ts +4 -2
- package/dist/esm/import-protection-plugin/postCompileUsage.js +31 -150
- package/dist/esm/import-protection-plugin/postCompileUsage.js.map +1 -1
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +13 -9
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +1 -1
- package/dist/esm/import-protection-plugin/sourceLocation.d.ts +32 -66
- package/dist/esm/import-protection-plugin/sourceLocation.js +129 -56
- package/dist/esm/import-protection-plugin/sourceLocation.js.map +1 -1
- package/dist/esm/import-protection-plugin/trace.d.ts +10 -0
- package/dist/esm/import-protection-plugin/trace.js +30 -44
- package/dist/esm/import-protection-plugin/trace.js.map +1 -1
- package/dist/esm/import-protection-plugin/utils.d.ts +8 -4
- package/dist/esm/import-protection-plugin/utils.js +43 -1
- package/dist/esm/import-protection-plugin/utils.js.map +1 -1
- package/dist/esm/import-protection-plugin/virtualModules.d.ts +7 -1
- package/dist/esm/import-protection-plugin/virtualModules.js +104 -135
- package/dist/esm/import-protection-plugin/virtualModules.js.map +1 -1
- package/package.json +6 -6
- package/src/import-protection-plugin/defaults.ts +8 -19
- package/src/import-protection-plugin/plugin.ts +776 -433
- package/src/import-protection-plugin/postCompileUsage.ts +57 -229
- package/src/import-protection-plugin/rewriteDeniedImports.ts +34 -42
- package/src/import-protection-plugin/sourceLocation.ts +184 -185
- package/src/import-protection-plugin/trace.ts +38 -49
- package/src/import-protection-plugin/utils.ts +62 -1
- package/src/import-protection-plugin/virtualModules.ts +163 -177
|
@@ -1,120 +1,15 @@
|
|
|
1
|
+
import babel from '@babel/core'
|
|
1
2
|
import * as t from '@babel/types'
|
|
2
3
|
import { parseAst } from '@tanstack/router-utils'
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function collectPatternBindings(
|
|
7
|
-
node: t.Node | null | undefined,
|
|
8
|
-
out: Set<string>,
|
|
9
|
-
): void {
|
|
10
|
-
if (!node) return
|
|
11
|
-
if (t.isIdentifier(node)) {
|
|
12
|
-
out.add(node.name)
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
if (t.isRestElement(node)) {
|
|
16
|
-
collectPatternBindings(node.argument, out)
|
|
17
|
-
return
|
|
18
|
-
}
|
|
19
|
-
if (t.isAssignmentPattern(node)) {
|
|
20
|
-
collectPatternBindings(node.left, out)
|
|
21
|
-
return
|
|
22
|
-
}
|
|
23
|
-
if (t.isObjectPattern(node)) {
|
|
24
|
-
for (const prop of node.properties) {
|
|
25
|
-
if (t.isRestElement(prop)) {
|
|
26
|
-
collectPatternBindings(prop.argument, out)
|
|
27
|
-
} else if (t.isObjectProperty(prop)) {
|
|
28
|
-
collectPatternBindings(prop.value as t.Node, out)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return
|
|
32
|
-
}
|
|
33
|
-
if (t.isArrayPattern(node)) {
|
|
34
|
-
for (const el of node.elements) {
|
|
35
|
-
collectPatternBindings(el, out)
|
|
36
|
-
}
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function isBindingPosition(node: t.Node, parent: t.Node | null): boolean {
|
|
42
|
-
if (!parent) return false
|
|
43
|
-
if (t.isFunctionDeclaration(parent) && parent.id === node) return true
|
|
44
|
-
if (t.isFunctionExpression(parent) && parent.id === node) return true
|
|
45
|
-
if (t.isClassDeclaration(parent) && parent.id === node) return true
|
|
46
|
-
if (t.isClassExpression(parent) && parent.id === node) return true
|
|
47
|
-
if (t.isVariableDeclarator(parent) && parent.id === node) return true
|
|
48
|
-
if (t.isImportSpecifier(parent) && parent.local === node) return true
|
|
49
|
-
if (t.isImportDefaultSpecifier(parent) && parent.local === node) return true
|
|
50
|
-
if (t.isImportNamespaceSpecifier(parent) && parent.local === node) return true
|
|
51
|
-
if (
|
|
52
|
-
t.isObjectProperty(parent) &&
|
|
53
|
-
parent.key === node &&
|
|
54
|
-
!parent.computed &&
|
|
55
|
-
// In `{ foo }`, the identifier is also a value reference and must count as
|
|
56
|
-
// usage. Babel represents this as `shorthand: true`.
|
|
57
|
-
!parent.shorthand
|
|
58
|
-
)
|
|
59
|
-
return true
|
|
60
|
-
if (t.isObjectMethod(parent) && parent.key === node && !parent.computed)
|
|
61
|
-
return true
|
|
62
|
-
if (t.isExportSpecifier(parent) && parent.exported === node) return true
|
|
63
|
-
return false
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function isPreferredUsage(node: t.Node, parent: t.Node | null): boolean {
|
|
67
|
-
if (!parent) return false
|
|
68
|
-
if (t.isCallExpression(parent) && parent.callee === node) return true
|
|
69
|
-
if (t.isNewExpression(parent) && parent.callee === node) return true
|
|
70
|
-
if (t.isMemberExpression(parent) && parent.object === node) return true
|
|
71
|
-
return false
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function isScopeNode(node: t.Node): boolean {
|
|
75
|
-
return (
|
|
76
|
-
t.isProgram(node) ||
|
|
77
|
-
t.isFunctionDeclaration(node) ||
|
|
78
|
-
t.isFunctionExpression(node) ||
|
|
79
|
-
t.isArrowFunctionExpression(node) ||
|
|
80
|
-
t.isBlockStatement(node) ||
|
|
81
|
-
t.isCatchClause(node)
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** `var` hoists to the nearest function or program scope, not block scopes. */
|
|
86
|
-
function isFunctionScopeNode(node: t.Node): boolean {
|
|
87
|
-
return (
|
|
88
|
-
t.isProgram(node) ||
|
|
89
|
-
t.isFunctionDeclaration(node) ||
|
|
90
|
-
t.isFunctionExpression(node) ||
|
|
91
|
-
t.isArrowFunctionExpression(node)
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function collectScopeBindings(node: t.Node, out: Set<string>): void {
|
|
96
|
-
if (
|
|
97
|
-
t.isFunctionDeclaration(node) ||
|
|
98
|
-
t.isFunctionExpression(node) ||
|
|
99
|
-
t.isArrowFunctionExpression(node)
|
|
100
|
-
) {
|
|
101
|
-
for (const p of node.params) {
|
|
102
|
-
collectPatternBindings(p, out)
|
|
103
|
-
}
|
|
104
|
-
return
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (t.isCatchClause(node)) {
|
|
108
|
-
collectPatternBindings(node.param, out)
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
}
|
|
5
|
+
type UsagePos = { line: number; column0: number }
|
|
112
6
|
|
|
113
7
|
/**
|
|
114
8
|
* Given transformed code, returns the first "meaningful" usage position for an
|
|
115
9
|
* import from `source` that survives compilation.
|
|
116
10
|
*
|
|
117
|
-
*
|
|
11
|
+
* "Preferred" positions (call, new, member-access) take priority over bare
|
|
12
|
+
* identifier references. The returned column is 0-based (Babel loc semantics).
|
|
118
13
|
*/
|
|
119
14
|
export function findPostCompileUsagePos(
|
|
120
15
|
code: string,
|
|
@@ -122,7 +17,7 @@ export function findPostCompileUsagePos(
|
|
|
122
17
|
): UsagePos | undefined {
|
|
123
18
|
const ast = parseAst({ code })
|
|
124
19
|
|
|
125
|
-
//
|
|
20
|
+
// Collect local names bound from this specifier
|
|
126
21
|
const imported = new Set<string>()
|
|
127
22
|
for (const node of ast.program.body) {
|
|
128
23
|
if (t.isImportDeclaration(node) && node.source.value === source) {
|
|
@@ -138,129 +33,62 @@ export function findPostCompileUsagePos(
|
|
|
138
33
|
let preferred: UsagePos | undefined
|
|
139
34
|
let anyUsage: UsagePos | undefined
|
|
140
35
|
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
return false
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function record(node: t.Node, kind: 'preferred' | 'any') {
|
|
159
|
-
const loc = node.loc?.start
|
|
160
|
-
if (!loc) return
|
|
161
|
-
const pos: UsagePos = { line: loc.line, column0: loc.column }
|
|
162
|
-
if (kind === 'preferred') {
|
|
163
|
-
preferred ||= pos
|
|
164
|
-
} else {
|
|
165
|
-
anyUsage ||= pos
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function pushScope(node: t.Node): void {
|
|
170
|
-
const bindings = new Set<string>()
|
|
171
|
-
collectScopeBindings(node, bindings)
|
|
172
|
-
scopes.push({ bindings, isFnScope: isFunctionScopeNode(node) })
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function popScope(): void {
|
|
176
|
-
scopes.pop()
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** Find the nearest function/program scope entry in the stack. */
|
|
180
|
-
function nearestFnScope(): ScopeEntry {
|
|
181
|
-
for (let i = scopes.length - 1; i >= 0; i--) {
|
|
182
|
-
if (scopes[i]!.isFnScope) return scopes[i]!
|
|
183
|
-
}
|
|
184
|
-
// Should never happen (index 0 is always a function scope).
|
|
185
|
-
return scopes[0]!
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// The walker accepts AST nodes, arrays (from node children like
|
|
189
|
-
// `body`, `params`, etc.), or null/undefined for optional children.
|
|
190
|
-
type Walkable =
|
|
191
|
-
| t.Node
|
|
192
|
-
| ReadonlyArray<t.Node | null | undefined>
|
|
193
|
-
| null
|
|
194
|
-
| undefined
|
|
195
|
-
|
|
196
|
-
function walk(node: Walkable, parent: t.Node | null) {
|
|
197
|
-
if (!node) return
|
|
198
|
-
if (preferred && anyUsage) return
|
|
199
|
-
|
|
200
|
-
if (Array.isArray(node)) {
|
|
201
|
-
for (const n of node) walk(n, parent)
|
|
202
|
-
return
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// After the array check + early return, node is guaranteed to be t.Node.
|
|
206
|
-
// TypeScript doesn't narrow ReadonlyArray from the union, so we assert.
|
|
207
|
-
const astNode = node as t.Node
|
|
208
|
-
|
|
209
|
-
// Skip import declarations entirely
|
|
210
|
-
if (t.isImportDeclaration(astNode)) return
|
|
211
|
-
|
|
212
|
-
const enterScope = isScopeNode(astNode)
|
|
213
|
-
if (enterScope) {
|
|
214
|
-
pushScope(astNode)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Add lexical bindings for variable declarations and class/function decls.
|
|
218
|
-
// Note: function/class *declaration* identifiers bind in the parent scope,
|
|
219
|
-
// so we register them before walking children.
|
|
220
|
-
if (t.isFunctionDeclaration(astNode) && astNode.id) {
|
|
221
|
-
scopes[scopes.length - 2]?.bindings.add(astNode.id.name)
|
|
222
|
-
}
|
|
223
|
-
if (t.isClassDeclaration(astNode) && astNode.id) {
|
|
224
|
-
scopes[scopes.length - 2]?.bindings.add(astNode.id.name)
|
|
225
|
-
}
|
|
226
|
-
if (t.isVariableDeclarator(astNode)) {
|
|
227
|
-
// `var` hoists to the nearest function/program scope, not block scope.
|
|
228
|
-
const isVar = t.isVariableDeclaration(parent) && parent.kind === 'var'
|
|
229
|
-
const target = isVar
|
|
230
|
-
? nearestFnScope().bindings
|
|
231
|
-
: scopes[scopes.length - 1]!.bindings
|
|
232
|
-
collectPatternBindings(astNode.id, target)
|
|
233
|
-
}
|
|
36
|
+
// babel.traverse can throw on malformed scopes (e.g. duplicate bindings from
|
|
37
|
+
// import + const re-declaration) because parseAst doesn't attach a hub
|
|
38
|
+
try {
|
|
39
|
+
babel.traverse(ast, {
|
|
40
|
+
ImportDeclaration(path) {
|
|
41
|
+
path.skip()
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
Identifier(path: babel.NodePath<t.Identifier>) {
|
|
45
|
+
if (preferred && anyUsage) {
|
|
46
|
+
path.stop()
|
|
47
|
+
return
|
|
48
|
+
}
|
|
234
49
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
50
|
+
const { node, parent, scope } = path
|
|
51
|
+
if (!imported.has(node.name)) return
|
|
52
|
+
|
|
53
|
+
// Skip binding positions (declarations, import specifiers, etc.)
|
|
54
|
+
if (path.isBindingIdentifier()) return
|
|
55
|
+
|
|
56
|
+
// Skip non-shorthand object property keys — they don't reference the import
|
|
57
|
+
if (
|
|
58
|
+
t.isObjectProperty(parent) &&
|
|
59
|
+
parent.key === node &&
|
|
60
|
+
!parent.computed &&
|
|
61
|
+
!parent.shorthand
|
|
62
|
+
)
|
|
63
|
+
return
|
|
64
|
+
if (t.isObjectMethod(parent) && parent.key === node && !parent.computed)
|
|
65
|
+
return
|
|
66
|
+
if (t.isExportSpecifier(parent) && parent.exported === node) return
|
|
67
|
+
|
|
68
|
+
// Skip if shadowed by a closer binding
|
|
69
|
+
const binding = scope.getBinding(node.name)
|
|
70
|
+
if (binding && binding.kind !== 'module') return
|
|
71
|
+
|
|
72
|
+
const loc = node.loc?.start
|
|
73
|
+
if (!loc) return
|
|
74
|
+
const pos: UsagePos = { line: loc.line, column0: loc.column }
|
|
75
|
+
|
|
76
|
+
const isPreferred =
|
|
77
|
+
(t.isCallExpression(parent) && parent.callee === node) ||
|
|
78
|
+
(t.isNewExpression(parent) && parent.callee === node) ||
|
|
79
|
+
(t.isMemberExpression(parent) && parent.object === node)
|
|
80
|
+
|
|
81
|
+
if (isPreferred) {
|
|
82
|
+
preferred ||= pos
|
|
239
83
|
} else {
|
|
240
|
-
|
|
84
|
+
anyUsage ||= pos
|
|
241
85
|
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
// all child properties generically.
|
|
248
|
-
const record_ = astNode as unknown as Record<string, unknown>
|
|
249
|
-
for (const key of Object.keys(record_)) {
|
|
250
|
-
const value = record_[key]
|
|
251
|
-
if (!value) continue
|
|
252
|
-
if (key === 'loc' || key === 'start' || key === 'end') continue
|
|
253
|
-
if (key === 'parent') continue
|
|
254
|
-
if (typeof value === 'string' || typeof value === 'number') continue
|
|
255
|
-
walk(value as Walkable, astNode)
|
|
256
|
-
if (preferred && anyUsage) break
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (enterScope) {
|
|
260
|
-
popScope()
|
|
261
|
-
}
|
|
86
|
+
},
|
|
87
|
+
})
|
|
88
|
+
} catch {
|
|
89
|
+
// Scope analysis failed — cannot determine usage positions reliably
|
|
90
|
+
return undefined
|
|
262
91
|
}
|
|
263
92
|
|
|
264
|
-
walk(ast.program, null)
|
|
265
93
|
return preferred ?? anyUsage
|
|
266
94
|
}
|
|
@@ -2,14 +2,36 @@ import * as t from '@babel/types'
|
|
|
2
2
|
import { generateFromAst, parseAst } from '@tanstack/router-utils'
|
|
3
3
|
|
|
4
4
|
import { MOCK_MODULE_ID } from './virtualModules'
|
|
5
|
-
|
|
6
|
-
// ---------------------------------------------------------------------------
|
|
7
|
-
// Export name collection (for dev mock-edge modules)
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
5
|
+
import { getOrCreate } from './utils'
|
|
9
6
|
|
|
10
7
|
export function isValidExportName(name: string): boolean {
|
|
11
|
-
if (name === 'default') return false
|
|
12
|
-
|
|
8
|
+
if (name === 'default' || name.length === 0) return false
|
|
9
|
+
const first = name.charCodeAt(0)
|
|
10
|
+
// First char: A-Z (65-90), a-z (97-122), _ (95), $ (36)
|
|
11
|
+
if (
|
|
12
|
+
!(
|
|
13
|
+
(first >= 65 && first <= 90) ||
|
|
14
|
+
(first >= 97 && first <= 122) ||
|
|
15
|
+
first === 95 ||
|
|
16
|
+
first === 36
|
|
17
|
+
)
|
|
18
|
+
)
|
|
19
|
+
return false
|
|
20
|
+
for (let i = 1; i < name.length; i++) {
|
|
21
|
+
const ch = name.charCodeAt(i)
|
|
22
|
+
// Subsequent: A-Z, a-z, 0-9 (48-57), _, $
|
|
23
|
+
if (
|
|
24
|
+
!(
|
|
25
|
+
(ch >= 65 && ch <= 90) ||
|
|
26
|
+
(ch >= 97 && ch <= 122) ||
|
|
27
|
+
(ch >= 48 && ch <= 57) ||
|
|
28
|
+
ch === 95 ||
|
|
29
|
+
ch === 36
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
return true
|
|
13
35
|
}
|
|
14
36
|
|
|
15
37
|
/**
|
|
@@ -23,13 +45,8 @@ export function collectMockExportNamesBySource(
|
|
|
23
45
|
|
|
24
46
|
const namesBySource = new Map<string, Set<string>>()
|
|
25
47
|
const add = (source: string, name: string) => {
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
if (!set) {
|
|
29
|
-
set = new Set<string>()
|
|
30
|
-
namesBySource.set(source, set)
|
|
31
|
-
}
|
|
32
|
-
set.add(name)
|
|
48
|
+
if (name === 'default' || name.length === 0) return
|
|
49
|
+
getOrCreate(namesBySource, source, () => new Set<string>()).add(name)
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
for (const node of ast.program.body) {
|
|
@@ -66,10 +83,6 @@ export function collectMockExportNamesBySource(
|
|
|
66
83
|
return out
|
|
67
84
|
}
|
|
68
85
|
|
|
69
|
-
// ---------------------------------------------------------------------------
|
|
70
|
-
// AST-based import rewriting
|
|
71
|
-
// ---------------------------------------------------------------------------
|
|
72
|
-
|
|
73
86
|
/**
|
|
74
87
|
* Rewrite static imports/re-exports from denied sources using Babel AST transforms.
|
|
75
88
|
*
|
|
@@ -101,16 +114,13 @@ export function rewriteDeniedImports(
|
|
|
101
114
|
for (let i = ast.program.body.length - 1; i >= 0; i--) {
|
|
102
115
|
const node = ast.program.body[i]!
|
|
103
116
|
|
|
104
|
-
// --- import declarations ---
|
|
105
117
|
if (t.isImportDeclaration(node)) {
|
|
106
|
-
// Skip type-only imports
|
|
107
118
|
if (node.importKind === 'type') continue
|
|
108
119
|
if (!deniedSources.has(node.source.value)) continue
|
|
109
120
|
|
|
110
121
|
const mockVar = `__tss_deny_${mockCounter++}`
|
|
111
122
|
const replacements: Array<t.Statement> = []
|
|
112
123
|
|
|
113
|
-
// import __tss_deny_N from '<mock>'
|
|
114
124
|
replacements.push(
|
|
115
125
|
t.importDeclaration(
|
|
116
126
|
[t.importDefaultSpecifier(t.identifier(mockVar))],
|
|
@@ -119,18 +129,10 @@ export function rewriteDeniedImports(
|
|
|
119
129
|
)
|
|
120
130
|
|
|
121
131
|
for (const specifier of node.specifiers) {
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
t.variableDeclarator(
|
|
127
|
-
t.identifier(specifier.local.name),
|
|
128
|
-
t.identifier(mockVar),
|
|
129
|
-
),
|
|
130
|
-
]),
|
|
131
|
-
)
|
|
132
|
-
} else if (t.isImportNamespaceSpecifier(specifier)) {
|
|
133
|
-
// import * as ns from 'denied' -> const ns = __tss_deny_N
|
|
132
|
+
if (
|
|
133
|
+
t.isImportDefaultSpecifier(specifier) ||
|
|
134
|
+
t.isImportNamespaceSpecifier(specifier)
|
|
135
|
+
) {
|
|
134
136
|
replacements.push(
|
|
135
137
|
t.variableDeclaration('const', [
|
|
136
138
|
t.variableDeclarator(
|
|
@@ -140,9 +142,7 @@ export function rewriteDeniedImports(
|
|
|
140
142
|
]),
|
|
141
143
|
)
|
|
142
144
|
} else if (t.isImportSpecifier(specifier)) {
|
|
143
|
-
// Skip type-only specifiers
|
|
144
145
|
if (specifier.importKind === 'type') continue
|
|
145
|
-
// import { a as b } from 'denied' -> const b = __tss_deny_N.a
|
|
146
146
|
const importedName = t.isIdentifier(specifier.imported)
|
|
147
147
|
? specifier.imported.name
|
|
148
148
|
: specifier.imported.value
|
|
@@ -165,7 +165,6 @@ export function rewriteDeniedImports(
|
|
|
165
165
|
continue
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
// --- export { x } from 'denied' ---
|
|
169
168
|
if (t.isExportNamedDeclaration(node) && node.source) {
|
|
170
169
|
if (node.exportKind === 'type') continue
|
|
171
170
|
if (!deniedSources.has(node.source.value)) continue
|
|
@@ -173,15 +172,12 @@ export function rewriteDeniedImports(
|
|
|
173
172
|
const mockVar = `__tss_deny_${mockCounter++}`
|
|
174
173
|
const replacements: Array<t.Statement> = []
|
|
175
174
|
|
|
176
|
-
// import __tss_deny_N from '<mock>'
|
|
177
175
|
replacements.push(
|
|
178
176
|
t.importDeclaration(
|
|
179
177
|
[t.importDefaultSpecifier(t.identifier(mockVar))],
|
|
180
178
|
t.stringLiteral(getMockModuleId(node.source.value)),
|
|
181
179
|
),
|
|
182
180
|
)
|
|
183
|
-
|
|
184
|
-
// For each re-exported specifier, create an exported const
|
|
185
181
|
const exportSpecifiers: Array<{
|
|
186
182
|
localName: string
|
|
187
183
|
exportedName: string
|
|
@@ -195,7 +191,6 @@ export function rewriteDeniedImports(
|
|
|
195
191
|
: specifier.exported.value
|
|
196
192
|
|
|
197
193
|
const internalVar = `__tss_reexport_${localName}`
|
|
198
|
-
// const __tss_reexport_x = __tss_deny_N.x
|
|
199
194
|
replacements.push(
|
|
200
195
|
t.variableDeclaration('const', [
|
|
201
196
|
t.variableDeclarator(
|
|
@@ -211,7 +206,6 @@ export function rewriteDeniedImports(
|
|
|
211
206
|
}
|
|
212
207
|
}
|
|
213
208
|
|
|
214
|
-
// export { __tss_reexport_x as x, ... }
|
|
215
209
|
if (exportSpecifiers.length > 0) {
|
|
216
210
|
replacements.push(
|
|
217
211
|
t.exportNamedDeclaration(
|
|
@@ -231,12 +225,10 @@ export function rewriteDeniedImports(
|
|
|
231
225
|
continue
|
|
232
226
|
}
|
|
233
227
|
|
|
234
|
-
// --- export * from 'denied' ---
|
|
235
228
|
if (t.isExportAllDeclaration(node)) {
|
|
236
229
|
if (node.exportKind === 'type') continue
|
|
237
230
|
if (!deniedSources.has(node.source.value)) continue
|
|
238
231
|
|
|
239
|
-
// Remove the star re-export entirely
|
|
240
232
|
ast.program.body.splice(i, 1)
|
|
241
233
|
modified = true
|
|
242
234
|
continue
|