@bobfrankston/npmglobalize 1.0.160 → 1.0.161

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
@@ -189,6 +189,31 @@ npmglobalize -np # --nopublish (formerly --apply)
189
189
  npmglobalize --cleanup # Restore original file: references
190
190
  ```
191
191
 
192
+ ### 📝 Release Notes via `.commitmsg`
193
+
194
+ For multi-line or reusable release notes, write them to a `.commitmsg` file in the package root instead of passing them on the command line:
195
+
196
+ ```bash
197
+ cat > .commitmsg <<'EOF'
198
+ Added foo feature
199
+ Fixed bar regression
200
+ EOF
201
+ npmglobalize
202
+ ```
203
+
204
+ Behavior:
205
+ - If `-m` / `-message` is **not** given and `.commitmsg` exists, its contents are used as the commit message (and force a release even if the working tree is otherwise clean).
206
+ - After a successful `npm publish`, npmglobalize:
207
+ 1. Appends the contents to `npmchanges.md` under a `## v<version> — <YYYY-MM-DD>` header (creating the file if needed)
208
+ 2. Deletes `.commitmsg`
209
+ 3. Commits both changes as `Log v<version> to npmchanges.md` and pushes
210
+
211
+ Notes:
212
+ - **Git/GitHub only.** npm publish does not consume git commit messages; `npmchanges.md` lives in the git repo and on GitHub but is excluded from the published npm tarball (the standard `*.md` rule keeps only `README.md`).
213
+ - If both `-m` and `.commitmsg` are present, `-m` wins and `.commitmsg` is left alone (not consumed).
214
+ - If publish fails, `.commitmsg` is preserved for the next attempt.
215
+ - `.commitmsg` is auto-added to `.npmignore` (security pattern) so it never leaks into the tarball.
216
+
192
217
  ### 🔧 Git Integration & Error Recovery
193
218
 
194
219
  **Automatic tag conflict resolution**:
@@ -288,6 +313,8 @@ Publishing requires being on a branch so commits and tags can be properly tracke
288
313
  -nopublish, -np Just transform, don't publish (persisted to config)
289
314
  -cleanup Restore file: dependencies from .dependencies backup
290
315
  -m, -message <msg> Custom commit message (forces release even without changes)
