@antongolub/lockfile 0.0.0-snapshot.43 → 0.0.0-snapshot.44
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 +130 -202
- package/SCHEMAS.md +120 -0
- package/dist/_npm-flat-types-DwOV4BpV.d.ts +14 -0
- package/dist/_pnpm-flat-core-_4KM9kQj.d.ts +37 -0
- package/dist/_yarn-berry-core-EKBJ_ohM.d.ts +16 -0
- package/dist/formats/bun-text.d.ts +34 -0
- package/dist/formats/bun-text.js +1399 -0
- package/dist/formats/npm-1.d.ts +34 -0
- package/dist/formats/npm-1.js +1651 -0
- package/dist/formats/npm-2.d.ts +24 -0
- package/dist/formats/npm-2.js +1955 -0
- package/dist/formats/npm-3.d.ts +24 -0
- package/dist/formats/npm-3.js +1727 -0
- package/dist/formats/pnpm-v5.d.ts +38 -0
- package/dist/formats/pnpm-v5.js +2108 -0
- package/dist/formats/pnpm-v6.d.ts +28 -0
- package/dist/formats/pnpm-v6.js +2634 -0
- package/dist/formats/pnpm-v9.d.ts +28 -0
- package/dist/formats/pnpm-v9.js +2634 -0
- package/dist/formats/yarn-berry-v4.d.ts +24 -0
- package/dist/formats/yarn-berry-v4.js +2252 -0
- package/dist/formats/yarn-berry-v5.d.ts +24 -0
- package/dist/formats/yarn-berry-v5.js +2247 -0
- package/dist/formats/yarn-berry-v6.d.ts +24 -0
- package/dist/formats/yarn-berry-v6.js +2247 -0
- package/dist/formats/yarn-berry-v7.d.ts +24 -0
- package/dist/formats/yarn-berry-v7.js +2247 -0
- package/dist/formats/yarn-berry-v8.d.ts +24 -0
- package/dist/formats/yarn-berry-v8.js +2248 -0
- package/dist/formats/yarn-berry-v9.d.ts +24 -0
- package/dist/formats/yarn-berry-v9.js +2248 -0
- package/dist/formats/yarn-classic.d.ts +34 -0
- package/dist/formats/yarn-classic.js +1599 -0
- package/dist/graph-BzsItuAI.d.ts +154 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +6814 -0
- package/package.json +106 -60
- package/target/cjs/index.cjs +0 -1096
- package/target/cjs/vendor.cjs +0 -8500
- package/target/dts/analyze.d.ts +0 -7
- package/target/dts/cli.d.ts +0 -11
- package/target/dts/common.d.ts +0 -28
- package/target/dts/convert.d.ts +0 -3
- package/target/dts/format.d.ts +0 -2
- package/target/dts/formats/npm-1.d.ts +0 -24
- package/target/dts/formats/npm-2.d.ts +0 -16
- package/target/dts/formats/npm-3.d.ts +0 -36
- package/target/dts/formats/yarn-berry.d.ts +0 -22
- package/target/dts/formats/yarn-classic.d.ts +0 -16
- package/target/dts/index.d.ts +0 -7
- package/target/dts/interface.d.ts +0 -90
- package/target/dts/parse.d.ts +0 -3
- package/target/dts/util.d.ts +0 -11
- package/target/dts/vendor.d.ts +0 -3
- package/target/esm/cli.mjs +0 -77
- package/target/esm/index.mjs +0 -1017
- package/target/esm/vendor.mjs +0 -8458
package/README.md
CHANGED
|
@@ -1,238 +1,166 @@
|
|
|
1
1
|
# @antongolub/lockfile
|
|
2
|
-
> Read and write lockfiles with reasonable losses
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
> Universal lockfile model and converter for **npm**, **yarn**, **pnpm**, **bun**.
|
|
4
|
+
|
|
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. It looks acceptable to a developer staring at a
|
|
9
|
+
single repo, but it becomes a real headache for IS, DevOps and release
|
|
10
|
+
engineers — and impossible for any tool that needs to reason about
|
|
11
|
+
dependency graphs across the ecosystem.
|
|
12
|
+
|
|
13
|
+
This library models the dependency graph independent of any specific
|
|
14
|
+
package manager, then projects it back into the format you need.
|
|
15
|
+
Conversion is one use case; modification (audit-fix, override pinning,
|
|
16
|
+
license filtering) is the headline.
|
|
8
17
|
|
|
9
|
-
The `package.json` manifest contains its own deps requirements, the `lockfile` holds the deps resolution snapshot<sup>*</sup>,
|
|
10
|
-
so both of them are required to build a dependency graph. We can try to convert this data into a normalized representation for further analysis and processing (for example, to fix vulnerabilities).
|
|
11
|
-
And then, if necessary, try convert it back to the original/another format.
|
|
12
18
|
</p>
|
|
13
19
|
|
|
14
20
|
## Status
|
|
15
|
-
Proof of concept. The API may change significantly ⚠️
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
🔒 **Contract preview, implementation in progress.** The public API
|
|
23
|
+
(`parse` / `stringify`) is locked. Adapter implementations are landing
|
|
24
|
+
incrementally — see [SCHEMAS.md](./SCHEMAS.md) for what's recognised.
|
|
25
|
+
Not yet published; `npm install` will appear once the first adapters
|
|
26
|
+
ship end-to-end.
|
|
22
27
|
|
|
23
|
-
##
|
|
24
|
-
_tl;dr_
|
|
25
|
-
```ts
|
|
26
|
-
import fs from 'fs/promises'
|
|
27
|
-
import {parse, analyze} from '@antongolub/lockfile'
|
|
28
|
+
## Concept
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
A target lockfile is **constructed** from facts gathered across whatever
|
|
31
|
+
sources are available: the input lockfile bytes, project `package.json`s,
|
|
32
|
+
the package-manager cache, and (opt-in) the registry. The simplest case is
|
|
33
|
+
*conversion* — parse one format, stringify another. The general case is
|
|
34
|
+
*construction*: assemble what the target requires from whichever source can
|
|
35
|
+
supply it.
|
|
31
36
|
|
|
32
|
-
|
|
33
|
-
const idx = analyze(snapshot) // An index to represent repo dep graphs
|
|
37
|
+
Three layers, never collapsed:
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
- **Manifest** — declared constraints from `package.json`(s).
|
|
40
|
+
- **Graph** — resolved package instances (peer-aware) and the edges
|
|
41
|
+
between them. The canonical internal model. Modifiers operate here.
|
|
42
|
+
- **Layout** — physical projection on disk: hoisted, isolated (pnpm-style),
|
|
43
|
+
PnP, nm-linked.
|
|
44
|
+
|
|
45
|
+
Conversion is **lossy by design**. We aim for *semantically equivalent*,
|
|
46
|
+
not *byte-identical*. Irreducible facts (integrity hashes, resolution URLs,
|
|
47
|
+
signatures) are the exception — they are never silently lost.
|
|
39
48
|
|
|
40
49
|
## API
|
|
41
|
-
### JS/TS
|
|
42
|
-
```ts
|
|
43
|
-
import { parse, format, analyze, convert } from '@antongolub/lockfile'
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const snapshot = parse(lf, pkgJson)
|
|
51
|
+
```ts
|
|
52
|
+
import { parse, stringify } from '@antongolub/lockfile'
|
|
48
53
|
|
|
49
|
-
const
|
|
50
|
-
const
|
|
54
|
+
const lf = parse(rawLockfileBytes)
|
|
55
|
+
const str = stringify(lf, { format: 'npm-3' })
|
|
56
|
+
```
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
const meta2 = await fetchMeta(snapshot) // does the same, but from the remote registry
|
|
54
|
-
const lf3 = format(snapshot, 'npm-3', {meta}) // format with options
|
|
58
|
+
Two top-level operations, modelled on `JSON.parse` / `JSON.stringify`:
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// [
|
|
59
|
-
// [ '', '@antongolub/npm-test@4.0.1' ],
|
|
60
|
-
// [ '@antongolub/npm-test@4.0.1', '@antongolub/npm-test@3.0.1' ],
|
|
61
|
-
// [ '@antongolub/npm-test@3.0.1', '@antongolub/npm-test@2.0.1' ],
|
|
62
|
-
// [ '@antongolub/npm-test@2.0.1', '@antongolub/npm-test@1.0.0' ]
|
|
63
|
-
// ]
|
|
60
|
+
```ts
|
|
61
|
+
parse(input: string | Uint8Array, options?: ParseOptions): Lockfile
|
|
64
62
|
|
|
65
|
-
|
|
63
|
+
stringify(lockfile: Lockfile, options: StringifyOptions): string
|
|
66
64
|
```
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
- `parse` auto-detects the format by content sniffing. Pass
|
|
67
|
+
`{ format: '<id>' }` to skip detection. Pass `{ manifests }` for
|
|
68
|
+
formats that need extra workspace context (notably `yarn-classic`).
|
|
69
|
+
- `stringify`'s `options.format` is **required** — there is no implicit
|
|
70
|
+
"same as parsed". Round-tripping is an explicit choice the caller makes.
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
`Lockfile` is the public alias for the internal canonical-graph type.
|
|
73
|
+
`FormatId` is a string-literal union — see
|
|
74
|
+
[SCHEMAS.md](./SCHEMAS.md) for the full list.
|
|
75
|
+
|
|
76
|
+
### Options
|
|
75
77
|
|
|
76
|
-
| Command / Option | Description |
|
|
77
|
-
|------------------|---------------------------------------------------------------------------------------|
|
|
78
|
-
| `parse` | Parses lockfiles and package manifests into a snapshot |
|
|
79
|
-
| `format` | Formats a snapshot into a lockfile |
|
|
80
|
-
| `convert` | Converts a lockfile into another format. Shortcut for `parse` + `format` |
|
|
81
|
-
| `--input` | A comma-separated list of files to parse: `snapshot.json` or `yarn.lock,package.json` |
|
|
82
|
-
| `--output` | A file to write the result to: `snapshot.json` or `yarn.lock` |
|
|
83
|
-
| `--format` | A lockfile format: `npm-1`, `npm-2`, `npm-3`, `yarn-berry`, `yarn-classic` |
|
|
84
|
-
|
|
85
|
-
### Terms
|
|
86
|
-
`nmtree` — fs projection of deps, directories structure
|
|
87
|
-
`deptree` — bounds full dep paths with their resolved packages
|
|
88
|
-
`depgraph` — describes how resolved pkgs are related with each other
|
|
89
|
-
|
|
90
|
-
### Lockfiles types
|
|
91
|
-
| Package manager | Meta format | Read | Write |
|
|
92
|
-
|----------------------|-------------|------|-------|
|
|
93
|
-
| npm <7 | 1 | ✓ | ✓ |
|
|
94
|
-
| npm >=7 | 2 | ✓ | |
|
|
95
|
-
| npm >=9 | 3 | ✓ | |
|
|
96
|
-
| yarn 1 (classic) | 1 | ✓ | ✓ |
|
|
97
|
-
| yarn 2, 3, 4 (berry) | 5, 6, 7 | ✓ | ✓ |
|
|
98
|
-
|
|
99
|
-
### Dependency protocols
|
|
100
|
-
| Type | Supported | Example | Description |
|
|
101
|
-
|-----------|-----------|-----------------------------------------|----------------------------------------------------------------|
|
|
102
|
-
| semver | ✓ | `^1.2.3` | Resolves from the default registry |
|
|
103
|
-
| tag | | `latest` | Resolves from the default registry |
|
|
104
|
-
| npm | ✓ | `npm:name@...` | Resolves from the npm registry |
|
|
105
|
-
| git | | `git@github.com:foo/bar.git` | Downloads a public package from a Git repository |
|
|
106
|
-
| github | | `github:foo/bar` | Downloads a public package from GitHub |
|
|
107
|
-
| github | ✓ | `foo/bar` | Alias for the github: protocol |
|
|
108
|
-
| file | | `file:./my-package` | Copies the target location into the cache |
|
|
109
|
-
| link | | `link:./my-folder` | Creates a link to the ./my-folder folder (ignore dependencies) |
|
|
110
|
-
| patch | _limited_ | `patch:left-pad@1.0.0#./my-patch.patch` | Creates a patched copy of the original package |
|
|
111
|
-
| portal | | `portal:./my-folder` | Creates a link to the ./my-folder folder (follow dependencies) |
|
|
112
|
-
| workspace | _limited_ | `workspace:*` | Creates a link to a package in another workspace |
|
|
113
|
-
|
|
114
|
-
https://v3.yarnpkg.com/features/protocols
|
|
115
|
-
https://yarnpkg.com/protocols
|
|
116
|
-
https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies
|
|
117
|
-
|
|
118
|
-
### `TSnapshot`
|
|
119
78
|
```ts
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
sha512?: string
|
|
128
|
-
sha256?: string
|
|
129
|
-
sha1?: string
|
|
130
|
-
checksum?: string
|
|
131
|
-
md5?: string
|
|
132
|
-
}
|
|
133
|
-
source: {
|
|
134
|
-
type: TSourceType // npm, workspace, gh, patch, etc
|
|
135
|
-
id: string
|
|
136
|
-
registry?: string
|
|
137
|
-
}
|
|
138
|
-
// optional pm-specific lockfile meta
|
|
139
|
-
manifest?: TManifest
|
|
140
|
-
conditions?: string
|
|
141
|
-
dependencies?: TDependencies
|
|
142
|
-
dependenciesMeta?: TDependenciesMeta
|
|
143
|
-
devDependencies?: TDependencies
|
|
144
|
-
optionalDependencies?: TDependencies
|
|
145
|
-
peerDependencies?: TDependencies
|
|
146
|
-
peerDependenciesMeta?: TDependenciesMeta
|
|
147
|
-
bin?: Record<string, string>
|
|
148
|
-
engines?: Record<string, string>
|
|
149
|
-
funding?: Record<string, string>
|
|
79
|
+
type ParseOptions = {
|
|
80
|
+
format?: FormatId // skip auto-detect
|
|
81
|
+
manifests?: Manifests // package.jsons keyed by workspace path
|
|
82
|
+
pmConfig?: PmConfig // .npmrc / .yarnrc.yml / pnpm-workspace.yaml / bunfig.toml
|
|
83
|
+
installDir?: string // path to node_modules / .pnp.cjs (refinement)
|
|
84
|
+
cache?: CacheAdapter // PM cache (refinement)
|
|
85
|
+
registry?: RegistryAdapter // network access (opt-in)
|
|
150
86
|
}
|
|
151
|
-
```
|
|
152
87
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
key: string
|
|
162
|
-
chunks: string[]
|
|
163
|
-
parents: TEntry[]
|
|
164
|
-
id: string
|
|
165
|
-
name: string
|
|
166
|
-
version: string
|
|
167
|
-
entry: TEntry
|
|
168
|
-
depth: number // the lowest level where the dep@ver first time occurs
|
|
169
|
-
}>
|
|
170
|
-
prod: Set<TEntry>
|
|
171
|
-
getEntryId ({name, version}: TEntry): string
|
|
172
|
-
getEntry (name: string, version?: string): TEntry | undefined,
|
|
173
|
-
getEntryByRange (name: string, range: string): TEntry | undefined
|
|
174
|
-
getEntryDeps(entry: TEntry): TEntry[]
|
|
88
|
+
type StringifyOptions = {
|
|
89
|
+
format: FormatId // required
|
|
90
|
+
manifests?: Manifests
|
|
91
|
+
pmConfig?: PmConfig
|
|
92
|
+
installDir?: string
|
|
93
|
+
cache?: CacheAdapter
|
|
94
|
+
registry?: RegistryAdapter
|
|
95
|
+
onDiagnostic?: (d: Diagnostic) => void
|
|
175
96
|
}
|
|
176
97
|
```
|
|
177
98
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
99
|
+
`pmConfig` / `installDir` / `cache` / `registry` are progressive
|
|
100
|
+
**refinement opt-ins**: each unlocks more information at higher cost. The
|
|
101
|
+
default succeeds offline, against the lockfile bytes (and `manifests`)
|
|
102
|
+
alone.
|
|
103
|
+
|
|
104
|
+
### Sub-imports
|
|
105
|
+
|
|
106
|
+
| Surface | Importable as | Contains |
|
|
107
|
+
|---------|---------------|----------|
|
|
108
|
+
| Root | `@antongolub/lockfile` | `parse`, `stringify`, plus types: `Lockfile`, `FormatId`, `ParseOptions`, `StringifyOptions`, `Manifest`, `Manifests` |
|
|
109
|
+
| Modifiers | `@antongolub/lockfile/modify` | audit-fix, override-pin, license-filter |
|
|
110
|
+
| Registry | `@antongolub/lockfile/registry` | adapters for live npm, file cache, frozen-from-lockfile |
|
|
111
|
+
| Per-format | `@antongolub/lockfile/formats/<id>` | direct access to a single adapter (test surface; not a primary user API) |
|
|
112
|
+
|
|
113
|
+
### Errors
|
|
114
|
+
|
|
115
|
+
`parse` / `stringify` throw a single `LockfileError` discriminated by
|
|
116
|
+
`code`:
|
|
117
|
+
|
|
189
118
|
```ts
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
119
|
+
'PARSE_FAILED' | 'FORMAT_DETECT_FAILED' | 'FORMAT_MISMATCH'
|
|
120
|
+
| 'CAPABILITY_LACK' | 'MISSING_MANIFEST'
|
|
121
|
+
| 'IRREDUCIBLE_LOSS' | 'INVARIANT_VIOLATION'
|
|
193
122
|
```
|
|
194
123
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
let max = 0
|
|
199
|
-
let chain: TEntry[] = []
|
|
200
|
-
|
|
201
|
-
for (const e of Object.values(idx.tree)) {
|
|
202
|
-
if (e.depth > max) {
|
|
203
|
-
max = e.depth
|
|
204
|
-
chain = [...e.parents, e.entry]
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return chain
|
|
208
|
-
}
|
|
124
|
+
Reducible losses (e.g. dropped patches when emitting `npm-1` from a
|
|
125
|
+
yarn-berry source) surface as `Diagnostic` events via the
|
|
126
|
+
`onDiagnostic` callback, not exceptions.
|
|
209
127
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
128
|
+
## Schemas
|
|
129
|
+
|
|
130
|
+
Every recognised lockfile schema is enumerated in
|
|
131
|
+
[SCHEMAS.md](./SCHEMAS.md), with adapter ids, the schema-marker each
|
|
132
|
+
carries, the package-manager versions that emit it by default, and
|
|
133
|
+
permalinked sources. Use that table as the index when calling
|
|
134
|
+
`parse({ format })` or `stringify({ format })`.
|
|
216
135
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
136
|
+
## Predecessor and inspirations
|
|
137
|
+
|
|
138
|
+
This project is the architectural successor to
|
|
139
|
+
[`yarn-audit-fix`](https://github.com/antongolub/yarn-audit-fix), generalised
|
|
140
|
+
beyond yarn.
|
|
141
|
+
|
|
142
|
+
Earlier work in this space:
|
|
143
|
+
|
|
144
|
+
- [synp](https://github.com/imsnif/synp)
|
|
145
|
+
- [snyk-nodejs-lockfile-parser](https://github.com/snyk/nodejs-lockfile-parser)
|
|
146
|
+
- [`@yarnpkg/lockfile`](https://github.com/yarnpkg/yarn/tree/master/packages/lockfile)
|
|
147
|
+
- [`pnpm/lockfile-utils`](https://github.com/pnpm/pnpm/tree/main/lockfile)
|
|
148
|
+
|
|
149
|
+
## Package-manager docs
|
|
150
|
+
|
|
151
|
+
- [`package-lock.json`](https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json)
|
|
152
|
+
— npm
|
|
153
|
+
- [yarn lockfile (classic)](https://classic.yarnpkg.com/lang/en/docs/yarn-lock/)
|
|
154
|
+
/ [yarn lockfile (berry)](https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-core/sources/Project.ts)
|
|
155
|
+
- [`pnpm/spec/lockfile/`](https://github.com/pnpm/spec/tree/master/lockfile)
|
|
156
|
+
— pnpm
|
|
157
|
+
- [bun lockfile](https://bun.com/docs/pm/lockfile) — bun
|
|
158
|
+
|
|
159
|
+
## Compatibility
|
|
160
|
+
|
|
161
|
+
- **Node ≥ 20.** No browser build planned.
|
|
162
|
+
- **ESM only.** Consumers on CommonJS use dynamic `await import(…)`.
|
|
236
163
|
|
|
237
164
|
## License
|
|
165
|
+
|
|
238
166
|
[MIT](./LICENSE)
|
package/SCHEMAS.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
|
|
37
|
+
**Schema numbers that don't exist:**
|
|
38
|
+
- `__metadata.version: 1` and `2` were never used by berry.
|
|
39
|
+
- `__metadata.version: 7` was skipped — yarn went `6 → 8` in 4.0.0.
|
|
40
|
+
|
|
41
|
+
`YARN_LOCKFILE_VERSION_OVERRIDE` (yarn 4+) lets one binary write any
|
|
42
|
+
schema version it can read; structural fidelity to the canonical
|
|
43
|
+
writer is not guaranteed.
|
|
44
|
+
|
|
45
|
+
## pnpm
|
|
46
|
+
|
|
47
|
+
| Adapter id | Marker | Default writer |
|
|
48
|
+
|------------|--------------------------|----------------------|
|
|
49
|
+
| `pnpm-v5` | `lockfileVersion: 5.x` | pnpm `>=3 <8` (pnpm 7 stayed on `5.4` by default) |
|
|
50
|
+
| `pnpm-v6` | `lockfileVersion: '6.0'`/`'6.1'` | pnpm `>=8 <9` |
|
|
51
|
+
| `pnpm-v9` | `lockfileVersion: '9.0'` | pnpm `>=9` |
|
|
52
|
+
|
|
53
|
+
**Schema numbers that don't exist:** `7` and `8`. pnpm 9 jumped
|
|
54
|
+
straight from `6.x` to `9.0`.
|
|
55
|
+
|
|
56
|
+
## bun
|
|
57
|
+
|
|
58
|
+
| Adapter id | Marker | Default writer | Status |
|
|
59
|
+
|---------------|---------------------------------|----------------|--------|
|
|
60
|
+
| `bun-text` | `bun.lock` filename + JSONC | bun `>=1.2` | primary bun target |
|
|
61
|
+
| `bun-binary` | `bun.lockb` filename + magic | bun `<1.2` | detect-only — not parsed |
|
|
62
|
+
|
|
63
|
+
`bun-binary` is a **permanent non-goal**: when `parse()` detects
|
|
64
|
+
`bun.lockb` magic bytes it throws with a hint to migrate via bun's
|
|
65
|
+
own tooling (`bun install --save-text-lockfile`). The library handles
|
|
66
|
+
the resulting `bun.lock` via the `bun-text` adapter. bun's own
|
|
67
|
+
binary reader stays in bun for back-compat — that is bun's
|
|
68
|
+
responsibility, not ours.
|
|
69
|
+
|
|
70
|
+
## Sources
|
|
71
|
+
|
|
72
|
+
Where each schema is canonically defined. Permalinks pinned at specific
|
|
73
|
+
release tags / commits so claims here stay anchored.
|
|
74
|
+
|
|
75
|
+
### npm
|
|
76
|
+
|
|
77
|
+
- [npm v7 series — beta release & semver-major changes](https://blog.npmjs.org/post/626173315965468672/npm-v7-series-beta-release-and-semver-major.html)
|
|
78
|
+
— introduces `lockfileVersion: 2` (`packages` block, workspaces).
|
|
79
|
+
- [package-lock.json docs (npm v9)](https://docs.npmjs.com/cli/v9/configuring-npm/package-lock-json/)
|
|
80
|
+
— schema reference for v3.
|
|
81
|
+
- [GitHub: dependency-graph and Dependabot support npm v9](https://github.blog/changelog/2023-03-10-dependency-graph-and-dependabot-support-npm-v9/)
|
|
82
|
+
— confirms v3 drops the legacy `dependencies` mirror.
|
|
83
|
+
|
|
84
|
+
### yarn
|
|
85
|
+
|
|
86
|
+
- [`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)
|
|
87
|
+
— `LOCKFILE_VERSION = 4`.
|
|
88
|
+
- [`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)
|
|
89
|
+
— `LOCKFILE_VERSION = 5` (one-minor window).
|
|
90
|
+
- [`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)
|
|
91
|
+
— `LOCKFILE_VERSION = 6`.
|
|
92
|
+
- [`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)
|
|
93
|
+
— bumps to 8; `YARN_LOCKFILE_VERSION_OVERRIDE` env var introduced here.
|
|
94
|
+
- [`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)
|
|
95
|
+
— current `LOCKFILE_VERSION = 9`.
|
|
96
|
+
- [Yarn 4.0 release blog](https://yarnpkg.com/blog/release/4.0)
|
|
97
|
+
— narrative context (no explicit lockfile-bump mention).
|
|
98
|
+
|
|
99
|
+
### pnpm
|
|
100
|
+
|
|
101
|
+
- [`pnpm/spec` — lockfile/](https://github.com/pnpm/spec/tree/master/lockfile)
|
|
102
|
+
— official per-version schema docs (`5.md`, `5.2.md`, `6.0.md`, `9.0.md`).
|
|
103
|
+
- [`pnpm/spec/lockfile/6.0.md`](https://github.com/pnpm/spec/blob/master/lockfile/6.0.md)
|
|
104
|
+
— pnpm 8's schema, including the package-id grammar shift.
|
|
105
|
+
- [`pnpm/spec/lockfile/9.0.md`](https://github.com/pnpm/spec/blob/master/lockfile/9.0.md)
|
|
106
|
+
— pnpm 9's `packages` / `snapshots` split.
|
|
107
|
+
- [pnpm Discussion #6857](https://github.com/orgs/pnpm/discussions/6857)
|
|
108
|
+
— maintainer rationale for the `6 → 9` jump:
|
|
109
|
+
*"in the future lockfile version will equal the pnpm version in
|
|
110
|
+
which it got introduced."*
|
|
111
|
+
|
|
112
|
+
### bun
|
|
113
|
+
|
|
114
|
+
- [Bun docs — Lockfile](https://bun.com/docs/pm/lockfile)
|
|
115
|
+
— current schema reference for `bun.lock`.
|
|
116
|
+
- [Bun blog — text-based lockfile](https://bun.com/blog/bun-lock-text-lockfile)
|
|
117
|
+
— text format introduced in 1.1.39, default in 1.2.
|
|
118
|
+
- [`bun-lock` source](https://github.com/oven-sh/bun) — `src/install/lockfile.zig`
|
|
119
|
+
for the binary serializer.
|
|
120
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { D as Diagnostic } from './graph-BzsItuAI.js';
|
|
2
|
+
|
|
3
|
+
interface NpmFamilyParseOptions {
|
|
4
|
+
}
|
|
5
|
+
interface NpmFamilyStringifyOptions {
|
|
6
|
+
lineEnding?: 'lf' | 'crlf';
|
|
7
|
+
onDiagnostic?: (diagnostic: Diagnostic) => void;
|
|
8
|
+
}
|
|
9
|
+
interface NpmFamilyEnrichOptions {
|
|
10
|
+
}
|
|
11
|
+
interface NpmFamilyOptimizeOptions {
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type { NpmFamilyEnrichOptions as N, NpmFamilyOptimizeOptions as a, NpmFamilyParseOptions as b, NpmFamilyStringifyOptions as c };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { D as Diagnostic } from './graph-BzsItuAI.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
|
+
}
|
|
19
|
+
interface PnpmManifest {
|
|
20
|
+
name?: string;
|
|
21
|
+
version?: string;
|
|
22
|
+
dependencies?: Record<string, string>;
|
|
23
|
+
devDependencies?: Record<string, string>;
|
|
24
|
+
optionalDependencies?: Record<string, string>;
|
|
25
|
+
peerDependencies?: Record<string, string>;
|
|
26
|
+
}
|
|
27
|
+
interface PnpmFamilyEnrichOptions {
|
|
28
|
+
manifests?: Record<string, PnpmManifest>;
|
|
29
|
+
}
|
|
30
|
+
interface PnpmFamilyOptimizeOptions {
|
|
31
|
+
}
|
|
32
|
+
interface PnpmSettings {
|
|
33
|
+
autoInstallPeers?: boolean;
|
|
34
|
+
excludeLinksFromLockfile?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type { PnpmFamilyEnrichOptions as P, PnpmManifest as a, PnpmFamilyOptimizeOptions as b, PnpmFamilyParseOptions as c, PnpmSettings as d, PnpmFamilyStringifyOptions as e };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { D as Diagnostic } from './graph-BzsItuAI.js';
|
|
2
|
+
|
|
3
|
+
interface YarnBerryFamilyParseOptions {
|
|
4
|
+
workspaceRoot?: string;
|
|
5
|
+
}
|
|
6
|
+
interface YarnBerryFamilyStringifyOptions {
|
|
7
|
+
lineEnding?: 'lf' | 'crlf';
|
|
8
|
+
cacheKey?: string;
|
|
9
|
+
onDiagnostic?: (diagnostic: Diagnostic) => void;
|
|
10
|
+
}
|
|
11
|
+
interface YarnBerryFamilyEnrichOptions {
|
|
12
|
+
}
|
|
13
|
+
interface YarnBerryFamilyOptimizeOptions {
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type { YarnBerryFamilyEnrichOptions as Y, YarnBerryFamilyOptimizeOptions as a, YarnBerryFamilyParseOptions as b, YarnBerryFamilyStringifyOptions as c };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { D as Diagnostic, G as Graph } from '../graph-BzsItuAI.js';
|
|
2
|
+
|
|
3
|
+
interface BunTextParseOptions {
|
|
4
|
+
}
|
|
5
|
+
interface BunTextStringifyOptions {
|
|
6
|
+
lineEnding?: 'lf' | 'crlf';
|
|
7
|
+
onDiagnostic?: (diagnostic: Diagnostic) => void;
|
|
8
|
+
}
|
|
9
|
+
interface BunTextManifest {
|
|
10
|
+
name?: string;
|
|
11
|
+
version?: string;
|
|
12
|
+
dependencies?: Record<string, string>;
|
|
13
|
+
devDependencies?: Record<string, string>;
|
|
14
|
+
optionalDependencies?: Record<string, string>;
|
|
15
|
+
peerDependencies?: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
interface BunTextEnrichOptions {
|
|
18
|
+
manifests?: Record<string, BunTextManifest>;
|
|
19
|
+
}
|
|
20
|
+
interface BunTextOptimizeOptions {
|
|
21
|
+
}
|
|
22
|
+
declare function check(input: string): boolean;
|
|
23
|
+
declare function parse(input: string, _options?: BunTextParseOptions): Graph;
|
|
24
|
+
declare function stringify(graph: Graph, options?: BunTextStringifyOptions): string;
|
|
25
|
+
declare function enrich(graph: Graph, options?: BunTextEnrichOptions): {
|
|
26
|
+
graph: Graph;
|
|
27
|
+
diagnostics: Diagnostic[];
|
|
28
|
+
};
|
|
29
|
+
declare function optimize(graph: Graph, _options?: BunTextOptimizeOptions): {
|
|
30
|
+
graph: Graph;
|
|
31
|
+
diagnostics: Diagnostic[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export { type BunTextEnrichOptions, type BunTextManifest, type BunTextOptimizeOptions, type BunTextParseOptions, type BunTextStringifyOptions, check, enrich, optimize, parse, stringify };
|