@antongolub/lockfile 0.0.0-snapshot.7 → 0.0.0-snapshot.71
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 +173 -94
- package/SCHEMAS.md +121 -0
- package/dist/_npm-flat-types-CR16JZFS.d.ts +18 -0
- package/dist/_pnpm-flat-core-DmGs4UQu.d.ts +41 -0
- package/dist/_yarn-berry-core-BhE-AhmX.d.ts +19 -0
- package/dist/complete.d.ts +68 -0
- package/dist/complete.js +335 -0
- package/dist/enrich.d.ts +34 -0
- package/dist/enrich.js +245 -0
- package/dist/formats/bun-text.d.ts +51 -0
- package/dist/formats/bun-text.js +1733 -0
- package/dist/formats/npm-1.d.ts +34 -0
- package/dist/formats/npm-1.js +1854 -0
- package/dist/formats/npm-2.d.ts +24 -0
- package/dist/formats/npm-2.js +2415 -0
- package/dist/formats/npm-3.d.ts +24 -0
- package/dist/formats/npm-3.js +2180 -0
- package/dist/formats/pnpm-v5.d.ts +38 -0
- package/dist/formats/pnpm-v5.js +2391 -0
- package/dist/formats/pnpm-v6.d.ts +28 -0
- package/dist/formats/pnpm-v6.js +3068 -0
- package/dist/formats/pnpm-v9.d.ts +28 -0
- package/dist/formats/pnpm-v9.js +3068 -0
- package/dist/formats/yarn-berry-v10.d.ts +24 -0
- package/dist/formats/yarn-berry-v10.js +3204 -0
- package/dist/formats/yarn-berry-v4.d.ts +24 -0
- package/dist/formats/yarn-berry-v4.js +3208 -0
- package/dist/formats/yarn-berry-v5.d.ts +24 -0
- package/dist/formats/yarn-berry-v5.js +3203 -0
- package/dist/formats/yarn-berry-v6.d.ts +24 -0
- package/dist/formats/yarn-berry-v6.js +3203 -0
- package/dist/formats/yarn-berry-v7.d.ts +24 -0
- package/dist/formats/yarn-berry-v7.js +3203 -0
- package/dist/formats/yarn-berry-v8.d.ts +24 -0
- package/dist/formats/yarn-berry-v8.js +3204 -0
- package/dist/formats/yarn-berry-v9.d.ts +24 -0
- package/dist/formats/yarn-berry-v9.js +3204 -0
- package/dist/formats/yarn-classic.d.ts +48 -0
- package/dist/formats/yarn-classic.js +2183 -0
- package/dist/graph-CPo-SvS2.d.ts +223 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.js +11186 -0
- package/dist/modify-DuBV5-5V.d.ts +219 -0
- package/dist/modify.d.ts +20 -0
- package/dist/modify.js +1005 -0
- package/dist/optimize-B6TOjYyj.d.ts +33 -0
- package/dist/optimize.d.ts +80 -0
- package/dist/optimize.js +256 -0
- package/dist/registry.d.ts +64 -0
- package/dist/registry.js +687 -0
- package/dist/types-BPMSHpCF.d.ts +48 -0
- package/package.json +149 -36
- package/target/es6/analyze.d.ts +0 -2
- package/target/es6/common.d.ts +0 -26
- package/target/es6/format.d.ts +0 -2
- package/target/es6/formats/npm-1.d.ts +0 -22
- package/target/es6/formats/npm-2.d.ts +0 -16
- package/target/es6/formats/npm-3.d.ts +0 -29
- package/target/es6/formats/yarn-1.d.ts +0 -14
- package/target/es6/formats/yarn-5.d.ts +0 -20
- package/target/es6/formats/yarn-6.d.ts +0 -0
- package/target/es6/formats/yarn-7.d.ts +0 -0
- package/target/es6/formats/yarn-berry.d.ts +0 -20
- package/target/es6/formats/yarn-classic.d.ts +0 -14
- package/target/es6/index.d.ts +0 -5
- package/target/es6/index.js +0 -655
- package/target/es6/index.js.map +0 -7
- package/target/es6/interface.d.ts +0 -72
- package/target/es6/npm-1.d.ts +0 -19
- package/target/es6/npm-2.d.ts +0 -0
- package/target/es6/packument.d.ts +0 -0
- package/target/es6/parse.d.ts +0 -2
- package/target/es6/util.d.ts +0 -4
- package/target/es6/workspace.d.ts +0 -16
- package/target/es6/yarn-1.d.ts +0 -13
- package/target/es6/yarn-5.d.ts +0 -19
- package/target/es6/yarn-6.d.ts +0 -0
- package/target/es6/yarn-7.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,114 +1,193 @@
|
|
|
1
|
-
# lockfile
|
|
2
|
-
> Read and write lockfiles with reasonable losses
|
|
1
|
+
# @antongolub/lockfile
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
Each package manager brings its own philosophy of how to describe, store and control project dependencies.
|
|
6
|
-
It _seems_ acceptable for developers, but literally becomes a ~~pain in *** ***~~ headache for isec, devops and release engineers.
|
|
7
|
-
This lib is a naive attempt to build a pm-independent, generic, extensible and reliable deps representation.
|
|
3
|
+
> Universal lockfile model and converter for **npm**, **yarn**, **pnpm**, **bun**.
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
<p><img alt="@antongolub/lockfile — universal lockfile model and converter for npm, yarn, pnpm, bun" src="./pics/lockfile.svg" align="right" width="300">
|
|
6
|
+
|
|
7
|
+
Each package manager brings its own philosophy of how to describe, store and
|
|
8
|
+
control project dependencies. Inside a single repo it's invisible to the
|
|
9
|
+
developer — but it becomes a recurring cost for InfoSec, DevOps and release
|
|
10
|
+
engineers, and makes consistent policy unenforceable across the enterprise.
|
|
11
|
+
|
|
12
|
+
This library models the dependency graph independent of any specific
|
|
13
|
+
package manager, then projects it back into the format you need.
|
|
14
|
+
Conversion is one use case; modification (audit-fix, override pinning,
|
|
15
|
+
license filtering) is the headline.
|
|
16
|
+
|
|
17
|
+
</p>
|
|
12
18
|
|
|
13
19
|
## Status
|
|
14
|
-
⚠️ Initial draft. Alpha-version
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
**Snapshot preview.** Every format below parses and stringifies; conversion is
|
|
22
|
+
*semantically equivalent*, not byte-identical (see [Concept](#concept)).
|
|
23
|
+
Published as `0.0.0-snapshot.*` builds — the first stable release is pending.
|
|
24
|
+
[SCHEMAS.md](./SCHEMAS.md) maps each format id to the package-manager versions
|
|
25
|
+
that emit it.
|
|
26
|
+
|
|
27
|
+
> **ℹ️ Active R&D — snapshot channel.** While the project is under active research &
|
|
28
|
+
> development, every release ships to the **snapshot channel** (`0.0.0-snapshot.N`,
|
|
29
|
+
> published under the `snapshot` npm dist-tag) rather than `latest`. Install the newest
|
|
30
|
+
> snapshot with `npm i @antongolub/lockfile@snapshot`, or pin an exact build
|
|
31
|
+
> (e.g. `npm i @antongolub/lockfile@0.0.0-snapshot.61`). The first stable `latest`
|
|
32
|
+
> release is pending.
|
|
33
|
+
|
|
34
|
+
| Format | `detect` | `parse` | `stringify` |
|
|
35
|
+
|--------|:-:|:-:|:-:|
|
|
36
|
+
| `npm-1` · `npm-2` · `npm-3` | ✓ | ✓ | ✓ |
|
|
37
|
+
| `yarn-classic` | ✓ | ✓ | ✓ |
|
|
38
|
+
| `yarn-berry-v4` … `yarn-berry-v10`| ✓ | ✓ | ✓ |
|
|
39
|
+
| `pnpm-v5` · `pnpm-v6` · `pnpm-v9` | ✓ | ✓ | ✓ |
|
|
40
|
+
| `bun-text` | ✓ | ✓ | ✓ |
|
|
41
|
+
|
|
42
|
+
Graph-level operations apply to **any** parsed graph, regardless of source
|
|
43
|
+
format: `convert` (parse any → stringify any), `modify` (audit-fix,
|
|
44
|
+
override-pin, license-filter), and `optimize` (orphan GC / dedup).
|
|
45
|
+
|
|
46
|
+
## Concept
|
|
47
|
+
|
|
48
|
+
A target lockfile is **constructed** from facts gathered across whatever
|
|
49
|
+
sources are available: the input lockfile bytes, project `package.json`s,
|
|
50
|
+
the package-manager cache, and (opt-in) the registry. The simplest case is
|
|
51
|
+
*conversion* — parse one format, stringify another. The general case is
|
|
52
|
+
*construction*: assemble what the target requires from whichever source can
|
|
53
|
+
supply it.
|
|
54
|
+
|
|
55
|
+
Three layers, never collapsed:
|
|
56
|
+
|
|
57
|
+
- **Manifest** — declared constraints from `package.json`(s).
|
|
58
|
+
- **Graph** — resolved package instances (peer-aware) and the edges
|
|
59
|
+
between them. The canonical internal model. Modifiers operate here.
|
|
60
|
+
- **Layout** — physical projection on disk: hoisted, isolated (pnpm-style),
|
|
61
|
+
PnP, nm-linked.
|
|
62
|
+
|
|
63
|
+
Conversion is **lossy by design**. We aim for *semantically equivalent*,
|
|
64
|
+
not *byte-identical*. Irreducible facts (integrity hashes, resolution URLs,
|
|
65
|
+
signatures) are the exception — they are never silently lost.
|
|
66
|
+
|
|
67
|
+
## API
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { parse, stringify, convert } from '@antongolub/lockfile'
|
|
71
|
+
|
|
72
|
+
// explicit format (it's always the first argument):
|
|
73
|
+
const graph = parse('pnpm-v9', raw)
|
|
74
|
+
const out = stringify('npm-3', graph)
|
|
75
|
+
|
|
76
|
+
// or one step, auto-detecting the source:
|
|
77
|
+
const npm = convert(raw, { to: 'npm-3' })
|
|
20
78
|
```
|
|
21
79
|
|
|
22
|
-
|
|
80
|
+
The format is **explicit**, never implicit — `parse` and `stringify` both take
|
|
81
|
+
it as the first argument; `detect` sniffs it from the bytes when you don't know
|
|
82
|
+
it. Round-tripping is a choice the caller makes, not a default.
|
|
83
|
+
|
|
23
84
|
```ts
|
|
24
|
-
|
|
85
|
+
detect(input: string): FormatId | undefined
|
|
86
|
+
check(format: FormatId, input: string): boolean
|
|
87
|
+
parse(format: FormatId, input: string, opts?: ParseOptions): Graph
|
|
88
|
+
stringify(format: FormatId, graph: Graph, opts?: StringifyOptions): string
|
|
89
|
+
convert(input: string, opts: ConvertOptions): string // parse(from) → stringify(to)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`Graph` is the canonical, package-manager-independent model; `FormatId` is a
|
|
93
|
+
string-literal union (the [Status](#status) table lists every id, and
|
|
94
|
+
[SCHEMAS.md](./SCHEMAS.md) maps each to the package-manager versions behind it).
|
|
95
|
+
|
|
96
|
+
### Operating on the graph
|
|
25
97
|
|
|
26
|
-
|
|
98
|
+
The graph is where the value lives — `modify` and `optimize` transform it,
|
|
99
|
+
format-agnostically:
|
|
27
100
|
|
|
28
|
-
|
|
29
|
-
|
|
101
|
+
- **`modify`** applies a `Primitive[]` — `replaceVersion`, `pinOverride`,
|
|
102
|
+
`addDependency`, `removeDependency`, `applyPatch`, `filterLicense` — the
|
|
103
|
+
building blocks of audit-fix, override-pinning and license filtering.
|
|
104
|
+
- **`optimize`** runs orphan GC / dedup over the graph.
|
|
105
|
+
- **`overridesOf(graph)`** reads the canonical overrides back out.
|
|
30
106
|
|
|
31
|
-
|
|
32
|
-
const meta2 = await fetchMeta(snapshot) // does the same, but from the remote registry
|
|
33
|
-
const lf3 = format(snapshot, 'npm-3', {meta}) // format with options
|
|
107
|
+
### Options
|
|
34
108
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
109
|
+
```ts
|
|
110
|
+
type ParseOptions = {
|
|
111
|
+
workspaceRoot?: string // FS root for out-of-lockfile reads (patch bytes, manifests)
|
|
112
|
+
manifests?: Record<string, Manifest> // package.jsons keyed by workspace path
|
|
113
|
+
onDiagnostic?: (d: Diagnostic) => void
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
type StringifyOptions = {
|
|
117
|
+
lineEnding?: 'lf' | 'crlf'
|
|
118
|
+
cacheKey?: string // yarn-berry cache-key prefix
|
|
119
|
+
overrides?: OverrideConstraint[] // canonical overrides → native projection
|
|
120
|
+
onDiagnostic?: (d: Diagnostic) => void
|
|
121
|
+
}
|
|
43
122
|
```
|
|
44
123
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
###
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
| patch | |
|
|
66
|
-
| file | |
|
|
67
|
-
| github | |
|
|
68
|
-
| tag | |
|
|
69
|
-
|
|
70
|
-
https://yarnpkg.com/features/protocols
|
|
71
|
-
|
|
72
|
-
### `TSnapshot`
|
|
124
|
+
`manifests` supplies the workspace/override context the lockfile bytes cannot
|
|
125
|
+
carry on their own (notably for `yarn-classic` monorepos); everything else
|
|
126
|
+
succeeds offline against the bytes alone. Registry- and cache-backed refinement
|
|
127
|
+
ships as opt-in adapters (see [Sub-imports](#sub-imports)).
|
|
128
|
+
|
|
129
|
+
### Sub-imports
|
|
130
|
+
|
|
131
|
+
| Surface | Importable as | Contains |
|
|
132
|
+
|---------|---------------|----------|
|
|
133
|
+
| Root | `@antongolub/lockfile` | `detect`, `check`, `parse`, `stringify`, `convert`, `modify`, `optimize`, `overridesOf`, plus types `Graph`, `FormatId`, `ParseOptions`, `StringifyOptions`, `ConvertOptions`, `Manifest` |
|
|
134
|
+
| Modifiers | `@antongolub/lockfile/modify` | the individual `Primitive` functions behind `modify` (audit-fix, override-pin, license-filter) |
|
|
135
|
+
| Optimize | `@antongolub/lockfile/optimize` | the individual GC passes behind `optimize` |
|
|
136
|
+
| Registry | `@antongolub/lockfile/registry` | `frozenRegistry`, `liveRegistry`, `fsCache`, `npmCache`, `pnpmCache` |
|
|
137
|
+
| Per-format | `@antongolub/lockfile/formats/<id>` | a single adapter directly (test surface; not a primary user API) |
|
|
138
|
+
|
|
139
|
+
### Errors
|
|
140
|
+
|
|
141
|
+
`parse` / `stringify` throw a single `LockfileError` discriminated by
|
|
142
|
+
`code`:
|
|
143
|
+
|
|
73
144
|
```ts
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
hashes: {
|
|
79
|
-
sha512?: string
|
|
80
|
-
sha256?: string
|
|
81
|
-
sha1?: string
|
|
82
|
-
checksum?: string
|
|
83
|
-
md5?: string
|
|
84
|
-
}
|
|
85
|
-
source: string
|
|
86
|
-
sourceType: TSourceType
|
|
87
|
-
|
|
88
|
-
// optional pm-specific lockfile meta
|
|
89
|
-
manifest?: TManifest
|
|
90
|
-
conditions?: string
|
|
91
|
-
dependencies?: TDependencies
|
|
92
|
-
dependenciesMeta?: TDependenciesMeta
|
|
93
|
-
optionalDependencies?: TDependencies
|
|
94
|
-
peerDependencies?: TDependencies
|
|
95
|
-
peerDependenciesMeta?: TDependenciesMeta
|
|
96
|
-
bin?: Record<string, string>
|
|
97
|
-
engines?: Record<string, string>
|
|
98
|
-
funding?: Record<string, string>
|
|
99
|
-
}>
|
|
145
|
+
'PARSE_FAILED' | 'FORMAT_DETECT_FAILED' | 'FORMAT_MISMATCH'
|
|
146
|
+
| 'CAPABILITY_LACK' | 'MISSING_MANIFEST' | 'MISSING_REQUIRED_FIELD'
|
|
147
|
+
| 'INVALID_INPUT' | 'ENRICH_REQUIRED' | 'IRREDUCIBLE_LOSS'
|
|
148
|
+
| 'PIPELINE_DIVERGED' | 'REGISTRY_UNREACHABLE' | 'INVARIANT_VIOLATION'
|
|
100
149
|
```
|
|
101
150
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
151
|
+
Reducible losses (e.g. dropped patches when emitting `npm-1` from a
|
|
152
|
+
yarn-berry source) surface as `Diagnostic` events via the
|
|
153
|
+
`onDiagnostic` callback, not exceptions.
|
|
154
|
+
|
|
155
|
+
## Schemas
|
|
156
|
+
|
|
157
|
+
Every recognised lockfile schema is enumerated in
|
|
158
|
+
[SCHEMAS.md](./SCHEMAS.md), with adapter ids, the schema-marker each
|
|
159
|
+
carries, the package-manager versions that emit it by default, and
|
|
160
|
+
permalinked sources. Use that table as the index when calling
|
|
161
|
+
`parse({ format })` or `stringify({ format })`.
|
|
162
|
+
|
|
163
|
+
## Predecessor and inspirations
|
|
164
|
+
|
|
165
|
+
This project is the architectural successor to
|
|
166
|
+
[`yarn-audit-fix`](https://github.com/antongolub/yarn-audit-fix), generalised
|
|
167
|
+
beyond yarn.
|
|
168
|
+
|
|
169
|
+
Earlier work in this space:
|
|
170
|
+
|
|
171
|
+
- [synp](https://github.com/imsnif/synp)
|
|
172
|
+
- [snyk-nodejs-lockfile-parser](https://github.com/snyk/nodejs-lockfile-parser)
|
|
173
|
+
- [`@yarnpkg/lockfile`](https://github.com/yarnpkg/yarn/tree/master/packages/lockfile)
|
|
174
|
+
- [`pnpm/lockfile-utils`](https://github.com/pnpm/pnpm/tree/main/lockfile)
|
|
175
|
+
|
|
176
|
+
## Package-manager docs
|
|
177
|
+
|
|
178
|
+
- [`package-lock.json`](https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json)
|
|
179
|
+
— npm
|
|
180
|
+
- [yarn lockfile (classic)](https://classic.yarnpkg.com/lang/en/docs/yarn-lock/)
|
|
181
|
+
/ [yarn lockfile (berry)](https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-core/sources/Project.ts)
|
|
182
|
+
- [`pnpm/spec/lockfile/`](https://github.com/pnpm/spec/tree/master/lockfile)
|
|
183
|
+
— pnpm
|
|
184
|
+
- [bun lockfile](https://bun.com/docs/pm/lockfile) — bun
|
|
185
|
+
|
|
186
|
+
## Compatibility
|
|
187
|
+
|
|
188
|
+
- **Node ≥ 20.** No browser build planned.
|
|
189
|
+
- **ESM only.** Consumers on CommonJS use dynamic `await import(…)`.
|
|
108
190
|
|
|
109
|
-
|
|
110
|
-
* [synp](https://github.com/imsnif/synp)
|
|
111
|
-
* [snyk-nodejs-lockfile-parser](https://github.com/snyk/nodejs-lockfile-parser)
|
|
191
|
+
## License
|
|
112
192
|
|
|
113
|
-
### License
|
|
114
193
|
[MIT](./LICENSE)
|
package/SCHEMAS.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Lockfile schemas
|
|
2
|
+
|
|
3
|
+
Public reference for every lockfile schema this project recognises:
|
|
4
|
+
how to identify each, which package-manager versions emit it by
|
|
5
|
+
default, and which can install from it. Adapter ids match the
|
|
6
|
+
`FormatId` literal accepted by `parse({ format })` and required by
|
|
7
|
+
`stringify({ format })`.
|
|
8
|
+
|
|
9
|
+
## npm
|
|
10
|
+
|
|
11
|
+
| Adapter id | Marker | Default writer | Reader |
|
|
12
|
+
|------------|--------|----------------|--------|
|
|
13
|
+
| `npm-1` | `lockfileVersion: 1` | npm `>=5 <7` | npm `>=5` |
|
|
14
|
+
| `npm-2` | `lockfileVersion: 2` | npm `>=7 <9` | npm `>=7` |
|
|
15
|
+
| `npm-3` | `lockfileVersion: 3` | npm `>=9` | npm `>=7` |
|
|
16
|
+
|
|
17
|
+
`npm install --lockfile-version=N` overrides the writer choice within
|
|
18
|
+
the supported range.
|
|
19
|
+
|
|
20
|
+
## yarn
|
|
21
|
+
|
|
22
|
+
`yarn-classic` and `yarn-berry-*` use different lockfile schemas. The
|
|
23
|
+
"v" suffix on berry adapters is `__metadata.version`. Yarn classic
|
|
24
|
+
uses a `# yarn lockfile v1` *comment header* instead — unrelated to
|
|
25
|
+
berry's `__metadata`.
|
|
26
|
+
|
|
27
|
+
| Adapter id | Marker | Default writer | Reader |
|
|
28
|
+
|-------------------|------------------------------|----------------------|---------|
|
|
29
|
+
| `yarn-classic` | `# yarn lockfile v1` header | yarn `>=1 <2` | yarn `>=1 <2` (native); yarn `>=2` via `yarn import` |
|
|
30
|
+
| `yarn-berry-v3` | `__metadata.version: 3` | yarn `>=2.0.0-rc.4 <2.0.0-rc.20` (pre-release only) | yarn `>=2` |
|
|
31
|
+
| `yarn-berry-v4` | `__metadata.version: 4` | yarn `>=2.0.0-rc.20 <3.1` | yarn `>=2` |
|
|
32
|
+
| `yarn-berry-v5` | `__metadata.version: 5` | yarn `=3.1.0` (one minor) | yarn `>=3.1` |
|
|
33
|
+
| `yarn-berry-v6` | `__metadata.version: 6` | yarn `>=3.2 <4` | yarn `>=3.2` |
|
|
34
|
+
| `yarn-berry-v8` | `__metadata.version: 8` | yarn `>=4.0 <4.14` | yarn `>=4` |
|
|
35
|
+
| `yarn-berry-v9` | `__metadata.version: 9` | yarn `>=4.14` | yarn `>=4.14` |
|
|
36
|
+
| `yarn-berry-v10` | `__metadata.version: 10` | yarn 5 (dev branch) | yarn 5+ (preview — reverse-engineered from yarnpkg/berry master) |
|
|
37
|
+
|
|
38
|
+
**Schema numbers that don't exist:**
|
|
39
|
+
- `__metadata.version: 1` and `2` were never used by berry.
|
|
40
|
+
- `__metadata.version: 7` was skipped — yarn went `6 → 8` in 4.0.0.
|
|
41
|
+
|
|
42
|
+
`YARN_LOCKFILE_VERSION_OVERRIDE` (yarn 4+) lets one binary write any
|
|
43
|
+
schema version it can read; structural fidelity to the canonical
|
|
44
|
+
writer is not guaranteed.
|
|
45
|
+
|
|
46
|
+
## pnpm
|
|
47
|
+
|
|
48
|
+
| Adapter id | Marker | Default writer |
|
|
49
|
+
|------------|--------------------------|----------------------|
|
|
50
|
+
| `pnpm-v5` | `lockfileVersion: 5.x` | pnpm `>=3 <8` (pnpm 7 stayed on `5.4` by default) |
|
|
51
|
+
| `pnpm-v6` | `lockfileVersion: '6.0'`/`'6.1'` | pnpm `>=8 <9` |
|
|
52
|
+
| `pnpm-v9` | `lockfileVersion: '9.0'` | pnpm `>=9` |
|
|
53
|
+
|
|
54
|
+
**Schema numbers that don't exist:** `7` and `8`. pnpm 9 jumped
|
|
55
|
+
straight from `6.x` to `9.0`.
|
|
56
|
+
|
|
57
|
+
## bun
|
|
58
|
+
|
|
59
|
+
| Adapter id | Marker | Default writer | Status |
|
|
60
|
+
|---------------|---------------------------------|----------------|--------|
|
|
61
|
+
| `bun-text` | `bun.lock` filename + JSONC | bun `>=1.2` | primary bun target |
|
|
62
|
+
| `bun-binary` | `bun.lockb` filename + magic | bun `<1.2` | detect-only — not parsed |
|
|
63
|
+
|
|
64
|
+
`bun-binary` is a **permanent non-goal**: when `parse()` detects
|
|
65
|
+
`bun.lockb` magic bytes it throws with a hint to migrate via bun's
|
|
66
|
+
own tooling (`bun install --save-text-lockfile`). The library handles
|
|
67
|
+
the resulting `bun.lock` via the `bun-text` adapter. bun's own
|
|
68
|
+
binary reader stays in bun for back-compat — that is bun's
|
|
69
|
+
responsibility, not ours.
|
|
70
|
+
|
|
71
|
+
## Sources
|
|
72
|
+
|
|
73
|
+
Where each schema is canonically defined. Permalinks pinned at specific
|
|
74
|
+
release tags / commits so claims here stay anchored.
|
|
75
|
+
|
|
76
|
+
### npm
|
|
77
|
+
|
|
78
|
+
- [npm v7 series — beta release & semver-major changes](https://blog.npmjs.org/post/626173315965468672/npm-v7-series-beta-release-and-semver-major.html)
|
|
79
|
+
— introduces `lockfileVersion: 2` (`packages` block, workspaces).
|
|
80
|
+
- [package-lock.json docs (npm v9)](https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json/)
|
|
81
|
+
— schema reference for v3.
|
|
82
|
+
- [GitHub: dependency-graph and Dependabot support npm v9](https://github.blog/changelog/2023-03-10-dependency-graph-and-dependabot-support-npm-v9/)
|
|
83
|
+
— confirms v3 drops the legacy `dependencies` mirror.
|
|
84
|
+
|
|
85
|
+
### yarn
|
|
86
|
+
|
|
87
|
+
- [`Project.ts` at @yarnpkg/cli/2.4.3](https://github.com/yarnpkg/berry/blob/@yarnpkg/cli/2.4.3/packages/yarnpkg-core/sources/Project.ts)
|
|
88
|
+
— `LOCKFILE_VERSION = 4`.
|
|
89
|
+
- [`Project.ts` at @yarnpkg/cli/3.1.0](https://github.com/yarnpkg/berry/blob/@yarnpkg/cli/3.1.0/packages/yarnpkg-core/sources/Project.ts)
|
|
90
|
+
— `LOCKFILE_VERSION = 5` (one-minor window).
|
|
91
|
+
- [`Project.ts` at @yarnpkg/cli/3.2.0](https://github.com/yarnpkg/berry/blob/@yarnpkg/cli/3.2.0/packages/yarnpkg-core/sources/Project.ts)
|
|
92
|
+
— `LOCKFILE_VERSION = 6`.
|
|
93
|
+
- [`Project.ts` at @yarnpkg/cli/4.0.0](https://github.com/yarnpkg/berry/blob/@yarnpkg/cli/4.0.0/packages/yarnpkg-core/sources/Project.ts)
|
|
94
|
+
— bumps to 8; `YARN_LOCKFILE_VERSION_OVERRIDE` env var introduced here.
|
|
95
|
+
- [`Project.ts` at @yarnpkg/cli/4.14.1](https://github.com/yarnpkg/berry/blob/@yarnpkg/cli/4.14.1/packages/yarnpkg-core/sources/Project.ts)
|
|
96
|
+
— current `LOCKFILE_VERSION = 9`.
|
|
97
|
+
- [Yarn 4.0 release blog](https://yarnpkg.com/blog/release/4.0)
|
|
98
|
+
— narrative context (no explicit lockfile-bump mention).
|
|
99
|
+
|
|
100
|
+
### pnpm
|
|
101
|
+
|
|
102
|
+
- [`pnpm/spec` — lockfile/](https://github.com/pnpm/spec/tree/master/lockfile)
|
|
103
|
+
— official per-version schema docs (`5.md`, `5.2.md`, `6.0.md`, `9.0.md`).
|
|
104
|
+
- [`pnpm/spec/lockfile/6.0.md`](https://github.com/pnpm/spec/blob/master/lockfile/6.0.md)
|
|
105
|
+
— pnpm 8's schema, including the package-id grammar shift.
|
|
106
|
+
- [`pnpm/spec/lockfile/9.0.md`](https://github.com/pnpm/spec/blob/master/lockfile/9.0.md)
|
|
107
|
+
— pnpm 9's `packages` / `snapshots` split.
|
|
108
|
+
- [pnpm Discussion #6857](https://github.com/orgs/pnpm/discussions/6857)
|
|
109
|
+
— maintainer rationale for the `6 → 9` jump:
|
|
110
|
+
*"in the future lockfile version will equal the pnpm version in
|
|
111
|
+
which it got introduced."*
|
|
112
|
+
|
|
113
|
+
### bun
|
|
114
|
+
|
|
115
|
+
- [Bun docs — Lockfile](https://bun.com/docs/pm/lockfile)
|
|
116
|
+
— current schema reference for `bun.lock`.
|
|
117
|
+
- [Bun blog — text-based lockfile](https://bun.com/blog/bun-lock-text-lockfile)
|
|
118
|
+
— text format introduced in 1.1.39, default in 1.2.
|
|
119
|
+
- [`bun-lock` source](https://github.com/oven-sh/bun) — `src/install/lockfile.zig`
|
|
120
|
+
for the binary serializer.
|
|
121
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { D as Diagnostic, O as OverrideConstraint } from './graph-CPo-SvS2.js';
|
|
2
|
+
|
|
3
|
+
interface NpmFamilyParseOptions {
|
|
4
|
+
}
|
|
5
|
+
interface NpmFamilyStringifyOptions {
|
|
6
|
+
lineEnding?: 'lf' | 'crlf';
|
|
7
|
+
onDiagnostic?: (diagnostic: Diagnostic) => void;
|
|
8
|
+
/** Caller-declared overrides (ADR-0025 §4) projected into the root entry's
|
|
9
|
+
* `overrides` block at `packages[""]`. npm-1 (no packages block) cannot
|
|
10
|
+
* carry them — a loss diagnostic fires instead. */
|
|
11
|
+
overrides?: OverrideConstraint[];
|
|
12
|
+
}
|
|
13
|
+
interface NpmFamilyEnrichOptions {
|
|
14
|
+
}
|
|
15
|
+
interface NpmFamilyOptimizeOptions {
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type { NpmFamilyEnrichOptions as N, NpmFamilyOptimizeOptions as a, NpmFamilyParseOptions as b, NpmFamilyStringifyOptions as c };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { D as Diagnostic, O as OverrideConstraint } from './graph-CPo-SvS2.js';
|
|
2
|
+
|
|
3
|
+
interface PnpmFamilyParseOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Filesystem root used by F2 patch-slot extraction (ADR-0014 §4.F2).
|
|
6
|
+
* When the `overrides:` block carries `patch:<spec>#<workspace-path>`
|
|
7
|
+
* entries the resolver reads `<workspaceRoot>/<workspace-path>` bytes
|
|
8
|
+
* and emits the canonical sha512-hex on `Node.patch`. Absent / unreadable
|
|
9
|
+
* patch sources fall back to the ADR-0011 `unresolved-<sha256-hex>`
|
|
10
|
+
* sentinel computed from the locator string.
|
|
11
|
+
*/
|
|
12
|
+
workspaceRoot?: string;
|
|
13
|
+
}
|
|
14
|
+
interface PnpmFamilyStringifyOptions {
|
|
15
|
+
lineEnding?: 'lf' | 'crlf';
|
|
16
|
+
settings?: PnpmSettings;
|
|
17
|
+
onDiagnostic?: (diagnostic: Diagnostic) => void;
|
|
18
|
+
/** Caller-declared overrides (ADR-0025 §4) overlaid onto the pnpm
|
|
19
|
+
* `overrides:` block. Caller wins per key; pre-existing `patch:` directives
|
|
20
|
+
* (F2) survive on collision. */
|
|
21
|
+
overrides?: OverrideConstraint[];
|
|
22
|
+
}
|
|
23
|
+
interface PnpmManifest {
|
|
24
|
+
name?: string;
|
|
25
|
+
version?: string;
|
|
26
|
+
dependencies?: Record<string, string>;
|
|
27
|
+
devDependencies?: Record<string, string>;
|
|
28
|
+
optionalDependencies?: Record<string, string>;
|
|
29
|
+
peerDependencies?: Record<string, string>;
|
|
30
|
+
}
|
|
31
|
+
interface PnpmFamilyEnrichOptions {
|
|
32
|
+
manifests?: Record<string, PnpmManifest>;
|
|
33
|
+
}
|
|
34
|
+
interface PnpmFamilyOptimizeOptions {
|
|
35
|
+
}
|
|
36
|
+
interface PnpmSettings {
|
|
37
|
+
autoInstallPeers?: boolean;
|
|
38
|
+
excludeLinksFromLockfile?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type { PnpmFamilyEnrichOptions as P, PnpmManifest as a, PnpmFamilyOptimizeOptions as b, PnpmFamilyParseOptions as c, PnpmSettings as d, PnpmFamilyStringifyOptions as e };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { O as OverrideConstraint, D as Diagnostic } from './graph-CPo-SvS2.js';
|
|
2
|
+
|
|
3
|
+
interface YarnBerryFamilyParseOptions {
|
|
4
|
+
workspaceRoot?: string;
|
|
5
|
+
overrides?: OverrideConstraint[];
|
|
6
|
+
}
|
|
7
|
+
interface YarnBerryFamilyStringifyOptions {
|
|
8
|
+
lineEnding?: 'lf' | 'crlf';
|
|
9
|
+
cacheKey?: string;
|
|
10
|
+
onDiagnostic?: (diagnostic: Diagnostic) => void;
|
|
11
|
+
}
|
|
12
|
+
interface YarnBerryFamilyEnrichOptions {
|
|
13
|
+
workspaceRoot?: string;
|
|
14
|
+
peerMetaResolver?: (parentName: string, parentVersion: string, peerName: string) => boolean | undefined;
|
|
15
|
+
}
|
|
16
|
+
interface YarnBerryFamilyOptimizeOptions {
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type { YarnBerryFamilyEnrichOptions as Y, YarnBerryFamilyOptimizeOptions as a, YarnBerryFamilyParseOptions as b, YarnBerryFamilyStringifyOptions as c };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { N as NodeId, D as Diagnostic, G as Graph, E as EdgeTriple, a as Node, b as EdgeKind } from './graph-CPo-SvS2.js';
|
|
2
|
+
import { R as RegistryAdapter } from './types-BPMSHpCF.js';
|
|
3
|
+
|
|
4
|
+
interface CompletionSeed {
|
|
5
|
+
/** NodeIds the modifier added in the just-completed mutate phase. */
|
|
6
|
+
recentlyAdded: Set<NodeId>;
|
|
7
|
+
/** NodeIds the mutate phase orphaned. The completion frontier excludes
|
|
8
|
+
* these — optimize phase collects. */
|
|
9
|
+
recentlyOrphaned: Set<NodeId>;
|
|
10
|
+
}
|
|
11
|
+
interface CompletionResult {
|
|
12
|
+
graph: Graph;
|
|
13
|
+
added: NodeId[];
|
|
14
|
+
wired: EdgeTriple[];
|
|
15
|
+
unresolved: Diagnostic[];
|
|
16
|
+
}
|
|
17
|
+
interface CompletionOptions {
|
|
18
|
+
seed?: CompletionSeed;
|
|
19
|
+
onDiagnostic?: (d: Diagnostic) => void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Walk graph, query registry for missing transitive deps, wire edges.
|
|
23
|
+
* Monotone-additive: returned graph ⊇ input graph (no removals).
|
|
24
|
+
*/
|
|
25
|
+
declare function completeTransitives(graph: Graph, registry: RegistryAdapter, options?: CompletionOptions): Promise<CompletionResult>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Walk consumer → root via incoming-edge BFS.
|
|
29
|
+
* Returns nodes in BFS order: consumer first, deeper ancestors last.
|
|
30
|
+
* Cycles tolerated via `seen`.
|
|
31
|
+
*/
|
|
32
|
+
declare function ancestorsOf(graph: Graph, consumer: NodeId): Node[];
|
|
33
|
+
/**
|
|
34
|
+
* Find-up resolve per ADR-0023 §5.1.
|
|
35
|
+
*
|
|
36
|
+
* Returns the closest-ancestor satisfying node, or undefined if either
|
|
37
|
+
* (a) no ancestor declares `name` at all → caller may install nested at the
|
|
38
|
+
* consumer's level, or
|
|
39
|
+
* (b) the closest ancestor that declares `name` does so with a conflicting
|
|
40
|
+
* range → "block hoist", caller installs nested fallback (npm-3 style).
|
|
41
|
+
*
|
|
42
|
+
* Tiebreaker:
|
|
43
|
+
* 1. Highest semver-comparable version wins (`semver.rcompare`).
|
|
44
|
+
* 2. On version tie, lowest NodeId lex order wins.
|
|
45
|
+
*
|
|
46
|
+
* `depKind` is part of the §5.1 normative signature but does NOT affect the
|
|
47
|
+
* algorithm body in v1: every dep-kind (dep / dev / optional / peer) follows
|
|
48
|
+
* the same closest-ancestor reuse + block-hoist contract. The parameter is
|
|
49
|
+
* carried verbatim so future kind-filtered hoist policies (e.g. peer-deps
|
|
50
|
+
* needing a stricter find-up, or optional-deps allowed to silently fail
|
|
51
|
+
* differently from regular deps) can branch on it without a signature
|
|
52
|
+
* migration. Per the ADR §5.1 pseudocode body and the v1 normative scope, no
|
|
53
|
+
* kind-specific branch is taken yet.
|
|
54
|
+
*/
|
|
55
|
+
declare function resolveFindUp(graph: Graph, consumerId: NodeId, name: string, range: string, depKind: EdgeKind): NodeId | undefined;
|
|
56
|
+
|
|
57
|
+
type CompletionDiagnosticCode = 'COMPLETION_NODE_ADDED' | 'COMPLETION_EDGE_RESOLVED' | 'COMPLETION_UNRESOLVED' | 'COMPLETION_NODE_UNKNOWN' | 'COMPLETION_VERSION_UNKNOWN' | 'COMPLETION_PEER_CONTEXT_INCOMPLETE';
|
|
58
|
+
interface CompletionDiagnostic extends Diagnostic {
|
|
59
|
+
code: CompletionDiagnosticCode;
|
|
60
|
+
}
|
|
61
|
+
declare function completionNodeAdded(nodeId: NodeId): CompletionDiagnostic;
|
|
62
|
+
declare function completionEdgeResolved(triple: EdgeTriple): CompletionDiagnostic;
|
|
63
|
+
declare function completionUnresolved(consumer: NodeId, depName: string, depRange: string): CompletionDiagnostic;
|
|
64
|
+
declare function completionNodeUnknown(nodeId: NodeId): CompletionDiagnostic;
|
|
65
|
+
declare function completionVersionUnknown(nodeId: NodeId): CompletionDiagnostic;
|
|
66
|
+
declare function completionPeerContextIncomplete(nodeId: NodeId, peerName: string, peerRange: string): CompletionDiagnostic;
|
|
67
|
+
|
|
68
|
+
export { type CompletionDiagnostic, type CompletionDiagnosticCode, type CompletionOptions, type CompletionResult, type CompletionSeed, ancestorsOf, completeTransitives, completionEdgeResolved, completionNodeAdded, completionNodeUnknown, completionPeerContextIncomplete, completionUnresolved, completionVersionUnknown, resolveFindUp };
|