depfresh 0.9.2 → 0.10.1

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,17 +1,17 @@
1
- # depzy
1
+ # depfresh
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/depzy)](https://www.npmjs.com/package/depzy)
3
+ [![npm version](https://img.shields.io/npm/v/depfresh)](https://www.npmjs.com/package/depfresh)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
5
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9+-3178c6)](https://www.typescriptlang.org/)
6
6
  [![Node.js](https://img.shields.io/badge/Node.js-24+-339933)](https://nodejs.org/)
7
7
 
8
- Keep your npm dependencies fresh. Fast, correct, zero-config.
8
+ Keep your npm dependencies fresh. Fast, correct, zero-config. Your AI agent already knows how to use this. You don't even need to read this README -- it did.
9
9
 
10
- Spiritual successor to [taze](https://github.com/antfu/taze) by Anthony Fu - a tool that did the job well until maintenance slowed and issues piled up. I took the best ideas, rewrote everything from scratch, fixed the bugs that sat open for years, and made it work for humans and AI agents alike. Credit where it's due.
10
+ Spiritual successor to [taze](https://github.com/antfu/taze) by Anthony Fu -- a tool that did the job well until maintenance slowed and issues piled up. I took the best ideas, rewrote everything from scratch, fixed the bugs that sat open for years, and made it work for humans and AI agents alike. Credit where it's due.
11
11
 
12
12
  ## Features
13
13
 
14
- - **Zero-config dependency checking** -- run `depzy` and it tells you what's outdated. No YAML. No PhD.
14
+ - **Zero-config dependency checking** -- run `depfresh` and it tells you what's outdated. No YAML. No PhD.
15
15
  - **Monorepo & workspace support** -- pnpm, bun, yarn, npm. Auto-detected. Catalog deps included.
16
16
  - **7 range modes** -- `default`, `major`, `minor`, `patch`, `latest`, `newest`, `next`. One flag, total control.
17
17
  - **Interactive cherry-picking** -- grouped multiselect with colour-coded severity. Pick what you want, ignore the rest.
@@ -35,48 +35,56 @@ Spiritual successor to [taze](https://github.com/antfu/taze) by Anthony Fu - a t
35
35
 
36
36
  Because `npm outdated` gives you a table and then abandons you. Because Renovate requires a PhD in YAML. Because your AI coding assistant should be able to update your deps without you holding its hand.
37
37
 
38
- depzy checks every `package.json` in your project, tells you what's outdated, and optionally writes the updates. Monorepos, workspace catalogs, private registries - it handles all of it without a config file.
38
+ depfresh checks every `package.json` in your project, tells you what's outdated, and optionally writes the updates. Monorepos, workspace catalogs, private registries - it handles all of it without a config file.
39
39
 
40
40
  ## Install
41
41
 
42
42
  ```bash
43
- npm install -g depzy
43
+ npm install -g depfresh
44
44
  ```
45
45
 
46
46
  Or don't install globally. I'm not your parent.
47
47
 
48
48
  ```bash
49
- npx depzy
50
- pnpm dlx depzy
51
- bunx depzy
49
+ npx depfresh
50
+ pnpm dlx depfresh
51
+ bunx depfresh
52
52
  ```
53
53
 
54
+ Lost? `depfresh help` prints every flag and mode. `depfresh --help-json` spits out the full CLI contract as JSON for the robots. Between the two of them, there's no excuse for not knowing what this thing does.
55
+
54
56
  ## Usage
55
57
 
56
58
  ```bash
57
59
  # Check for outdated dependencies
58
- depzy
60
+ depfresh
61
+
62
+ # Lost? This prints everything.
63
+ depfresh help
64
+
65
+ # Same thing but for machines and AI agents who can't read tables
66
+ depfresh --help-json
59
67
 
60
68
  # Actually update them
61
- depzy --write
69
+ depfresh --write
62
70
 
63
71
  # Interactive mode -- pick what to update like a civilised person
64
- depzy --interactive
72
+ depfresh --interactive
65
73
 
66
74
  # Only minor/patch updates (living cautiously)
67
- depzy minor -w
75
+ depfresh minor -w
68
76
 
69
77
  # JSON output for scripts and AI agents
70
- depzy --output json
78
+ depfresh --output json
71
79
 
72
80
  # Filter specific packages
73
- depzy --include "react,vue" --exclude "eslint"
81
+ depfresh --include "react,vue" --exclude "eslint"
74
82
 
75
83
  # Verify each dep individually, revert failures
76
- depzy -w --verify-command "pnpm test"
84
+ depfresh -w --verify-command "pnpm test"
77
85
 
78
86
  # CI: fail if anything is outdated
79
- depzy --fail-on-outdated
87
+ depfresh --fail-on-outdated
80
88
  ```
81
89
 
82
90
  ## CLI Flags
@@ -103,10 +111,10 @@ The top flags to get you started. Full reference with all 27+ flags: **[docs/cli
103
111
 
104
112
  ## Config File
105
113
 
106
- Zero config works. But if you want it, create `depzy.config.ts` (or `.depzyrc`, or add a `depzy` key to `package.json`):
114
+ Zero config works. But if you want it, create `depfresh.config.ts` (or `.depfreshrc`, or add a `depfresh` key to `package.json`):
107
115
 
108
116
  ```typescript
109
- import { defineConfig } from 'depzy'
117
+ import { defineConfig } from 'depfresh'
110
118
 
111
119
  export default defineConfig({
112
120
  mode: 'minor',
@@ -140,17 +148,33 @@ Full options reference: **[docs/configuration/](docs/configuration/)**
140
148
  ]
141
149
  }
142
150
  ],
151
+ "errors": [
152
+ {
153
+ "name": "some-private-pkg",
154
+ "source": "dependencies",
155
+ "currentVersion": "^1.0.0",
156
+ "message": "Failed to resolve from registry"
157
+ }
158
+ ],
143
159
  "summary": {
144
160
  "total": 12,
145
161
  "major": 1,
146
162
  "minor": 7,
147
163
  "patch": 4,
148
- "packages": 3
164
+ "packages": 3,
165
+ "scannedPackages": 3,
166
+ "packagesWithUpdates": 3,
167
+ "plannedUpdates": 0,
168
+ "appliedUpdates": 0,
169
+ "revertedUpdates": 0
149
170
  },
150
171
  "meta": {
172
+ "schemaVersion": 1,
151
173
  "cwd": "/path/to/project",
152
174
  "mode": "default",
153
- "timestamp": "2026-02-22T12:00:00.000Z"
175
+ "timestamp": "2026-02-22T12:00:00.000Z",
176
+ "noPackagesFound": false,
177
+ "didWrite": false
154
178
  }
155
179
  }
156
180
  ```
@@ -159,33 +183,49 @@ Full schema and field reference: **[docs/output-formats/](docs/output-formats/)*
159
183
 
160
184
  ## AI Agent Usage
161
185
 
162
- depzy was designed to work with AI coding assistants out of the box. No special configuration needed.
186
+ depfresh was designed to work with AI coding assistants out of the box. No special configuration needed. Run it blind and it tells you what to do next.
187
+
188
+ **Auto-discovery** -- when stdout isn't a TTY (piped, captured by an agent), depfresh prints a hint to stderr: `Tip: Use --output json for structured output. Run --help-json for CLI capabilities.` Agents are stateless. They don't remember your last hint.
189
+
190
+ **`--help-json`** returns a full machine-readable contract: version, flags, enums, exit codes, plus:
191
+ - `workflows` -- 4 copy-paste agent recipes (`checkOnly`, `safeUpdate`, `fullUpdate`, `selective`)
192
+ - `flagRelationships` -- which flags require or conflict with others
193
+ - `configFiles` -- every supported config file pattern
194
+ - `jsonOutputSchema` -- field descriptions of the JSON envelope
163
195
 
164
196
  ```bash
165
- # Check for updates, get structured output
166
- depzy --output json --loglevel silent
197
+ # First run -- just see what happens (agents get the stderr hint)
198
+ depfresh
199
+
200
+ # Discover the full CLI contract
201
+ depfresh --help-json
167
202
 
168
- # Apply all updates
169
- depzy --write
203
+ # Check for updates, get structured output
204
+ depfresh --output json
170
205
 
171
206
  # Apply only safe updates
172
- depzy --write --mode patch
207
+ depfresh --write --mode minor --output json
173
208
 
174
209
  # Selective update
175
- depzy --write --include "typescript,vitest"
210
+ depfresh --write --include "typescript,vitest" --output json
211
+
212
+ # Full send
213
+ depfresh --write --mode latest --output json
176
214
  ```
177
215
 
178
216
  **Exit codes are semantic:**
179
217
  - `0` -- all deps up to date (or updates were written)
180
218
  - `1` -- updates available (with `--fail-on-outdated`)
181
- - `2` -- error
219
+ - `2` -- error (structured JSON error envelope when `--output json` is active)
220
+
221
+ **Structured errors** -- when `--output json` is active and something fails, you get a JSON error envelope with `error.code`, `error.message`, and `error.retryable` instead of plaintext stderr. Resolution failures for individual deps appear in the `errors[]` array of the normal envelope.
182
222
 
183
- **TTY detection** -- when stdout isn't a terminal (piped, captured by an agent), depzy automatically suppresses spinners and interactive prompts. `NO_COLOR` is respected.
223
+ **TTY detection** -- when stdout isn't a terminal, depfresh automatically suppresses spinners and interactive prompts. `NO_COLOR` is respected.
184
224
 
185
225
  ## Programmatic API
186
226
 
187
227
  ```typescript
188
- import { check, resolveConfig } from 'depzy'
228
+ import { check, resolveConfig } from 'depfresh'
189
229
 
190
230
  const options = await resolveConfig({
191
231
  cwd: process.cwd(),
@@ -208,7 +248,7 @@ const exitCode = await check(options)
208
248
 
209
249
  ## Monorepo Support
210
250
 
211
- depzy auto-detects workspace structures. No config needed.
251
+ depfresh auto-detects workspace structures. No config needed.
212
252
 
213
253
  | Package Manager | Workspaces | Catalogs |
214
254
  |----------------|------------|----------|
@@ -217,11 +257,11 @@ depzy auto-detects workspace structures. No config needed.
217
257
  | Yarn | `workspaces` in `package.json` | `.yarnrc.yml` catalogs |
218
258
  | npm | `workspaces` in `package.json` | -- |
219
259
 
220
- Workspace catalogs are resolved and updated in-place. Your `pnpm-workspace.yaml` catalog entries get depzyaded alongside your `package.json` deps. No manual sync needed.
260
+ Workspace catalogs are resolved and updated in-place. Your `pnpm-workspace.yaml` catalog entries get depfreshaded alongside your `package.json` deps. No manual sync needed.
221
261
 
222
262
  ## Private Registries
223
263
 
224
- depzy reads `.npmrc` from your project and home directory. Scoped registries, auth tokens, proxies -- all respected.
264
+ depfresh reads `.npmrc` from your project and home directory. Scoped registries, auth tokens, proxies -- all respected.
225
265
 
226
266
  ```ini
227
267
  # .npmrc
@@ -235,7 +275,7 @@ This was broken in taze for 4+ years. I fixed it on day one. You're welcome.
235
275
 
236
276
  Not to throw shade at taze -- it served the community well for years. But some things needed fixing, and "PR welcome" only goes so far when the PRs sit open for months.
237
277
 
238
- | Problem | taze | depzy |
278
+ | Problem | taze | depfresh |
239
279
  |---------|------|------|
240
280
  | `.npmrc` / private registries | Ignored | Full support |
241
281
  | Network retry | None | Exponential backoff |
@@ -255,7 +295,9 @@ The full docs, for people who read manuals before assembling furniture.
255
295
  - **[CLI Reference](docs/cli/)** -- all 27+ flags, modes, sorting, filtering, hooks, interactive, CI, workspaces
256
296
  - **[Configuration](docs/configuration/)** -- config files, every option, packageMode, depFields, private registries, cache
257
297
  - **[Programmatic API](docs/api/)** -- exported functions, lifecycle callbacks, types, workflow examples
258
- - **[Output Formats](docs/output-formats/)** -- table, JSON, SARIF, exit codes, AI agent integration
298
+ - **[Output Formats](docs/output-formats/)** -- table, JSON, exit codes, AI agent integration
299
+ - **[Agent Workflows](docs/agents/README.md)** -- copy-paste quickstarts for Codex, Claude Code, and Gemini CLI
300
+ - **[Integrations](docs/integrations/README.md)** -- GitHub Actions and thin MCP wrapper guidance
259
301
  - **[Troubleshooting](docs/troubleshooting.md)** -- common issues, workspace gotchas, known limitations
260
302
 
261
303
  ## Requirements
@@ -264,7 +306,7 @@ The full docs, for people who read manuals before assembling furniture.
264
306
 
265
307
  ## Standing on the Shoulders of People Who Actually Did the Work
266
308
 
267
- depzy wouldn't exist without [taze](https://github.com/antfu/taze). I rewrote everything from scratch, yes, but "from scratch" is easy when someone else already figured out what the thing should do. Every bug report, every feature PR, every typo fix in the taze repo was a free lesson in what users actually need. I just took notes and built a new house on someone else's blueprint.
309
+ depfresh wouldn't exist without [taze](https://github.com/antfu/taze). I rewrote everything from scratch, yes, but "from scratch" is easy when someone else already figured out what the thing should do. Every bug report, every feature PR, every typo fix in the taze repo was a free lesson in what users actually need. I just took notes and built a new house on someone else's blueprint.
268
310
 
269
311
  So here's to every contributor who opened a PR on taze. Some of you added features I shamelessly reimplemented. Some of you fixed bugs that taught me where the landmines were. Some of you fixed typos, and honestly, that's braver than any architecture decision I've ever made.
270
312
 
@@ -0,0 +1,129 @@
1
+ import { v as version, a as args } from '../cli.mjs';
2
+ import { C as CONFIG_FILES } from './config.mjs';
3
+ import { V as VALID_LOG_LEVELS, a as VALID_SORT_OPTIONS, b as VALID_OUTPUTS, c as VALID_MODES } from '../shared/depfresh.CFLB6fqi.mjs';
4
+ import 'citty';
5
+ import 'node:fs/promises';
6
+ import 'node:url';
7
+ import 'defu';
8
+ import 'pathe';
9
+ import '../shared/depfresh.FmznAfq4.mjs';
10
+ import '../shared/depfresh.Dxgqypc6.mjs';
11
+ import 'ansis';
12
+
13
+ const ENUM_VALUES_BY_FLAG = {
14
+ mode: VALID_MODES,
15
+ output: VALID_OUTPUTS,
16
+ sort: VALID_SORT_OPTIONS,
17
+ loglevel: VALID_LOG_LEVELS
18
+ };
19
+ const EXIT_CODES = {
20
+ "0": "Success (no updates found, or updates written successfully).",
21
+ "1": "Outdated dependencies found with --fail-on-outdated and without --write.",
22
+ "2": "Fatal/runtime/configuration error (including invalid enum flag values)."
23
+ };
24
+ const WORKFLOWS = {
25
+ checkOnly: {
26
+ description: "Check for outdated dependencies and return structured JSON",
27
+ command: "depfresh --output json"
28
+ },
29
+ safeUpdate: {
30
+ description: "Apply only minor and patch updates",
31
+ command: "depfresh --write --mode minor --output json"
32
+ },
33
+ fullUpdate: {
34
+ description: "Update everything to the latest version",
35
+ command: "depfresh --write --mode latest --output json"
36
+ },
37
+ selective: {
38
+ description: "Update specific packages by name",
39
+ command: 'depfresh --write --include "pkg1,pkg2" --output json'
40
+ }
41
+ };
42
+ const FLAG_RELATIONSHIPS = {
43
+ install: { requires: ["write"] },
44
+ update: { requires: ["write"] },
45
+ execute: { requires: ["write"] },
46
+ "verify-command": { requires: ["write"] },
47
+ interactive: { requires: ["write"] },
48
+ "deps-only": { conflicts: ["dev-only"] },
49
+ "dev-only": { conflicts: ["deps-only"] }
50
+ };
51
+ const JSON_OUTPUT_SCHEMA = {
52
+ "packages[]": "Array of scanned packages with their updates",
53
+ "packages[].name": "Package name from package.json",
54
+ "packages[].updates[]": "Array of dependencies with available updates",
55
+ "packages[].updates[].name": "Dependency name",
56
+ "packages[].updates[].current": "Current version range",
57
+ "packages[].updates[].target": "Target version range",
58
+ "packages[].updates[].diff": "Semver diff type: major | minor | patch",
59
+ "packages[].updates[].source": "Dependency field (dependencies, devDependencies, etc.)",
60
+ "errors[]": "Array of dependencies that failed to resolve",
61
+ "errors[].name": "Dependency name",
62
+ "errors[].source": "Dependency field",
63
+ "errors[].currentVersion": "Current version range",
64
+ "errors[].message": "Error description",
65
+ "summary.total": "Total number of available updates",
66
+ "summary.major": "Count of major updates",
67
+ "summary.minor": "Count of minor updates",
68
+ "summary.patch": "Count of patch updates",
69
+ "meta.schemaVersion": "JSON schema version (currently 1)",
70
+ "meta.cwd": "Working directory used",
71
+ "meta.mode": "Version range mode used",
72
+ "meta.timestamp": "ISO 8601 timestamp",
73
+ "meta.didWrite": "Whether package files were written"
74
+ };
75
+ function buildFlagDefinitions(argsDef) {
76
+ const positional = {};
77
+ const flags = {};
78
+ for (const [name, rawDef] of Object.entries(argsDef)) {
79
+ const def = rawDef;
80
+ if (!def.type) continue;
81
+ const capability = {
82
+ type: def.type,
83
+ ...def.description ? { description: def.description } : {},
84
+ ...def.alias ? { alias: def.alias } : {},
85
+ ...def.default !== void 0 ? { default: def.default } : {},
86
+ ...ENUM_VALUES_BY_FLAG[name] ? { values: ENUM_VALUES_BY_FLAG[name] } : {}
87
+ };
88
+ if (def.type === "positional") {
89
+ positional[name] = capability;
90
+ } else {
91
+ flags[name] = capability;
92
+ }
93
+ }
94
+ if (positional.mode_arg) {
95
+ positional.mode_arg.values = VALID_MODES;
96
+ }
97
+ return { positional, flags };
98
+ }
99
+ function getCliCapabilities() {
100
+ const { positional, flags } = buildFlagDefinitions(args);
101
+ return {
102
+ schemaVersion: 1,
103
+ version,
104
+ command: "depfresh",
105
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
106
+ enums: {
107
+ mode: VALID_MODES,
108
+ output: VALID_OUTPUTS,
109
+ sort: VALID_SORT_OPTIONS,
110
+ loglevel: VALID_LOG_LEVELS
111
+ },
112
+ exitCodes: EXIT_CODES,
113
+ positional,
114
+ flags,
115
+ workflows: WORKFLOWS,
116
+ flagRelationships: FLAG_RELATIONSHIPS,
117
+ configFiles: [...CONFIG_FILES],
118
+ jsonOutputSchema: JSON_OUTPUT_SCHEMA,
119
+ discoverability: {
120
+ helpJsonFlag: "depfresh --help-json",
121
+ capabilitiesCommand: "depfresh capabilities --json"
122
+ }
123
+ };
124
+ }
125
+ function outputCliCapabilities() {
126
+ console.log(JSON.stringify(getCliCapabilities(), null, 2));
127
+ }
128
+
129
+ export { getCliCapabilities, outputCliCapabilities };
@@ -2,7 +2,8 @@ import { readFile, access } from 'node:fs/promises';
2
2
  import { pathToFileURL } from 'node:url';
3
3
  import { defu } from 'defu';
4
4
  import { join } from 'pathe';
5
- import { c as createLogger, a as ConfigError } from '../shared/depfresh.B1o7OHO_.mjs';
5
+ import { C as ConfigError } from '../shared/depfresh.FmznAfq4.mjs';
6
+ import { c as createLogger } from '../shared/depfresh.Dxgqypc6.mjs';
6
7
 
7
8
  const DEFAULT_OPTIONS = {
8
9
  cwd: ".",
@@ -39,21 +40,21 @@ const DEFAULT_OPTIONS = {
39
40
  const TS_RE = /\.[mc]?ts$/;
40
41
  const JS_RE = /\.[mc]?js$/;
41
42
  const CONFIG_FILES = [
42
- "depzy.config.ts",
43
- "depzy.config.mts",
44
- "depzy.config.cts",
45
- "depzy.config.js",
46
- "depzy.config.mjs",
47
- "depzy.config.cjs",
48
- "depzy.config.json",
49
- ".depzyrc.ts",
50
- ".depzyrc.mts",
51
- ".depzyrc.cts",
52
- ".depzyrc.js",
53
- ".depzyrc.mjs",
54
- ".depzyrc.cjs",
55
- ".depzyrc.json",
56
- ".depzyrc"
43
+ "depfresh.config.ts",
44
+ "depfresh.config.mts",
45
+ "depfresh.config.cts",
46
+ "depfresh.config.js",
47
+ "depfresh.config.mjs",
48
+ "depfresh.config.cjs",
49
+ "depfresh.config.json",
50
+ ".depfreshrc.ts",
51
+ ".depfreshrc.mts",
52
+ ".depfreshrc.cts",
53
+ ".depfreshrc.js",
54
+ ".depfreshrc.mjs",
55
+ ".depfreshrc.cjs",
56
+ ".depfreshrc.json",
57
+ ".depfreshrc"
57
58
  ];
58
59
  async function exists(path) {
59
60
  try {
@@ -102,7 +103,7 @@ async function loadConfigFile(cwd) {
102
103
  try {
103
104
  const content = await readFile(pkgPath, "utf-8");
104
105
  const pkg = JSON.parse(content);
105
- if (pkg.depzy) return pkg.depzy;
106
+ if (pkg.depfresh) return pkg.depfresh;
106
107
  } catch (error) {
107
108
  throw new ConfigError(`Failed to parse package.json at ${pkgPath}`, { cause: error });
108
109
  }
@@ -120,7 +121,8 @@ async function resolveConfig(overrides = {}) {
120
121
 
121
122
  const config = {
122
123
  __proto__: null,
124
+ CONFIG_FILES: CONFIG_FILES,
123
125
  resolveConfig: resolveConfig
124
126
  };
125
127
 
126
- export { DEFAULT_OPTIONS as D, config as c, resolveConfig as r };
128
+ export { CONFIG_FILES as C, DEFAULT_OPTIONS as D, config as c, resolveConfig as r };
@@ -1,13 +1,15 @@
1
- import { c as check } from '../shared/depfresh.ClIHCCxD.mjs';
2
- export { d as detectPackageManager } from '../shared/depfresh.ClIHCCxD.mjs';
1
+ import { c as check } from '../shared/depfresh.BkxecpDK.mjs';
2
+ export { d as detectPackageManager } from '../shared/depfresh.BkxecpDK.mjs';
3
3
  import 'ansis';
4
- import '../shared/depfresh.B1o7OHO_.mjs';
4
+ import '../shared/depfresh.Dxgqypc6.mjs';
5
5
  import 'node:fs';
6
6
  import 'node:os';
7
7
  import 'find-up-simple';
8
8
  import 'ini';
9
9
  import 'pathe';
10
+ import './json-output.mjs';
10
11
  import 'node:child_process';
12
+ import '../shared/depfresh.FmznAfq4.mjs';
11
13
  import 'detect-indent';
12
14
  import 'semver';
13
15
  import 'pnpm-workspace-yaml';
@@ -1,14 +1,16 @@
1
1
  import * as readline from 'node:readline';
2
2
  import * as semver from 'semver';
3
- import { g as getVersionPrefix, f as applyVersionPrefix, h as getDiff, t as timeDifference, s as stripAnsi, i as truncate, j as padEnd, b as colorizeVersionDiff, a as arrow, e as colorDiff } from '../shared/depfresh.ClIHCCxD.mjs';
3
+ import { g as getVersionPrefix, f as applyVersionPrefix, h as getDiff, t as timeDifference, s as stripAnsi, i as truncate, j as padEnd, b as colorizeVersionDiff, a as arrow, e as colorDiff } from '../shared/depfresh.BkxecpDK.mjs';
4
4
  import c from 'ansis';
5
- import '../shared/depfresh.B1o7OHO_.mjs';
5
+ import '../shared/depfresh.Dxgqypc6.mjs';
6
6
  import 'node:fs';
7
7
  import 'node:os';
8
8
  import 'find-up-simple';
9
9
  import 'ini';
10
10
  import 'pathe';
11
+ import './json-output.mjs';
11
12
  import 'node:child_process';
13
+ import '../shared/depfresh.FmznAfq4.mjs';
12
14
  import 'detect-indent';
13
15
  import 'pnpm-workspace-yaml';
14
16
  import 'yaml';
@@ -1,7 +1,8 @@
1
1
  import './config.mjs';
2
- import { c as createLogger } from '../shared/depfresh.B1o7OHO_.mjs';
2
+ import '../shared/depfresh.FmznAfq4.mjs';
3
3
  import { execSync } from 'node:child_process';
4
- import '../shared/depfresh.ClIHCCxD.mjs';
4
+ import { c as createLogger } from '../shared/depfresh.Dxgqypc6.mjs';
5
+ import '../shared/depfresh.BkxecpDK.mjs';
5
6
 
6
7
  function detectGlobalPackageManager(pm) {
7
8
  if (pm && (pm === "npm" || pm === "pnpm" || pm === "bun")) {
@@ -1,13 +1,15 @@
1
1
  import * as p from '@clack/prompts';
2
2
  import c from 'ansis';
3
- import { a as arrow, b as colorizeVersionDiff, e as colorDiff } from '../shared/depfresh.ClIHCCxD.mjs';
4
- import '../shared/depfresh.B1o7OHO_.mjs';
3
+ import { a as arrow, b as colorizeVersionDiff, e as colorDiff } from '../shared/depfresh.BkxecpDK.mjs';
4
+ import '../shared/depfresh.Dxgqypc6.mjs';
5
5
  import 'node:fs';
6
6
  import 'node:os';
7
7
  import 'find-up-simple';
8
8
  import 'ini';
9
9
  import 'pathe';
10
+ import './json-output.mjs';
10
11
  import 'node:child_process';
12
+ import '../shared/depfresh.FmznAfq4.mjs';
11
13
  import 'detect-indent';
12
14
  import 'semver';
13
15
  import 'pnpm-workspace-yaml';
@@ -0,0 +1,65 @@
1
+ const RETRYABLE_CODES = /* @__PURE__ */ new Set(["ERR_REGISTRY", "ERR_CACHE"]);
2
+ function buildJsonPackage(name, updates) {
3
+ return {
4
+ name,
5
+ updates: updates.map((u) => ({
6
+ name: u.name,
7
+ current: u.currentVersion,
8
+ target: u.targetVersion,
9
+ diff: u.diff,
10
+ source: u.source,
11
+ ...u.deprecated ? { deprecated: u.deprecated } : {},
12
+ ...u.publishedAt ? { publishedAt: u.publishedAt } : {},
13
+ ...u.currentVersionTime ? { currentVersionTime: u.currentVersionTime } : {}
14
+ }))
15
+ };
16
+ }
17
+ function outputJsonEnvelope(packages, options, executionState, errors = []) {
18
+ const allUpdates = packages.flatMap((p) => p.updates);
19
+ const count = (diff) => allUpdates.filter((u) => u.diff === diff).length;
20
+ const output = {
21
+ packages,
22
+ errors,
23
+ summary: {
24
+ total: allUpdates.length,
25
+ major: count("major"),
26
+ minor: count("minor"),
27
+ patch: count("patch"),
28
+ packages: packages.length,
29
+ scannedPackages: executionState.scannedPackages,
30
+ packagesWithUpdates: executionState.packagesWithUpdates,
31
+ plannedUpdates: executionState.plannedUpdates,
32
+ appliedUpdates: executionState.appliedUpdates,
33
+ revertedUpdates: executionState.revertedUpdates
34
+ },
35
+ meta: {
36
+ schemaVersion: 1,
37
+ cwd: options.cwd,
38
+ mode: options.mode,
39
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
40
+ noPackagesFound: executionState.noPackagesFound,
41
+ didWrite: executionState.didWrite
42
+ }
43
+ };
44
+ console.log(JSON.stringify(output, null, 2));
45
+ }
46
+ function outputJsonError(error, options) {
47
+ const code = error instanceof Error && "code" in error ? error.code : "ERR_UNKNOWN";
48
+ const message = error instanceof Error ? error.message : String(error);
49
+ const output = {
50
+ error: {
51
+ code,
52
+ message,
53
+ retryable: RETRYABLE_CODES.has(code)
54
+ },
55
+ meta: {
56
+ schemaVersion: 1,
57
+ cwd: options.cwd,
58
+ mode: options.mode,
59
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
60
+ }
61
+ };
62
+ console.log(JSON.stringify(output, null, 2));
63
+ }
64
+
65
+ export { buildJsonPackage, outputJsonEnvelope, outputJsonError };
@@ -1,12 +1,14 @@
1
- const VALID_MODES = /* @__PURE__ */ new Set([
2
- "default",
3
- "major",
4
- "minor",
5
- "patch",
6
- "latest",
7
- "newest",
8
- "next"
9
- ]);
1
+ import { C as ConfigError } from '../shared/depfresh.FmznAfq4.mjs';
2
+ import { a as VALID_SORT_OPTIONS, V as VALID_LOG_LEVELS, b as VALID_OUTPUTS, c as VALID_MODES } from '../shared/depfresh.CFLB6fqi.mjs';
3
+
4
+ function validateEnum(value, flagName, validValues) {
5
+ if (typeof value !== "string" || !validValues.includes(value)) {
6
+ throw new ConfigError(
7
+ `Invalid value for ${flagName}: "${String(value)}". Expected one of: ${validValues.join(", ")}.`
8
+ );
9
+ }
10
+ return value;
11
+ }
10
12
  async function normalizeArgs(args) {
11
13
  const { resolveConfig } = await import('./config.mjs').then(function (n) { return n.c; });
12
14
  const depFields = {};
@@ -20,7 +22,11 @@ async function normalizeArgs(args) {
20
22
  depFields.peerDependencies = false;
21
23
  depFields.optionalDependencies = false;
22
24
  }
23
- const mode = args.mode_arg && VALID_MODES.has(args.mode_arg) ? args.mode_arg : args.mode;
25
+ const modeValue = args.mode_arg ?? args.mode;
26
+ const mode = validateEnum(modeValue, "--mode", VALID_MODES);
27
+ const output = validateEnum(args.output, "--output", VALID_OUTPUTS);
28
+ const sort = validateEnum(args.sort, "--sort", VALID_SORT_OPTIONS);
29
+ const loglevel = validateEnum(args.loglevel, "--loglevel", VALID_LOG_LEVELS);
24
30
  const include = typeof args.include === "string" ? args.include.split(",").map((s) => s.trim()) : void 0;
25
31
  const exclude = typeof args.exclude === "string" ? args.exclude.split(",").map((s) => s.trim()) : void 0;
26
32
  return resolveConfig({
@@ -35,13 +41,13 @@ async function normalizeArgs(args) {
35
41
  global: args.global,
36
42
  peer: args.peer,
37
43
  includeLocked: args["include-locked"],
38
- output: args.output,
44
+ output,
39
45
  concurrency: Number.parseInt(args.concurrency, 10),
40
- loglevel: args.loglevel,
46
+ loglevel,
41
47
  depFields,
42
48
  all: args.all,
43
49
  group: args.group,
44
- sort: args.sort,
50
+ sort,
45
51
  timediff: args.timediff,
46
52
  cooldown: Number.parseInt(args.cooldown, 10),
47
53
  nodecompat: args.nodecompat,