makepack 1.7.14 → 1.7.16
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 +322 -79
- package/package.json +2 -1
- package/src/actions/build/bundler.js +150 -80
- package/src/actions/build/index.js +65 -61
package/README.md
CHANGED
|
@@ -1,122 +1,365 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="./logo.png" alt="makepack" width="90"/>
|
|
4
|
+
|
|
5
|
+
# makepack
|
|
6
|
+
|
|
7
|
+
<strong>A zero‑config (yet configurable) CLI to scaffold, develop, build, and publish modern JavaScript / TypeScript / React libraries.</strong>
|
|
8
|
+
|
|
9
|
+
<p>
|
|
10
|
+
Create a production‑ready npm package in seconds: pick a template, start a hot‑reloading dev server, bundle to ESM + CJS (and optionally a single bundle), generate type declarations, and publish – all with one tool.
|
|
3
11
|
</p>
|
|
4
12
|
|
|
5
|
-
<
|
|
13
|
+
<p>
|
|
14
|
+
<!-- Badges (add/adjust once published on npm) -->
|
|
15
|
+
<a href="https://www.npmjs.com/package/makepack"><img src="https://img.shields.io/npm/v/makepack?color=3B82F6" alt="npm version"/></a>
|
|
16
|
+
<a href="https://github.com/devnax/makepack/actions"><img src="https://img.shields.io/badge/build-passing-brightgreen" alt="build"/></a>
|
|
17
|
+
<a href="https://github.com/devnax/makepack/issues"><img src="https://img.shields.io/github/issues/devnax/makepack" alt="issues"/></a>
|
|
18
|
+
<a href="#license"><img src="https://img.shields.io/badge/license-TBD-lightgrey" alt="license"/></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
</div>
|
|
6
22
|
|
|
7
|
-
|
|
23
|
+
---
|
|
8
24
|
|
|
25
|
+
## ✨ Features
|
|
9
26
|
|
|
10
|
-
|
|
27
|
+
- Rapid project creation with four templates:
|
|
28
|
+
- TypeScript library
|
|
29
|
+
- JavaScript library
|
|
30
|
+
- React + TypeScript component library
|
|
31
|
+
- React + JavaScript component library
|
|
32
|
+
- Development server with hot reload + optional Express middleware (`express.ts` / `express.js`)
|
|
33
|
+
- Automatic dependency graph tracking (via `madge`) for efficient reloads
|
|
34
|
+
- Incremental TypeScript compilation and declaration output
|
|
35
|
+
- Dual module build (`esm`, `cjs`, or both) with optional single bundled file
|
|
36
|
+
- Tree‑shaken and optionally minified output
|
|
37
|
+
- Sourcemaps & type declarations by default
|
|
38
|
+
- Clean build output in an isolated `.mpack` directory (publish‑ready)
|
|
39
|
+
- Simple release workflow (`makepack release` or `npm run release` guidance)
|
|
11
40
|
|
|
12
|
-
|
|
41
|
+
---
|
|
13
42
|
|
|
14
|
-
|
|
15
|
-
|
|
43
|
+
## 🚀 Quick Start
|
|
44
|
+
|
|
45
|
+
Install globally (recommended) or use `npx`.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install -g makepack # global
|
|
49
|
+
# or
|
|
50
|
+
npx makepack create # without global install
|
|
16
51
|
```
|
|
17
52
|
|
|
18
|
-
|
|
53
|
+
Create a new project:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
makepack create
|
|
57
|
+
# Answer the interactive prompts:
|
|
58
|
+
# - Project name
|
|
59
|
+
# - Template
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Enter the project (if created in a new folder) and start the dev server:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cd your-project
|
|
66
|
+
npm start
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Build the library:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
makepack build
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Release (after building):
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
makepack release # publishes the contents of ./.mpack to npm
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> Tip: You can also run via package scripts (auto‑generated or added manually): `npm run build` / `npm run start`.
|
|
19
82
|
|
|
20
|
-
## 🎯 Why Choose makepack?
|
|
21
|
-
- **Zero-Config Setup** – Instantly scaffold a structured project.
|
|
22
|
-
- **TypeScript Support** – Seamlessly work with modern JavaScript.
|
|
23
|
-
- **Integrated Dev Server** – Run your package with Vite and Express.
|
|
24
|
-
- **Efficient Build System** – Generate optimized ESM and CJS outputs.
|
|
25
|
-
- **One-Command Publish** – Deploy your package to npm effortlessly.
|
|
26
83
|
---
|
|
27
84
|
|
|
28
|
-
##
|
|
85
|
+
## 📦 Generated Project Structure
|
|
29
86
|
|
|
30
|
-
|
|
31
|
-
Quickly initialize a structured package with the following setup:
|
|
87
|
+
Depending on template, you’ll get something like:
|
|
32
88
|
|
|
33
89
|
```
|
|
34
|
-
|
|
35
|
-
.
|
|
36
|
-
|
|
37
|
-
|
|
90
|
+
your-lib/
|
|
91
|
+
package.json
|
|
92
|
+
readme.md
|
|
93
|
+
tsconfig.json (TypeScript templates)
|
|
94
|
+
src/
|
|
95
|
+
index.(ts|js|tsx|jsx)
|
|
96
|
+
(React templates include an example component + export)
|
|
38
97
|
```
|
|
39
98
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
99
|
+
During development/build:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
.mpack/ # Build output (cleaned & regenerated each build)
|
|
103
|
+
package.json # Stripped (scripts & "type" removed for publishing clarity)
|
|
104
|
+
readme.md
|
|
105
|
+
dist files # ESM/CJS outputs + declarations + sourcemaps
|
|
43
106
|
```
|
|
44
|
-
Follow the interactive prompts to configure your project.
|
|
45
107
|
|
|
46
|
-
|
|
47
|
-
Run a Vite + Express server to develop and test your package in real-time.
|
|
108
|
+
> Do not edit files inside `.mpack` directly. Treat it as a disposable publish directory.
|
|
48
109
|
|
|
49
|
-
|
|
50
|
-
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 🧪 Development Server
|
|
113
|
+
|
|
114
|
+
Run: `makepack start --port 3000`
|
|
115
|
+
|
|
116
|
+
Features:
|
|
117
|
+
- Hot reload on dependency change
|
|
118
|
+
- Optional custom Express bootstrap via a root `express.ts` or `express.js` exporting a default function `(app) => { ... }`
|
|
119
|
+
- Safe handler wrapping to catch async errors
|
|
120
|
+
|
|
121
|
+
Example `express.ts`:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { Express } from 'express';
|
|
125
|
+
|
|
126
|
+
export default function routes(app: Express) {
|
|
127
|
+
app.get('/health', (_req, res) => {
|
|
128
|
+
res.json({ ok: true, ts: Date.now() });
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
If present, it’s reloaded automatically when edited.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 🏗 Build System
|
|
138
|
+
|
|
139
|
+
Command:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
makepack build [options]
|
|
51
143
|
```
|
|
52
144
|
|
|
53
|
-
|
|
54
|
-
|
|
145
|
+
| Option | Default | Values | Description |
|
|
146
|
+
| ---------------------- | ------- | -------------------- | --------------------------------------------------- |
|
|
147
|
+
| `--format` / `-f` | `both` | `cjs`, `esm`, `both` | Module formats to output |
|
|
148
|
+
| `--bundle` / `-b` | `false` | `true/false` | Bundle into a single file (rollup/esbuild assisted) |
|
|
149
|
+
| `--minify` / `-m` | `false` | `true/false` | Minify output (Terser) |
|
|
150
|
+
| `--sourcemap` / `-s` | `true` | `true/false` | Emit source maps |
|
|
151
|
+
| `--declaration` / `-d` | `true` | `true/false` | Emit TypeScript `.d.ts` files |
|
|
152
|
+
|
|
153
|
+
Behavior notes:
|
|
154
|
+
- The tool auto‑detects `src/index.(ts|js|tsx|jsx)` as the entry.
|
|
155
|
+
- Boolean flags accept either actual booleans or string equivalents: `--minify=true`.
|
|
156
|
+
- Output is always placed in `.mpack/` (cleaned each run).
|
|
157
|
+
- `package.json` in output has `scripts` and `type` removed for neutral publishing.
|
|
55
158
|
|
|
56
|
-
|
|
159
|
+
### Example Builds
|
|
160
|
+
|
|
161
|
+
Dual build with declarations (default):
|
|
162
|
+
|
|
163
|
+
```bash
|
|
57
164
|
makepack build
|
|
58
165
|
```
|
|
59
166
|
|
|
60
|
-
|
|
61
|
-
|
|
167
|
+
ESM only, minified, bundled:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
makepack build --format=esm --bundle=true --minify=true
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Disable sourcemaps & declarations (faster):
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
makepack build -s=false -d=false
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 🚢 Releasing
|
|
182
|
+
|
|
183
|
+
1. Ensure you are logged in to npm: `npm login`
|
|
184
|
+
2. Build your package: `makepack build`
|
|
185
|
+
3. Publish from the generated directory:
|
|
186
|
+
- Quick command: `makepack release`
|
|
187
|
+
- Manual: `cd .mpack && npm publish`
|
|
188
|
+
|
|
189
|
+
> The release command simply runs `npm publish` inside `.mpack` after verifying a build exists.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 🔌 Express Integration (Optional)
|
|
194
|
+
|
|
195
|
+
Add `express.ts` or `express.js` in the project root. Export a default function receiving the Express `app`. Example with middleware:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import compression from 'compression';
|
|
199
|
+
|
|
200
|
+
export default function(app) {
|
|
201
|
+
app.use(compression());
|
|
202
|
+
app.get('/', (_req, res) => res.send('Hello from makepack dev server'));
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The file and all its dependency graph (resolved via `madge`) are watched; edits trigger a reload.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 🧬 Technology Stack
|
|
211
|
+
|
|
212
|
+
| Area | Tooling |
|
|
213
|
+
| ---------- | ---------------------------------------------------------------------- |
|
|
214
|
+
| CLI | `commander` |
|
|
215
|
+
| Dev Server | `express`, `vite`, `chokidar`, `madge` |
|
|
216
|
+
| Builds | `rollup`, `@rollup/plugin-*`, `esbuild`, `rollup-plugin-dts`, `terser` |
|
|
217
|
+
| UX | `inquirer`, `ora` |
|
|
218
|
+
| FS/Utils | `fs-extra`, `lodash.debounce` |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 🛠 Templates Overview
|
|
223
|
+
|
|
224
|
+
| Template | Use Case | Entry | Extras |
|
|
225
|
+
| ----------------------- | ----------------------------- | --------------- | ------------------- |
|
|
226
|
+
| `typescript` | Library in TypeScript | `src/index.ts` | `tsconfig.json` |
|
|
227
|
+
| `javascript` | Plain JS library | `src/index.js` | – |
|
|
228
|
+
| `react with typescript` | React component library (TSX) | `src/index.tsx` | React + types setup |
|
|
229
|
+
| `react with javascript` | React component library (JSX) | `src/index.jsx` | React setup |
|
|
230
|
+
|
|
231
|
+
Generated React templates export a sample component you can replace.
|
|
62
232
|
|
|
63
|
-
|
|
64
|
-
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 🔄 Lifecycle Summary
|
|
236
|
+
|
|
237
|
+
1. `create` → scaffold + install deps
|
|
238
|
+
2. `start` → hot dev (optionally with express middleware)
|
|
239
|
+
3. `build` → produce distributable code in `.mpack`
|
|
240
|
+
4. `release` → publish the build to npm
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 📘 Command Reference
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
makepack create # Interactive project scaffolding
|
|
248
|
+
makepack start --port 4000 # Start dev server on custom port
|
|
249
|
+
makepack build [flags] # Build library
|
|
250
|
+
makepack release # Publish from .mpack
|
|
65
251
|
```
|
|
66
252
|
|
|
253
|
+
See build flags in the [Build System](#-build-system) section.
|
|
254
|
+
|
|
67
255
|
---
|
|
68
256
|
|
|
69
|
-
##
|
|
257
|
+
## 🧩 Using From `package.json`
|
|
258
|
+
|
|
259
|
+
You can wire scripts (some templates already do this):
|
|
260
|
+
|
|
261
|
+
```jsonc
|
|
262
|
+
{
|
|
263
|
+
"scripts": {
|
|
264
|
+
"start": "makepack start --port 3000",
|
|
265
|
+
"build": "makepack build",
|
|
266
|
+
"release": "makepack release"
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Run with `npm run build` etc.
|
|
272
|
+
|
|
273
|
+
---
|
|
70
274
|
|
|
71
|
-
|
|
275
|
+
## 🧷 Best Practices
|
|
72
276
|
|
|
73
|
-
|
|
277
|
+
- Keep a clean root: limit extra build artifacts outside `src/`.
|
|
278
|
+
- Export your public API from a single `src/index.*`.
|
|
279
|
+
- Use semantic versioning (e.g. `npm version patch`).
|
|
280
|
+
- For React libraries, avoid bundling peer deps – list `react` & `react-dom` as `peerDependencies` in your own `package.json` before publishing.
|
|
281
|
+
- Add a LICENSE file (see below) – required for many consumers.
|
|
74
282
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 🐞 Troubleshooting
|
|
286
|
+
|
|
287
|
+
| Issue | Cause | Fix |
|
|
288
|
+
| --------------------- | ------------------------------------ | ----------------------------------------------------------------------- |
|
|
289
|
+
| "No entry file found" | Missing `src/index.*` | Create `src/index.ts` or equivalent |
|
|
290
|
+
| Express not reloading | File outside dependency graph | Import files directly from `express.(ts | js)` |
|
|
291
|
+
| Declarations missing | `--declaration=false` or JS template | Use TS template or enable flag |
|
|
292
|
+
| Publish fails | Not built | Run `makepack build` first |
|
|
293
|
+
| ESM import errors | Missing `"type": "module"` in root | Add `type` back in your source project (it’s stripped only in `.mpack`) |
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 🤝 Contributing
|
|
298
|
+
|
|
299
|
+
Contributions welcome! Suggested flow:
|
|
300
|
+
|
|
301
|
+
1. Fork & clone
|
|
302
|
+
2. Create a feature branch: `git checkout -b feat/your-idea`
|
|
303
|
+
3. Implement + add/update docs
|
|
304
|
+
4. Commit with conventional style: `feat(build): add xyz`
|
|
305
|
+
5. Open a PR
|
|
306
|
+
|
|
307
|
+
Please include clear reproduction steps for any bug fix.
|
|
308
|
+
|
|
309
|
+
### Future Ideas (Open for PRs)
|
|
310
|
+
- Plugin system for custom build steps
|
|
311
|
+
- Peer dependency auto‑detection
|
|
312
|
+
- Template customization presets
|
|
313
|
+
- E2E test harness
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## 🔐 Security
|
|
318
|
+
|
|
319
|
+
No network calls are performed beyond npm install/publish and user code execution. Always audit generated dependencies before publishing.
|
|
320
|
+
|
|
321
|
+
Report vulnerabilities via GitHub Issues (consider labeling as `security`). Avoid posting exploit details publicly – request a private channel if needed.
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## 📄 License
|
|
326
|
+
|
|
327
|
+
License: **TBD** (e.g. MIT). Add a `LICENSE` file such as:
|
|
328
|
+
|
|
329
|
+
```text
|
|
330
|
+
MIT License
|
|
331
|
+
Copyright (c) 2025 Devnax
|
|
332
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy...
|
|
111
333
|
```
|
|
112
334
|
|
|
113
335
|
---
|
|
114
336
|
|
|
115
|
-
##
|
|
337
|
+
## 🙋 FAQ
|
|
338
|
+
|
|
339
|
+
**Why strip `scripts` and `type` from the published package.json?**
|
|
340
|
+
To minimize accidental exposure of internal scripts and to keep the distributed package neutral; consumers rarely need them.
|
|
341
|
+
|
|
342
|
+
**Can I output only one format?**
|
|
343
|
+
Yes: `--format=esm` or `--format=cjs`.
|
|
344
|
+
|
|
345
|
+
**How do I include assets (e.g. CSS)?**
|
|
346
|
+
Import them from your entry; configure rollup/esbuild plugins in future versions (PRs welcome) – currently you’d manually copy in a post-step.
|
|
347
|
+
|
|
348
|
+
**Does it support monorepos?**
|
|
349
|
+
Not natively; you can still run it per package folder.
|
|
350
|
+
|
|
351
|
+
**Why another tool?**
|
|
352
|
+
To reduce the ceremony of picking + wiring rollup, tsconfig, scripts, vite dev preview, express hooks, and publish layout – all unified.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 📬 Support
|
|
116
357
|
|
|
117
|
-
|
|
358
|
+
Open an issue for bugs, ideas, or questions: https://github.com/devnax/makepack/issues
|
|
118
359
|
|
|
119
360
|
---
|
|
120
361
|
|
|
121
|
-
|
|
362
|
+
<div align="center">
|
|
363
|
+
<sub>Built with ❤️ to streamline modern package creation.</sub>
|
|
364
|
+
</div>
|
|
122
365
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "makepack",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A CLI tool to create, build, and manage JavaScript, TypeScript, React, and React-TypeScript libraries for npm projects.",
|
|
6
6
|
"categories": [
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"react": "^19.1.0",
|
|
44
44
|
"react-dom": "^19.0.0",
|
|
45
45
|
"rollup": "^4.43.0",
|
|
46
|
+
"rollup-plugin-copy": "^3.5.0",
|
|
46
47
|
"rollup-plugin-dts": "^6.2.1",
|
|
47
48
|
"tslib": "^2.8.1",
|
|
48
49
|
"vite": "^6.0.2"
|
|
@@ -4,129 +4,199 @@ import commonjs from "@rollup/plugin-commonjs";
|
|
|
4
4
|
import typescript from "@rollup/plugin-typescript";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import dts from "rollup-plugin-dts";
|
|
7
|
-
import json from
|
|
7
|
+
import json from "@rollup/plugin-json";
|
|
8
8
|
import terser from "@rollup/plugin-terser";
|
|
9
|
+
import fs from "fs/promises";
|
|
10
|
+
import fss from "fs";
|
|
9
11
|
import { loadRollupConfig, loadViteConfig } from "../../helpers.js";
|
|
10
12
|
|
|
13
|
+
const MAX_DIR_CONCURRENCY = 16;
|
|
14
|
+
const MAX_FILE_COPY_CONCURRENCY = 32;
|
|
15
|
+
|
|
16
|
+
// --------------------- Batched multi-entry collector ---------------------
|
|
17
|
+
async function getEntriesBatch(root) {
|
|
18
|
+
const entries = {};
|
|
19
|
+
const dirs = [root];
|
|
20
|
+
|
|
21
|
+
async function worker() {
|
|
22
|
+
while (dirs.length) {
|
|
23
|
+
const dir = dirs.shift();
|
|
24
|
+
const items = await fs.readdir(dir, { withFileTypes: true });
|
|
25
|
+
|
|
26
|
+
for (const item of items) {
|
|
27
|
+
const full = path.join(dir, item.name);
|
|
28
|
+
if (item.isDirectory()) {
|
|
29
|
+
dirs.push(full);
|
|
30
|
+
} else if (/\.(ts|tsx|js|jsx)$/.test(item.name)) {
|
|
31
|
+
const name = path.relative(root, full).replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
32
|
+
entries[name] = full;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const workers = Array.from({ length: MAX_DIR_CONCURRENCY }, () => worker());
|
|
39
|
+
await Promise.all(workers);
|
|
40
|
+
|
|
41
|
+
return entries;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// --------------------- Batched parallel asset copy ---------------------
|
|
45
|
+
function isCodeFile(filename) {
|
|
46
|
+
return /\.(ts|tsx|js|jsx|cjs|mjs|d\.ts)$/i.test(filename);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function isSkippedDir(name) {
|
|
50
|
+
return name === "node_modules" || name === ".git" || name === ".next";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function copyAssetsBatched(rootdir, outdir) {
|
|
54
|
+
const queue = [];
|
|
55
|
+
|
|
56
|
+
async function walk(dir) {
|
|
57
|
+
const items = await fs.readdir(dir, { withFileTypes: true });
|
|
58
|
+
for (const item of items) {
|
|
59
|
+
const full = path.join(dir, item.name);
|
|
60
|
+
const rel = path.relative(rootdir, full);
|
|
61
|
+
|
|
62
|
+
if (rel.split(path.sep).some(p => isSkippedDir(p))) continue;
|
|
63
|
+
|
|
64
|
+
if (item.isDirectory()) {
|
|
65
|
+
await walk(full);
|
|
66
|
+
} else if (!isCodeFile(item.name)) {
|
|
67
|
+
queue.push({ src: full, rel });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
await walk(rootdir);
|
|
73
|
+
|
|
74
|
+
async function worker() {
|
|
75
|
+
while (queue.length) {
|
|
76
|
+
const { src, rel } = queue.shift();
|
|
77
|
+
const dest = path.join(outdir, rel);
|
|
78
|
+
await fs.mkdir(path.dirname(dest), { recursive: true });
|
|
79
|
+
await fs.copyFile(src, dest);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const workers = Array.from({ length: MAX_FILE_COPY_CONCURRENCY }, () => worker());
|
|
84
|
+
await Promise.all(workers);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// --------------------- Main Bundler ---------------------
|
|
11
88
|
async function bundler(args, spinner) {
|
|
89
|
+
const rootdir = args.rootdir;
|
|
90
|
+
const outdir = args.outdir;
|
|
91
|
+
|
|
92
|
+
// Multi-entry
|
|
93
|
+
const entries = await getEntriesBatch(rootdir);
|
|
94
|
+
const isTs = Object.values(entries).some(f => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
12
95
|
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const viteRollupConfig = viteConfig?.build?.rollupOptions || {}
|
|
96
|
+
const viteConfig = await loadViteConfig();
|
|
97
|
+
const rollupConfig = await loadRollupConfig();
|
|
98
|
+
const viteRollupConfig = viteConfig?.build?.rollupOptions || {};
|
|
17
99
|
Object.assign(rollupConfig || {}, viteRollupConfig);
|
|
18
100
|
|
|
19
101
|
const config = {
|
|
20
102
|
...rollupConfig,
|
|
21
|
-
input:
|
|
22
|
-
external:
|
|
23
|
-
if (rollupConfig && typeof rollupConfig.external ===
|
|
24
|
-
if (rollupConfig.external(id))
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (rollupConfig.external.includes(id)) {
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
103
|
+
input: { ...entries },
|
|
104
|
+
external: id => {
|
|
105
|
+
if (rollupConfig && typeof rollupConfig.external === "function") {
|
|
106
|
+
if (rollupConfig.external(id)) return true;
|
|
107
|
+
}
|
|
108
|
+
if (Array.isArray(rollupConfig && rollupConfig.external)) {
|
|
109
|
+
if (rollupConfig.external.includes(id)) return true;
|
|
31
110
|
}
|
|
32
|
-
return !id.startsWith(
|
|
111
|
+
return !id.startsWith(".") && !id.startsWith("/") && !/^[A-Za-z]:\\/.test(id);
|
|
33
112
|
},
|
|
34
113
|
plugins: [
|
|
35
114
|
json(),
|
|
36
|
-
resolve({
|
|
37
|
-
extensions: ['.js', '.ts', '.jsx', '.tsx', '.json', '.mjs', '.cjs'],
|
|
38
|
-
browser: false
|
|
39
|
-
}),
|
|
115
|
+
resolve({ extensions: [".js", ".ts", ".jsx", ".tsx", ".json", ".mjs", ".cjs"] }),
|
|
40
116
|
commonjs(),
|
|
41
117
|
typescript({
|
|
42
118
|
tsconfig: false,
|
|
43
119
|
target: "ES2017",
|
|
44
120
|
module: "ESNext",
|
|
45
121
|
jsx: "react-jsx",
|
|
46
|
-
moduleResolution: "node",
|
|
122
|
+
moduleResolution: "node",
|
|
47
123
|
esModuleInterop: true,
|
|
48
|
-
skipLibCheck: false,
|
|
49
124
|
strict: true,
|
|
50
125
|
importHelpers: true,
|
|
126
|
+
skipLibCheck: false,
|
|
51
127
|
forceConsistentCasingInFileNames: true,
|
|
52
128
|
declaration: false,
|
|
53
129
|
emitDeclarationOnly: false,
|
|
54
|
-
rootDir: path.resolve(process.cwd(),
|
|
130
|
+
rootDir: path.resolve(process.cwd(), rootdir)
|
|
55
131
|
}),
|
|
56
132
|
args.minify ? terser() : null,
|
|
57
|
-
...rollupConfig?.plugins || []
|
|
133
|
+
...(rollupConfig?.plugins || [])
|
|
58
134
|
]
|
|
59
135
|
};
|
|
60
136
|
|
|
61
137
|
const bundle = await rollup(config);
|
|
62
|
-
const esm = {
|
|
63
|
-
dir: args.outdir,
|
|
64
|
-
format: "esm",
|
|
65
|
-
sourcemap: args.sourcemap,
|
|
66
|
-
compact: true,
|
|
67
|
-
strict: true,
|
|
68
|
-
exports: "named"
|
|
69
|
-
};
|
|
70
|
-
if (!args.bundle) {
|
|
71
|
-
esm.preserveModules = true
|
|
72
|
-
esm.preserveModulesRoot = args.rootdir
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
let cjs = {
|
|
76
|
-
...esm,
|
|
77
|
-
dir: args.outdir,
|
|
78
|
-
format: "cjs",
|
|
79
|
-
dynamicImportInCjs: true,
|
|
80
|
-
esModule: true,
|
|
81
|
-
}
|
|
82
138
|
|
|
83
|
-
|
|
139
|
+
// --------------------- Determine output formats ---------------------
|
|
140
|
+
const outputs = [];
|
|
84
141
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
format: "
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
142
|
+
// Default: build both esm and cjs
|
|
143
|
+
if (!args.format || args.format === "both") {
|
|
144
|
+
outputs.push({
|
|
145
|
+
dir: outdir,
|
|
146
|
+
format: "esm",
|
|
147
|
+
sourcemap: args.sourcemap,
|
|
148
|
+
preserveModules: true,
|
|
149
|
+
preserveModulesRoot: rootdir,
|
|
150
|
+
entryFileNames: "[name].mjs"
|
|
151
|
+
});
|
|
152
|
+
outputs.push({
|
|
153
|
+
dir: outdir,
|
|
154
|
+
format: "cjs",
|
|
155
|
+
sourcemap: args.sourcemap,
|
|
156
|
+
preserveModules: true,
|
|
157
|
+
preserveModulesRoot: rootdir,
|
|
158
|
+
entryFileNames: "[name].cjs"
|
|
159
|
+
});
|
|
160
|
+
} else if (args.format === "esm" || args.format === "cjs") {
|
|
161
|
+
outputs.push({
|
|
162
|
+
dir: outdir,
|
|
163
|
+
format: args.format,
|
|
164
|
+
sourcemap: args.sourcemap,
|
|
165
|
+
preserveModules: true,
|
|
166
|
+
preserveModulesRoot: rootdir,
|
|
167
|
+
entryFileNames: args.format === "esm" ? "[name].mjs" : "[name].cjs"
|
|
168
|
+
});
|
|
169
|
+
} else if (args.format === "iife" || args.format === "umd") {
|
|
170
|
+
outputs.push({
|
|
171
|
+
dir: outdir,
|
|
172
|
+
format: args.format,
|
|
173
|
+
name: args.name || "Bundle",
|
|
174
|
+
sourcemap: args.sourcemap,
|
|
175
|
+
entryFileNames: "[name].js"
|
|
176
|
+
});
|
|
108
177
|
}
|
|
109
178
|
|
|
110
|
-
for (const output of
|
|
179
|
+
for (const output of outputs) {
|
|
111
180
|
await bundle.write(output);
|
|
112
181
|
}
|
|
182
|
+
|
|
113
183
|
await bundle.close();
|
|
114
184
|
|
|
115
|
-
//
|
|
185
|
+
// --------------------- Parallel asset copy ---------------------
|
|
186
|
+
await copyAssetsBatched(rootdir, outdir);
|
|
187
|
+
|
|
188
|
+
// --------------------- DTS Generation ---------------------
|
|
116
189
|
if (isTs && args.declaration) {
|
|
117
|
-
spinner.text = "Generating TypeScript declarations
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
});
|
|
122
|
-
await bundlets.write({
|
|
190
|
+
spinner.text = "Generating TypeScript declarations…";
|
|
191
|
+
const dtsBundle = await rollup({ ...config, plugins: [dts()] });
|
|
192
|
+
await dtsBundle.write({
|
|
193
|
+
dir: outdir,
|
|
123
194
|
format: "esm",
|
|
124
195
|
preserveModules: true,
|
|
125
|
-
preserveModulesRoot:
|
|
126
|
-
dir: path.join(args.outdir),
|
|
196
|
+
preserveModulesRoot: rootdir
|
|
127
197
|
});
|
|
128
|
-
await
|
|
198
|
+
await dtsBundle.close();
|
|
129
199
|
}
|
|
130
200
|
}
|
|
131
201
|
|
|
132
|
-
export default bundler;
|
|
202
|
+
export default bundler;
|
|
@@ -1,75 +1,79 @@
|
|
|
1
|
-
import fs from 'fs-extra'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import ora from 'ora'
|
|
4
|
-
import { concolor, logger } from '../../helpers.js'
|
|
5
|
-
import bundler from './bundler.js'
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { concolor, logger } from '../../helpers.js';
|
|
5
|
+
import bundler from './bundler.js';
|
|
6
6
|
|
|
7
7
|
const build = async (args) => {
|
|
8
|
-
/*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
/*
|
|
9
|
+
args options:
|
|
10
|
+
--format=both
|
|
11
|
+
--bundle=true
|
|
12
|
+
--minify=false
|
|
13
|
+
--sourcemap=true
|
|
14
|
+
--declaration=true
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
// Convert string "true"/"false" to boolean
|
|
18
|
+
const beBool = (f) =>
|
|
19
|
+
typeof args[f] === 'string' ? args[f].toLowerCase() === 'true' : !!args[f];
|
|
17
20
|
|
|
18
21
|
const outdir = path.join(process.cwd(), '.mpack');
|
|
19
22
|
const rootdir = path.join(process.cwd(), 'src');
|
|
20
23
|
|
|
21
|
-
let entry = '';
|
|
22
|
-
let entryts = path.join(rootdir, 'index.ts');
|
|
23
|
-
let entryjs = path.join(rootdir, 'index.js');
|
|
24
|
-
let entrytsx = path.join(rootdir, 'index.tsx');
|
|
25
|
-
let entryjsx = path.join(rootdir, 'index.jsx');
|
|
26
|
-
|
|
27
|
-
if (fs.existsSync(entryts)) {
|
|
28
|
-
entry = "index.ts";
|
|
29
|
-
} else if (fs.existsSync(entryjs)) {
|
|
30
|
-
entry = "index.js";
|
|
31
|
-
} else if (fs.existsSync(entrytsx)) {
|
|
32
|
-
entry = "index.tsx";
|
|
33
|
-
} else if (fs.existsSync(entryjsx)) {
|
|
34
|
-
entry = "index.jsx";
|
|
35
|
-
} else {
|
|
36
|
-
throw new Error("No entry file found in src directory. Please provide an index.ts or index.js file.");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
24
|
args = {
|
|
40
|
-
format: args.format ||
|
|
41
|
-
bundle:
|
|
42
|
-
minify:
|
|
43
|
-
sourcemap:
|
|
44
|
-
declaration:
|
|
25
|
+
format: args.format || 'both',
|
|
26
|
+
bundle: beBool('bundle'),
|
|
27
|
+
minify: beBool('minify'),
|
|
28
|
+
sourcemap: beBool('sourcemap'),
|
|
29
|
+
declaration: beBool('declaration'),
|
|
45
30
|
outdir,
|
|
46
31
|
rootdir,
|
|
47
|
-
|
|
48
|
-
}
|
|
32
|
+
};
|
|
49
33
|
|
|
50
|
-
|
|
51
|
-
fs.rmSync(outdir, { recursive: true, force: true });
|
|
52
|
-
}
|
|
53
|
-
fs.mkdirSync(outdir)
|
|
54
|
-
const spinner = ora("✨ Bundling your package..\n").start();
|
|
55
|
-
await bundler(args, spinner);
|
|
56
|
-
spinner.text = "Copying package.json and readme.md files..."
|
|
57
|
-
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
58
|
-
if (fs.existsSync(pkgPath)) {
|
|
59
|
-
const pkgjson = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
60
|
-
delete pkgjson.scripts
|
|
61
|
-
delete pkgjson.type
|
|
62
|
-
fs.writeFileSync(path.join(outdir, 'package.json'), JSON.stringify(pkgjson, null, 2));
|
|
63
|
-
} else {
|
|
64
|
-
logger.error("package.json not found!");
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
34
|
+
const spinner = ora('✨ Building your package...\n').start();
|
|
67
35
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
36
|
+
try {
|
|
37
|
+
// Remove old build folder
|
|
38
|
+
await fs.remove(outdir);
|
|
39
|
+
await fs.mkdirp(outdir);
|
|
40
|
+
|
|
41
|
+
// Run bundler
|
|
42
|
+
await bundler(args, spinner);
|
|
43
|
+
|
|
44
|
+
spinner.text = '📦 Copying package.json and readme.md files...';
|
|
45
|
+
|
|
46
|
+
// Copy package.json
|
|
47
|
+
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
48
|
+
if (await fs.pathExists(pkgPath)) {
|
|
49
|
+
const pkgjson = await fs.readJson(pkgPath);
|
|
50
|
+
delete pkgjson.scripts;
|
|
51
|
+
delete pkgjson.type;
|
|
52
|
+
await fs.writeJson(path.join(outdir, 'package.json'), pkgjson, { spaces: 2 });
|
|
53
|
+
} else {
|
|
54
|
+
spinner.fail(concolor.red('package.json not found!'));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Copy readme.md if exists
|
|
59
|
+
const readmePath = path.join(process.cwd(), 'readme.md');
|
|
60
|
+
if (await fs.pathExists(readmePath)) {
|
|
61
|
+
await fs.copy(readmePath, path.join(outdir, 'readme.md'));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
spinner.succeed(concolor.bold(concolor.green('Build successfully completed!\n')));
|
|
65
|
+
console.log(concolor.bold('To publish your package, run:'));
|
|
66
|
+
console.log(
|
|
67
|
+
`${concolor.yellow('`npm run release`')} or navigate to \`.mpack\` and run: ${concolor.yellow(
|
|
68
|
+
'`npm publish`\n'
|
|
69
|
+
)}`
|
|
70
|
+
);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
spinner.fail(concolor.red('Build failed!'));
|
|
73
|
+
logger.error(err);
|
|
74
|
+
} finally {
|
|
75
|
+
spinner.stop();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
74
78
|
|
|
75
|
-
export default build
|
|
79
|
+
export default build;
|