@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.
Files changed (78) hide show
  1. package/README.md +173 -94
  2. package/SCHEMAS.md +121 -0
  3. package/dist/_npm-flat-types-CR16JZFS.d.ts +18 -0
  4. package/dist/_pnpm-flat-core-DmGs4UQu.d.ts +41 -0
  5. package/dist/_yarn-berry-core-BhE-AhmX.d.ts +19 -0
  6. package/dist/complete.d.ts +68 -0
  7. package/dist/complete.js +335 -0
  8. package/dist/enrich.d.ts +34 -0
  9. package/dist/enrich.js +245 -0
  10. package/dist/formats/bun-text.d.ts +51 -0
  11. package/dist/formats/bun-text.js +1733 -0
  12. package/dist/formats/npm-1.d.ts +34 -0
  13. package/dist/formats/npm-1.js +1854 -0
  14. package/dist/formats/npm-2.d.ts +24 -0
  15. package/dist/formats/npm-2.js +2415 -0
  16. package/dist/formats/npm-3.d.ts +24 -0
  17. package/dist/formats/npm-3.js +2180 -0
  18. package/dist/formats/pnpm-v5.d.ts +38 -0
  19. package/dist/formats/pnpm-v5.js +2391 -0
  20. package/dist/formats/pnpm-v6.d.ts +28 -0
  21. package/dist/formats/pnpm-v6.js +3068 -0
  22. package/dist/formats/pnpm-v9.d.ts +28 -0
  23. package/dist/formats/pnpm-v9.js +3068 -0
  24. package/dist/formats/yarn-berry-v10.d.ts +24 -0
  25. package/dist/formats/yarn-berry-v10.js +3204 -0
  26. package/dist/formats/yarn-berry-v4.d.ts +24 -0
  27. package/dist/formats/yarn-berry-v4.js +3208 -0
  28. package/dist/formats/yarn-berry-v5.d.ts +24 -0
  29. package/dist/formats/yarn-berry-v5.js +3203 -0
  30. package/dist/formats/yarn-berry-v6.d.ts +24 -0
  31. package/dist/formats/yarn-berry-v6.js +3203 -0
  32. package/dist/formats/yarn-berry-v7.d.ts +24 -0
  33. package/dist/formats/yarn-berry-v7.js +3203 -0
  34. package/dist/formats/yarn-berry-v8.d.ts +24 -0
  35. package/dist/formats/yarn-berry-v8.js +3204 -0
  36. package/dist/formats/yarn-berry-v9.d.ts +24 -0
  37. package/dist/formats/yarn-berry-v9.js +3204 -0
  38. package/dist/formats/yarn-classic.d.ts +48 -0
  39. package/dist/formats/yarn-classic.js +2183 -0
  40. package/dist/graph-CPo-SvS2.d.ts +223 -0
  41. package/dist/index.d.ts +88 -0
  42. package/dist/index.js +11186 -0
  43. package/dist/modify-DuBV5-5V.d.ts +219 -0
  44. package/dist/modify.d.ts +20 -0
  45. package/dist/modify.js +1005 -0
  46. package/dist/optimize-B6TOjYyj.d.ts +33 -0
  47. package/dist/optimize.d.ts +80 -0
  48. package/dist/optimize.js +256 -0
  49. package/dist/registry.d.ts +64 -0
  50. package/dist/registry.js +687 -0
  51. package/dist/types-BPMSHpCF.d.ts +48 -0
  52. package/package.json +149 -36
  53. package/target/es6/analyze.d.ts +0 -2
  54. package/target/es6/common.d.ts +0 -26
  55. package/target/es6/format.d.ts +0 -2
  56. package/target/es6/formats/npm-1.d.ts +0 -22
  57. package/target/es6/formats/npm-2.d.ts +0 -16
  58. package/target/es6/formats/npm-3.d.ts +0 -29
  59. package/target/es6/formats/yarn-1.d.ts +0 -14
  60. package/target/es6/formats/yarn-5.d.ts +0 -20
  61. package/target/es6/formats/yarn-6.d.ts +0 -0
  62. package/target/es6/formats/yarn-7.d.ts +0 -0
  63. package/target/es6/formats/yarn-berry.d.ts +0 -20
  64. package/target/es6/formats/yarn-classic.d.ts +0 -14
  65. package/target/es6/index.d.ts +0 -5
  66. package/target/es6/index.js +0 -655
  67. package/target/es6/index.js.map +0 -7
  68. package/target/es6/interface.d.ts +0 -72
  69. package/target/es6/npm-1.d.ts +0 -19
  70. package/target/es6/npm-2.d.ts +0 -0
  71. package/target/es6/packument.d.ts +0 -0
  72. package/target/es6/parse.d.ts +0 -2
  73. package/target/es6/util.d.ts +0 -4
  74. package/target/es6/workspace.d.ts +0 -16
  75. package/target/es6/yarn-1.d.ts +0 -13
  76. package/target/es6/yarn-5.d.ts +0 -19
  77. package/target/es6/yarn-6.d.ts +0 -0
  78. 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
