swc-plugin-auto-import 0.0.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/README.md
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# SWC Auto Import Plugin
|
|
2
|
+
|
|
3
|
+
An SWC plugin similar to [unplugin-auto-import](https://github.com/unplugin/unplugin-auto-import) that automatically imports APIs without manually writing import statements.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- ✨ Auto import APIs from popular frameworks (Vue, React, Vue Router, etc.)
|
|
8
|
+
- 🎯 Support for custom import configuration
|
|
9
|
+
- 🔍 Smart detection: avoids duplicate imports and local declarations
|
|
10
|
+
- ⚡ Compile-time transformation with zero runtime overhead
|
|
11
|
+
- 🛠️ Native TypeScript support
|
|
12
|
+
|
|
13
|
+
## 📦 Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install swc-plugin-auto-import
|
|
17
|
+
# or
|
|
18
|
+
yarn add swc-plugin-auto-import
|
|
19
|
+
# or
|
|
20
|
+
pnpm add swc-plugin-auto-import
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 🔧 Configuration
|
|
24
|
+
|
|
25
|
+
### Configure in `.swcrc`
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"jsc": {
|
|
30
|
+
"experimental": {
|
|
31
|
+
"plugins": [
|
|
32
|
+
[
|
|
33
|
+
"swc-plugin-auto-import",
|
|
34
|
+
{
|
|
35
|
+
"presets": ["vue", "react"],
|
|
36
|
+
"imports": {
|
|
37
|
+
"@vueuse/core": ["useMouse", "useFetch"],
|
|
38
|
+
"axios": [["default", "axios"]]
|
|
39
|
+
},
|
|
40
|
+
"debug": false
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Usage with Next.js
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
// next.config.js
|
|
53
|
+
module.exports = {
|
|
54
|
+
experimental: {
|
|
55
|
+
swcPlugins: [
|
|
56
|
+
[
|
|
57
|
+
'swc-plugin-auto-import',
|
|
58
|
+
{
|
|
59
|
+
presets: ['react'],
|
|
60
|
+
imports: {
|
|
61
|
+
'lodash-es': ['debounce', 'throttle'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Usage with Rspack
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
// rspack.config.js
|
|
74
|
+
module.exports = {
|
|
75
|
+
module: {
|
|
76
|
+
rules: [
|
|
77
|
+
{
|
|
78
|
+
test: /\.(js|jsx|ts|tsx)$/,
|
|
79
|
+
loader: 'builtin:swc-loader',
|
|
80
|
+
options: {
|
|
81
|
+
jsc: {
|
|
82
|
+
experimental: {
|
|
83
|
+
plugins: [
|
|
84
|
+
[
|
|
85
|
+
'swc-plugin-auto-import',
|
|
86
|
+
{
|
|
87
|
+
presets: ['react'],
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 📖 Usage Examples
|
|
101
|
+
|
|
102
|
+
### Vue 3 Auto Import
|
|
103
|
+
|
|
104
|
+
**Configuration:**
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"presets": ["vue"]
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Input:**
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
const count = ref(0)
|
|
116
|
+
const doubled = computed(() => count.value * 2)
|
|
117
|
+
|
|
118
|
+
onMounted(() => {
|
|
119
|
+
console.log('Component mounted')
|
|
120
|
+
})
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Output:**
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
import { ref, computed, onMounted } from 'vue'
|
|
127
|
+
|
|
128
|
+
const count = ref(0)
|
|
129
|
+
const doubled = computed(() => count.value * 2)
|
|
130
|
+
|
|
131
|
+
onMounted(() => {
|
|
132
|
+
console.log('Component mounted')
|
|
133
|
+
})
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### React Hooks Auto Import
|
|
137
|
+
|
|
138
|
+
**Configuration:**
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"presets": ["react"]
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Input:**
|
|
147
|
+
|
|
148
|
+
```jsx
|
|
149
|
+
const [count, setCount] = useState(0)
|
|
150
|
+
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
console.log(count)
|
|
153
|
+
}, [count])
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Output:**
|
|
157
|
+
|
|
158
|
+
```jsx
|
|
159
|
+
import { useState, useEffect } from 'react'
|
|
160
|
+
|
|
161
|
+
const [count, setCount] = useState(0)
|
|
162
|
+
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
console.log(count)
|
|
165
|
+
}, [count])
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Custom Library Import
|
|
169
|
+
|
|
170
|
+
**Configuration:**
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"imports": {
|
|
175
|
+
"@vueuse/core": ["useMouse", "useKeyboard"],
|
|
176
|
+
"lodash-es": ["debounce", "throttle"],
|
|
177
|
+
"axios": [["default", "axios"]]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Input:**
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
const { x, y } = useMouse()
|
|
186
|
+
const debouncedFn = debounce(() => {}, 300)
|
|
187
|
+
|
|
188
|
+
axios.get('/api/data')
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Output:**
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
import { useMouse } from '@vueuse/core'
|
|
195
|
+
import { debounce } from 'lodash-es'
|
|
196
|
+
import { default as axios } from 'axios'
|
|
197
|
+
|
|
198
|
+
const { x, y } = useMouse()
|
|
199
|
+
const debouncedFn = debounce(() => {}, 300)
|
|
200
|
+
|
|
201
|
+
axios.get('/api/data')
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## ⚙️ Configuration Options
|
|
205
|
+
|
|
206
|
+
### `presets`
|
|
207
|
+
|
|
208
|
+
**Type:** `string[]`
|
|
209
|
+
**Default:** `[]`
|
|
210
|
+
|
|
211
|
+
Preset configurations. Currently supported:
|
|
212
|
+
|
|
213
|
+
- `"vue"` - Vue 3 Composition API
|
|
214
|
+
- `"react"` - React Hooks
|
|
215
|
+
- `"vue-router"` - Vue Router Composition API
|
|
216
|
+
- `"react-router"` - React Router Hooks
|
|
217
|
+
|
|
218
|
+
### `imports`
|
|
219
|
+
|
|
220
|
+
**Type:** `Record<string, string[] | [string, string][]>`
|
|
221
|
+
**Default:** `{}`
|
|
222
|
+
|
|
223
|
+
Custom import configuration.
|
|
224
|
+
|
|
225
|
+
**Format:**
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"package-name": ["namedExport1", "namedExport2", ["exportName", "alias"]]
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Example:**
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"@vueuse/core": ["useMouse", "useFetch"],
|
|
238
|
+
"axios": [["default", "axios"]],
|
|
239
|
+
"date-fns": ["format", "parseISO"]
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### `debug`
|
|
244
|
+
|
|
245
|
+
**Type:** `boolean`
|
|
246
|
+
**Default:** `false`
|
|
247
|
+
|
|
248
|
+
Enable debug mode (reserved field in current version).
|
|
249
|
+
|
|
250
|
+
## 📋 Built-in Presets
|
|
251
|
+
|
|
252
|
+
### Vue Preset
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
ref, computed, reactive, watch, watchEffect, onMounted, onUnmounted,
|
|
256
|
+
onBeforeMount, onBeforeUnmount, onUpdated, onBeforeUpdate, nextTick,
|
|
257
|
+
defineComponent, createApp, toRef, toRefs, unref, isRef
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### React Preset
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
useState, useEffect, useContext, useReducer, useCallback, useMemo,
|
|
264
|
+
useRef, useLayoutEffect, useImperativeHandle
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Vue Router Preset
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
useRouter, useRoute
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### React Router Preset
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
useNavigate, useLocation, useParams, useSearchParams
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## 🎯 Smart Features
|
|
280
|
+
|
|
281
|
+
### 1. No Duplicate Imports
|
|
282
|
+
|
|
283
|
+
If an API is already imported, the plugin won't add it again:
|
|
284
|
+
|
|
285
|
+
```js
|
|
286
|
+
// Input
|
|
287
|
+
import { ref } from 'vue'
|
|
288
|
+
const count = ref(0)
|
|
289
|
+
|
|
290
|
+
// Output - unchanged
|
|
291
|
+
import { ref } from 'vue'
|
|
292
|
+
const count = ref(0)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### 2. No Import for Local Declarations
|
|
296
|
+
|
|
297
|
+
If an identifier is locally declared, the plugin won't add an import:
|
|
298
|
+
|
|
299
|
+
```js
|
|
300
|
+
// Input
|
|
301
|
+
function ref() {
|
|
302
|
+
return 'local ref'
|
|
303
|
+
}
|
|
304
|
+
const data = ref()
|
|
305
|
+
|
|
306
|
+
// Output - unchanged, no import added
|
|
307
|
+
function ref() {
|
|
308
|
+
return 'local ref'
|
|
309
|
+
}
|
|
310
|
+
const data = ref()
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## 🔄 Comparison with unplugin-auto-import
|
|
314
|
+
|
|
315
|
+
| Feature | unplugin-auto-import | swc-auto-import |
|
|
316
|
+
| ------------------ | -------------------- | --------------- |
|
|
317
|
+
| Runtime | Vite/Webpack/Rollup | SWC Compiler |
|
|
318
|
+
| Performance | Fast | Very Fast |
|
|
319
|
+
| .d.ts Generation | ✅ | Planned |
|
|
320
|
+
| TypeScript Support | ✅ | ✅ |
|
|
321
|
+
| Custom Resolvers | ✅ | Planned |
|
|
322
|
+
| ESLint Integration | ✅ | Planned |
|
|
323
|
+
|
|
324
|
+
## 🛠️ Development
|
|
325
|
+
|
|
326
|
+
### Build Plugin
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
# Build WASM plugin
|
|
330
|
+
cargo build-wasip1 --release
|
|
331
|
+
|
|
332
|
+
# Run tests
|
|
333
|
+
cargo test
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Project Structure
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
swc-plugin-auto-import/
|
|
340
|
+
├── src/
|
|
341
|
+
│ ├── lib.rs # Plugin source
|
|
342
|
+
│ ├── config.rs # Configuration
|
|
343
|
+
│ ├── presets.rs # Presets
|
|
344
|
+
│ ├── collector.rs # Identifier collector
|
|
345
|
+
│ └── visitor.rs # AST visitor
|
|
346
|
+
├── Cargo.toml # Rust configuration
|
|
347
|
+
├── package.json # npm package config
|
|
348
|
+
└── README.md # Documentation
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## 📝 How It Works
|
|
352
|
+
|
|
353
|
+
1. **Scanning Phase**: Traverse AST to collect used, imported, and declared identifiers
|
|
354
|
+
2. **Matching Phase**: Find identifiers that need auto-import based on presets and custom config
|
|
355
|
+
3. **Filtering Phase**: Exclude already imported and locally declared identifiers
|
|
356
|
+
4. **Insertion Phase**: Insert generated import statements at the top of the module
|
|
357
|
+
|
|
358
|
+
## 🤝 Contributing
|
|
359
|
+
|
|
360
|
+
Issues and Pull Requests are welcome!
|
|
361
|
+
|
|
362
|
+
## 📄 License
|
|
363
|
+
|
|
364
|
+
ISC License
|
|
365
|
+
|
|
366
|
+
## 🔗 Links
|
|
367
|
+
|
|
368
|
+
- [SWC Official Documentation](https://swc.rs/)
|
|
369
|
+
- [unplugin-auto-import](https://github.com/unplugin/unplugin-auto-import)
|
|
370
|
+
- [SWC Plugin Development Guide](https://swc.rs/docs/plugin/ecmascript/getting-started)
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "swc-plugin-auto-import",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"description": "SWC plugin for auto importing APIs on-demand, inspired by unplugin-auto-import",
|
|
6
|
+
"author": "Brendan Dash <me@aiwan.run> (https://aiwan.run)",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Debbl/swc-plugin-auto-import"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"swc-plugin",
|
|
14
|
+
"auto-import",
|
|
15
|
+
"vue",
|
|
16
|
+
"react",
|
|
17
|
+
"swc",
|
|
18
|
+
"transform"
|
|
19
|
+
],
|
|
20
|
+
"main": "target/wasm32-wasip1/release/swc_plugin_auto_import.wasm",
|
|
21
|
+
"files": [
|
|
22
|
+
"target/wasm32-wasip1/release/swc_plugin_auto_import.wasm"
|
|
23
|
+
],
|
|
24
|
+
"preferUnplugged": true,
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@debbl/eslint-config": "^3.14.3",
|
|
27
|
+
"@swc/core": "^1.15.8",
|
|
28
|
+
"bumpp": "^10.3.2",
|
|
29
|
+
"eslint": "^9.39.2",
|
|
30
|
+
"eslint-config-prettier": "^10.1.8"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "cargo build-wasip1 --release",
|
|
34
|
+
"test": "cargo test",
|
|
35
|
+
"release": "pnpm build && bumpp && pnpm publish",
|
|
36
|
+
"lint": "eslint",
|
|
37
|
+
"lint:fix": "eslint --fix"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
Binary file
|