@tanstack/start-plugin-core 1.167.34 → 1.168.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 +1 -1
- 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 +12 -19
- 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 +4 -0
- package/dist/esm/index.js +3 -1
- 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/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/schema.js +1 -1
- 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/start-manifest-plugin/manifestBuilder.d.ts +3 -6
- package/dist/esm/start-manifest-plugin/manifestBuilder.js +34 -81
- package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -1
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +4 -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/plugin.js +4 -12
- package/dist/esm/vite/plugin.js.map +1 -1
- package/dist/esm/vite/plugins.d.ts +1 -5
- package/dist/esm/vite/plugins.js +2 -17
- package/dist/esm/vite/plugins.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/dist/esm/vite/start-manifest-plugin/normalized-client-build.js +2 -2
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js.map +1 -1
- package/dist/esm/vite/start-manifest-plugin/plugin.d.ts +1 -2
- package/dist/esm/vite/start-manifest-plugin/plugin.js +48 -14
- package/dist/esm/vite/start-manifest-plugin/plugin.js.map +1 -1
- package/package.json +17 -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 +35 -20
- package/src/{import-protection-plugin → import-protection}/virtualModules.ts +30 -177
- package/src/index.ts +5 -0
- 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 +1600 -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/start-manifest-plugin/manifestBuilder.ts +53 -116
- package/src/utils.ts +4 -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/plugin.ts +1 -18
- package/src/vite/plugins.ts +2 -33
- 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/src/vite/start-manifest-plugin/normalized-client-build.ts +15 -16
- package/src/vite/start-manifest-plugin/plugin.ts +121 -38
- 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
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Vite Import Protection - Adapter Internals
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This document covers the Vite-specific orchestration around the shared
|
|
6
|
+
import-protection core in `src/import-protection/INTERNALS.md`.
|
|
7
|
+
|
|
8
|
+
Vite owns:
|
|
9
|
+
|
|
10
|
+
- `resolveId`-first violation discovery
|
|
11
|
+
- dev/build deferral decisions tied to Vite lifecycle hooks
|
|
12
|
+
- the transform-cache plugin and post-transform graph bookkeeping
|
|
13
|
+
- Vite virtual-module id resolution and loading
|
|
14
|
+
- bundle-time survival checks in `generateBundle`
|
|
15
|
+
|
|
16
|
+
Shared AST analysis, rewrite logic, source extraction, mock export discovery,
|
|
17
|
+
usage lookup, source locations, and mock code generation are described in the
|
|
18
|
+
shared internals doc.
|
|
19
|
+
|
|
20
|
+
## Plugin Shape
|
|
21
|
+
|
|
22
|
+
`importProtectionPlugin()` returns two Vite plugins:
|
|
23
|
+
|
|
24
|
+
1. `tanstack-start-core:import-protection`
|
|
25
|
+
2. `tanstack-start-core:import-protection-transform-cache`
|
|
26
|
+
|
|
27
|
+
The first plugin owns resolve-time detection and reporting decisions. The
|
|
28
|
+
second plugin owns transformed-result caching, post-transform import graph
|
|
29
|
+
updates, self-denial transforms, and dev pending-violation verification.
|
|
30
|
+
|
|
31
|
+
## Why Vite Uses Two Plugins
|
|
32
|
+
|
|
33
|
+
Vite discovers many violations in `resolveId`, but accurate source locations and
|
|
34
|
+
post-transform graph truth require transformed code that only exists later.
|
|
35
|
+
|
|
36
|
+
So the adapter splits responsibilities:
|
|
37
|
+
|
|
38
|
+
- `resolveId`: detect, classify, defer/report, substitute mock ids where needed
|
|
39
|
+
- later transform hook: cache transformed code/maps, self-deny files, compute
|
|
40
|
+
post-transform imports, and process pending violations
|
|
41
|
+
|
|
42
|
+
## Vite State Model
|
|
43
|
+
|
|
44
|
+
Per environment, Vite keeps `EnvState` with:
|
|
45
|
+
|
|
46
|
+
- `graph`
|
|
47
|
+
- `mockExportsByImporter`
|
|
48
|
+
- `resolveCache`
|
|
49
|
+
- `resolveCacheByFile`
|
|
50
|
+
- `importLocCache`
|
|
51
|
+
- `seenViolations`
|
|
52
|
+
- `serverFnLookupModules`
|
|
53
|
+
- `transformResultCache`
|
|
54
|
+
- `transformResultKeysByFile`
|
|
55
|
+
- `transformResultProvider`
|
|
56
|
+
- `postTransformImports`
|
|
57
|
+
- `pendingViolations`
|
|
58
|
+
- `deferredBuildViolations`
|
|
59
|
+
|
|
60
|
+
Cross-environment shared state is intentionally small:
|
|
61
|
+
|
|
62
|
+
- `fileMarkerKind`
|
|
63
|
+
|
|
64
|
+
This is larger than the Rsbuild state model because Vite must bridge resolve-
|
|
65
|
+
time detection with later transform/bundle verification.
|
|
66
|
+
|
|
67
|
+
## Detection Flow
|
|
68
|
+
|
|
69
|
+
Vite is `resolveId`-driven.
|
|
70
|
+
|
|
71
|
+
That means the adapter may see violations before:
|
|
72
|
+
|
|
73
|
+
- the Start compiler removes safe-boundary imports
|
|
74
|
+
- tree-shaking removes false-positive edges
|
|
75
|
+
- transformed importer code is available
|
|
76
|
+
|
|
77
|
+
So Vite must decide whether to report immediately or defer.
|
|
78
|
+
|
|
79
|
+
## Deferral Policy
|
|
80
|
+
|
|
81
|
+
The shared helper is:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
shouldDefer = isBuild || isDevMock
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Adapter meaning:
|
|
88
|
+
|
|
89
|
+
- dev + error: report immediately with `ctx.error()`
|
|
90
|
+
- dev + mock: store `pendingViolations`, then verify later from post-transform
|
|
91
|
+
edges and reachability
|
|
92
|
+
- build + mock/error: store `deferredBuildViolations`, then verify in
|
|
93
|
+
`generateBundle`
|
|
94
|
+
|
|
95
|
+
This is the main adapter-specific state machine difference from Rsbuild.
|
|
96
|
+
|
|
97
|
+
## Dev Strategy
|
|
98
|
+
|
|
99
|
+
### Dev + Error
|
|
100
|
+
|
|
101
|
+
Vite throws immediately in `resolveId`.
|
|
102
|
+
|
|
103
|
+
This is intentionally aggressive and can still produce known barrel false
|
|
104
|
+
positives because there is no tree-shaking in the dev server.
|
|
105
|
+
|
|
106
|
+
Pre-transform resolve paths like `SERVER_FN_LOOKUP` are silenced in this mode
|
|
107
|
+
because there is no later deferred verification path.
|
|
108
|
+
|
|
109
|
+
### Dev + Mock
|
|
110
|
+
|
|
111
|
+
Vite defers all violations into `pendingViolations`.
|
|
112
|
+
|
|
113
|
+
Later, the transform-cache plugin:
|
|
114
|
+
|
|
115
|
+
1. caches transformed code and sourcemaps
|
|
116
|
+
2. resolves post-transform imports
|
|
117
|
+
3. records graph edges from transformed code
|
|
118
|
+
4. runs `processPendingViolations()`
|
|
119
|
+
|
|
120
|
+
Pending verification uses two checks:
|
|
121
|
+
|
|
122
|
+
1. edge survival after the Start compiler transform
|
|
123
|
+
2. graph reachability from entries using post-transform edges
|
|
124
|
+
|
|
125
|
+
This is how Vite suppresses many dev false positives without bundling.
|
|
126
|
+
|
|
127
|
+
## Build Strategy
|
|
128
|
+
|
|
129
|
+
Vite build uses mock-first, verify-later behavior.
|
|
130
|
+
|
|
131
|
+
At resolve time it substitutes mocks silently and records deferred violations.
|
|
132
|
+
At `generateBundle`, it checks whether each unique mock id survived tree-
|
|
133
|
+
shaking.
|
|
134
|
+
|
|
135
|
+
If the mock survived:
|
|
136
|
+
|
|
137
|
+
- error mode: fail the build
|
|
138
|
+
- mock mode: emit a warning
|
|
139
|
+
|
|
140
|
+
If the mock was removed, the violation is suppressed as a false positive.
|
|
141
|
+
|
|
142
|
+
## Self-Denial In Vite
|
|
143
|
+
|
|
144
|
+
For file-based violations, `resolveId` does not return a virtual mock id.
|
|
145
|
+
Instead it returns the physical file path, and the later transform-cache plugin
|
|
146
|
+
replaces the file contents with a mock module.
|
|
147
|
+
|
|
148
|
+
This Vite-specific choice exists for two reasons:
|
|
149
|
+
|
|
150
|
+
- avoid cross-environment cache contamination in shared resolver caches
|
|
151
|
+
- avoid cold-start export-resolution issues when importer AST data is not yet
|
|
152
|
+
available
|
|
153
|
+
|
|
154
|
+
## Vite Virtual Modules
|
|
155
|
+
|
|
156
|
+
The shared mock generators use abstract ids like:
|
|
157
|
+
|
|
158
|
+
- `\0tanstack-start-import-protection:mock`
|
|
159
|
+
- `\0tanstack-start-import-protection:mock-edge:...`
|
|
160
|
+
- `\0tanstack-start-import-protection:mock-runtime:...`
|
|
161
|
+
- `\0tanstack-start-import-protection:marker:*`
|
|
162
|
+
|
|
163
|
+
The Vite adapter adds:
|
|
164
|
+
|
|
165
|
+
- resolved Vite ids via `resolveViteId(...)`
|
|
166
|
+
- support for browser-prefixed ids via `__x00__`
|
|
167
|
+
- `loadResolvedVirtualModule()` for serving the generated code
|
|
168
|
+
|
|
169
|
+
This id transport is adapter-specific. The generated module contents are shared.
|
|
170
|
+
|
|
171
|
+
## Warm-Start Considerations
|
|
172
|
+
|
|
173
|
+
Vite can skip `resolveId` on warm cache hits, so the adapter maintains its own
|
|
174
|
+
graph and transform-result caches to recover enough information for traces and
|
|
175
|
+
pending-violation verification.
|
|
176
|
+
|
|
177
|
+
Special care is taken not to treat pre-transform lookup edges as authoritative
|
|
178
|
+
reachability edges.
|
|
179
|
+
|
|
180
|
+
## Practical Maintainer Rule
|
|
181
|
+
|
|
182
|
+
When changing Vite import protection, ask:
|
|
183
|
+
|
|
184
|
+
1. Is this really about Vite lifecycle timing or state?
|
|
185
|
+
2. If not, should it move into the shared import-protection core?
|
|
186
|
+
3. If yes, does it belong in resolve-time detection, transform-cache handling,
|
|
187
|
+
or bundle-time verification?
|
|
@@ -1,69 +1,87 @@
|
|
|
1
1
|
import { normalizePath } from 'vite'
|
|
2
2
|
|
|
3
|
-
import { resolveViteId } from '
|
|
4
|
-
import { VITE_ENVIRONMENT_NAMES } from '
|
|
5
|
-
import {
|
|
3
|
+
import { resolveViteId } from '../../utils'
|
|
4
|
+
import { VITE_ENVIRONMENT_NAMES } from '../../constants'
|
|
5
|
+
import {
|
|
6
|
+
ImportGraph,
|
|
7
|
+
buildTrace,
|
|
8
|
+
formatViolation,
|
|
9
|
+
} from '../../import-protection/trace'
|
|
6
10
|
import {
|
|
7
11
|
getDefaultImportProtectionRules,
|
|
8
12
|
getMarkerSpecifiers,
|
|
9
|
-
} from '
|
|
10
|
-
import { compileMatchers, matchesAny } from '
|
|
13
|
+
} from '../../import-protection/defaults'
|
|
14
|
+
import { compileMatchers, matchesAny } from '../../import-protection/matchers'
|
|
15
|
+
import {
|
|
16
|
+
getImportProtectionEnvType,
|
|
17
|
+
getImportProtectionRelativePath,
|
|
18
|
+
getImportProtectionRulesForEnvironment,
|
|
19
|
+
shouldCheckImportProtectionImporter,
|
|
20
|
+
} from '../../import-protection/adapterUtils'
|
|
11
21
|
import {
|
|
12
22
|
buildResolutionCandidates,
|
|
13
23
|
buildSourceCandidates,
|
|
14
24
|
canonicalizeResolvedId,
|
|
25
|
+
checkFileDenial,
|
|
15
26
|
clearNormalizeFilePathCache,
|
|
16
27
|
debugLog,
|
|
17
28
|
dedupePatterns,
|
|
29
|
+
dedupeViolationKey,
|
|
18
30
|
escapeRegExp,
|
|
19
|
-
extractImportSources,
|
|
20
31
|
getOrCreate,
|
|
32
|
+
isFileExcluded,
|
|
21
33
|
isInsideDirectory,
|
|
22
34
|
matchesDebugFilter,
|
|
23
35
|
normalizeFilePath,
|
|
24
36
|
relativizePath,
|
|
25
37
|
shouldDeferViolation,
|
|
26
|
-
} from '
|
|
38
|
+
} from '../../import-protection/utils'
|
|
27
39
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
} from '
|
|
32
|
-
import {
|
|
33
|
-
|
|
34
|
-
generateDevSelfDenialModule,
|
|
35
|
-
generateSelfContainedMockModule,
|
|
36
|
-
getResolvedVirtualModuleMatchers,
|
|
37
|
-
loadResolvedVirtualModule,
|
|
38
|
-
makeMockEdgeModuleId,
|
|
39
|
-
mockRuntimeModuleIdFromViolation,
|
|
40
|
-
resolveInternalVirtualModuleId,
|
|
41
|
-
resolvedMarkerVirtualModuleId,
|
|
42
|
-
} from './virtualModules'
|
|
43
|
-
import { ExtensionlessAbsoluteIdResolver } from './extensionlessAbsoluteIdResolver'
|
|
40
|
+
getImportSources,
|
|
41
|
+
getMockExportNamesBySource,
|
|
42
|
+
getNamedExports,
|
|
43
|
+
} from '../../import-protection/analysis'
|
|
44
|
+
import { rewriteDeniedImports } from '../../import-protection/rewrite'
|
|
45
|
+
import { ExtensionlessAbsoluteIdResolver } from '../../import-protection/extensionlessAbsoluteIdResolver'
|
|
44
46
|
import {
|
|
45
47
|
IMPORT_PROTECTION_DEBUG,
|
|
46
48
|
SERVER_FN_LOOKUP_QUERY,
|
|
47
49
|
VITE_BROWSER_VIRTUAL_PREFIX,
|
|
48
|
-
} from '
|
|
50
|
+
} from '../../import-protection/constants'
|
|
49
51
|
import {
|
|
50
52
|
ImportLocCache,
|
|
51
53
|
addTraceImportLocations,
|
|
52
54
|
buildCodeSnippet,
|
|
53
55
|
buildLineIndex,
|
|
56
|
+
createImportSpecifierLocationIndex,
|
|
54
57
|
findImportStatementLocationFromTransformed,
|
|
55
58
|
findPostCompileUsageLocation,
|
|
59
|
+
normalizeSourceMap,
|
|
56
60
|
pickOriginalCodeFromSourcesContent,
|
|
57
|
-
} from '
|
|
61
|
+
} from '../../import-protection/sourceLocation'
|
|
62
|
+
import {
|
|
63
|
+
MOCK_BUILD_PREFIX,
|
|
64
|
+
generateDevSelfDenialModule,
|
|
65
|
+
generateSelfContainedMockModule,
|
|
66
|
+
getResolvedVirtualModuleMatchers,
|
|
67
|
+
loadResolvedVirtualModule,
|
|
68
|
+
makeMockEdgeModuleId,
|
|
69
|
+
mockRuntimeModuleIdFromViolation,
|
|
70
|
+
resolveInternalVirtualModuleId,
|
|
71
|
+
resolvedMarkerVirtualModuleId,
|
|
72
|
+
} from './virtualModules'
|
|
58
73
|
import type { PluginOption, ViteDevServer } from 'vite'
|
|
59
|
-
import type {
|
|
60
|
-
|
|
74
|
+
import type {
|
|
75
|
+
Loc,
|
|
76
|
+
TraceStep,
|
|
77
|
+
ViolationInfo,
|
|
78
|
+
} from '../../import-protection/trace'
|
|
61
79
|
import type {
|
|
62
80
|
SourceMapLike,
|
|
63
81
|
TransformResult,
|
|
64
82
|
TransformResultProvider,
|
|
65
|
-
} from '
|
|
66
|
-
import type { ImportProtectionOptions } from '
|
|
83
|
+
} from '../../import-protection/sourceLocation'
|
|
84
|
+
import type { ImportProtectionOptions } from '../../schema'
|
|
67
85
|
import type {
|
|
68
86
|
EnvRules,
|
|
69
87
|
EnvState,
|
|
@@ -85,31 +103,7 @@ export function importProtectionPlugin(
|
|
|
85
103
|
const extensionlessIdResolver = new ExtensionlessAbsoluteIdResolver()
|
|
86
104
|
const resolveExtensionlessAbsoluteId = (id: string) =>
|
|
87
105
|
extensionlessIdResolver.resolve(id)
|
|
88
|
-
|
|
89
|
-
const importPatternCache = new Map<string, Array<RegExp>>()
|
|
90
|
-
|
|
91
|
-
function findFirstImportSpecifierIndex(code: string, source: string): number {
|
|
92
|
-
let patterns = importPatternCache.get(source)
|
|
93
|
-
if (!patterns) {
|
|
94
|
-
const escaped = escapeRegExp(source)
|
|
95
|
-
patterns = [
|
|
96
|
-
new RegExp(`\\bimport\\s+(['"])${escaped}\\1`),
|
|
97
|
-
new RegExp(`\\bfrom\\s+(['"])${escaped}\\1`),
|
|
98
|
-
new RegExp(`\\bimport\\s*\\(\\s*(['"])${escaped}\\1\\s*\\)`),
|
|
99
|
-
]
|
|
100
|
-
importPatternCache.set(source, patterns)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
let best = -1
|
|
104
|
-
for (const re of patterns) {
|
|
105
|
-
const m = re.exec(code)
|
|
106
|
-
if (!m) continue
|
|
107
|
-
const idx = m.index + m[0].indexOf(source)
|
|
108
|
-
if (idx === -1) continue
|
|
109
|
-
if (best === -1 || idx < best) best = idx
|
|
110
|
-
}
|
|
111
|
-
return best
|
|
112
|
-
}
|
|
106
|
+
const importSpecifierLocationIndex = createImportSpecifierLocationIndex()
|
|
113
107
|
|
|
114
108
|
/**
|
|
115
109
|
* Build an import trace using Vite's per-environment module graph, which
|
|
@@ -265,7 +259,7 @@ export function importProtectionPlugin(
|
|
|
265
259
|
provider,
|
|
266
260
|
trace,
|
|
267
261
|
env.importLocCache,
|
|
268
|
-
|
|
262
|
+
importSpecifierLocationIndex.find,
|
|
269
263
|
)
|
|
270
264
|
|
|
271
265
|
if (trace.length > 0) {
|
|
@@ -361,7 +355,7 @@ export function importProtectionPlugin(
|
|
|
361
355
|
importer,
|
|
362
356
|
candidate,
|
|
363
357
|
env.importLocCache,
|
|
364
|
-
|
|
358
|
+
importSpecifierLocationIndex.find,
|
|
365
359
|
))
|
|
366
360
|
if (loc) return loc
|
|
367
361
|
}
|
|
@@ -383,7 +377,6 @@ export function importProtectionPlugin(
|
|
|
383
377
|
importer: string,
|
|
384
378
|
source: string,
|
|
385
379
|
resolvedId: string,
|
|
386
|
-
relativePath: string,
|
|
387
380
|
traceOverride?: Array<TraceStep>,
|
|
388
381
|
): Promise<ViolationInfo | undefined> {
|
|
389
382
|
const normalizedResolvedId = normalizeFilePath(resolvedId)
|
|
@@ -406,21 +399,11 @@ export function importProtectionPlugin(
|
|
|
406
399
|
{
|
|
407
400
|
type: 'marker',
|
|
408
401
|
resolved: normalizedResolvedId,
|
|
409
|
-
message: buildMarkerViolationMessage(relativePath, markerKind),
|
|
410
402
|
},
|
|
411
403
|
traceOverride,
|
|
412
404
|
)
|
|
413
405
|
}
|
|
414
406
|
|
|
415
|
-
function buildMarkerViolationMessage(
|
|
416
|
-
relativePath: string,
|
|
417
|
-
markerKind: 'server' | 'client' | undefined,
|
|
418
|
-
): string {
|
|
419
|
-
return markerKind === 'server'
|
|
420
|
-
? `Module "${relativePath}" is marked server-only but is imported in the client environment`
|
|
421
|
-
: `Module "${relativePath}" is marked client-only but is imported in the server environment`
|
|
422
|
-
}
|
|
423
|
-
|
|
424
407
|
async function buildFileViolationInfo(
|
|
425
408
|
provider: TransformResultProvider,
|
|
426
409
|
env: EnvState,
|
|
@@ -433,8 +416,6 @@ export function importProtectionPlugin(
|
|
|
433
416
|
pattern: string | RegExp,
|
|
434
417
|
traceOverride?: Array<TraceStep>,
|
|
435
418
|
): Promise<ViolationInfo> {
|
|
436
|
-
const relativePath = getRelativePath(resolvedPath)
|
|
437
|
-
|
|
438
419
|
return buildViolationInfo(
|
|
439
420
|
provider,
|
|
440
421
|
env,
|
|
@@ -447,44 +428,13 @@ export function importProtectionPlugin(
|
|
|
447
428
|
type: 'file',
|
|
448
429
|
pattern,
|
|
449
430
|
resolved: resolvedPath,
|
|
450
|
-
message: `Import "${source}" (resolved to "${relativePath}") is denied in the ${envType} environment`,
|
|
451
431
|
},
|
|
452
432
|
traceOverride,
|
|
453
433
|
)
|
|
454
434
|
}
|
|
455
435
|
|
|
456
|
-
function getEnvType(envName: string): 'client' | 'server' {
|
|
457
|
-
return config.envTypeMap.get(envName) ?? 'server'
|
|
458
|
-
}
|
|
459
|
-
|
|
460
436
|
function getRulesForEnvironment(envName: string): EnvRules {
|
|
461
|
-
|
|
462
|
-
return type === 'client'
|
|
463
|
-
? config.compiledRules.client
|
|
464
|
-
: config.compiledRules.server
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
/**
|
|
468
|
-
* Check if a relative path matches any denied file pattern for the given
|
|
469
|
-
* environment, respecting `excludeFiles`. Returns the matching pattern
|
|
470
|
-
* or `undefined` if the file is not denied.
|
|
471
|
-
*/
|
|
472
|
-
function checkFileDenial(
|
|
473
|
-
relativePath: string,
|
|
474
|
-
matchers: {
|
|
475
|
-
files: Array<CompiledMatcher>
|
|
476
|
-
excludeFiles: Array<CompiledMatcher>
|
|
477
|
-
},
|
|
478
|
-
): CompiledMatcher | undefined {
|
|
479
|
-
if (
|
|
480
|
-
matchers.excludeFiles.length > 0 &&
|
|
481
|
-
matchesAny(relativePath, matchers.excludeFiles)
|
|
482
|
-
) {
|
|
483
|
-
return undefined
|
|
484
|
-
}
|
|
485
|
-
return matchers.files.length > 0
|
|
486
|
-
? matchesAny(relativePath, matchers.files)
|
|
487
|
-
: undefined
|
|
437
|
+
return getImportProtectionRulesForEnvironment(config, envName) as EnvRules
|
|
488
438
|
}
|
|
489
439
|
|
|
490
440
|
const environmentNames = new Set<string>([
|
|
@@ -589,7 +539,7 @@ export function importProtectionPlugin(
|
|
|
589
539
|
return []
|
|
590
540
|
|
|
591
541
|
try {
|
|
592
|
-
parsedBySource =
|
|
542
|
+
parsedBySource = getMockExportNamesBySource(importerCode)
|
|
593
543
|
|
|
594
544
|
// Also index by resolved physical IDs so later lookups match.
|
|
595
545
|
await recordMockExportsForImporter(
|
|
@@ -680,18 +630,23 @@ export function importProtectionPlugin(
|
|
|
680
630
|
|
|
681
631
|
if (namesBySource.size === 0) return
|
|
682
632
|
|
|
633
|
+
const resolvedAliases = new Map<string, Array<string>>()
|
|
683
634
|
for (const [source, names] of namesBySource) {
|
|
684
635
|
try {
|
|
685
636
|
const resolvedId = await resolveSource(source)
|
|
686
637
|
if (!resolvedId) continue
|
|
687
638
|
|
|
688
|
-
|
|
689
|
-
|
|
639
|
+
resolvedAliases.set(normalizeFilePath(resolvedId), names)
|
|
640
|
+
resolvedAliases.set(resolveExtensionlessAbsoluteId(resolvedId), names)
|
|
690
641
|
} catch {
|
|
691
642
|
// Best-effort only
|
|
692
643
|
}
|
|
693
644
|
}
|
|
694
645
|
|
|
646
|
+
for (const [source, names] of resolvedAliases) {
|
|
647
|
+
namesBySource.set(source, names)
|
|
648
|
+
}
|
|
649
|
+
|
|
695
650
|
const existing = env.mockExportsByImporter.get(importerFile)
|
|
696
651
|
if (!existing) {
|
|
697
652
|
env.mockExportsByImporter.set(importerFile, namesBySource)
|
|
@@ -712,34 +667,15 @@ export function importProtectionPlugin(
|
|
|
712
667
|
|
|
713
668
|
const shouldCheckImporterCache = new Map<string, boolean>()
|
|
714
669
|
function shouldCheckImporter(importer: string): boolean {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
// Excluded or ignored importers are never checked.
|
|
721
|
-
const excluded =
|
|
722
|
-
(config.excludeMatchers.length > 0 &&
|
|
723
|
-
matchesAny(relativePath, config.excludeMatchers)) ||
|
|
724
|
-
(config.ignoreImporterMatchers.length > 0 &&
|
|
725
|
-
matchesAny(relativePath, config.ignoreImporterMatchers))
|
|
726
|
-
|
|
727
|
-
if (excluded) {
|
|
728
|
-
result = false
|
|
729
|
-
} else if (config.includeMatchers.length > 0) {
|
|
730
|
-
result = !!matchesAny(relativePath, config.includeMatchers)
|
|
731
|
-
} else if (config.srcDirectory) {
|
|
732
|
-
result = isInsideDirectory(importer, config.srcDirectory)
|
|
733
|
-
} else {
|
|
734
|
-
result = true
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
shouldCheckImporterCache.set(importer, result)
|
|
738
|
-
return result
|
|
670
|
+
return shouldCheckImportProtectionImporter(
|
|
671
|
+
config,
|
|
672
|
+
importer,
|
|
673
|
+
shouldCheckImporterCache,
|
|
674
|
+
)
|
|
739
675
|
}
|
|
740
676
|
|
|
741
677
|
function dedupeKey(info: ViolationInfo): string {
|
|
742
|
-
return
|
|
678
|
+
return dedupeViolationKey(info)
|
|
743
679
|
}
|
|
744
680
|
|
|
745
681
|
function hasSeen(env: EnvState, key: string): boolean {
|
|
@@ -750,7 +686,7 @@ export function importProtectionPlugin(
|
|
|
750
686
|
}
|
|
751
687
|
|
|
752
688
|
function getRelativePath(absolutePath: string): string {
|
|
753
|
-
return
|
|
689
|
+
return getImportProtectionRelativePath(config.root, absolutePath)
|
|
754
690
|
}
|
|
755
691
|
|
|
756
692
|
/** Reset all caches on an EnvState (called from buildStart). */
|
|
@@ -1354,7 +1290,6 @@ export function importProtectionPlugin(
|
|
|
1354
1290
|
// Clear memoization caches that grow unboundedly across builds
|
|
1355
1291
|
clearNormalizeFilePathCache()
|
|
1356
1292
|
extensionlessIdResolver.clear()
|
|
1357
|
-
importPatternCache.clear()
|
|
1358
1293
|
shouldCheckImporterCache.clear()
|
|
1359
1294
|
|
|
1360
1295
|
// Clear per-env caches
|
|
@@ -1391,7 +1326,7 @@ export function importProtectionPlugin(
|
|
|
1391
1326
|
async resolveId(source, importer, _options) {
|
|
1392
1327
|
const envName = this.environment.name
|
|
1393
1328
|
const env = getEnv(envName)
|
|
1394
|
-
const envType =
|
|
1329
|
+
const envType = getImportProtectionEnvType(config, envName)
|
|
1395
1330
|
const provider = env.transformResultProvider
|
|
1396
1331
|
const isScanResolve = !!(_options as Record<string, unknown>).scan
|
|
1397
1332
|
|
|
@@ -1500,10 +1435,6 @@ export function importProtectionPlugin(
|
|
|
1500
1435
|
source,
|
|
1501
1436
|
{
|
|
1502
1437
|
type: 'marker',
|
|
1503
|
-
message: buildMarkerViolationMessage(
|
|
1504
|
-
getRelativePath(normalizedImporter),
|
|
1505
|
-
markerKind,
|
|
1506
|
-
),
|
|
1507
1438
|
},
|
|
1508
1439
|
)
|
|
1509
1440
|
const markerResult = await reportOrDeferViolation(
|
|
@@ -1563,7 +1494,6 @@ export function importProtectionPlugin(
|
|
|
1563
1494
|
importerFile,
|
|
1564
1495
|
specifier,
|
|
1565
1496
|
normalizedImporter,
|
|
1566
|
-
getRelativePath(normalizedImporter),
|
|
1567
1497
|
)
|
|
1568
1498
|
if (markerInfo) {
|
|
1569
1499
|
deferViolation(
|
|
@@ -1610,7 +1540,6 @@ export function importProtectionPlugin(
|
|
|
1610
1540
|
{
|
|
1611
1541
|
type: 'specifier',
|
|
1612
1542
|
pattern: specifierMatch.pattern,
|
|
1613
|
-
message: `Import "${source}" is denied in the ${envType} environment`,
|
|
1614
1543
|
},
|
|
1615
1544
|
)
|
|
1616
1545
|
|
|
@@ -1678,15 +1607,10 @@ export function importProtectionPlugin(
|
|
|
1678
1607
|
// exports `index.client.js`) are not treated as user-authored
|
|
1679
1608
|
// environment boundaries. Users can override `excludeFiles` per
|
|
1680
1609
|
// environment to narrow or widen this exclusion.
|
|
1681
|
-
const isExcludedFile =
|
|
1682
|
-
matchers.excludeFiles.length > 0 &&
|
|
1683
|
-
matchesAny(relativePath, matchers.excludeFiles)
|
|
1610
|
+
const isExcludedFile = isFileExcluded(relativePath, matchers)
|
|
1684
1611
|
|
|
1685
1612
|
if (!isExcludedFile) {
|
|
1686
|
-
const fileMatch =
|
|
1687
|
-
matchers.files.length > 0
|
|
1688
|
-
? matchesAny(relativePath, matchers.files)
|
|
1689
|
-
: undefined
|
|
1613
|
+
const fileMatch = checkFileDenial(relativePath, matchers)
|
|
1690
1614
|
|
|
1691
1615
|
if (fileMatch) {
|
|
1692
1616
|
const info = await buildFileViolationInfo(
|
|
@@ -1719,7 +1643,6 @@ export function importProtectionPlugin(
|
|
|
1719
1643
|
importer,
|
|
1720
1644
|
source,
|
|
1721
1645
|
resolved,
|
|
1722
|
-
relativePath,
|
|
1723
1646
|
)
|
|
1724
1647
|
if (markerInfo) {
|
|
1725
1648
|
return reportOrDeferViolation(
|
|
@@ -1891,7 +1814,7 @@ export function importProtectionPlugin(
|
|
|
1891
1814
|
async handler(code, id) {
|
|
1892
1815
|
const envName = this.environment.name
|
|
1893
1816
|
const file = normalizeFilePath(id)
|
|
1894
|
-
const envType =
|
|
1817
|
+
const envType = getImportProtectionEnvType(config, envName)
|
|
1895
1818
|
const matchers = getRulesForEnvironment(envName)
|
|
1896
1819
|
const isBuild = config.command === 'build'
|
|
1897
1820
|
|
|
@@ -1930,7 +1853,7 @@ export function importProtectionPlugin(
|
|
|
1930
1853
|
// Falls back to empty list on non-standard syntax.
|
|
1931
1854
|
let exportNames: Array<string> = []
|
|
1932
1855
|
try {
|
|
1933
|
-
exportNames =
|
|
1856
|
+
exportNames = getNamedExports(code)
|
|
1934
1857
|
} catch {
|
|
1935
1858
|
// Parsing may fail on non-standard syntax
|
|
1936
1859
|
}
|
|
@@ -1952,7 +1875,6 @@ export function importProtectionPlugin(
|
|
|
1952
1875
|
specifier: relativizePath(file, config.root),
|
|
1953
1876
|
resolved: file,
|
|
1954
1877
|
pattern: selfFileMatch.pattern,
|
|
1955
|
-
message: `File "${relativizePath(file, config.root)}" is denied in the ${envType} environment`,
|
|
1956
1878
|
trace: [],
|
|
1957
1879
|
},
|
|
1958
1880
|
config.mockAccess,
|
|
@@ -2009,7 +1931,7 @@ export function importProtectionPlugin(
|
|
|
2009
1931
|
// Dev mode: resolve imports, populate graph, detect violations,
|
|
2010
1932
|
// and rewrite denied imports.
|
|
2011
1933
|
const isDevMock = config.effectiveBehavior === 'mock'
|
|
2012
|
-
const importSources =
|
|
1934
|
+
const importSources = getImportSources(code)
|
|
2013
1935
|
const resolvedChildren = new Set<string>()
|
|
2014
1936
|
const deniedSourceReplacements = new Map<string, string>()
|
|
2015
1937
|
for (const src of importSources) {
|
|
@@ -2116,14 +2038,7 @@ export function importProtectionPlugin(
|
|
|
2116
2038
|
}
|
|
2117
2039
|
|
|
2118
2040
|
const normalizedMap = rewritten.map
|
|
2119
|
-
?
|
|
2120
|
-
...rewritten.map,
|
|
2121
|
-
version: Number(rewritten.map.version),
|
|
2122
|
-
sourcesContent:
|
|
2123
|
-
rewritten.map.sourcesContent?.map(
|
|
2124
|
-
(s: string | null) => s ?? '',
|
|
2125
|
-
) ?? [],
|
|
2126
|
-
}
|
|
2041
|
+
? normalizeSourceMap(rewritten.map)
|
|
2127
2042
|
: {
|
|
2128
2043
|
version: 3,
|
|
2129
2044
|
file: id,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { CompileStartFrameworkOptions, GetConfigFn } from '
|
|
2
|
-
import type { ImportProtectionBehavior } from '
|
|
3
|
-
import type { CompiledMatcher } from '
|
|
4
|
-
import type { ImportGraph, ViolationInfo } from '
|
|
1
|
+
import type { CompileStartFrameworkOptions, GetConfigFn } from '../../types'
|
|
2
|
+
import type { ImportProtectionBehavior } from '../../schema'
|
|
3
|
+
import type { CompiledMatcher } from '../../import-protection/matchers'
|
|
4
|
+
import type { ImportGraph, ViolationInfo } from '../../import-protection/trace'
|
|
5
5
|
import type {
|
|
6
6
|
ImportLocCache,
|
|
7
7
|
TransformResult,
|
|
8
8
|
TransformResultProvider,
|
|
9
|
-
} from '
|
|
9
|
+
} from '../../import-protection/sourceLocation'
|
|
10
10
|
|
|
11
11
|
/** Compiled deny/exclude patterns for one environment (client or server). */
|
|
12
12
|
export interface EnvRules {
|