@vzn/vx-lockfile 0.0.594 → 0.0.596
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/package.json +2 -2
- package/src/blocks.ts +1 -2
- package/src/bun.ts +1 -22
- package/src/json.ts +25 -0
- package/src/npm.ts +1 -22
- package/src/pnpm.ts +3 -8
- package/src/prune.ts +2 -3
- package/src/yarn.ts +1 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx-lockfile",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.596",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Lockfile plugins for vx — pnpm(), bun(), npm(), yarn(): each keys every task on its project's own resolved dependency closure from the package manager's lockfile, so a lockfile change re-keys only the projects it reaches; --affected follows the same answer; `vx prune` cuts the workspace and the lockfile to a Docker subset.",
|
|
6
6
|
"keywords": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@vzn/vx": "^0.0.
|
|
40
|
+
"@vzn/vx": "^0.0.596"
|
|
41
41
|
},
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|
package/src/blocks.ts
CHANGED
|
@@ -19,8 +19,7 @@ export function pruneEntries(
|
|
|
19
19
|
keep: (keyLine: string) => boolean,
|
|
20
20
|
): string[] {
|
|
21
21
|
const pad = ' '.repeat(indent)
|
|
22
|
-
const isKey = (l: string): boolean =>
|
|
23
|
-
l.startsWith(pad) && l.length > indent && l[indent] !== ' ' && l[indent] !== '#'
|
|
22
|
+
const isKey = (l: string): boolean => l.startsWith(pad) && /^[^\s#]/.test(l.slice(indent))
|
|
24
23
|
const head: string[] = []
|
|
25
24
|
let i = from
|
|
26
25
|
while (i < to && !isKey(lines[i]!)) head.push(lines[i++]!)
|
package/src/bun.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// Bun.JSONC is the parser: no dependency, and the file is Bun's own.
|
|
12
12
|
|
|
13
13
|
import { reachDigests } from '@vzn/vx'
|
|
14
|
+
import { depsOf, record, type Json } from './json.js'
|
|
14
15
|
import type { PruneScope } from './scope.js'
|
|
15
16
|
|
|
16
17
|
export interface Lockfile {
|
|
@@ -35,7 +36,6 @@ export interface Entry {
|
|
|
35
36
|
readonly resolution: string
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
type Json = Record<string, unknown>
|
|
39
39
|
/** The top-level fields the digest reads per workspace. */
|
|
40
40
|
// Read per workspace: the workspaces and packages themselves, and the fields
|
|
41
41
|
// whose whole effect is the `packages` entry a workspace reaches — how a
|
|
@@ -51,13 +51,6 @@ const PER_WORKSPACE = new Set([
|
|
|
51
51
|
'patchedDependencies',
|
|
52
52
|
])
|
|
53
53
|
|
|
54
|
-
const DEP_FIELDS = [
|
|
55
|
-
'dependencies',
|
|
56
|
-
'devDependencies',
|
|
57
|
-
'optionalDependencies',
|
|
58
|
-
'peerDependencies',
|
|
59
|
-
] as const
|
|
60
|
-
|
|
61
54
|
export function parseLockfile(text: string): Lockfile {
|
|
62
55
|
let doc: unknown
|
|
63
56
|
try {
|
|
@@ -110,20 +103,6 @@ export function parseLockfile(text: string): Lockfile {
|
|
|
110
103
|
}
|
|
111
104
|
}
|
|
112
105
|
|
|
113
|
-
function depsOf(m: Json): ReadonlyMap<string, string> {
|
|
114
|
-
const out = new Map<string, string>()
|
|
115
|
-
for (const field of DEP_FIELDS) {
|
|
116
|
-
const deps = record(m[field])
|
|
117
|
-
if (deps === undefined) continue
|
|
118
|
-
for (const [name, spec] of Object.entries(deps)) out.set(name, String(spec))
|
|
119
|
-
}
|
|
120
|
-
return out
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function record(v: unknown): Json | undefined {
|
|
124
|
-
return v !== null && typeof v === 'object' && !Array.isArray(v) ? (v as Json) : undefined
|
|
125
|
-
}
|
|
126
|
-
|
|
127
106
|
/**
|
|
128
107
|
* Where dependency `name` of the package at node_modules path `from`
|
|
129
108
|
* lives: the deepest `…/name` key up the path, then the root. A workspace
|
package/src/json.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type Json = Record<string, unknown>
|
|
2
|
+
|
|
3
|
+
const DEP_FIELDS = [
|
|
4
|
+
'dependencies',
|
|
5
|
+
'devDependencies',
|
|
6
|
+
'optionalDependencies',
|
|
7
|
+
'peerDependencies',
|
|
8
|
+
] as const
|
|
9
|
+
|
|
10
|
+
export function depsOf(
|
|
11
|
+
e: Json,
|
|
12
|
+
fields: readonly string[] = DEP_FIELDS,
|
|
13
|
+
): ReadonlyMap<string, string> {
|
|
14
|
+
const out = new Map<string, string>()
|
|
15
|
+
for (const field of fields) {
|
|
16
|
+
const deps = record(e[field])
|
|
17
|
+
if (deps === undefined) continue
|
|
18
|
+
for (const [name, spec] of Object.entries(deps)) out.set(name, String(spec))
|
|
19
|
+
}
|
|
20
|
+
return out
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function record(v: unknown): Json | undefined {
|
|
24
|
+
return v !== null && typeof v === 'object' && !Array.isArray(v) ? (v as Json) : undefined
|
|
25
|
+
}
|
package/src/npm.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
// ancestor directory's, else `node_modules/d` — Node's own walk.
|
|
9
9
|
|
|
10
10
|
import { reachDigests } from '@vzn/vx'
|
|
11
|
+
import { depsOf, record, type Json } from './json.js'
|
|
11
12
|
import type { PruneScope } from './scope.js'
|
|
12
13
|
|
|
13
14
|
export interface Lockfile {
|
|
@@ -27,14 +28,6 @@ export interface Entry {
|
|
|
27
28
|
readonly isWorkspace: boolean
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
type Json = Record<string, unknown>
|
|
31
|
-
const DEP_FIELDS = [
|
|
32
|
-
'dependencies',
|
|
33
|
-
'devDependencies',
|
|
34
|
-
'optionalDependencies',
|
|
35
|
-
'peerDependencies',
|
|
36
|
-
] as const
|
|
37
|
-
|
|
38
31
|
export function parseLockfile(text: string): Lockfile {
|
|
39
32
|
let doc: unknown
|
|
40
33
|
try {
|
|
@@ -74,20 +67,6 @@ export function parseLockfile(text: string): Lockfile {
|
|
|
74
67
|
return { version, packages, global }
|
|
75
68
|
}
|
|
76
69
|
|
|
77
|
-
function depsOf(e: Json): ReadonlyMap<string, string> {
|
|
78
|
-
const out = new Map<string, string>()
|
|
79
|
-
for (const field of DEP_FIELDS) {
|
|
80
|
-
const deps = record(e[field])
|
|
81
|
-
if (deps === undefined) continue
|
|
82
|
-
for (const [name, spec] of Object.entries(deps)) out.set(name, String(spec))
|
|
83
|
-
}
|
|
84
|
-
return out
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function record(v: unknown): Json | undefined {
|
|
88
|
-
return v !== null && typeof v === 'object' && !Array.isArray(v) ? (v as Json) : undefined
|
|
89
|
-
}
|
|
90
|
-
|
|
91
70
|
/**
|
|
92
71
|
* Node's walk: `p/node_modules/name`, then the same under each ancestor
|
|
93
72
|
* directory that is not itself a `node_modules`, then `node_modules/name`.
|
package/src/pnpm.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import { reachDigests } from '@vzn/vx'
|
|
15
15
|
import { pruneSections } from './blocks.js'
|
|
16
|
+
import { record } from './json.js'
|
|
16
17
|
import type { PruneScope } from './scope.js'
|
|
17
18
|
|
|
18
19
|
export interface Lockfile {
|
|
@@ -59,11 +60,9 @@ export function parseLockfile(text: string): Lockfile {
|
|
|
59
60
|
// with "regenerate it", which regenerates the same two documents.
|
|
60
61
|
const parsed: unknown = Bun.YAML.parse(text)
|
|
61
62
|
const docs = (Array.isArray(parsed) ? parsed : [parsed]).filter((d) => d !== null)
|
|
62
|
-
const doc = docs.at(-1)
|
|
63
|
+
const doc = record(docs.at(-1))
|
|
63
64
|
const leading = docs.slice(0, -1)
|
|
64
|
-
if (doc === undefined
|
|
65
|
-
throw new Error('pnpm-lock.yaml: not a YAML document')
|
|
66
|
-
}
|
|
65
|
+
if (doc === undefined) throw new Error('pnpm-lock.yaml: not a YAML document')
|
|
67
66
|
const version = scalar(doc['lockfileVersion'])
|
|
68
67
|
const major = Number.parseInt(version, 10)
|
|
69
68
|
if (!Number.isFinite(major) || major < 5) {
|
|
@@ -148,10 +147,6 @@ function scalar(v: unknown): string {
|
|
|
148
147
|
: ''
|
|
149
148
|
}
|
|
150
149
|
|
|
151
|
-
function record(v: unknown): Yaml | undefined {
|
|
152
|
-
return v !== null && typeof v === 'object' && !Array.isArray(v) ? (v as Yaml) : undefined
|
|
153
|
-
}
|
|
154
|
-
|
|
155
150
|
/** JSON with sorted keys, so YAML key order cannot move a digest. */
|
|
156
151
|
export function stable(v: unknown): string {
|
|
157
152
|
return JSON.stringify(v, (_k, val: unknown) =>
|
package/src/prune.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type ProjectMeta,
|
|
26
26
|
} from '@vzn/vx'
|
|
27
27
|
import * as bunLock from './bun.js'
|
|
28
|
+
import { record } from './json.js'
|
|
28
29
|
import * as npmLock from './npm.js'
|
|
29
30
|
import * as pnpmLock from './pnpm.js'
|
|
30
31
|
import * as yarnLock from './yarn.js'
|
|
@@ -317,9 +318,7 @@ async function namedFiles(root: string, manifest: Record<string, unknown>): Prom
|
|
|
317
318
|
const p = path.join(root, file)
|
|
318
319
|
if (!(await exists(p))) return {}
|
|
319
320
|
const doc: unknown = Bun.YAML.parse(await Bun.file(p).text())
|
|
320
|
-
return doc
|
|
321
|
-
? (doc as Record<string, unknown>)
|
|
322
|
-
: {}
|
|
321
|
+
return record(doc) ?? {}
|
|
323
322
|
}
|
|
324
323
|
named.push(...values((await yaml('pnpm-workspace.yaml'))['patchedDependencies']))
|
|
325
324
|
const yarnrc = await yaml('.yarnrc.yml')
|
package/src/yarn.ts
CHANGED
|
@@ -15,6 +15,7 @@ import path from 'node:path'
|
|
|
15
15
|
import { reachDigests } from '@vzn/vx'
|
|
16
16
|
import { stable } from './pnpm.js'
|
|
17
17
|
import { pruneEntries, yamlKey } from './blocks.js'
|
|
18
|
+
import { depsOf, record } from './json.js'
|
|
18
19
|
import type { PruneScope } from './scope.js'
|
|
19
20
|
|
|
20
21
|
export interface Lockfile {
|
|
@@ -45,8 +46,6 @@ export interface Entry {
|
|
|
45
46
|
readonly resolution: string
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
type Json = Record<string, unknown>
|
|
49
|
-
|
|
50
49
|
export function parseLockfile(text: string): Lockfile {
|
|
51
50
|
const head = text.slice(0, 400)
|
|
52
51
|
if (/^# yarn lockfile v1/m.test(head)) return parseClassic(text)
|
|
@@ -196,20 +195,6 @@ function unquote(s: string): string {
|
|
|
196
195
|
return s.length >= 2 && s.startsWith('"') && s.endsWith('"') ? s.slice(1, -1) : s
|
|
197
196
|
}
|
|
198
197
|
|
|
199
|
-
function depsOf(e: Json, fields: readonly string[]): ReadonlyMap<string, string> {
|
|
200
|
-
const out = new Map<string, string>()
|
|
201
|
-
for (const field of fields) {
|
|
202
|
-
const deps = record(e[field])
|
|
203
|
-
if (deps === undefined) continue
|
|
204
|
-
for (const [name, spec] of Object.entries(deps)) out.set(name, String(spec))
|
|
205
|
-
}
|
|
206
|
-
return out
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function record(v: unknown): Json | undefined {
|
|
210
|
-
return v !== null && typeof v === 'object' && !Array.isArray(v) ? (v as Json) : undefined
|
|
211
|
-
}
|
|
212
|
-
|
|
213
198
|
/**
|
|
214
199
|
* `bar` + `npm:^2` → the entry keyed `bar@npm:^2`; classic: `bar@^2`. A
|
|
215
200
|
* bare range gets berry's `npm:` prefix. A `workspace:` range resolves to
|