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 CHANGED
@@ -1,122 +1,365 @@
1
- <p align="center">
2
- <a href="https://github.com/devnax/makepack" rel="noopener" target="_blank"><img src="https://raw.githubusercontent.com/devnax/makepack/main/logo.png" alt="Makepack logo"></a>
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
- <h1 align="center">Makepack</h1>
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
- **MakePack** is a command-line interface (CLI) tool that helps you to quickly set up, build, and manage JavaScript, TypeScript, React, and React-TypeScript libraries for use in npm projects. With just a few simple commands, you can generate your own libraries, start a development server, or build and publish your project to the npm repository.
23
+ ---
8
24
 
25
+ ## ✨ Features
9
26
 
10
- ## 📥 Installation
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
- Install `makepack` globally to get started:
41
+ ---
13
42
 
14
- ```sh
15
- npm install -g makepack
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
- ## 📜 CLI Commands
85
+ ## 📦 Generated Project Structure
29
86
 
30
- ### `makepack create` Scaffold a New Project
31
- Quickly initialize a structured package with the following setup:
87
+ Depending on template, you’ll get something like:
32
88
 
33
89
  ```
34
- src/index.ts or tsx or js or jsx
35
- .gitignore
36
- package.json
37
- README.md
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
- Run:
41
- ```sh
42
- makepack create
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
- ### 🚀 `makepack start` Launch the Development Server
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
- ```sh
50
- makepack start
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
- ### 🏗️ `makepack build` Compile Your Package
54
- Builds and optimizes your package into the `build` directory.
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
- ```sh
159
+ ### Example Builds
160
+
161
+ Dual build with declarations (default):
162
+
163
+ ```bash
57
164
  makepack build
58
165
  ```
59
166
 
60
- ### 📦 `makepack publish` – Deploy to NPM
61
- Publish your package to the npm registry in one command.
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
- ```sh
64
- makepack publish
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
- ## ⚙️ Configuration
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
- Customize your project by creating a `makepack.js` file in the root directory. This file allows full control over the build and dev environment.
275
+ ## 🧷 Best Practices
72
276
 
73
- ### 🔧 Default Configuration
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
- ```js
76
- module.exports = (prevConfig) => ({
77
- build: {
78
- outdir: "build",
79
- types: true,
80
- formatPackageJson: (p) => p,
81
- configs: [
82
- {
83
- entryPoints: "src/**/*.{tsx,ts,js,jsx}",
84
- outdir: "esm",
85
- format: "esm",
86
- sourcemap: true,
87
- jsx: 'automatic',
88
- loader: {
89
- '.ts': 'ts',
90
- '.tsx': 'tsx'
91
- },
92
- },
93
- {
94
- entryPoints: "src/**/*.{tsx,ts,js,jsx}",
95
- outdir: "",
96
- format: "cjs",
97
- sourcemap: true,
98
- jsx: 'automatic',
99
- loader: {
100
- '.ts': 'ts',
101
- '.tsx': 'tsx'
102
- },
103
- }
104
- ]
105
- },
106
- start: {
107
- port: 5000,
108
- entry: "App.tsx",
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
- ## 📜 License
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
- `makepack` is released under the **MIT License**, allowing free usage in both open-source and commercial projects.
358
+ Open an issue for bugs, ideas, or questions: https://github.com/devnax/makepack/issues
118
359
 
119
360
  ---
120
361
 
121
- 🚀 **Start building your next NPM package with `makepack` today!**
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.14",
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 '@rollup/plugin-json';
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 isTs = args.entry.endsWith('.ts') || args.entry.endsWith('.tsx')
14
- const viteConfig = await loadViteConfig()
15
- const rollupConfig = await loadRollupConfig()
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: [args.entry],
22
- external: (id) => {
23
- if (rollupConfig && typeof rollupConfig.external === 'function') {
24
- if (rollupConfig.external(id)) {
25
- return true;
26
- }
27
- } else if (Array.isArray(rollupConfig && rollupConfig.external)) {
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('.') && !id.startsWith('/') && !/^[A-Za-z]:\\/.test(id);
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", // ✅ Correct and lowercase
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(), args.rootdir),
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
- let outputOptions = []
139
+ // --------------------- Determine output formats ---------------------
140
+ const outputs = [];
84
141
 
85
- if (args.format === "both") {
86
- outputOptions = [
87
- { ...esm, entryFileNames: '[name].mjs' },
88
- cjs,
89
- ]
90
- } else if (args.format === "esm") {
91
- outputOptions = [esm];
92
- } else if (args.format === "cjs") {
93
- outputOptions = [cjs];
94
- } else if (args.format === "iife") {
95
- outputOptions = [{
96
- ...esm,
97
- format: "iife",
98
- name: args.name || path.basename(args.entry, path.extname(args.entry)),
99
- entryFileNames: '[name].js',
100
- }];
101
- } else if (args.format === "umd") {
102
- outputOptions = [{
103
- ...esm,
104
- format: "umd",
105
- name: args.name || path.basename(args.entry, path.extname(args.entry)),
106
- entryFileNames: '[name].js',
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 outputOptions) {
179
+ for (const output of outputs) {
111
180
  await bundle.write(output);
112
181
  }
182
+
113
183
  await bundle.close();
114
184
 
115
- // If TypeScript declaration files are requested, generate them
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 bundlets = await rollup({
119
- ...config,
120
- plugins: [dts()],
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: args.rootdir,
126
- dir: path.join(args.outdir),
196
+ preserveModulesRoot: rootdir
127
197
  });
128
- await bundlets.close();
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
- /* args
9
- --format=both
10
- --bundle=true,
11
- --minify=false,
12
- --sourcemap=true,
13
- --declaration=true,
8
+ /*
9
+ args options:
10
+ --format=both
11
+ --bundle=true
12
+ --minify=false
13
+ --sourcemap=true
14
+ --declaration=true
14
15
  */
15
16
 
16
- let printBool = (f) => typeof args[f] === 'string' ? (args[f] === 'true') : args[f];
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 || "both",
41
- bundle: printBool('bundle'),
42
- minify: printBool('minify'),
43
- sourcemap: printBool('sourcemap'),
44
- declaration: printBool('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
- entry: path.join(rootdir, entry),
48
- }
32
+ };
49
33
 
50
- if (fs.existsSync(outdir)) {
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
- fs.copyFileSync(path.join(process.cwd(), '/readme.md'), path.join(outdir, `/readme.md`))
69
- spinner.succeed(concolor.bold(concolor.green(`Build successfully completed\n`)));
70
- console.log(concolor.bold(`To publish your package to npm run:`));
71
- console.log(`${concolor.yellow(`\`npm run release\``)} Or navigate to \`.mpack\` and run: ${concolor.yellow(`\`npm publish\`\n`)}`);
72
- spinner.stop();
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;