- ## Motivation
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
- 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/other format.
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
- ## Getting started
17
- ### Install
18
- ```shell
19
- yarn add @antongolub/lockfile
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
- ## Usage
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
- import { parse, format, analyze } from '@antongolub/lockfile'
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
- const snapshot = parse('yarn.lock <raw contents>', 'package.json <raw contents>', './packages/foo/package.json <raw contents>')
98
+ The graph is where the value lives `modify` and `optimize` transform it,
99
+ format-agnostically:
27
100
 
28
- const lf = format(snapshot)
29
- const lf2 = format(snapshot, 'npm-1') // Throws err: npm v1 meta does not support workspaces
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
- const meta = await readMeta() // reads local package.jsons data to gather required data like `engines`, `license`, `bins`, etc
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
- const idx = analyze(snapshot)
36
- idx.edges
37
- // [
38
- // [ '', '@antongolub/npm-test@4.0.1' ],
39
- // [ '@antongolub/npm-test@4.0.1', '@antongolub/npm-test@3.0.1' ],
40
- // [ '@antongolub/npm-test@3.0.1', '@antongolub/npm-test@2.0.1' ],
41
- // [ '@antongolub/npm-test@2.0.1', '@antongolub/npm-test@1.0.0' ]
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
- ### Terms
46
- * `nmtree` fs projection of deps, directories structure
47
- * `deptree` bounds full dep paths with their resolved packages
48
- * `depgraph` describes how resolved pkgs are related with each other
49
-
50
- ### Lockfiles formats
51
- | Package manager | Meta format | Read | Write |
52
- |------------------|-------------|------|-------|
53
- | npm <7 | 1 | ✓ | ✓ |
54
- | npm >=7 | 2 | | |
55
- | npm >=9 | 3 | | |
56
- | yarn 1 (classic) | 1 | ✓ | |
57
- | yarn 2 (berry) | 5, 6, 7 | ✓ | |
58
-
59
- ### Reference protocols
60
- | Type | Supported |
61
- |-----------|-----------|
62
- | semver | ✓ |
63
- | npm | ✓ |
64
- | workspace | |
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
- export type TSnapshot = Record<string, {
75
- name: string
76
- version: string
77
- ranges: string[]
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
- ### Caveats
103
- * There is an infinite number of `nmtrees` that corresponds to the specified `deptree`, but among them there is a finite set of effective (sufficient) for the target criterion — for example, nesting, size, homogeneity of versions
104
- * npm1: `optional: true` label is not supported by `format`
105
- * yarn berry: no idea how to resolve and inject PnP patches https://github.com/yarnpkg/berry/tree/master/packages/plugin-compat
106
- * npm2 and npm3 requires `engines` and `funding` data, while yarn* or npm1 does not contain it
107
- * many `nmtree` projections may correspond the specified `depgraph`
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
- ### Inspired by
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 };