pmsec 0.5.0 → 0.5.2

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/cli.mjs +20 -7
package/README.md CHANGED
@@ -38,7 +38,7 @@ Zero runtime dependencies, ESM, requires Node 22+.
38
38
  | `pmsec disable` | Remove every key the bundle set; other keys in the file are preserved. |
39
39
  | `pmsec --version` | Print the installed pmsec version. |
40
40
 
41
- Options: `--tool npm,pnpm,yarn,bun,cargo,mise,uv`, `--days N` (override the 3-day default), `--json`.
41
+ Options: `--tool npm,pnpm,yarn,bun,cargo,mise,uv`, `--days N` (override the 3-day default), `--force` (overwrite stricter existing cooldowns; default is monotonic), `--json`.
42
42
 
43
43
  When the target file is owned by another user (typical: `~/.npmrc` left
44
44
  root-owned by an old `sudo npm config set`), the write fails with `EACCES`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmsec",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/cli.mjs CHANGED
@@ -31,6 +31,7 @@ Commands:
31
31
  Options:
32
32
  --tool TOOL[,TOOL] Restrict to specific tools (npm,pnpm,yarn,bun,cargo,mise,uv)
33
33
  --days N Override cooldown days (default 3)
34
+ --force Overwrite stricter existing cooldowns (otherwise enable is monotonic)
34
35
  --json Emit JSON output
35
36
  -V, --version Show version
36
37
  -h, --help Show this help
@@ -38,6 +39,7 @@ Options:
38
39
  Examples:
39
40
  npx pmsec enable
40
41
  npx pmsec enable --days 7
42
+ npx pmsec enable --days 1 --force
41
43
  npx pmsec check
42
44
  npx pmsec disable --tool npm
43
45
  `;
@@ -49,13 +51,14 @@ function parseDays(raw) {
49
51
  }
50
52
 
51
53
  function parse(argv) {
52
- const opts = { command: null, json: false, only: null, days: BUNDLE_DAYS, help: false, version: false };
54
+ const opts = { command: null, json: false, only: null, days: BUNDLE_DAYS, force: false, help: false, version: false };
53
55
  const positional = [];
54
56
  for (let i = 0; i < argv.length; i++) {
55
57
  const a = argv[i];
56
58
  if (a === "-h" || a === "--help") opts.help = true;
57
59
  else if (a === "-V" || a === "--version") opts.version = true;
58
60
  else if (a === "--json") opts.json = true;
61
+ else if (a === "--force") opts.force = true;
59
62
  else if (a === "--tool") opts.only = argv[++i].split(",");
60
63
  else if (a.startsWith("--tool=")) opts.only = a.slice(7).split(",");
61
64
  else if (a === "--days") opts.days = parseDays(argv[++i]);
@@ -134,7 +137,7 @@ function explainFsError(e, tool) {
134
137
  return `${tool}: ${e?.message ?? e}`;
135
138
  }
136
139
 
137
- async function runEnable(targets, json, days, env, home, platform, out, err) {
140
+ async function runEnable(targets, json, days, force, env, home, platform, out, err) {
138
141
  const results = [];
139
142
  const failures = [];
140
143
  const warnings = [];
@@ -142,18 +145,28 @@ async function runEnable(targets, json, days, env, home, platform, out, err) {
142
145
  const warn = preflightWarn(t);
143
146
  if (warn) warnings.push({ tool: t.name, warn });
144
147
  try {
145
- const r = await t.write(days, env, home, platform);
146
- results.push({ tool: t.name, path: r.path, days, ok: true, warn });
148
+ let effective = days;
149
+ let kept = false;
150
+ if (!force) {
151
+ const current = await t.read(env, home, platform);
152
+ const currentDays = current.days ?? 0;
153
+ effective = Math.max(currentDays, days);
154
+ kept = currentDays >= days && currentDays > 0;
155
+ }
156
+ const r = await t.write(effective, env, home, platform);
157
+ results.push({ tool: t.name, path: r.path, days: effective, requested: days, kept, forced: force, ok: true, warn });
147
158
  } catch (e) {
148
159
  failures.push({ tool: t.name, error: explainFsError(e, t.name) });
149
- results.push({ tool: t.name, path: e?.path ?? null, days, ok: false, error: explainFsError(e, t.name), warn });
160
+ results.push({ tool: t.name, path: e?.path ?? null, days, requested: days, kept: false, forced: force, ok: false, error: explainFsError(e, t.name), warn });
150
161
  }
151
162
  }
152
163
  if (json) out.write(JSON.stringify({ enabled: true, bundleDays: days, results, warnings, ok: failures.length === 0 }, null, 2) + "\n");
153
164
  else for (const r of results) {
154
165
  if (r.ok) {
166
+ const action = r.kept ? "keep " : "enable ";
167
+ const note = r.kept ? ` (kept existing ${r.days}d ≥ ${r.requested}d)` : "";
155
168
  const tail = r.warn ? `\n ⚠ ${r.warn}` : "";
156
- out.write(`enable ${r.tool.padEnd(4)} [${r.path}]${tail}\n`);
169
+ out.write(`${action} ${r.tool.padEnd(4)} [${r.path}]${note}${tail}\n`);
157
170
  } else {
158
171
  out.write(`FAIL ${r.tool.padEnd(4)} ${r.error}\n`);
159
172
  }
@@ -201,7 +214,7 @@ export async function run(argv, {
201
214
  catch (e) { err.write(`pmsec: ${e.message}\n`); return 2; }
202
215
  try {
203
216
  if (opts.command === "check") return await runCheck(targets, opts, env, home, platform, out, err);
204
- if (opts.command === "enable") return await runEnable(targets, opts.json, opts.days, env, home, platform, out, err);
217
+ if (opts.command === "enable") return await runEnable(targets, opts.json, opts.days, opts.force, env, home, platform, out, err);
205
218
  if (opts.command === "disable") return await runDisable(targets, opts.json, env, home, platform, out, err);
206
219
  err.write(`pmsec: unknown command "${opts.command}"\n`);
207
220
  return 2;