@tanstack/start-plugin-core 1.167.35 → 1.169.0
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/adapterUtils.d.ts +27 -0
- package/dist/esm/import-protection/adapterUtils.js +31 -0
- package/dist/esm/import-protection/adapterUtils.js.map +1 -0
- package/dist/esm/import-protection/analysis.d.ts +36 -0
- package/dist/esm/import-protection/analysis.js +407 -0
- package/dist/esm/import-protection/analysis.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/ast.js +1 -1
- package/dist/esm/import-protection/ast.js.map +1 -0
- package/dist/esm/import-protection/constants.d.ts +11 -0
- package/dist/esm/{import-protection-plugin → import-protection}/constants.js +7 -2
- package/dist/esm/import-protection/constants.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/defaults.js +1 -1
- package/dist/esm/import-protection/defaults.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.js +2 -2
- package/dist/esm/import-protection/extensionlessAbsoluteIdResolver.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/matchers.js +1 -1
- package/dist/esm/import-protection/matchers.js.map +1 -0
- package/dist/esm/{import-protection-plugin/rewriteDeniedImports.d.ts → import-protection/rewrite.d.ts} +0 -4
- package/dist/esm/import-protection/rewrite.js +121 -0
- package/dist/esm/import-protection/rewrite.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.d.ts +32 -3
- package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.js +65 -10
- package/dist/esm/import-protection/sourceLocation.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/trace.d.ts +0 -1
- package/dist/esm/{import-protection-plugin → import-protection}/trace.js +1 -1
- package/dist/esm/import-protection/trace.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/utils.d.ts +18 -1
- package/dist/esm/{import-protection-plugin → import-protection}/utils.js +13 -20
- package/dist/esm/import-protection/utils.js.map +1 -0
- package/dist/esm/import-protection/virtualModules.d.ts +25 -0
- package/dist/esm/{import-protection-plugin → import-protection}/virtualModules.js +5 -117
- package/dist/esm/import-protection/virtualModules.js.map +1 -0
- package/dist/esm/index.d.ts +1 -5
- package/dist/esm/index.js +2 -4
- package/dist/esm/post-build.d.ts +9 -0
- package/dist/esm/post-build.js +37 -0
- package/dist/esm/post-build.js.map +1 -0
- package/dist/esm/prerender.d.ts +11 -0
- package/dist/esm/prerender.js +159 -0
- package/dist/esm/prerender.js.map +1 -0
- package/dist/esm/rsbuild/dev-server.d.ts +21 -0
- package/dist/esm/rsbuild/dev-server.js +76 -0
- package/dist/esm/rsbuild/dev-server.js.map +1 -0
- package/dist/esm/rsbuild/import-protection.d.ts +10 -0
- package/dist/esm/rsbuild/import-protection.js +775 -0
- package/dist/esm/rsbuild/import-protection.js.map +1 -0
- package/dist/esm/rsbuild/index.d.ts +4 -0
- package/dist/esm/rsbuild/index.js +3 -0
- package/dist/esm/rsbuild/normalized-client-build.d.ts +18 -0
- package/dist/esm/rsbuild/normalized-client-build.js +207 -0
- package/dist/esm/rsbuild/normalized-client-build.js.map +1 -0
- package/dist/esm/rsbuild/planning.d.ts +52 -0
- package/dist/esm/rsbuild/planning.js +108 -0
- package/dist/esm/rsbuild/planning.js.map +1 -0
- package/dist/esm/rsbuild/plugin.d.ts +4 -0
- package/dist/esm/rsbuild/plugin.js +344 -0
- package/dist/esm/rsbuild/plugin.js.map +1 -0
- package/dist/esm/rsbuild/post-build.d.ts +6 -0
- package/dist/esm/rsbuild/post-build.js +57 -0
- package/dist/esm/rsbuild/post-build.js.map +1 -0
- package/dist/esm/rsbuild/schema.d.ts +3372 -0
- package/dist/esm/rsbuild/schema.js +12 -0
- package/dist/esm/rsbuild/schema.js.map +1 -0
- package/dist/esm/rsbuild/start-compiler-host.d.ts +20 -0
- package/dist/esm/rsbuild/start-compiler-host.js +150 -0
- package/dist/esm/rsbuild/start-compiler-host.js.map +1 -0
- package/dist/esm/rsbuild/start-router-plugin.d.ts +18 -0
- package/dist/esm/rsbuild/start-router-plugin.js +63 -0
- package/dist/esm/rsbuild/start-router-plugin.js.map +1 -0
- package/dist/esm/rsbuild/swc-rsc.d.ts +14 -0
- package/dist/esm/rsbuild/swc-rsc.js +93 -0
- package/dist/esm/rsbuild/swc-rsc.js.map +1 -0
- package/dist/esm/rsbuild/types.d.ts +17 -0
- package/dist/esm/rsbuild/types.js +0 -0
- package/dist/esm/rsbuild/virtual-modules.d.ts +53 -0
- package/dist/esm/rsbuild/virtual-modules.js +287 -0
- package/dist/esm/rsbuild/virtual-modules.js.map +1 -0
- package/dist/esm/schema.d.ts +43 -43
- package/dist/esm/start-compiler/compiler.d.ts +1 -1
- package/dist/esm/start-compiler/compiler.js +80 -9
- package/dist/esm/start-compiler/compiler.js.map +1 -1
- package/dist/esm/start-compiler/handleCreateServerFn.js +9 -0
- package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -1
- package/dist/esm/start-compiler/host.js +5 -1
- package/dist/esm/start-compiler/host.js.map +1 -1
- package/dist/esm/start-compiler/types.d.ts +1 -0
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +10 -1
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.js +41 -92
- package/dist/esm/vite/import-protection-plugin/plugin.js.map +1 -0
- package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/types.d.ts +5 -5
- package/dist/esm/vite/import-protection-plugin/virtualModules.d.ts +8 -0
- package/dist/esm/vite/import-protection-plugin/virtualModules.js +49 -0
- package/dist/esm/vite/import-protection-plugin/virtualModules.js.map +1 -0
- package/dist/esm/vite/index.d.ts +5 -0
- package/dist/esm/vite/index.js +4 -0
- package/dist/esm/vite/plugin.js +1 -1
- package/dist/esm/vite/plugin.js.map +1 -1
- package/dist/esm/vite/post-server-build.js +14 -32
- package/dist/esm/vite/post-server-build.js.map +1 -1
- package/dist/esm/vite/prerender.d.ts +2 -2
- package/dist/esm/vite/prerender.js +17 -147
- package/dist/esm/vite/prerender.js.map +1 -1
- package/dist/esm/vite/schema.d.ts +23 -23
- package/dist/esm/vite/start-compiler-plugin/hot-update.d.ts +2 -0
- package/dist/esm/vite/start-compiler-plugin/hot-update.js +16 -0
- package/dist/esm/vite/start-compiler-plugin/hot-update.js.map +1 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js +9 -4
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -1
- package/dist/esm/vite/start-compiler-plugin/plugin.js +86 -13
- package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -1
- package/package.json +32 -4
- package/src/import-protection/INTERNALS.md +266 -0
- package/src/import-protection/adapterUtils.ts +94 -0
- package/src/import-protection/analysis.ts +853 -0
- package/src/{import-protection-plugin → import-protection}/constants.ts +7 -0
- package/src/import-protection/rewrite.ts +229 -0
- package/src/{import-protection-plugin → import-protection}/sourceLocation.ts +125 -9
- package/src/{import-protection-plugin → import-protection}/trace.ts +0 -1
- package/src/{import-protection-plugin → import-protection}/utils.ts +36 -21
- package/src/{import-protection-plugin → import-protection}/virtualModules.ts +30 -177
- package/src/index.ts +1 -8
- package/src/post-build.ts +64 -0
- package/src/prerender.ts +292 -0
- package/src/rsbuild/INTERNALS-import-protection.md +169 -0
- package/src/rsbuild/dev-server.ts +129 -0
- package/src/rsbuild/import-protection.ts +1599 -0
- package/src/rsbuild/index.ts +4 -0
- package/src/rsbuild/normalized-client-build.ts +346 -0
- package/src/rsbuild/planning.ts +234 -0
- package/src/rsbuild/plugin.ts +754 -0
- package/src/rsbuild/post-build.ts +96 -0
- package/src/rsbuild/schema.ts +31 -0
- package/src/rsbuild/start-compiler-host.ts +250 -0
- package/src/rsbuild/start-router-plugin.ts +86 -0
- package/src/rsbuild/swc-rsc.ts +166 -0
- package/src/rsbuild/types.ts +20 -0
- package/src/rsbuild/virtual-modules.ts +565 -0
- package/src/start-compiler/compiler.ts +153 -19
- package/src/start-compiler/handleCreateServerFn.ts +18 -0
- package/src/start-compiler/types.ts +1 -0
- package/src/utils.ts +14 -0
- package/src/vite/import-protection-plugin/INTERNALS.md +187 -0
- package/src/{import-protection-plugin → vite/import-protection-plugin}/plugin.ts +73 -158
- package/src/{import-protection-plugin → vite/import-protection-plugin}/types.ts +5 -5
- package/src/vite/import-protection-plugin/virtualModules.ts +122 -0
- package/src/vite/index.ts +8 -0
- package/src/vite/plugin.ts +1 -1
- package/src/vite/post-server-build.ts +14 -57
- package/src/vite/prerender.ts +19 -260
- package/src/vite/start-compiler-plugin/hot-update.ts +24 -0
- package/src/vite/start-compiler-plugin/module-specifier.ts +15 -5
- package/src/vite/start-compiler-plugin/plugin.ts +193 -18
- package/dist/esm/import-protection-plugin/ast.js.map +0 -1
- package/dist/esm/import-protection-plugin/constants.d.ts +0 -6
- package/dist/esm/import-protection-plugin/constants.js.map +0 -1
- package/dist/esm/import-protection-plugin/defaults.js.map +0 -1
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +0 -1
- package/dist/esm/import-protection-plugin/matchers.js.map +0 -1
- package/dist/esm/import-protection-plugin/plugin.js.map +0 -1
- package/dist/esm/import-protection-plugin/postCompileUsage.d.ts +0 -13
- package/dist/esm/import-protection-plugin/postCompileUsage.js +0 -63
- package/dist/esm/import-protection-plugin/postCompileUsage.js.map +0 -1
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +0 -205
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +0 -1
- package/dist/esm/import-protection-plugin/sourceLocation.js.map +0 -1
- package/dist/esm/import-protection-plugin/trace.js.map +0 -1
- package/dist/esm/import-protection-plugin/utils.js.map +0 -1
- package/dist/esm/import-protection-plugin/virtualModules.d.ts +0 -78
- package/dist/esm/import-protection-plugin/virtualModules.js.map +0 -1
- package/dist/esm/start-compiler/load-module.d.ts +0 -14
- package/dist/esm/start-compiler/load-module.js +0 -18
- package/dist/esm/start-compiler/load-module.js.map +0 -1
- package/src/import-protection-plugin/INTERNALS.md +0 -700
- package/src/import-protection-plugin/postCompileUsage.ts +0 -100
- package/src/import-protection-plugin/rewriteDeniedImports.ts +0 -379
- package/src/start-compiler/load-module.ts +0 -31
- /package/dist/esm/{import-protection-plugin → import-protection}/ast.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/defaults.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/matchers.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.d.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/ast.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/defaults.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/matchers.ts +0 -0
|
@@ -2,6 +2,13 @@ import { SERVER_FN_LOOKUP } from '../constants'
|
|
|
2
2
|
|
|
3
3
|
export const SERVER_FN_LOOKUP_QUERY = `?${SERVER_FN_LOOKUP}`
|
|
4
4
|
|
|
5
|
+
export const MOCK_MODULE_ID = 'tanstack-start-import-protection:mock'
|
|
6
|
+
export const MOCK_BUILD_PREFIX = 'tanstack-start-import-protection:mock:build:'
|
|
7
|
+
export const MOCK_EDGE_PREFIX = 'tanstack-start-import-protection:mock-edge:'
|
|
8
|
+
export const MOCK_RUNTIME_PREFIX =
|
|
9
|
+
'tanstack-start-import-protection:mock-runtime:'
|
|
10
|
+
export const MARKER_PREFIX = 'tanstack-start-import-protection:marker:'
|
|
11
|
+
|
|
5
12
|
export const IMPORT_PROTECTION_DEBUG =
|
|
6
13
|
process.env.TSR_IMPORT_PROTECTION_DEBUG === '1' ||
|
|
7
14
|
process.env.TSR_IMPORT_PROTECTION_DEBUG === 'true'
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import * as t from '@babel/types'
|
|
2
|
+
import { generateFromAst } from '@tanstack/router-utils'
|
|
3
|
+
|
|
4
|
+
import { parseImportProtectionAst } from './ast'
|
|
5
|
+
import { MOCK_MODULE_ID } from './constants'
|
|
6
|
+
import type { ParsedAst } from './ast'
|
|
7
|
+
import type { SourceMapLike } from './sourceLocation'
|
|
8
|
+
|
|
9
|
+
function getModuleExportName(node: t.Identifier | t.StringLiteral): string {
|
|
10
|
+
return t.isIdentifier(node) ? node.name : node.value
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function toMemberExpressionProperty(name: string): {
|
|
14
|
+
property: t.Identifier | t.StringLiteral
|
|
15
|
+
computed: boolean
|
|
16
|
+
} {
|
|
17
|
+
return t.isValidIdentifier(name)
|
|
18
|
+
? { property: t.identifier(name), computed: false }
|
|
19
|
+
: { property: t.stringLiteral(name), computed: true }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function toModuleExportNameNode(name: string): t.Identifier | t.StringLiteral {
|
|
23
|
+
return t.isValidIdentifier(name) ? t.identifier(name) : t.stringLiteral(name)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function createInternalReexportVarName(
|
|
27
|
+
localName: string,
|
|
28
|
+
mockIndex: number,
|
|
29
|
+
usedNames: Set<string>,
|
|
30
|
+
): string {
|
|
31
|
+
const baseName = t.isValidIdentifier(localName)
|
|
32
|
+
? `__tss_reexport_${localName}`
|
|
33
|
+
: `__tss_reexport_${mockIndex}`
|
|
34
|
+
|
|
35
|
+
let candidate = baseName
|
|
36
|
+
let suffix = 0
|
|
37
|
+
while (usedNames.has(candidate)) {
|
|
38
|
+
suffix++
|
|
39
|
+
candidate = `${baseName}_${suffix}`
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
usedNames.add(candidate)
|
|
43
|
+
return candidate
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Rewrite static imports/re-exports from denied sources using Babel AST transforms.
|
|
48
|
+
*
|
|
49
|
+
* Transforms:
|
|
50
|
+
* import { a as b, c } from 'denied'
|
|
51
|
+
* Into:
|
|
52
|
+
* import __tss_deny_0 from 'tanstack-start-import-protection:mock'
|
|
53
|
+
* const b = __tss_deny_0.a
|
|
54
|
+
* const c = __tss_deny_0.c
|
|
55
|
+
*
|
|
56
|
+
* Also handles:
|
|
57
|
+
* import def from 'denied' -> import def from mock
|
|
58
|
+
* import * as ns from 'denied' -> import ns from mock
|
|
59
|
+
* export { x } from 'denied' -> export const x = mock.x
|
|
60
|
+
* export * from 'denied' -> removed
|
|
61
|
+
* export { x as y } from 'denied' -> export const y = mock.x
|
|
62
|
+
*/
|
|
63
|
+
export function rewriteDeniedImports(
|
|
64
|
+
code: string,
|
|
65
|
+
id: string,
|
|
66
|
+
deniedSources: Set<string>,
|
|
67
|
+
getMockModuleId: (source: string) => string = () => MOCK_MODULE_ID,
|
|
68
|
+
): { code: string; map?: SourceMapLike } | undefined {
|
|
69
|
+
return rewriteDeniedImportsFromAst(
|
|
70
|
+
parseImportProtectionAst(code),
|
|
71
|
+
id,
|
|
72
|
+
deniedSources,
|
|
73
|
+
getMockModuleId,
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function rewriteDeniedImportsFromAst(
|
|
78
|
+
ast: ParsedAst,
|
|
79
|
+
id: string,
|
|
80
|
+
deniedSources: Set<string>,
|
|
81
|
+
getMockModuleId: (source: string) => string = () => MOCK_MODULE_ID,
|
|
82
|
+
): { code: string; map?: SourceMapLike } | undefined {
|
|
83
|
+
let modified = false
|
|
84
|
+
let mockCounter = 0
|
|
85
|
+
|
|
86
|
+
// Walk program body in reverse so splice indices stay valid
|
|
87
|
+
for (let i = ast.program.body.length - 1; i >= 0; i--) {
|
|
88
|
+
const node = ast.program.body[i]!
|
|
89
|
+
|
|
90
|
+
if (t.isImportDeclaration(node)) {
|
|
91
|
+
if (node.importKind === 'type') continue
|
|
92
|
+
if (!deniedSources.has(node.source.value)) continue
|
|
93
|
+
|
|
94
|
+
const mockVar = `__tss_deny_${mockCounter++}`
|
|
95
|
+
const replacements: Array<t.Statement> = []
|
|
96
|
+
|
|
97
|
+
replacements.push(
|
|
98
|
+
t.importDeclaration(
|
|
99
|
+
[t.importDefaultSpecifier(t.identifier(mockVar))],
|
|
100
|
+
t.stringLiteral(getMockModuleId(node.source.value)),
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
for (const specifier of node.specifiers) {
|
|
105
|
+
if (
|
|
106
|
+
t.isImportDefaultSpecifier(specifier) ||
|
|
107
|
+
t.isImportNamespaceSpecifier(specifier)
|
|
108
|
+
) {
|
|
109
|
+
replacements.push(
|
|
110
|
+
t.variableDeclaration('const', [
|
|
111
|
+
t.variableDeclarator(
|
|
112
|
+
t.identifier(specifier.local.name),
|
|
113
|
+
t.identifier(mockVar),
|
|
114
|
+
),
|
|
115
|
+
]),
|
|
116
|
+
)
|
|
117
|
+
} else if (t.isImportSpecifier(specifier)) {
|
|
118
|
+
if (specifier.importKind === 'type') continue
|
|
119
|
+
const importedName = getModuleExportName(specifier.imported)
|
|
120
|
+
const memberProperty = toMemberExpressionProperty(importedName)
|
|
121
|
+
replacements.push(
|
|
122
|
+
t.variableDeclaration('const', [
|
|
123
|
+
t.variableDeclarator(
|
|
124
|
+
t.identifier(specifier.local.name),
|
|
125
|
+
t.memberExpression(
|
|
126
|
+
t.identifier(mockVar),
|
|
127
|
+
memberProperty.property,
|
|
128
|
+
memberProperty.computed,
|
|
129
|
+
),
|
|
130
|
+
),
|
|
131
|
+
]),
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
ast.program.body.splice(i, 1, ...replacements)
|
|
137
|
+
modified = true
|
|
138
|
+
continue
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (t.isExportNamedDeclaration(node) && node.source) {
|
|
142
|
+
if (node.exportKind === 'type') continue
|
|
143
|
+
if (!deniedSources.has(node.source.value)) continue
|
|
144
|
+
|
|
145
|
+
const mockIndex = mockCounter++
|
|
146
|
+
const mockVar = `__tss_deny_${mockIndex}`
|
|
147
|
+
const replacements: Array<t.Statement> = []
|
|
148
|
+
|
|
149
|
+
replacements.push(
|
|
150
|
+
t.importDeclaration(
|
|
151
|
+
[t.importDefaultSpecifier(t.identifier(mockVar))],
|
|
152
|
+
t.stringLiteral(getMockModuleId(node.source.value)),
|
|
153
|
+
),
|
|
154
|
+
)
|
|
155
|
+
const usedInternalVars = new Set<string>()
|
|
156
|
+
const exportSpecifiers: Array<{
|
|
157
|
+
localName: string
|
|
158
|
+
exportedName: string
|
|
159
|
+
}> = []
|
|
160
|
+
for (const specifier of node.specifiers) {
|
|
161
|
+
if (t.isExportSpecifier(specifier)) {
|
|
162
|
+
if (specifier.exportKind === 'type') continue
|
|
163
|
+
const localName = getModuleExportName(specifier.local)
|
|
164
|
+
const exportedName = getModuleExportName(specifier.exported)
|
|
165
|
+
const memberProperty = toMemberExpressionProperty(localName)
|
|
166
|
+
|
|
167
|
+
const internalVar = createInternalReexportVarName(
|
|
168
|
+
localName,
|
|
169
|
+
mockIndex,
|
|
170
|
+
usedInternalVars,
|
|
171
|
+
)
|
|
172
|
+
replacements.push(
|
|
173
|
+
t.variableDeclaration('const', [
|
|
174
|
+
t.variableDeclarator(
|
|
175
|
+
t.identifier(internalVar),
|
|
176
|
+
t.memberExpression(
|
|
177
|
+
t.identifier(mockVar),
|
|
178
|
+
memberProperty.property,
|
|
179
|
+
memberProperty.computed,
|
|
180
|
+
),
|
|
181
|
+
),
|
|
182
|
+
]),
|
|
183
|
+
)
|
|
184
|
+
exportSpecifiers.push({ localName: internalVar, exportedName })
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (exportSpecifiers.length > 0) {
|
|
189
|
+
replacements.push(
|
|
190
|
+
t.exportNamedDeclaration(
|
|
191
|
+
null,
|
|
192
|
+
exportSpecifiers.map((s) =>
|
|
193
|
+
t.exportSpecifier(
|
|
194
|
+
t.identifier(s.localName),
|
|
195
|
+
toModuleExportNameNode(s.exportedName),
|
|
196
|
+
),
|
|
197
|
+
),
|
|
198
|
+
),
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
ast.program.body.splice(i, 1, ...replacements)
|
|
203
|
+
modified = true
|
|
204
|
+
continue
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (t.isExportAllDeclaration(node)) {
|
|
208
|
+
if (node.exportKind === 'type') continue
|
|
209
|
+
if (!deniedSources.has(node.source.value)) continue
|
|
210
|
+
|
|
211
|
+
ast.program.body.splice(i, 1)
|
|
212
|
+
modified = true
|
|
213
|
+
continue
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (!modified) return undefined
|
|
218
|
+
|
|
219
|
+
const result = generateFromAst(ast, {
|
|
220
|
+
sourceMaps: true,
|
|
221
|
+
sourceFileName: id,
|
|
222
|
+
filename: id,
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
code: result.code,
|
|
227
|
+
...(result.map ? { map: result.map as SourceMapLike } : {}),
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { SourceMapConsumer } from 'source-map'
|
|
2
2
|
import * as path from 'pathe'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
findOriginalUnsafeUsagePosFromResult,
|
|
6
|
+
findPostCompileUsagePosFromResult,
|
|
7
|
+
getImportSpecifierLocationFromResult,
|
|
8
|
+
} from './analysis'
|
|
5
9
|
import { getOrCreate, normalizeFilePath } from './utils'
|
|
10
|
+
import type { ImportAnalysis } from './analysis'
|
|
11
|
+
import type { ParsedAst } from './ast'
|
|
6
12
|
import type { Loc } from './trace'
|
|
7
13
|
import type { RawSourceMap } from 'source-map'
|
|
8
14
|
|
|
@@ -27,8 +33,11 @@ export interface TransformResult {
|
|
|
27
33
|
code: string
|
|
28
34
|
map: SourceMapLike | undefined
|
|
29
35
|
originalCode: string | undefined
|
|
36
|
+
originalResult?: TransformResult
|
|
30
37
|
/** Precomputed line index for `code` (index → line/col). */
|
|
31
38
|
lineIndex?: LineIndex
|
|
39
|
+
parsedAst?: ParsedAst
|
|
40
|
+
analysis?: ImportAnalysis
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
/**
|
|
@@ -41,6 +50,10 @@ export interface TransformResultProvider {
|
|
|
41
50
|
getTransformResult: (id: string) => TransformResult | undefined
|
|
42
51
|
}
|
|
43
52
|
|
|
53
|
+
export interface ImportSpecifierLocationIndex {
|
|
54
|
+
find: FindImportSpecifierLocationIndex
|
|
55
|
+
}
|
|
56
|
+
|
|
44
57
|
// Index → line/column conversion
|
|
45
58
|
|
|
46
59
|
export type LineIndex = {
|
|
@@ -81,6 +94,42 @@ function indexToLineColWithIndex(
|
|
|
81
94
|
return { line, column0: Math.max(0, idx - lineStart) }
|
|
82
95
|
}
|
|
83
96
|
|
|
97
|
+
export function indexToLineColumn(
|
|
98
|
+
lineIndex: LineIndex,
|
|
99
|
+
idx: number,
|
|
100
|
+
): { line: number; column: number } {
|
|
101
|
+
const { line, column0 } = indexToLineColWithIndex(lineIndex, idx)
|
|
102
|
+
return {
|
|
103
|
+
line,
|
|
104
|
+
column: column0 + 1,
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function normalizeSourceMap(map: SourceMapLike | null | undefined):
|
|
109
|
+
| {
|
|
110
|
+
version: number
|
|
111
|
+
file: string
|
|
112
|
+
sourceRoot?: string
|
|
113
|
+
sources: Array<string>
|
|
114
|
+
names: Array<string>
|
|
115
|
+
sourcesContent?: Array<string>
|
|
116
|
+
mappings: string
|
|
117
|
+
}
|
|
118
|
+
| undefined {
|
|
119
|
+
if (!map) {
|
|
120
|
+
return undefined
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
...map,
|
|
125
|
+
version: Number(map.version),
|
|
126
|
+
file: map.file ?? '',
|
|
127
|
+
names: Array.isArray(map.names) ? map.names : [],
|
|
128
|
+
sourcesContent:
|
|
129
|
+
map.sourcesContent?.map((value) => value ?? '') ?? undefined,
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
84
133
|
/**
|
|
85
134
|
* Pick the most-likely original source text for `importerFile` from
|
|
86
135
|
* a sourcemap that may contain multiple sources.
|
|
@@ -271,7 +320,40 @@ export class ImportLocCache {
|
|
|
271
320
|
}
|
|
272
321
|
}
|
|
273
322
|
|
|
274
|
-
export type
|
|
323
|
+
export type FindImportSpecifierLocationIndex = (
|
|
324
|
+
result: TransformResult,
|
|
325
|
+
source: string,
|
|
326
|
+
) => number
|
|
327
|
+
|
|
328
|
+
export function getOrCreateOriginalTransformResult(
|
|
329
|
+
result: TransformResult,
|
|
330
|
+
): TransformResult | undefined {
|
|
331
|
+
if (!result.originalCode) {
|
|
332
|
+
return undefined
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (!result.originalResult) {
|
|
336
|
+
result.originalResult = {
|
|
337
|
+
code: result.originalCode,
|
|
338
|
+
map: undefined,
|
|
339
|
+
originalCode: result.originalCode,
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return result.originalResult
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export function createImportSpecifierLocationIndex(): ImportSpecifierLocationIndex {
|
|
347
|
+
return {
|
|
348
|
+
find(result: TransformResult, source: string): number {
|
|
349
|
+
if (!result.code.includes(source)) {
|
|
350
|
+
return -1
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return getImportSpecifierLocationFromResult(result, source)
|
|
354
|
+
},
|
|
355
|
+
}
|
|
356
|
+
}
|
|
275
357
|
|
|
276
358
|
/**
|
|
277
359
|
* Find the location of an import statement in a transformed module
|
|
@@ -283,7 +365,7 @@ export async function findImportStatementLocationFromTransformed(
|
|
|
283
365
|
importerId: string,
|
|
284
366
|
source: string,
|
|
285
367
|
importLocCache: ImportLocCache,
|
|
286
|
-
|
|
368
|
+
findImportSpecifierLocationIndex: FindImportSpecifierLocationIndex,
|
|
287
369
|
): Promise<Loc | undefined> {
|
|
288
370
|
const importerFile = normalizeFilePath(importerId)
|
|
289
371
|
const cacheKey = `${importerFile}::${source}`
|
|
@@ -298,11 +380,12 @@ export async function findImportStatementLocationFromTransformed(
|
|
|
298
380
|
return undefined
|
|
299
381
|
}
|
|
300
382
|
|
|
301
|
-
const {
|
|
383
|
+
const { map } = res
|
|
302
384
|
|
|
303
|
-
const lineIndex =
|
|
385
|
+
const lineIndex =
|
|
386
|
+
res.lineIndex ?? (res.lineIndex = buildLineIndex(res.code))
|
|
304
387
|
|
|
305
|
-
const idx =
|
|
388
|
+
const idx = findImportSpecifierLocationIndex(res, source)
|
|
306
389
|
if (idx === -1) {
|
|
307
390
|
importLocCache.set(cacheKey, null)
|
|
308
391
|
return undefined
|
|
@@ -338,7 +421,7 @@ export async function findPostCompileUsageLocation(
|
|
|
338
421
|
res.lineIndex = buildLineIndex(code)
|
|
339
422
|
}
|
|
340
423
|
|
|
341
|
-
const pos =
|
|
424
|
+
const pos = findPostCompileUsagePosFromResult(res, source)
|
|
342
425
|
if (!pos) return undefined
|
|
343
426
|
|
|
344
427
|
return await mapGeneratedToOriginal(map, pos, importerFile)
|
|
@@ -347,6 +430,39 @@ export async function findPostCompileUsageLocation(
|
|
|
347
430
|
}
|
|
348
431
|
}
|
|
349
432
|
|
|
433
|
+
/**
|
|
434
|
+
* Best-effort original-source usage lookup for cases where a later transform
|
|
435
|
+
* removes or rewrites the import from emitted code but preserves the original
|
|
436
|
+
* source in `sourcesContent`.
|
|
437
|
+
*/
|
|
438
|
+
export function findOriginalUsageLocation(
|
|
439
|
+
provider: TransformResultProvider,
|
|
440
|
+
importerId: string,
|
|
441
|
+
source: string,
|
|
442
|
+
envType?: 'client' | 'server',
|
|
443
|
+
): Loc | undefined {
|
|
444
|
+
try {
|
|
445
|
+
const importerFile = normalizeFilePath(importerId)
|
|
446
|
+
const res = provider.getTransformResult(importerId)
|
|
447
|
+
if (!res) return undefined
|
|
448
|
+
const originalResult = getOrCreateOriginalTransformResult(res)
|
|
449
|
+
if (!originalResult) return undefined
|
|
450
|
+
|
|
451
|
+
const pos = envType
|
|
452
|
+
? findOriginalUnsafeUsagePosFromResult(originalResult, source, envType)
|
|
453
|
+
: findPostCompileUsagePosFromResult(originalResult, source)
|
|
454
|
+
if (!pos) return undefined
|
|
455
|
+
|
|
456
|
+
return {
|
|
457
|
+
file: importerFile,
|
|
458
|
+
line: pos.line,
|
|
459
|
+
column: pos.column0 + 1,
|
|
460
|
+
}
|
|
461
|
+
} catch {
|
|
462
|
+
return undefined
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
350
466
|
/**
|
|
351
467
|
* Annotate each trace hop with the location of the import that created the
|
|
352
468
|
* edge (file:line:col). Skips steps that already have a location.
|
|
@@ -360,7 +476,7 @@ export async function addTraceImportLocations(
|
|
|
360
476
|
column?: number
|
|
361
477
|
}>,
|
|
362
478
|
importLocCache: ImportLocCache,
|
|
363
|
-
|
|
479
|
+
findImportSpecifierLocationIndex: FindImportSpecifierLocationIndex,
|
|
364
480
|
): Promise<void> {
|
|
365
481
|
for (const step of trace) {
|
|
366
482
|
if (!step.specifier) continue
|
|
@@ -370,7 +486,7 @@ export async function addTraceImportLocations(
|
|
|
370
486
|
step.file,
|
|
371
487
|
step.specifier,
|
|
372
488
|
importLocCache,
|
|
373
|
-
|
|
489
|
+
findImportSpecifierLocationIndex,
|
|
374
490
|
)
|
|
375
491
|
if (!loc) continue
|
|
376
492
|
step.line = loc.line
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
relative,
|
|
5
5
|
resolve as resolvePath,
|
|
6
6
|
} from 'node:path'
|
|
7
|
-
import { normalizePath } from '
|
|
7
|
+
import { normalizePath } from '../utils'
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
IMPORT_PROTECTION_DEBUG,
|
|
@@ -26,6 +26,41 @@ export function dedupePatterns(patterns: Array<Pattern>): Array<Pattern> {
|
|
|
26
26
|
return out
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export interface FileMatchers {
|
|
30
|
+
files: Array<{ pattern: Pattern; test: (value: string) => boolean }>
|
|
31
|
+
excludeFiles: Array<{ pattern: Pattern; test: (value: string) => boolean }>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function isFileExcluded(
|
|
35
|
+
relativePath: string,
|
|
36
|
+
matchers: Pick<FileMatchers, 'excludeFiles'>,
|
|
37
|
+
): boolean {
|
|
38
|
+
return (
|
|
39
|
+
matchers.excludeFiles.length > 0 &&
|
|
40
|
+
matchers.excludeFiles.some((matcher) => matcher.test(relativePath))
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function checkFileDenial(
|
|
45
|
+
relativePath: string,
|
|
46
|
+
matchers: FileMatchers,
|
|
47
|
+
): FileMatchers['files'][number] | undefined {
|
|
48
|
+
if (isFileExcluded(relativePath, matchers)) {
|
|
49
|
+
return undefined
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return matchers.files.find((matcher) => matcher.test(relativePath))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function dedupeViolationKey(info: {
|
|
56
|
+
type: string
|
|
57
|
+
importer: string
|
|
58
|
+
specifier: string
|
|
59
|
+
resolved?: string
|
|
60
|
+
}): string {
|
|
61
|
+
return `${info.type}:${info.importer}:${info.specifier}:${info.resolved ?? ''}`
|
|
62
|
+
}
|
|
63
|
+
|
|
29
64
|
/** Strip both `?query` and `#hash` from a module ID. */
|
|
30
65
|
export function stripQueryAndHash(id: string): string {
|
|
31
66
|
const q = id.indexOf('?')
|
|
@@ -57,15 +92,6 @@ export function clearNormalizeFilePathCache(): void {
|
|
|
57
92
|
normalizeFilePathCache.clear()
|
|
58
93
|
}
|
|
59
94
|
|
|
60
|
-
/**
|
|
61
|
-
* Lightweight regex to extract all import/re-export source strings from
|
|
62
|
-
* post-transform code. Matches:
|
|
63
|
-
* - `from "..."` / `from '...'` (static import/export)
|
|
64
|
-
* - `import("...")` / `import('...')` (dynamic import)
|
|
65
|
-
*/
|
|
66
|
-
const importSourceRe =
|
|
67
|
-
/\bfrom\s+(?:"([^"]+)"|'([^']+)')|import\s*\(\s*(?:"([^"]+)"|'([^']+)')\s*\)/g
|
|
68
|
-
|
|
69
95
|
export function escapeRegExp(s: string): string {
|
|
70
96
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
71
97
|
}
|
|
@@ -93,17 +119,6 @@ export function relativizePath(p: string, root: string): string {
|
|
|
93
119
|
return ch === 47 ? p.slice(root.length + 1) : p.slice(root.length)
|
|
94
120
|
}
|
|
95
121
|
|
|
96
|
-
export function extractImportSources(code: string): Array<string> {
|
|
97
|
-
const sources: Array<string> = []
|
|
98
|
-
let m: RegExpExecArray | null
|
|
99
|
-
importSourceRe.lastIndex = 0
|
|
100
|
-
while ((m = importSourceRe.exec(code)) !== null) {
|
|
101
|
-
const src = m[1] ?? m[2] ?? m[3] ?? m[4]
|
|
102
|
-
if (src) sources.push(src)
|
|
103
|
-
}
|
|
104
|
-
return sources
|
|
105
|
-
}
|
|
106
|
-
|
|
107
122
|
/** Log import-protection debug output when debug mode is enabled. */
|
|
108
123
|
export function debugLog(...args: Array<unknown>): void {
|
|
109
124
|
if (!IMPORT_PROTECTION_DEBUG) return
|