prepare-package 2.0.7 → 2.1.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 +40 -0
- package/dist/index.js +71 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ npx prepare-package
|
|
|
46
46
|
* Two modes: **copy** (default) and **bundle** (esbuild)
|
|
47
47
|
* Copy mode: copies `src/` to `dist/`, replaces `{version}` in main file
|
|
48
48
|
* Bundle mode: builds ESM, CJS, and/or IIFE outputs via esbuild
|
|
49
|
+
* **Before/after hooks** — run arbitrary shell commands as part of the prepare lifecycle
|
|
49
50
|
* Blocks `npm publish` when local `file:` dependencies are detected
|
|
50
51
|
* Cleans up sensitive files (`.env`, `.DS_Store`, etc.) before publish
|
|
51
52
|
* Purges jsDelivr CDN cache after publish
|
|
@@ -140,6 +141,45 @@ To override the footer, set `build.cjs.footer` in your config.
|
|
|
140
141
|
#### IIFE global export
|
|
141
142
|
The IIFE build automatically unwraps the default export so `window[globalName]` is the class/function directly, not a `{ default }` wrapper.
|
|
142
143
|
|
|
144
|
+
### Hooks
|
|
145
|
+
|
|
146
|
+
Run arbitrary shell commands before or after the copy/bundle step. Useful for fetching remote data, generating files, uploading artifacts, or running any command that needs to happen as part of the prepare lifecycle — so the output lands in both your git commits and your published tarball.
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"preparePackage": {
|
|
151
|
+
"input": "src",
|
|
152
|
+
"output": "dist",
|
|
153
|
+
"hooks": {
|
|
154
|
+
"before": "node scripts/update-disposable-domains.js",
|
|
155
|
+
"after": "node scripts/notify-deploy.js"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
| Hook | When it runs | On failure |
|
|
162
|
+
|------|-------------|-----------|
|
|
163
|
+
| `before` | After publish safety checks, before the copy/bundle step | **Blocks** — throws and aborts prepare |
|
|
164
|
+
| `after` | After the copy/bundle step, before the CDN purge | **Warns** — logs a warning and continues |
|
|
165
|
+
|
|
166
|
+
Both hooks accept a single command string or an array of commands:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"preparePackage": {
|
|
171
|
+
"hooks": {
|
|
172
|
+
"before": [
|
|
173
|
+
"node scripts/update-disposable-domains.js",
|
|
174
|
+
"node scripts/build-manifest.js"
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Commands run synchronously from the package root with `stdio` inherited, so their output appears in the parent process. Hooks are **skipped** in watch mode (single-file updates) and during postinstall — they only run on full prepare runs (`npm run prepare`, `npm publish`, etc.).
|
|
182
|
+
|
|
143
183
|
## Usage
|
|
144
184
|
|
|
145
185
|
```shell
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,66 @@
|
|
|
1
1
|
const jetpack = require('fs-jetpack');
|
|
2
2
|
const fetch = require('wonderful-fetch');
|
|
3
3
|
const path = require('path');
|
|
4
|
+
const { spawn } = require('child_process');
|
|
4
5
|
const { default: chalk } = require('chalk');
|
|
5
6
|
const logger = require('./logger');
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Run a single shell command and resolve/reject when it exits.
|
|
10
|
+
* Streams stdio to the parent process so output is visible during prepare/publish.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} cmd - Shell command to run
|
|
13
|
+
* @param {string} cwd - Working directory for the command
|
|
14
|
+
* @returns {Promise<void>} - Resolves on exit code 0, rejects otherwise
|
|
15
|
+
*/
|
|
16
|
+
function runCommand(cmd, cwd) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const child = spawn(cmd, {
|
|
19
|
+
cwd: cwd,
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
shell: true,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
child.on('error', reject);
|
|
25
|
+
child.on('exit', (code) => {
|
|
26
|
+
if (code === 0) {
|
|
27
|
+
return resolve();
|
|
28
|
+
}
|
|
29
|
+
return reject(new Error(`Command exited with code ${code}`));
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Run a hook command (or array of commands) sequentially from the consumer's cwd.
|
|
36
|
+
*
|
|
37
|
+
* @param {string|string[]} command - Shell command(s) to run
|
|
38
|
+
* @param {string} cwd - Working directory for the command
|
|
39
|
+
* @param {string} label - 'before' or 'after' (used in logs)
|
|
40
|
+
* @param {boolean} blocking - If true, throws on failure; if false, warns and continues
|
|
41
|
+
*/
|
|
42
|
+
async function runHook(command, cwd, label, blocking) {
|
|
43
|
+
if (!command) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const commands = Array.isArray(command) ? command : [command];
|
|
48
|
+
|
|
49
|
+
for (const cmd of commands) {
|
|
50
|
+
logger.log(chalk.cyan(`Running ${label} hook: ${cmd}`));
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
await runCommand(cmd, cwd);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
if (blocking) {
|
|
56
|
+
logger.error(`${label} hook failed: ${cmd}`);
|
|
57
|
+
throw e;
|
|
58
|
+
}
|
|
59
|
+
logger.error(chalk.yellow(`${label} hook failed (non-blocking): ${cmd} — ${e.message}`));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
7
64
|
// const argv = require('yargs').argv;
|
|
8
65
|
|
|
9
66
|
// Helper function to check for local dependencies
|
|
@@ -111,6 +168,7 @@ module.exports = async function (options) {
|
|
|
111
168
|
theirPackageJSON.preparePackage.output = theirPackageJSON.preparePackage.output || './dist';
|
|
112
169
|
theirPackageJSON.preparePackage.replace = theirPackageJSON.preparePackage.replace || {};
|
|
113
170
|
theirPackageJSON.preparePackage.type = theirPackageJSON.preparePackage.type || 'copy';
|
|
171
|
+
theirPackageJSON.preparePackage.hooks = theirPackageJSON.preparePackage.hooks || {};
|
|
114
172
|
|
|
115
173
|
// Add script
|
|
116
174
|
theirPackageJSON.scripts = theirPackageJSON.scripts || {};
|
|
@@ -138,6 +196,13 @@ module.exports = async function (options) {
|
|
|
138
196
|
});
|
|
139
197
|
}
|
|
140
198
|
|
|
199
|
+
// Run the `before` hook
|
|
200
|
+
// Only runs on live preparation (not on prepare-package's own build) and never in postinstall
|
|
201
|
+
// or single-file watch mode (which runs on every file change).
|
|
202
|
+
if (isLivePreparation && !options.isPostInstall && !options.singleFile) {
|
|
203
|
+
await runHook(theirPackageJSON.preparePackage.hooks.before, options.cwd, 'before', true);
|
|
204
|
+
}
|
|
205
|
+
|
|
141
206
|
// --- BUNDLE MODE ---
|
|
142
207
|
if (isBundleMode) {
|
|
143
208
|
const { build } = require('./build');
|
|
@@ -225,6 +290,12 @@ module.exports = async function (options) {
|
|
|
225
290
|
// ... moveed to another package
|
|
226
291
|
}
|
|
227
292
|
|
|
293
|
+
// Run the `after` hook
|
|
294
|
+
// Non-blocking — failures warn but don't break the prepare flow (same philosophy as CDN purge).
|
|
295
|
+
if (isLivePreparation && !options.isPostInstall && !options.singleFile) {
|
|
296
|
+
await runHook(theirPackageJSON.preparePackage.hooks.after, options.cwd, 'after', false);
|
|
297
|
+
}
|
|
298
|
+
|
|
228
299
|
// If purge is disabled, then return
|
|
229
300
|
if (options.purge === false) {
|
|
230
301
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prepare-package",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Prepare a Node.js package before being published",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"chalk": "^5.6.2",
|
|
50
50
|
"chokidar": "^5.0.0",
|
|
51
|
-
"esbuild": "^0.
|
|
51
|
+
"esbuild": "^0.28.0",
|
|
52
52
|
"fs-jetpack": "^5.1.0",
|
|
53
|
-
"wonderful-fetch": "^2.0.
|
|
53
|
+
"wonderful-fetch": "^2.0.5"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"mocha": "^11.7.5"
|