depfresh 0.11.0 → 1.0.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 +60 -313
- package/dist/chunks/index.mjs +2 -2
- package/dist/chunks/index2.mjs +1 -1
- package/dist/chunks/index3.mjs +1 -1
- package/dist/chunks/interactive.mjs +1 -1
- package/dist/cli.mjs +29 -5
- package/dist/index.mjs +1 -1
- package/dist/shared/{depfresh.C-me_t4a.mjs → depfresh.CTatBHRg.mjs} +155 -5
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -5,129 +5,76 @@
|
|
|
5
5
|
[](https://www.typescriptlang.org/)
|
|
6
6
|
[](https://nodejs.org/)
|
|
7
7
|
|
|
8
|
-
Keep your
|
|
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.
|
|
11
|
-
|
|
12
|
-
## Features
|
|
13
|
-
|
|
14
|
-
- **Zero-config dependency checking** -- run `depfresh` and it tells you what's outdated. No YAML. No PhD.
|
|
15
|
-
- **Monorepo & workspace support** -- pnpm, bun, yarn, npm. Auto-detected. Catalog deps included.
|
|
16
|
-
- **7 range modes** -- `default`, `major`, `minor`, `patch`, `latest`, `newest`, `next`. One flag, total control.
|
|
17
|
-
- **Interactive cherry-picking** -- grouped multiselect with colour-coded severity. Pick what you want, ignore the rest.
|
|
18
|
-
- **Per-package modes** -- `packageMode` lets you set exact, glob, or regex patterns per dependency.
|
|
19
|
-
- **Write safely** -- `--write` updates files. `--verify-command` tests each dep individually and reverts failures.
|
|
20
|
-
- **Post-write hooks** -- `--execute`, `--install`, `--update`. Chain commands after writing.
|
|
21
|
-
- **Global packages** -- `--global` checks one detected manager, `--global-all` scans npm + pnpm + bun with deduped package names.
|
|
22
|
-
- **Private registries** -- full `.npmrc` support. Scoped registries, auth tokens, env vars. Fixed from day one.
|
|
23
|
-
- **JSON output** -- structured envelope for scripts and AI agents. No ANSI noise.
|
|
24
|
-
- **CI mode** -- `--fail-on-outdated` exits with code 1. Plug it into your pipeline.
|
|
25
|
-
- **SQLite cache** -- WAL mode, 30min TTL, auto-fallback to memory. Fast repeat runs.
|
|
26
|
-
- **Provenance tracking** -- warnings for unsigned or downgraded attestations.
|
|
27
|
-
- **Node engine compat** -- flags updates that don't match your Node version.
|
|
28
|
-
- **Cooldown filter** -- skip versions published less than N days ago. Let the early adopters find the bugs.
|
|
29
|
-
- **Sorting** -- 6 strategies: by diff severity, publish time, or name.
|
|
30
|
-
- **CRLF preservation** -- Windows line endings survive the write. You're welcome.
|
|
31
|
-
- **Nested workspace detection** -- auto-skips monorepos inside monorepos.
|
|
32
|
-
- **Programmatic API** -- lifecycle callbacks + addon system for custom workflows.
|
|
33
|
-
|
|
34
|
-
## Why
|
|
35
|
-
|
|
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
|
-
|
|
38
|
-
depfresh checks every package manifest (`package.json`, `package.yaml`) 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
|
-
|
|
40
|
-
If both `package.yaml` and `package.json` exist in the same directory, depfresh uses `package.yaml` and skips the sibling `package.json` to avoid duplicate package entries.
|
|
8
|
+
Keep your dependencies fresh. Zero config, fast, monorepo-ready. Your AI agent already knows how to use this.
|
|
41
9
|
|
|
42
10
|
## Install
|
|
43
11
|
|
|
44
12
|
```bash
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Or don't install globally. I'm not your parent.
|
|
49
|
-
|
|
50
|
-
```bash
|
|
13
|
+
# One-off run (no install)
|
|
51
14
|
npx depfresh
|
|
52
15
|
pnpm dlx depfresh
|
|
53
16
|
bunx depfresh
|
|
17
|
+
|
|
18
|
+
# Global install
|
|
19
|
+
npm install -g depfresh
|
|
20
|
+
|
|
21
|
+
# Local devDependency (recommended for team + CI)
|
|
22
|
+
pnpm add -D depfresh
|
|
54
23
|
```
|
|
55
24
|
|
|
56
|
-
|
|
25
|
+
| If you want... | Use | Example |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| Run once in any repo | One-off | `npx depfresh` |
|
|
28
|
+
| Always available on your machine | Global | `pnpm add -g depfresh` |
|
|
29
|
+
| Pinned for team/CI consistency | Local devDep | `npm install -D depfresh` |
|
|
57
30
|
|
|
58
|
-
##
|
|
31
|
+
## Quick Start
|
|
59
32
|
|
|
60
33
|
```bash
|
|
61
|
-
#
|
|
34
|
+
# What's outdated?
|
|
62
35
|
depfresh
|
|
63
36
|
|
|
64
|
-
#
|
|
65
|
-
depfresh help
|
|
66
|
-
|
|
67
|
-
# Same thing but for machines and AI agents who can't read tables
|
|
68
|
-
depfresh --help-json
|
|
69
|
-
|
|
70
|
-
# Actually update them
|
|
37
|
+
# Update everything
|
|
71
38
|
depfresh --write
|
|
72
39
|
|
|
73
|
-
# Interactive
|
|
74
|
-
depfresh
|
|
75
|
-
|
|
76
|
-
# Only minor/patch updates (living cautiously)
|
|
77
|
-
depfresh minor -w
|
|
40
|
+
# Interactive -- pick what to update
|
|
41
|
+
depfresh -I
|
|
78
42
|
|
|
79
43
|
# JSON output for scripts and AI agents
|
|
80
44
|
depfresh --output json
|
|
81
45
|
|
|
82
|
-
#
|
|
83
|
-
depfresh
|
|
84
|
-
|
|
85
|
-
# Verify each dep individually, revert failures
|
|
86
|
-
depfresh -w --verify-command "pnpm test"
|
|
46
|
+
# Only minor/patch (living cautiously)
|
|
47
|
+
depfresh minor -w
|
|
87
48
|
|
|
88
49
|
# CI: fail if anything is outdated
|
|
89
50
|
depfresh --fail-on-outdated
|
|
51
|
+
```
|
|
90
52
|
|
|
91
|
-
|
|
92
|
-
depfresh --ignore-paths "apps/legacy/**,examples/**"
|
|
53
|
+
## Features
|
|
93
54
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
55
|
+
- **Zero config** -- run `depfresh` and it works. No YAML. No PhD.
|
|
56
|
+
- **Monorepo & workspace support** -- pnpm, bun, yarn, npm. Auto-detected. Catalogs included.
|
|
57
|
+
- **7 range modes** -- `default`, `major`, `minor`, `patch`, `latest`, `newest`, `next`
|
|
58
|
+
- **Interactive cherry-picking** -- grouped multiselect with colour-coded severity
|
|
59
|
+
- **Per-package modes** -- `packageMode` with exact, glob, or regex patterns per dependency
|
|
60
|
+
- **Write safely** -- `--write` updates files. `--verify-command` tests each dep and reverts failures.
|
|
61
|
+
- **Post-write hooks** -- `--execute`, `--install`, `--update`. Chain commands after writing.
|
|
62
|
+
- **Global packages** -- `--global` for one manager, `--global-all` scans npm + pnpm + bun (deduped)
|
|
63
|
+
- **Private registries** -- full `.npmrc` support. Scoped registries, auth tokens, env vars.
|
|
64
|
+
- **GitHub dependencies** -- `github:owner/repo#tag` with protocol-preserving writes
|
|
65
|
+
- **JSON output** -- structured envelope for scripts and AI agents. No ANSI noise.
|
|
66
|
+
- **CI mode** -- `--fail-on-outdated` exits with code 1. Plug it into your pipeline.
|
|
67
|
+
- **SQLite cache** -- WAL mode, 30min TTL, auto-fallback to memory
|
|
68
|
+
- **Provenance tracking** -- warnings for unsigned or downgraded attestations
|
|
69
|
+
- **Node engine compat** -- flags updates that don't match your Node version
|
|
70
|
+
- **Cooldown filter** -- skip versions published less than N days ago
|
|
71
|
+
- **Programmatic API** -- lifecycle callbacks + addon system for custom workflows
|
|
97
72
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
73
|
+
Full CLI reference: **[docs/cli/](docs/cli/)**
|
|
74
|
+
|
|
75
|
+
## Configuration
|
|
101
76
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
The top flags to get you started. Full reference with all 27+ flags: **[docs/cli/](docs/cli/)**
|
|
105
|
-
|
|
106
|
-
| Flag | Alias | Default | Description |
|
|
107
|
-
|------|-------|---------|-------------|
|
|
108
|
-
| `--recursive` | `-r` | `true` | Recursively search for package manifests (`package.json`, `package.yaml`) |
|
|
109
|
-
| `--write` | `-w` | `false` | Write updated versions to package files |
|
|
110
|
-
| `--interactive` | `-I` | `false` | Select which deps to update |
|
|
111
|
-
| `--mode` | `-m` | `default` | Range mode: `default` `major` `minor` `patch` `latest` `newest` `next` |
|
|
112
|
-
| `--include` | `-n` | -- | Only include packages matching regex (comma-separated) |
|
|
113
|
-
| `--exclude` | `-x` | -- | Exclude packages matching regex (comma-separated) |
|
|
114
|
-
| `--ignore-paths` | -- | -- | Extra ignore globs (comma-separated), merged with default ignored paths |
|
|
115
|
-
| `--force` | `-f` | `false` | Force update even if version is satisfied (does not bypass cache) |
|
|
116
|
-
| `--refresh-cache` | -- | `false` | Bypass cache reads and fetch fresh metadata for this run |
|
|
117
|
-
| `--no-cache` | -- | `false` | Alias for `--refresh-cache` |
|
|
118
|
-
| `--global` | `-g` | `false` | Check global packages for one detected package manager |
|
|
119
|
-
| `--global-all` | -- | `false` | Check global packages across npm, pnpm, and bun with deduped package names |
|
|
120
|
-
| `--output` | `-o` | `table` | Output format: `table` `json` |
|
|
121
|
-
| `--execute` | `-e` | -- | Run command after writing (e.g. `"pnpm test"`) |
|
|
122
|
-
| `--verify-command` | `-V` | -- | Run command per dep, revert on failure |
|
|
123
|
-
| `--install` | `-i` | `false` | Run package manager install after writing |
|
|
124
|
-
| `--fail-on-outdated` | -- | `false` | Exit code 1 when outdated deps found (CI mode) |
|
|
125
|
-
| `--cooldown` | -- | `0` | Skip versions published less than N days ago |
|
|
126
|
-
| `--sort` | `-s` | `diff-asc` | Sort: `diff-asc` `diff-desc` `time-asc` `time-desc` `name-asc` `name-desc` |
|
|
127
|
-
|
|
128
|
-
## Config File
|
|
129
|
-
|
|
130
|
-
Zero config works. But if you want it, create `depfresh.config.ts` (or `.depfreshrc`, or add a `depfresh` key to `package.json`):
|
|
77
|
+
Zero config works. But if you want it:
|
|
131
78
|
|
|
132
79
|
```typescript
|
|
133
80
|
import { defineConfig } from 'depfresh'
|
|
@@ -142,237 +89,37 @@ export default defineConfig({
|
|
|
142
89
|
})
|
|
143
90
|
```
|
|
144
91
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
import { check, resolveConfig, type depfreshAddon } from 'depfresh'
|
|
149
|
-
|
|
150
|
-
const addon: depfreshAddon = {
|
|
151
|
-
name: 'audit-log',
|
|
152
|
-
afterPackageWrite(_ctx, pkg, changes) {
|
|
153
|
-
console.log(`updated ${pkg.name}: ${changes.length} changes`)
|
|
154
|
-
},
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const options = await resolveConfig({ write: true, addons: [addon] })
|
|
158
|
-
await check(options)
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Full options reference: **[docs/configuration/](docs/configuration/)**
|
|
162
|
-
|
|
163
|
-
## JSON Output
|
|
164
|
-
|
|
165
|
-
`--output json` emits a single structured envelope. No log noise. No ANSI codes. Just clean JSON that machines can parse without having an existential crisis.
|
|
166
|
-
|
|
167
|
-
```json
|
|
168
|
-
{
|
|
169
|
-
"packages": [
|
|
170
|
-
{
|
|
171
|
-
"name": "my-app",
|
|
172
|
-
"updates": [
|
|
173
|
-
{
|
|
174
|
-
"name": "react",
|
|
175
|
-
"current": "^18.2.0",
|
|
176
|
-
"target": "^19.1.0",
|
|
177
|
-
"diff": "major",
|
|
178
|
-
"source": "dependencies"
|
|
179
|
-
}
|
|
180
|
-
]
|
|
181
|
-
}
|
|
182
|
-
],
|
|
183
|
-
"errors": [
|
|
184
|
-
{
|
|
185
|
-
"name": "some-private-pkg",
|
|
186
|
-
"source": "dependencies",
|
|
187
|
-
"currentVersion": "^1.0.0",
|
|
188
|
-
"message": "Failed to resolve from registry"
|
|
189
|
-
}
|
|
190
|
-
],
|
|
191
|
-
"summary": {
|
|
192
|
-
"total": 12,
|
|
193
|
-
"major": 1,
|
|
194
|
-
"minor": 7,
|
|
195
|
-
"patch": 4,
|
|
196
|
-
"packages": 3,
|
|
197
|
-
"scannedPackages": 3,
|
|
198
|
-
"packagesWithUpdates": 3,
|
|
199
|
-
"plannedUpdates": 0,
|
|
200
|
-
"appliedUpdates": 0,
|
|
201
|
-
"revertedUpdates": 0
|
|
202
|
-
},
|
|
203
|
-
"meta": {
|
|
204
|
-
"schemaVersion": 1,
|
|
205
|
-
"cwd": "/path/to/project",
|
|
206
|
-
"mode": "default",
|
|
207
|
-
"timestamp": "2026-02-22T12:00:00.000Z",
|
|
208
|
-
"noPackagesFound": false,
|
|
209
|
-
"didWrite": false
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
Full schema and field reference: **[docs/output-formats/](docs/output-formats/)**
|
|
215
|
-
|
|
216
|
-
## AI Agent Usage
|
|
217
|
-
|
|
218
|
-
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.
|
|
219
|
-
|
|
220
|
-
**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.
|
|
221
|
-
|
|
222
|
-
**`--help-json`** returns a full machine-readable contract: version, flags, enums, exit codes, plus:
|
|
223
|
-
- `workflows` -- 4 copy-paste agent recipes (`checkOnly`, `safeUpdate`, `fullUpdate`, `selective`)
|
|
224
|
-
- `flagRelationships` -- which flags require or conflict with others
|
|
225
|
-
- `configFiles` -- every supported config file pattern
|
|
226
|
-
- `jsonOutputSchema` -- field descriptions of the JSON envelope
|
|
227
|
-
|
|
228
|
-
```bash
|
|
229
|
-
# First run -- just see what happens (agents get the stderr hint)
|
|
230
|
-
depfresh
|
|
231
|
-
|
|
232
|
-
# Discover the full CLI contract
|
|
233
|
-
depfresh --help-json
|
|
234
|
-
|
|
235
|
-
# Check for updates, get structured output
|
|
236
|
-
depfresh --output json
|
|
237
|
-
|
|
238
|
-
# Apply only safe updates
|
|
239
|
-
depfresh --write --mode minor --output json
|
|
240
|
-
|
|
241
|
-
# Selective update
|
|
242
|
-
depfresh --write --include "typescript,vitest" --output json
|
|
243
|
-
|
|
244
|
-
# Full send
|
|
245
|
-
depfresh --write --mode latest --output json
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
**Exit codes are semantic:**
|
|
249
|
-
- `0` -- all deps up to date (or updates were written)
|
|
250
|
-
- `1` -- updates available (with `--fail-on-outdated`)
|
|
251
|
-
- `2` -- error (structured JSON error envelope when `--output json` is active)
|
|
252
|
-
|
|
253
|
-
**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.
|
|
254
|
-
|
|
255
|
-
**TTY detection** -- when stdout isn't a terminal, depfresh automatically suppresses spinners and interactive prompts. `NO_COLOR` is respected.
|
|
256
|
-
|
|
257
|
-
## Programmatic API
|
|
258
|
-
|
|
259
|
-
```typescript
|
|
260
|
-
import { check, resolveConfig } from 'depfresh'
|
|
261
|
-
|
|
262
|
-
const options = await resolveConfig({
|
|
263
|
-
cwd: process.cwd(),
|
|
264
|
-
mode: 'minor',
|
|
265
|
-
write: true,
|
|
266
|
-
onDependencyResolved: (pkg, dep) => {
|
|
267
|
-
if (dep.diff === 'major') {
|
|
268
|
-
console.log(`Major update: ${dep.name} ${dep.currentVersion} -> ${dep.targetVersion}`)
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
beforePackageWrite: (pkg) => {
|
|
272
|
-
return true // return false to skip
|
|
273
|
-
},
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
const exitCode = await check(options)
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
Programmatic API with lifecycle callbacks, addon plugins, and full typed exports. Full reference: **[docs/api/](docs/api/)**
|
|
92
|
+
Supports `depfresh.config.ts`, `.depfreshrc`, or a `depfresh` key in `package.json`. Full reference: **[docs/configuration/](docs/configuration/)**
|
|
280
93
|
|
|
281
94
|
## Monorepo Support
|
|
282
95
|
|
|
283
|
-
depfresh auto-detects
|
|
96
|
+
depfresh auto-detects pnpm, bun, yarn, and npm workspaces -- no config needed. Workspace catalogs (`pnpm-workspace.yaml`, bun catalogs, yarn `.yarnrc.yml` catalogs) are resolved and updated in-place alongside your package manifests.
|
|
284
97
|
|
|
285
|
-
|
|
286
|
-
|----------------|------------|----------|
|
|
287
|
-
| pnpm | `pnpm-workspace.yaml` | `catalog:` protocol |
|
|
288
|
-
| Bun | `workspaces` in `package.json` or `package.yaml` | `workspaces.catalog` |
|
|
289
|
-
| Yarn | `workspaces` in `package.json` or `package.yaml` | `.yarnrc.yml` catalogs |
|
|
290
|
-
| npm | `workspaces` in `package.json` or `package.yaml` | -- |
|
|
98
|
+
Details: **[docs/configuration/workspaces.md](docs/configuration/workspaces.md)**
|
|
291
99
|
|
|
292
|
-
|
|
100
|
+
## AI Agent Friendly
|
|
293
101
|
|
|
294
|
-
|
|
102
|
+
depfresh was built for humans and machines. `--output json` emits a structured envelope. `--help-json` returns the full CLI contract (flags, enums, exit codes, agent workflows). Exit codes are semantic: `0` = up to date, `1` = updates available, `2` = error. Non-TTY environments automatically suppress spinners and interactive prompts.
|
|
295
103
|
|
|
296
|
-
|
|
104
|
+
Details: **[docs/agents/README.md](docs/agents/README.md)**
|
|
297
105
|
|
|
298
|
-
|
|
299
|
-
# .npmrc
|
|
300
|
-
@mycompany:registry=https://npm.mycompany.com/
|
|
301
|
-
//npm.mycompany.com/:_authToken=${NPM_TOKEN}
|
|
302
|
-
```
|
|
106
|
+
## Coming from taze?
|
|
303
107
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
## depfresh vs taze
|
|
307
|
-
|
|
308
|
-
Verified against taze v19.9.2 (commit `31c6fe8`, 2026-01-20). Not marketing. Real code inspection, runtime test runs, CLI smoke checks on actual repos.
|
|
309
|
-
|
|
310
|
-
### Feature parity (both have it)
|
|
311
|
-
|
|
312
|
-
| Feature | taze | depfresh | Notes |
|
|
313
|
-
|---------|------|----------|-------|
|
|
314
|
-
| 7 range modes | yes | yes | |
|
|
315
|
-
| Include/exclude filters | yes | yes | depfresh adds glob patterns alongside regex |
|
|
316
|
-
| Interactive TUI | yes | yes | Both have vim keys + per-version selection |
|
|
317
|
-
| `--cwd` | yes | yes | |
|
|
318
|
-
| `--fail-on-outdated` | yes | yes | |
|
|
319
|
-
| `package.yaml` support | yes | yes | |
|
|
320
|
-
| Addon/plugin API | yes | yes | |
|
|
321
|
-
| pnpm catalogs | yes | yes | |
|
|
322
|
-
| Yarn catalogs | yes | yes | |
|
|
323
|
-
| CRLF preservation | yes | yes | |
|
|
324
|
-
| CJK width handling | yes | yes | |
|
|
325
|
-
|
|
326
|
-
### Where depfresh is ahead
|
|
327
|
-
|
|
328
|
-
| Feature | taze | depfresh |
|
|
329
|
-
|---------|------|----------|
|
|
330
|
-
| JSON output envelope | no ([#201](https://github.com/antfu-collective/taze/issues/201) open) | Structured envelope with schema version |
|
|
331
|
-
| Machine-readable CLI contract | no | `--help-json` with workflows, flag relationships, schema |
|
|
332
|
-
| `--deps-only` / `--dev-only` | no ([#101](https://github.com/antfu-collective/taze/issues/101) open) | yes |
|
|
333
|
-
| `packageMode` precedence | buggy ([#91](https://github.com/antfu-collective/taze/issues/91) open) | Deterministic |
|
|
334
|
-
| Global package breadth | npm + pnpm | npm + pnpm + bun (`--global-all`) |
|
|
335
|
-
| Bun catalog writes | Bug history, data loss risk | Single-writer architecture, tested |
|
|
336
|
-
| `.npmrc` / private registries | Ignored for years | Full support from day one |
|
|
337
|
-
| `.npmrc` transport (proxy/TLS/CA) | Parsed, not applied | Applied via `undici` transport adapter |
|
|
338
|
-
| Network retry | None | Exponential backoff, non-transient errors fail fast |
|
|
339
|
-
| Cache | JSON file (race conditions) | SQLite WAL mode, memory fallback |
|
|
340
|
-
| Verify + rollback | no | `--verify-command` tests each dep, reverts failures |
|
|
341
|
-
| Typed error hierarchy | Limited | Structured subclasses with `.code` and `.cause` |
|
|
342
|
-
| Structured JSON errors | no | JSON error envelope with `error.code`, `error.retryable` |
|
|
343
|
-
| Explicit cache bypass | no | `--refresh-cache` / `--no-cache` |
|
|
344
|
-
|
|
345
|
-
### Where taze is ahead
|
|
346
|
-
|
|
347
|
-
| Area | Why |
|
|
348
|
-
|------|-----|
|
|
349
|
-
| Ecosystem adoption | 4,061 stars, years of trust, larger user base |
|
|
350
|
-
| npm config edge cases | `@npmcli/config` may cover obscure auth patterns we haven't hit yet |
|
|
351
|
-
|
|
352
|
-
### Numbers
|
|
353
|
-
|
|
354
|
-
| Metric | taze v19.9.2 | depfresh v0.11.0 |
|
|
355
|
-
|--------|-------------:|------------------:|
|
|
356
|
-
| Test files | 13 | 77 |
|
|
357
|
-
| Passing tests | 55 | 598 |
|
|
358
|
-
| CLI flags | 24 | 36 |
|
|
108
|
+
depfresh is a 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. depfresh rewrites everything from scratch, fixes long-standing bugs (private registries, bun catalogs, packageMode precedence), and adds structured JSON output, verify-and-rollback, SQLite caching, and proper AI agent support.
|
|
359
109
|
|
|
360
|
-
|
|
110
|
+
Migration guide: **[docs/compare/from-taze.md](docs/compare/from-taze.md)** | Full comparison: **[docs/compare/](docs/compare/)**
|
|
361
111
|
|
|
362
|
-
|
|
112
|
+
## Documentation
|
|
363
113
|
|
|
364
|
-
- **[CLI Reference](docs/cli/)** --
|
|
365
|
-
- **[Configuration](docs/configuration/)** -- config files,
|
|
366
|
-
- **[Programmatic API](docs/api/)** --
|
|
367
|
-
- **[Output Formats](docs/output-formats/)** -- table, JSON, exit codes
|
|
368
|
-
- **[Agent Workflows](docs/agents/README.md)** --
|
|
369
|
-
- **[Integrations](docs/integrations/README.md)** -- GitHub Actions and
|
|
114
|
+
- **[CLI Reference](docs/cli/)** -- flags, modes, sorting, filtering, hooks, interactive, CI
|
|
115
|
+
- **[Configuration](docs/configuration/)** -- config files, options, packageMode, private registries, cache
|
|
116
|
+
- **[Programmatic API](docs/api/)** -- functions, lifecycle callbacks, addon plugins, types
|
|
117
|
+
- **[Output Formats](docs/output-formats/)** -- table, JSON, exit codes
|
|
118
|
+
- **[Agent Workflows](docs/agents/README.md)** -- quickstarts for AI coding assistants
|
|
119
|
+
- **[Integrations](docs/integrations/README.md)** -- GitHub Actions and MCP wrapper guidance
|
|
120
|
+
- **[Compare](docs/compare/)** -- coverage matrix, migration guide, solved issues
|
|
370
121
|
- **[Troubleshooting](docs/troubleshooting.md)** -- common issues, workspace gotchas, known limitations
|
|
371
122
|
|
|
372
|
-
## Requirements
|
|
373
|
-
|
|
374
|
-
- Node.js >= 24
|
|
375
|
-
|
|
376
123
|
## Standing on the Shoulders of People Who Actually Did the Work
|
|
377
124
|
|
|
378
125
|
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.
|
package/dist/chunks/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as check } from '../shared/depfresh.
|
|
2
|
-
export { d as detectPackageManager } from '../shared/depfresh.
|
|
1
|
+
import { c as check } from '../shared/depfresh.CTatBHRg.mjs';
|
|
2
|
+
export { d as detectPackageManager } from '../shared/depfresh.CTatBHRg.mjs';
|
|
3
3
|
import 'ansis';
|
|
4
4
|
import '../shared/depfresh.Dxgqypc6.mjs';
|
|
5
5
|
import 'node:fs';
|
package/dist/chunks/index2.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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.
|
|
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.CTatBHRg.mjs';
|
|
4
4
|
import c from 'ansis';
|
|
5
5
|
import '../shared/depfresh.Dxgqypc6.mjs';
|
|
6
6
|
import 'node:fs';
|
package/dist/chunks/index3.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import './config.mjs';
|
|
|
2
2
|
import '../shared/depfresh.CHHNqHXD.mjs';
|
|
3
3
|
import { execSync } from 'node:child_process';
|
|
4
4
|
import { c as createLogger } from '../shared/depfresh.Dxgqypc6.mjs';
|
|
5
|
-
import '../shared/depfresh.
|
|
5
|
+
import '../shared/depfresh.CTatBHRg.mjs';
|
|
6
6
|
|
|
7
7
|
function addonVSCode(pkg, changes) {
|
|
8
8
|
const vscodeChange = changes.find((c) => c.name === "@types/vscode");
|
|
@@ -1,6 +1,6 @@
|
|
|
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.
|
|
3
|
+
import { a as arrow, b as colorizeVersionDiff, e as colorDiff } from '../shared/depfresh.CTatBHRg.mjs';
|
|
4
4
|
import '../shared/depfresh.Dxgqypc6.mjs';
|
|
5
5
|
import 'node:fs';
|
|
6
6
|
import 'node:os';
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { defineCommand, runMain } from 'citty';
|
|
2
|
+
import { renderUsage, defineCommand, runMain } from 'citty';
|
|
3
3
|
|
|
4
|
-
const version = "0.
|
|
4
|
+
const version = "1.0.0";
|
|
5
5
|
|
|
6
6
|
const migrationParityArgs = {
|
|
7
7
|
"ignore-paths": {
|
|
@@ -58,12 +58,12 @@ const args = {
|
|
|
58
58
|
include: {
|
|
59
59
|
type: "string",
|
|
60
60
|
alias: "n",
|
|
61
|
-
description: "Only include packages matching
|
|
61
|
+
description: "Only include packages matching these regex/glob patterns (comma-separated)"
|
|
62
62
|
},
|
|
63
63
|
exclude: {
|
|
64
64
|
type: "string",
|
|
65
65
|
alias: "x",
|
|
66
|
-
description: "Exclude packages matching
|
|
66
|
+
description: "Exclude packages matching these regex/glob patterns (comma-separated)"
|
|
67
67
|
},
|
|
68
68
|
force: {
|
|
69
69
|
type: "boolean",
|
|
@@ -219,6 +219,24 @@ function normalizeCliRawArgs(rawArgs) {
|
|
|
219
219
|
return ["--help", ...rawArgs.slice(1)];
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
const DOCUMENTATION_URL = "https://github.com/vcode-sh/depfresh/tree/main/docs";
|
|
223
|
+
const REPOSITORY_URL = "https://github.com/vcode-sh/depfresh";
|
|
224
|
+
function withHelpLinks(usage) {
|
|
225
|
+
return `${usage}
|
|
226
|
+
|
|
227
|
+
Docs: ${DOCUMENTATION_URL}
|
|
228
|
+
GitHub: ${REPOSITORY_URL}
|
|
229
|
+
`;
|
|
230
|
+
}
|
|
231
|
+
async function showUsageWithLinks(cmd, parent) {
|
|
232
|
+
try {
|
|
233
|
+
const usage = await renderUsage(cmd, parent);
|
|
234
|
+
console.log(withHelpLinks(usage));
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.error(error);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
222
240
|
const main = defineCommand({
|
|
223
241
|
meta: {
|
|
224
242
|
name: "depfresh",
|
|
@@ -228,6 +246,11 @@ const main = defineCommand({
|
|
|
228
246
|
args,
|
|
229
247
|
async run({ args: args2 }) {
|
|
230
248
|
try {
|
|
249
|
+
if (args2.mode_arg === "help") {
|
|
250
|
+
const { showUsage } = await import('citty');
|
|
251
|
+
await showUsage(main);
|
|
252
|
+
process.exit(0);
|
|
253
|
+
}
|
|
231
254
|
if (args2["help-json"]) {
|
|
232
255
|
const { outputCliCapabilities } = await import('./chunks/capabilities.mjs');
|
|
233
256
|
outputCliCapabilities();
|
|
@@ -261,7 +284,8 @@ const main = defineCommand({
|
|
|
261
284
|
}
|
|
262
285
|
});
|
|
263
286
|
runMain(main, {
|
|
264
|
-
rawArgs: normalizeCliRawArgs(process.argv.slice(2))
|
|
287
|
+
rawArgs: normalizeCliRawArgs(process.argv.slice(2)),
|
|
288
|
+
showUsage: showUsageWithLinks
|
|
265
289
|
});
|
|
266
290
|
|
|
267
291
|
export { args as a, version as v };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { D as DEFAULT_OPTIONS, r as resolveConfig } from './chunks/config.mjs';
|
|
2
2
|
export { A as AddonError, a as CacheError, C as ConfigError, R as RegistryError, b as ResolveError, W as WriteError, d as depfreshError } from './shared/depfresh.CHHNqHXD.mjs';
|
|
3
3
|
export { a as addonVSCode, c as createVSCodeAddon, d as defineConfig, l as loadGlobalPackages, b as loadGlobalPackagesAll, w as writeGlobalPackage } from './chunks/index3.mjs';
|
|
4
|
-
export { c as check, l as loadPackages, p as parseDependencies, r as resolvePackage, w as writePackage } from './shared/depfresh.
|
|
4
|
+
export { c as check, l as loadPackages, p as parseDependencies, r as resolvePackage, w as writePackage } from './shared/depfresh.CTatBHRg.mjs';
|
|
5
5
|
import 'node:fs/promises';
|
|
6
6
|
import 'node:url';
|
|
7
7
|
import 'defu';
|
|
@@ -390,14 +390,51 @@ function resolveTargetVersion(currentVersion, versions, distTags, mode) {
|
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
+
function parseGithubSpec(version) {
|
|
394
|
+
const githubMatch = version.match(/^github:([^#]+)#(.+)$/);
|
|
395
|
+
if (!githubMatch) {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
const repository = githubMatch[1]?.trim();
|
|
399
|
+
const ref = githubMatch[2]?.trim();
|
|
400
|
+
if (!(repository && ref)) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
const withoutTagPrefix = ref.startsWith("refs/tags/") ? ref.slice("refs/tags/".length) : ref;
|
|
404
|
+
const normalized = withoutTagPrefix.startsWith("v") ? withoutTagPrefix.slice(1) : withoutTagPrefix;
|
|
405
|
+
const valid = semver.valid(normalized);
|
|
406
|
+
if (!valid) {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
aliasName: `github:${repository}`,
|
|
411
|
+
currentVersion: valid
|
|
412
|
+
};
|
|
413
|
+
}
|
|
393
414
|
function parseProtocol(version) {
|
|
394
415
|
const npmMatch = version.match(/^npm:(.+)@(.+)$/);
|
|
395
416
|
if (npmMatch) {
|
|
396
|
-
return {
|
|
417
|
+
return {
|
|
418
|
+
protocol: "npm",
|
|
419
|
+
aliasName: npmMatch[1],
|
|
420
|
+
currentVersion: npmMatch[2]
|
|
421
|
+
};
|
|
397
422
|
}
|
|
398
423
|
const jsrMatch = version.match(/^jsr:(.+)@(.+)$/);
|
|
399
424
|
if (jsrMatch) {
|
|
400
|
-
return {
|
|
425
|
+
return {
|
|
426
|
+
protocol: "jsr",
|
|
427
|
+
aliasName: `jsr:${jsrMatch[1]}`,
|
|
428
|
+
currentVersion: jsrMatch[2]
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
const githubSpec = parseGithubSpec(version);
|
|
432
|
+
if (githubSpec) {
|
|
433
|
+
return {
|
|
434
|
+
protocol: "github",
|
|
435
|
+
aliasName: githubSpec.aliasName,
|
|
436
|
+
currentVersion: githubSpec.currentVersion
|
|
437
|
+
};
|
|
401
438
|
}
|
|
402
439
|
return { currentVersion: version };
|
|
403
440
|
}
|
|
@@ -434,6 +471,7 @@ function flattenOverrides(obj, source, deps, options, parents, includePatterns,
|
|
|
434
471
|
deps.push({
|
|
435
472
|
name,
|
|
436
473
|
currentVersion: protocol.currentVersion,
|
|
474
|
+
aliasName: protocol.aliasName,
|
|
437
475
|
source,
|
|
438
476
|
update: !isLocked(protocol.currentVersion) || options.includeLocked,
|
|
439
477
|
parents: [...parents, key],
|
|
@@ -495,7 +533,10 @@ function isDepFieldEnabled(field, options) {
|
|
|
495
533
|
function shouldSkipDependency(name, version, options, includePatterns = [], excludePatterns = []) {
|
|
496
534
|
if (version.startsWith("workspace:") && !options.includeWorkspace) return true;
|
|
497
535
|
if (version.startsWith("catalog:")) return true;
|
|
498
|
-
if (
|
|
536
|
+
if (version.startsWith("github:")) {
|
|
537
|
+
return !parseGithubSpec(version);
|
|
538
|
+
}
|
|
539
|
+
if (/^(link|file|git|https?):/.test(version)) return true;
|
|
499
540
|
if (includePatterns.length && !includePatterns.some((re) => re.test(name))) {
|
|
500
541
|
return true;
|
|
501
542
|
}
|
|
@@ -520,6 +561,7 @@ function parseDependencies(raw, options) {
|
|
|
520
561
|
deps.push({
|
|
521
562
|
name,
|
|
522
563
|
currentVersion: protocol.currentVersion,
|
|
564
|
+
aliasName: protocol.aliasName,
|
|
523
565
|
source: field,
|
|
524
566
|
update: !isLocked(protocol.currentVersion) || options.includeLocked,
|
|
525
567
|
parents: [],
|
|
@@ -997,6 +1039,9 @@ function loadCaBundle(cafilePath) {
|
|
|
997
1039
|
|
|
998
1040
|
async function fetchPackageData(name, options) {
|
|
999
1041
|
const registry = getRegistryForPackage(name, options.npmrc);
|
|
1042
|
+
if (name.startsWith("github:")) {
|
|
1043
|
+
return fetchGithubPackage(name.slice("github:".length), options);
|
|
1044
|
+
}
|
|
1000
1045
|
if (name.startsWith("jsr:")) {
|
|
1001
1046
|
return fetchJsrPackage(name.slice(4), options);
|
|
1002
1047
|
}
|
|
@@ -1011,7 +1056,11 @@ async function fetchNpmPackage(name, registry, options) {
|
|
|
1011
1056
|
if (registry.token) {
|
|
1012
1057
|
headers.authorization = registry.authType === "basic" ? `Basic ${registry.token}` : `Bearer ${registry.token}`;
|
|
1013
1058
|
}
|
|
1014
|
-
const
|
|
1059
|
+
const payload = await fetchWithRetry(url, headers, options);
|
|
1060
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
1061
|
+
throw new ResolveError(`Unexpected npm registry payload shape for ${url}`);
|
|
1062
|
+
}
|
|
1063
|
+
const json = payload;
|
|
1015
1064
|
const versionsObj = json.versions ?? {};
|
|
1016
1065
|
const versions = Object.keys(versionsObj).filter((v) => semver.valid(v));
|
|
1017
1066
|
const distTags = json["dist-tags"] ?? {};
|
|
@@ -1046,7 +1095,11 @@ async function fetchNpmPackage(name, registry, options) {
|
|
|
1046
1095
|
}
|
|
1047
1096
|
async function fetchJsrPackage(name, options) {
|
|
1048
1097
|
const url = `https://jsr.io/${name}/meta.json`;
|
|
1049
|
-
const
|
|
1098
|
+
const payload = await fetchWithRetry(url, {}, options);
|
|
1099
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
1100
|
+
throw new ResolveError(`Unexpected JSR payload shape for ${url}`);
|
|
1101
|
+
}
|
|
1102
|
+
const json = payload;
|
|
1050
1103
|
const versionsObj = json.versions ?? {};
|
|
1051
1104
|
const versions = Object.keys(versionsObj);
|
|
1052
1105
|
const latest = json.latest ?? versions[versions.length - 1] ?? "";
|
|
@@ -1056,6 +1109,59 @@ async function fetchJsrPackage(name, options) {
|
|
|
1056
1109
|
distTags: { latest }
|
|
1057
1110
|
};
|
|
1058
1111
|
}
|
|
1112
|
+
async function fetchGithubPackage(repository, options) {
|
|
1113
|
+
const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;
|
|
1114
|
+
const headers = {
|
|
1115
|
+
accept: "application/vnd.github+json",
|
|
1116
|
+
"user-agent": "depfresh"
|
|
1117
|
+
};
|
|
1118
|
+
if (token) {
|
|
1119
|
+
headers.authorization = `Bearer ${token}`;
|
|
1120
|
+
}
|
|
1121
|
+
const versions = /* @__PURE__ */ new Set();
|
|
1122
|
+
for (let page = 1; page <= 10; page++) {
|
|
1123
|
+
const url = `https://api.github.com/repos/${repository}/tags?per_page=100&page=${page}`;
|
|
1124
|
+
const payload = await fetchWithRetry(url, headers, options);
|
|
1125
|
+
if (!Array.isArray(payload)) {
|
|
1126
|
+
throw new ResolveError(`Unexpected GitHub tags payload shape for ${url}`);
|
|
1127
|
+
}
|
|
1128
|
+
if (payload.length === 0) {
|
|
1129
|
+
break;
|
|
1130
|
+
}
|
|
1131
|
+
for (const item of payload) {
|
|
1132
|
+
if (!item || typeof item !== "object") continue;
|
|
1133
|
+
const tagName = item.name;
|
|
1134
|
+
if (typeof tagName !== "string") continue;
|
|
1135
|
+
const normalized = normalizeGithubTag(tagName);
|
|
1136
|
+
if (normalized) {
|
|
1137
|
+
versions.add(normalized);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
if (payload.length < 100) {
|
|
1141
|
+
break;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
const sorted = Array.from(versions).sort(semver.compare);
|
|
1145
|
+
const latest = sorted[sorted.length - 1];
|
|
1146
|
+
if (!latest) {
|
|
1147
|
+
throw new ResolveError(`No semver tags found for github:${repository}`);
|
|
1148
|
+
}
|
|
1149
|
+
const repositoryUrl = `https://github.com/${repository}`;
|
|
1150
|
+
return {
|
|
1151
|
+
name: `github:${repository}`,
|
|
1152
|
+
versions: sorted,
|
|
1153
|
+
distTags: { latest },
|
|
1154
|
+
repository: repositoryUrl,
|
|
1155
|
+
homepage: repositoryUrl
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
function normalizeGithubTag(tag) {
|
|
1159
|
+
const trimmed = tag.trim();
|
|
1160
|
+
if (!trimmed) return null;
|
|
1161
|
+
const withoutTagPrefix = trimmed.startsWith("refs/tags/") ? trimmed.slice("refs/tags/".length) : trimmed;
|
|
1162
|
+
const withoutVPrefix = withoutTagPrefix.startsWith("v") ? withoutTagPrefix.slice(1) : withoutTagPrefix;
|
|
1163
|
+
return semver.valid(withoutVPrefix);
|
|
1164
|
+
}
|
|
1059
1165
|
async function fetchWithRetry(url, headers, options, attempt = 0) {
|
|
1060
1166
|
const controller = new AbortController();
|
|
1061
1167
|
const timer = setTimeout(() => controller.abort(), options.timeout);
|
|
@@ -1067,6 +1173,9 @@ async function fetchWithRetry(url, headers, options, attempt = 0) {
|
|
|
1067
1173
|
...transportInit
|
|
1068
1174
|
});
|
|
1069
1175
|
if (!response.ok) {
|
|
1176
|
+
if (isGithubRateLimit(response, url)) {
|
|
1177
|
+
throw createGithubRateLimitError(response, url);
|
|
1178
|
+
}
|
|
1070
1179
|
throw new RegistryError(
|
|
1071
1180
|
`HTTP ${response.status}: ${response.statusText} for ${url}`,
|
|
1072
1181
|
response.status,
|
|
@@ -1106,6 +1215,30 @@ function isAbortError(error) {
|
|
|
1106
1215
|
const named = error;
|
|
1107
1216
|
return named.name === "AbortError";
|
|
1108
1217
|
}
|
|
1218
|
+
function isGithubRateLimit(response, url) {
|
|
1219
|
+
if (!url.includes("api.github.com")) return false;
|
|
1220
|
+
if (response.status !== 403 && response.status !== 429) return false;
|
|
1221
|
+
return response.headers.get("x-ratelimit-remaining") === "0";
|
|
1222
|
+
}
|
|
1223
|
+
function createGithubRateLimitError(response, url) {
|
|
1224
|
+
const resetRaw = response.headers.get("x-ratelimit-reset");
|
|
1225
|
+
let resetHint = "";
|
|
1226
|
+
if (resetRaw) {
|
|
1227
|
+
const resetSeconds = Number.parseInt(resetRaw, 10);
|
|
1228
|
+
if (Number.isFinite(resetSeconds)) {
|
|
1229
|
+
resetHint = ` Resets at ${new Date(resetSeconds * 1e3).toISOString()}.`;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return new ResolveError(
|
|
1233
|
+
`GitHub API rate limit exceeded for ${url}.${resetHint} Set GITHUB_TOKEN or GH_TOKEN.`,
|
|
1234
|
+
{
|
|
1235
|
+
cause: {
|
|
1236
|
+
status: response.status,
|
|
1237
|
+
statusText: response.statusText
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1109
1242
|
function sleep(ms) {
|
|
1110
1243
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1111
1244
|
}
|
|
@@ -1258,6 +1391,9 @@ async function resolvePackage(pkg, options, externalCache, externalNpmrc, privat
|
|
|
1258
1391
|
}
|
|
1259
1392
|
}
|
|
1260
1393
|
|
|
1394
|
+
function isPeerScopedCatalog$1(name) {
|
|
1395
|
+
return name.trim().toLowerCase() === "peers";
|
|
1396
|
+
}
|
|
1261
1397
|
function parseCatalogDeps(catalog, parentPath, options) {
|
|
1262
1398
|
const deps = [];
|
|
1263
1399
|
for (const [name, version] of Object.entries(catalog)) {
|
|
@@ -1302,6 +1438,9 @@ const bunCatalogLoader = {
|
|
|
1302
1438
|
if (raw.workspaces?.catalogs) {
|
|
1303
1439
|
const catalogs = raw.workspaces.catalogs;
|
|
1304
1440
|
for (const [catalogName, catalog] of Object.entries(catalogs)) {
|
|
1441
|
+
if (!options.peer && isPeerScopedCatalog$1(catalogName)) {
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1305
1444
|
sources.push({
|
|
1306
1445
|
type: "bun",
|
|
1307
1446
|
name: catalogName,
|
|
@@ -1344,6 +1483,9 @@ const bun = {
|
|
|
1344
1483
|
bunCatalogLoader: bunCatalogLoader
|
|
1345
1484
|
};
|
|
1346
1485
|
|
|
1486
|
+
function isPeerScopedCatalog(name) {
|
|
1487
|
+
return name.trim().toLowerCase() === "peers";
|
|
1488
|
+
}
|
|
1347
1489
|
const pnpmCatalogLoader = {
|
|
1348
1490
|
async detect(cwd) {
|
|
1349
1491
|
return !!findUpSync("pnpm-workspace.yaml", { cwd });
|
|
@@ -1360,6 +1502,9 @@ const pnpmCatalogLoader = {
|
|
|
1360
1502
|
}
|
|
1361
1503
|
if (schema.catalogs && typeof schema.catalogs === "object") {
|
|
1362
1504
|
for (const [name, deps] of Object.entries(schema.catalogs)) {
|
|
1505
|
+
if (!options.peer && isPeerScopedCatalog(name)) {
|
|
1506
|
+
continue;
|
|
1507
|
+
}
|
|
1363
1508
|
catalogs.push(parseCatalogSection(deps, name, filepath, options, content));
|
|
1364
1509
|
}
|
|
1365
1510
|
}
|
|
@@ -1493,6 +1638,11 @@ function rebuildVersion(original, newVersion) {
|
|
|
1493
1638
|
if (npmMatch) return `${npmMatch[1]}${newVersion}`;
|
|
1494
1639
|
const jsrMatch = original.match(/^(jsr:.+@)/);
|
|
1495
1640
|
if (jsrMatch) return `${jsrMatch[1]}${newVersion}`;
|
|
1641
|
+
const githubMatch = original.match(/^(github:[^#]+#)(refs\/tags\/)?(v?)(.+)$/);
|
|
1642
|
+
if (githubMatch) {
|
|
1643
|
+
const [, prefix, tagPrefix = "", vPrefix = ""] = githubMatch;
|
|
1644
|
+
return `${prefix}${tagPrefix}${vPrefix}${newVersion}`;
|
|
1645
|
+
}
|
|
1496
1646
|
return newVersion;
|
|
1497
1647
|
}
|
|
1498
1648
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "depfresh",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Keep your npm dependencies fresh. Fast, correct, zero-config.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"lint:fix": "biome check --write .",
|
|
56
56
|
"format": "biome format --write .",
|
|
57
57
|
"typecheck": "tsc --noEmit",
|
|
58
|
+
"audit:coverage": "node scripts/audit/update-taze-coverage.mjs",
|
|
58
59
|
"prepublishOnly": "pnpm run build"
|
|
59
60
|
},
|
|
60
61
|
"dependencies": {
|