316
+ If -m not given, a `.commitmsg` file (if present) is used instead.
317
+ See "Release Notes via .commitmsg" below.
291
318
  ```
292
319
 
293
320
  ### Dependency Options
package/cli.js CHANGED
@@ -27,6 +27,9 @@ Release Options:
27
27
  -nopublish, -np Just transform, don't publish (persisted to config)
28
28
  -cleanup Restore from .dependencies
29
29
  -m, -message <msg> Custom commit message (forces release even without changes)
30
+ If -m not given and a .commitmsg file exists in cwd, its
31
+ contents are used. After a successful publish it is appended
32
+ to npmchanges.md (with version header) and deleted.
30
33
 
31
34
  Dependency Options:
32
35
  -update-deps, -ud Update package.json to latest (minor/patch only, safe)
@@ -41,7 +41,8 @@
41
41
  ".env*",
42
42
  "token*",
43
43
  "certs/",
44
- "*cert*/"
44
+ "*cert*/",
45
+ ".commitmsg"
45
46
  ],
46
47
  // Prompted or auto-added with --conform
47
48
  recommended: [
package/lib.js CHANGED
@@ -3919,11 +3919,29 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3919
3919
  }
3920
3920
  // Re-check git status after all transformations and potential commits
3921
3921
  currentGitStatus = getGitStatus(cwd);
3922
+ // If no -m given, fall back to .commitmsg file contents (one-shot changelog entry).
3923
+ // Consumed (appended to npmchanges.md + deleted) only after a successful publish.
3924
+ const commitMsgPath = path.join(cwd, '.commitmsg');
3925
+ let commitMsgFromFile = null;
3926
+ let effectiveMessage = message;
3927
+ if (!effectiveMessage && fs.existsSync(commitMsgPath)) {
3928
+ try {
3929
+ const content = fs.readFileSync(commitMsgPath, 'utf-8').trim();
3930
+ if (content) {
3931
+ commitMsgFromFile = content;
3932
+ effectiveMessage = content;
3933
+ console.log(colors.cyan(` Using .commitmsg for commit message (${content.split('\n')[0].slice(0, 60)}${content.length > 60 ? '…' : ''})`));
3934
+ }
3935
+ }
3936
+ catch (err) {
3937
+ console.error(colors.yellow(` Warning: could not read .commitmsg: ${err.message}`));
3938
+ }
3939
+ }
3922
3940
  // Check if there are changes to commit or a custom message
3923
3941
  // Skip this check for first publish (currentAccess null) or just-initialized repos
3924
3942
  const isFirstPublish = !currentAccess;
3925
3943
  let skipVersionBump = false;
3926
- if (!currentGitStatus.hasUncommitted && !message && !justInitialized && !isFirstPublish) {
3944
+ if (!currentGitStatus.hasUncommitted && !effectiveMessage && !justInitialized && !isFirstPublish) {
3927
3945
  // Check if the current version is actually on npm (it might have failed to publish previously)
3928
3946
  const versionCheck = spawnSafe('npm', ['view', `${pkg.name}@${pkg.version}`, 'version'], {
3929
3947
  shell: process.platform === 'win32',
@@ -4074,7 +4092,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
4074
4092
  }
4075
4093
  // Git operations
4076
4094
  if (currentGitStatus.hasUncommitted) {
4077
- const commitMsg = message || 'Pre-release commit';
4095
+ const commitMsg = effectiveMessage || 'Pre-release commit';
4078
4096
  console.log(`${timestamp()} Committing changes: ${commitMsg}`);
4079
4097
  if (!dryRun) {
4080
4098
  // Remove 'nul' files that break git on Windows
@@ -4701,6 +4719,36 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
4701
4719
  const finalAccess = effectiveNpmVisibility || currentAccess || (isScoped ? 'restricted' : 'public');
4702
4720
  const accessLabel = (finalAccess === 'restricted' || finalAccess === 'private') ? 'PRIVATE' : 'PUBLIC';
4703
4721
  console.log(`${timestamp()} ${colors.green(`✓ Published to npm as ${accessLabel}`)}`);
4722
+ // Consume .commitmsg: append to npmchanges.md, delete the file, commit+push.
4723
+ // Only runs if .commitmsg was actually used as the commit message.
4724
+ if (commitMsgFromFile) {
4725
+ try {
4726
+ const publishedVersion = readPackageJson(cwd).version;
4727
+ const npmChangesPath = path.join(cwd, 'npmchanges.md');
4728
+ const date = new Date().toISOString().slice(0, 10);
4729
+ const header = `## v${publishedVersion} — ${date}\n\n`;
4730
+ const entry = header + commitMsgFromFile.trim() + '\n\n';
4731
+ const existing = fs.existsSync(npmChangesPath)
4732
+ ? fs.readFileSync(npmChangesPath, 'utf-8')
4733
+ : '# npm Publish Changes\n\n';
4734
+ const sep = existing.endsWith('\n') ? '' : '\n';
4735
+ fs.writeFileSync(npmChangesPath, existing + sep + entry);
4736
+ try {
4737
+ fs.unlinkSync(commitMsgPath);
4738
+ }
4739
+ catch { /* ignore */ }
4740
+ runCommand('git', ['add', 'npmchanges.md', '.commitmsg'], { cwd, silent: true });
4741
+ const logResult = gitCommit(`Log v${publishedVersion} to npmchanges.md`, cwd);
4742
+ if (logResult.success) {
4743
+ console.log(colors.green(` ✓ Appended to npmchanges.md and removed .commitmsg`));
4744
+ if (currentGitStatus.hasRemote)
4745
+ pushWithProtection(cwd, verbose);
4746
+ }
4747
+ }
4748
+ catch (err) {
4749
+ console.error(colors.yellow(` Warning: could not update npmchanges.md: ${err.message}`));
4750
+ }
4751
+ }
4704
4752
  }
4705
4753
  else {
4706
4754
  console.log(` [dry-run] Would run: npm publish ${quiet ? '--quiet' : ''}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.160",
3
+ "version": "1.0.161",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",