flatlock 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +54 -1
  2. package/bin/flatlock-cmp.js +71 -45
  3. package/dist/compare.d.ts +25 -3
  4. package/dist/compare.d.ts.map +1 -1
  5. package/dist/detect.d.ts.map +1 -1
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/parsers/index.d.ts +2 -2
  9. package/dist/parsers/npm.d.ts +64 -37
  10. package/dist/parsers/npm.d.ts.map +1 -1
  11. package/dist/parsers/pnpm/detect.d.ts +136 -0
  12. package/dist/parsers/pnpm/detect.d.ts.map +1 -0
  13. package/dist/parsers/pnpm/index.d.ts +120 -0
  14. package/dist/parsers/pnpm/index.d.ts.map +1 -0
  15. package/dist/parsers/pnpm/internal.d.ts +5 -0
  16. package/dist/parsers/pnpm/internal.d.ts.map +1 -0
  17. package/dist/parsers/pnpm/shrinkwrap.d.ts +129 -0
  18. package/dist/parsers/pnpm/shrinkwrap.d.ts.map +1 -0
  19. package/dist/parsers/pnpm/v5.d.ts +139 -0
  20. package/dist/parsers/pnpm/v5.d.ts.map +1 -0
  21. package/dist/parsers/pnpm/v6plus.d.ts +212 -0
  22. package/dist/parsers/pnpm/v6plus.d.ts.map +1 -0
  23. package/dist/parsers/pnpm.d.ts +1 -59
  24. package/dist/parsers/pnpm.d.ts.map +1 -1
  25. package/dist/parsers/types.d.ts +23 -0
  26. package/dist/parsers/types.d.ts.map +1 -0
  27. package/dist/parsers/yarn-berry.d.ts +141 -52
  28. package/dist/parsers/yarn-berry.d.ts.map +1 -1
  29. package/dist/parsers/yarn-classic.d.ts +79 -33
  30. package/dist/parsers/yarn-classic.d.ts.map +1 -1
  31. package/dist/set.d.ts +189 -0
  32. package/dist/set.d.ts.map +1 -0
  33. package/package.json +7 -5
  34. package/src/compare.js +385 -28
  35. package/src/detect.js +3 -4
  36. package/src/index.js +9 -2
  37. package/src/parsers/index.js +10 -2
  38. package/src/parsers/npm.js +64 -16
  39. package/src/parsers/pnpm/detect.js +198 -0
  40. package/src/parsers/pnpm/index.js +289 -0
  41. package/src/parsers/pnpm/internal.js +41 -0
  42. package/src/parsers/pnpm/shrinkwrap.js +241 -0
  43. package/src/parsers/pnpm/v5.js +225 -0
  44. package/src/parsers/pnpm/v6plus.js +290 -0
  45. package/src/parsers/pnpm.js +11 -89
  46. package/src/parsers/types.js +10 -0
  47. package/src/parsers/yarn-berry.js +183 -36
  48. package/src/parsers/yarn-classic.js +81 -21
  49. package/src/set.js +618 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Parse pnpm package spec to extract name and version.
3
+ *
4
+ * This is the unified parser that auto-detects the format based on the spec pattern.
5
+ * It supports all pnpm lockfile versions without requiring version context.
6
+ *
7
+ * Detection heuristics:
8
+ * 1. If spec contains '(' -> v6+ format (peer deps in parentheses)
9
+ * 2. If spec contains '@' after position 0 and no '/' after the '@' -> v6+ format
10
+ * 3. Otherwise -> v5 or earlier format (slash separator)
11
+ *
12
+ * @param {string} spec - Package spec from pnpm lockfile
13
+ * @returns {{ name: string | null, version: string | null }}
14
+ *
15
+ * @example
16
+ * // v5 format - unscoped package
17
+ * parseSpec('/lodash/4.17.21')
18
+ * // => { name: 'lodash', version: '4.17.21' }
19
+ *
20
+ * @example
21
+ * // v5 format - scoped package
22
+ * parseSpec('/@babel/core/7.23.0')
23
+ * // => { name: '@babel/core', version: '7.23.0' }
24
+ *
25
+ * @example
26
+ * // v5 format - with peer dependency suffix (underscore)
27
+ * parseSpec('/styled-jsx/3.0.9_react@17.0.2')
28
+ * // => { name: 'styled-jsx', version: '3.0.9' }
29
+ *
30
+ * @example
31
+ * // v6 format - unscoped package (with leading slash)
32
+ * parseSpec('/lodash@4.17.21')
33
+ * // => { name: 'lodash', version: '4.17.21' }
34
+ *
35
+ * @example
36
+ * // v6 format - scoped package
37
+ * parseSpec('/@babel/core@7.23.0')
38
+ * // => { name: '@babel/core', version: '7.23.0' }
39
+ *
40
+ * @example
41
+ * // v9 format - unscoped package (no leading slash)
42
+ * parseSpec('lodash@4.17.21')
43
+ * // => { name: 'lodash', version: '4.17.21' }
44
+ *
45
+ * @example
46
+ * // v9 format - scoped package (no leading slash)
47
+ * parseSpec('@babel/core@7.23.0')
48
+ * // => { name: '@babel/core', version: '7.23.0' }
49
+ *
50
+ * @example
51
+ * // v9 format - with peer dependency suffix (parentheses)
52
+ * parseSpec('@babel/core@7.23.0(@types/node@20.0.0)')
53
+ * // => { name: '@babel/core', version: '7.23.0' }
54
+ *
55
+ * @example
56
+ * // v9 format - multiple peer dependencies
57
+ * parseSpec('@testing-library/react@14.0.0(react-dom@18.2.0)(react@18.2.0)')
58
+ * // => { name: '@testing-library/react', version: '14.0.0' }
59
+ *
60
+ * @example
61
+ * // Shrinkwrap v3/v4 format - with peer suffix (slash)
62
+ * parseSpec('/foo/1.0.0/bar@2.0.0')
63
+ * // => { name: 'foo', version: '1.0.0' }
64
+ *
65
+ * @example
66
+ * // link: protocol - skipped (returns null)
67
+ * parseSpec('link:packages/my-pkg')
68
+ * // => { name: null, version: null }
69
+ *
70
+ * @example
71
+ * // file: protocol - skipped (returns null)
72
+ * parseSpec('file:../local-package')
73
+ * // => { name: null, version: null }
74
+ *
75
+ * @example
76
+ * // Null input
77
+ * parseSpec(null)
78
+ * // => { name: null, version: null }
79
+ *
80
+ * @example
81
+ * // Prerelease version
82
+ * parseSpec('@verdaccio/ui-theme@6.0.0-6-next.50')
83
+ * // => { name: '@verdaccio/ui-theme', version: '6.0.0-6-next.50' }
84
+ */
85
+ export function parseSpec(spec: string): {
86
+ name: string | null;
87
+ version: string | null;
88
+ };
89
+ /**
90
+ * Extract package name from pnpm lockfile key.
91
+ * Wraps parseSpec to return just the name (consistent with other parsers).
92
+ *
93
+ * @param {string} key - pnpm lockfile key
94
+ * @returns {string | null} Package name
95
+ *
96
+ * @example
97
+ * parseLockfileKey('/@babel/core@7.23.0') // => '@babel/core'
98
+ * parseLockfileKey('/lodash/4.17.21') // => 'lodash'
99
+ */
100
+ export function parseLockfileKey(key: string): string | null;
101
+ /**
102
+ * Parse pnpm lockfile (shrinkwrap.yaml, pnpm-lock.yaml v5.x, v6, v9)
103
+ *
104
+ * @param {string | object} input - Lockfile content string or pre-parsed object
105
+ * @param {Object} [_options] - Parser options (unused, reserved for future use)
106
+ * @returns {Generator<Dependency>}
107
+ *
108
+ * @example
109
+ * // Parse from string
110
+ * const deps = [...fromPnpmLock(yamlContent)];
111
+ *
112
+ * @example
113
+ * // Parse from pre-parsed object
114
+ * const lockfile = yaml.load(content);
115
+ * const deps = [...fromPnpmLock(lockfile)];
116
+ */
117
+ export function fromPnpmLock(input: string | object, _options?: Object): Generator<Dependency>;
118
+ export { detectVersion } from "./detect.js";
119
+ export type Dependency = import("../types.js").Dependency;
120
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/parsers/pnpm/index.js"],"names":[],"mappings":"AA2BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFG;AACH,gCAzEW,MAAM,GACJ;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CA+H3D;AAED;;;;;;;;;;GAUG;AACH,sCAPW,MAAM,GACJ,MAAM,GAAG,IAAI,CAQzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,oCAbW,MAAM,GAAG,MAAM,aACf,MAAM,GACJ,SAAS,CAAC,UAAU,CAAC,CAoGjC;;yBA5Qa,OAAO,aAAa,EAAE,UAAU"}
@@ -0,0 +1,5 @@
1
+ export { detectVersion, hasLeadingSlash, usesAtSeparator, usesInlineSpecifiers, usesSnapshotsSplit } from "./detect.js";
2
+ export { extractPeerSuffix, hasPeerSuffix, parseSpecShrinkwrap } from "./shrinkwrap.js";
3
+ export { extractPeerSuffixV5, hasPeerSuffixV5, parseSpecV5 } from "./v5.js";
4
+ export { extractPeerSuffixV6Plus, hasPeerSuffixV6Plus, parsePeerDependencies, parseSpecV6Plus } from "./v6plus.js";
5
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/parsers/pnpm/internal.js"],"names":[],"mappings":""}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * @fileoverview Parser for pnpm shrinkwrap.yaml (v3/v4) format
3
+ *
4
+ * Shrinkwrap format (2016-2019) characteristics:
5
+ * - File: shrinkwrap.yaml
6
+ * - Version field: shrinkwrapVersion (number, typically 3 or 4)
7
+ * - Package key format: /name/version or /@scope/name/version
8
+ * - Peer dependency suffix: /peer@ver with ! escaping for scoped packages
9
+ * Example: /foo/1.0.0/bar@2.0.0+@scope!qar@3.0.0
10
+ *
11
+ * @module flatlock/parsers/pnpm/shrinkwrap
12
+ */
13
+ /**
14
+ * @typedef {Object} ParsedSpec
15
+ * @property {string|null} name - The package name (null if unparseable)
16
+ * @property {string|null} version - The package version (null if unparseable)
17
+ */
18
+ /**
19
+ * Parse a shrinkwrap.yaml package spec (v3/v4 format).
20
+ *
21
+ * Shrinkwrap format uses:
22
+ * - Slash separator between name and version: /name/version
23
+ * - Peer dependencies after another slash: /name/version/peer@ver
24
+ * - Scoped packages: /@scope/name/version
25
+ * - Scoped peer dependencies use `!` to escape the `@`: `/name/1.0.0/peer@2.0.0+@scope!qar@3.0.0`
26
+ *
27
+ * @param {string} spec - Package spec from shrinkwrap.yaml packages section
28
+ * @returns {ParsedSpec} Parsed name and version
29
+ *
30
+ * @example
31
+ * // Unscoped package
32
+ * parseSpecShrinkwrap('/lodash/4.17.21')
33
+ * // => { name: 'lodash', version: '4.17.21' }
34
+ *
35
+ * @example
36
+ * // Scoped package
37
+ * parseSpecShrinkwrap('/@babel/core/7.23.0')
38
+ * // => { name: '@babel/core', version: '7.23.0' }
39
+ *
40
+ * @example
41
+ * // With peer dependency suffix
42
+ * parseSpecShrinkwrap('/foo/1.0.0/bar@2.0.0')
43
+ * // => { name: 'foo', version: '1.0.0' }
44
+ *
45
+ * @example
46
+ * // With scoped peer dependency (`!` escapes `@`)
47
+ * parseSpecShrinkwrap('/foo/1.0.0/bar@2.0.0+@scope!qar@3.0.0')
48
+ * // => { name: 'foo', version: '1.0.0' }
49
+ *
50
+ * @example
51
+ * // Scoped package with peer deps
52
+ * parseSpecShrinkwrap('/@emotion/styled/10.0.27/react@17.0.2')
53
+ * // => { name: '@emotion/styled', version: '10.0.27' }
54
+ *
55
+ * @example
56
+ * // Multiple peer dependencies
57
+ * parseSpecShrinkwrap('/styled-components/5.3.6/react-dom@17.0.2+react@17.0.2')
58
+ * // => { name: 'styled-components', version: '5.3.6' }
59
+ *
60
+ * @example
61
+ * // Package with hyphenated name
62
+ * parseSpecShrinkwrap('/string-width/4.2.3')
63
+ * // => { name: 'string-width', version: '4.2.3' }
64
+ *
65
+ * @example
66
+ * // Scoped package with hyphenated name
67
+ * parseSpecShrinkwrap('/@babel/helper-compilation-targets/7.23.6')
68
+ * // => { name: '@babel/helper-compilation-targets', version: '7.23.6' }
69
+ *
70
+ * @example
71
+ * // link: protocol - skipped
72
+ * parseSpecShrinkwrap('link:packages/my-pkg')
73
+ * // => { name: null, version: null }
74
+ *
75
+ * @example
76
+ * // file: protocol - skipped
77
+ * parseSpecShrinkwrap('file:../local-package')
78
+ * // => { name: null, version: null }
79
+ *
80
+ * @example
81
+ * // Null input
82
+ * parseSpecShrinkwrap(null)
83
+ * // => { name: null, version: null }
84
+ *
85
+ * @example
86
+ * // Empty string
87
+ * parseSpecShrinkwrap('')
88
+ * // => { name: null, version: null }
89
+ */
90
+ export function parseSpecShrinkwrap(spec: string): ParsedSpec;
91
+ /**
92
+ * Check if a spec has peer dependency suffix (shrinkwrap v3/v4 format).
93
+ *
94
+ * In shrinkwrap v3/v4, peer dependencies are appended after the version
95
+ * with another slash: /name/version/peer@ver+peer2@ver
96
+ *
97
+ * @param {string} spec - Package spec from shrinkwrap.yaml
98
+ * @returns {boolean} True if the spec has peer dependency suffix
99
+ *
100
+ * @example
101
+ * hasPeerSuffix('/lodash/4.17.21') // => false
102
+ * hasPeerSuffix('/foo/1.0.0/bar@2.0.0') // => true
103
+ * hasPeerSuffix('/@babel/core/7.23.0') // => false
104
+ * hasPeerSuffix('/@emotion/styled/10.0.27/react@17.0.2') // => true
105
+ */
106
+ export function hasPeerSuffix(spec: string): boolean;
107
+ /**
108
+ * Extract the peer dependency suffix from a shrinkwrap spec.
109
+ *
110
+ * @param {string} spec - Package spec from shrinkwrap.yaml
111
+ * @returns {string|null} The peer suffix or null if none
112
+ *
113
+ * @example
114
+ * extractPeerSuffix('/lodash/4.17.21') // => null
115
+ * extractPeerSuffix('/foo/1.0.0/bar@2.0.0') // => 'bar@2.0.0'
116
+ * extractPeerSuffix('/foo/1.0.0/bar@2.0.0+@scope!qar@3.0.0') // => 'bar@2.0.0+@scope!qar@3.0.0'
117
+ */
118
+ export function extractPeerSuffix(spec: string): string | null;
119
+ export type ParsedSpec = {
120
+ /**
121
+ * - The package name (null if unparseable)
122
+ */
123
+ name: string | null;
124
+ /**
125
+ * - The package version (null if unparseable)
126
+ */
127
+ version: string | null;
128
+ };
129
+ //# sourceMappingURL=shrinkwrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shrinkwrap.d.ts","sourceRoot":"","sources":["../../../src/parsers/pnpm/shrinkwrap.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,0CA/DW,MAAM,GACJ,UAAU,CA0ItB;AAED;;;;;;;;;;;;;;GAcG;AACH,oCATW,MAAM,GACJ,OAAO,CA6BnB;AAED;;;;;;;;;;GAUG;AACH,wCARW,MAAM,GACJ,MAAM,GAAC,IAAI,CA6BvB;;;;;UAjOa,MAAM,GAAC,IAAI;;;;aACX,MAAM,GAAC,IAAI"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * @fileoverview Parser for pnpm-lock.yaml v5.x format
3
+ *
4
+ * pnpm-lock.yaml v5.x format (2019-2022) characteristics:
5
+ * - File: pnpm-lock.yaml
6
+ * - Version field: lockfileVersion (number like 5, 5.1, 5.2, 5.3, 5.4)
7
+ * - Package key format: /name/version or /@scope/name/version
8
+ * - Peer dependency suffix: _peer@ver with + escaping for scoped packages
9
+ * Example: /foo/1.0.0_bar@2.0.0+@scope+qar@3.0.0
10
+ *
11
+ * Key differences from shrinkwrap v3/v4:
12
+ * - Peer suffix uses _ instead of /
13
+ * - Scoped peer packages escape @ with + instead of !
14
+ *
15
+ * @module flatlock/parsers/pnpm/v5
16
+ */
17
+ /**
18
+ * @typedef {Object} ParsedSpec
19
+ * @property {string|null} name - The package name (null if unparseable)
20
+ * @property {string|null} version - The package version (null if unparseable)
21
+ */
22
+ /**
23
+ * Parse a pnpm-lock.yaml v5.x package spec.
24
+ *
25
+ * v5 format uses:
26
+ * - Slash separator between name and version: /name/version
27
+ * - Peer dependencies after underscore: /name/version_peer@ver
28
+ * - Scoped packages: /@scope/name/version
29
+ * - Multiple peers joined with +: /name/1.0.0_peer1@2.0.0+peer2@3.0.0
30
+ * - Scoped peer dependencies use + to escape the /: _@scope+pkg@1.0.0
31
+ *
32
+ * @param {string} spec - Package spec from pnpm-lock.yaml packages section
33
+ * @returns {ParsedSpec} Parsed name and version
34
+ *
35
+ * @example
36
+ * // Unscoped package
37
+ * parseSpecV5('/lodash/4.17.21')
38
+ * // => { name: 'lodash', version: '4.17.21' }
39
+ *
40
+ * @example
41
+ * // Scoped package
42
+ * parseSpecV5('/@babel/core/7.23.0')
43
+ * // => { name: '@babel/core', version: '7.23.0' }
44
+ *
45
+ * @example
46
+ * // With peer dependency suffix
47
+ * parseSpecV5('/styled-jsx/3.0.9_react@17.0.2')
48
+ * // => { name: 'styled-jsx', version: '3.0.9' }
49
+ *
50
+ * @example
51
+ * // With multiple peer dependencies
52
+ * parseSpecV5('/pkg/1.0.0_react-dom@17.0.2+react@17.0.2')
53
+ * // => { name: 'pkg', version: '1.0.0' }
54
+ *
55
+ * @example
56
+ * // Scoped package with peer deps
57
+ * parseSpecV5('/@emotion/styled/10.0.27_react@17.0.2')
58
+ * // => { name: '@emotion/styled', version: '10.0.27' }
59
+ *
60
+ * @example
61
+ * // Prerelease version
62
+ * parseSpecV5('/@verdaccio/ui-theme/6.0.0-6-next.50')
63
+ * // => { name: '@verdaccio/ui-theme', version: '6.0.0-6-next.50' }
64
+ *
65
+ * @example
66
+ * // Package with hyphenated name
67
+ * parseSpecV5('/string-width/4.2.3')
68
+ * // => { name: 'string-width', version: '4.2.3' }
69
+ *
70
+ * @example
71
+ * // Scoped package with hyphenated name
72
+ * parseSpecV5('/@babel/helper-compilation-targets/7.23.6')
73
+ * // => { name: '@babel/helper-compilation-targets', version: '7.23.6' }
74
+ *
75
+ * @example
76
+ * // Complex peer suffix with scoped peer
77
+ * parseSpecV5('/styled-components/5.3.6_@babel+core@7.23.0+react@18.2.0')
78
+ * // => { name: 'styled-components', version: '5.3.6' }
79
+ *
80
+ * @example
81
+ * // link: protocol - skipped
82
+ * parseSpecV5('link:packages/my-pkg')
83
+ * // => { name: null, version: null }
84
+ *
85
+ * @example
86
+ * // file: protocol - skipped
87
+ * parseSpecV5('file:../local-package')
88
+ * // => { name: null, version: null }
89
+ *
90
+ * @example
91
+ * // Null input
92
+ * parseSpecV5(null)
93
+ * // => { name: null, version: null }
94
+ *
95
+ * @example
96
+ * // Build metadata version
97
+ * parseSpecV5('/esbuild/0.19.12+sha512.abc123')
98
+ * // => { name: 'esbuild', version: '0.19.12+sha512.abc123' }
99
+ */
100
+ export function parseSpecV5(spec: string): ParsedSpec;
101
+ /**
102
+ * Check if a spec has peer dependency suffix (v5 format).
103
+ *
104
+ * In v5, peer dependencies are appended after the version
105
+ * with an underscore: /name/version_peer@ver+peer2@ver
106
+ *
107
+ * @param {string} spec - Package spec from pnpm-lock.yaml
108
+ * @returns {boolean} True if the spec has peer dependency suffix
109
+ *
110
+ * @example
111
+ * hasPeerSuffixV5('/lodash/4.17.21') // => false
112
+ * hasPeerSuffixV5('/foo/1.0.0_bar@2.0.0') // => true
113
+ * hasPeerSuffixV5('/@babel/core/7.23.0') // => false
114
+ * hasPeerSuffixV5('/@emotion/styled/10.0.27_react@17.0.2') // => true
115
+ */
116
+ export function hasPeerSuffixV5(spec: string): boolean;
117
+ /**
118
+ * Extract the peer dependency suffix from a v5 spec.
119
+ *
120
+ * @param {string} spec - Package spec from pnpm-lock.yaml v5
121
+ * @returns {string|null} The peer suffix or null if none
122
+ *
123
+ * @example
124
+ * extractPeerSuffixV5('/lodash/4.17.21') // => null
125
+ * extractPeerSuffixV5('/foo/1.0.0_bar@2.0.0') // => 'bar@2.0.0'
126
+ * extractPeerSuffixV5('/foo/1.0.0_bar@2.0.0+@scope+qar@3.0.0') // => 'bar@2.0.0+@scope+qar@3.0.0'
127
+ */
128
+ export function extractPeerSuffixV5(spec: string): string | null;
129
+ export type ParsedSpec = {
130
+ /**
131
+ * - The package name (null if unparseable)
132
+ */
133
+ name: string | null;
134
+ /**
135
+ * - The package version (null if unparseable)
136
+ */
137
+ version: string | null;
138
+ };
139
+ //# sourceMappingURL=v5.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v5.d.ts","sourceRoot":"","sources":["../../../src/parsers/pnpm/v5.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,kCApEW,MAAM,GACJ,UAAU,CA+ItB;AAED;;;;;;;;;;;;;;GAcG;AACH,sCATW,MAAM,GACJ,OAAO,CAcnB;AAED;;;;;;;;;;GAUG;AACH,0CARW,MAAM,GACJ,MAAM,GAAC,IAAI,CAkBvB;;;;;UA7Ma,MAAM,GAAC,IAAI;;;;aACX,MAAM,GAAC,IAAI"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * @fileoverview Parser for pnpm-lock.yaml v6+ format (v6.0 and v9.0)
3
+ *
4
+ * pnpm-lock.yaml v6+ format (2023+) characteristics:
5
+ * - File: pnpm-lock.yaml
6
+ * - Version field: lockfileVersion (string like '6.0', '9.0')
7
+ * - Package key format:
8
+ * - v6: /name@version or /@scope/name@version (with leading slash)
9
+ * - v9: name@version or @scope/name@version (no leading slash)
10
+ * - Peer dependency suffix: (peer@ver) in parentheses
11
+ * Example: /@babel/core@7.23.0(@types/node@20.0.0)
12
+ *
13
+ * Key differences from v5:
14
+ * - Uses @ separator between name and version instead of /
15
+ * - Peer suffix uses parentheses () instead of underscore _
16
+ * - Peer names are human-readable (no hashing)
17
+ * - v9 additionally removes leading slash from keys
18
+ *
19
+ * @module flatlock/parsers/pnpm/v6plus
20
+ */
21
+ /**
22
+ * @typedef {Object} ParsedSpec
23
+ * @property {string|null} name - The package name (null if unparseable)
24
+ * @property {string|null} version - The package version (null if unparseable)
25
+ */
26
+ /**
27
+ * Parse a pnpm-lock.yaml v6+ package spec.
28
+ *
29
+ * v6/v9 format uses:
30
+ * - @ separator between name and version: name@version
31
+ * - Leading slash in v6: /name@version, no slash in v9: name@version
32
+ * - Peer dependencies in parentheses: name@version(peer@ver)
33
+ * - Scoped packages: @scope/name@version
34
+ * - Multiple peers: name@version(peer1@ver)(peer2@ver)
35
+ *
36
+ * @param {string} spec - Package spec from pnpm-lock.yaml packages section
37
+ * @returns {ParsedSpec} Parsed name and version
38
+ *
39
+ * @example
40
+ * // Unscoped package (v6 format with leading slash)
41
+ * parseSpecV6Plus('/lodash@4.17.21')
42
+ * // => { name: 'lodash', version: '4.17.21' }
43
+ *
44
+ * @example
45
+ * // Unscoped package (v9 format without leading slash)
46
+ * parseSpecV6Plus('lodash@4.17.21')
47
+ * // => { name: 'lodash', version: '4.17.21' }
48
+ *
49
+ * @example
50
+ * // Scoped package (v6)
51
+ * parseSpecV6Plus('/@babel/core@7.23.0')
52
+ * // => { name: '@babel/core', version: '7.23.0' }
53
+ *
54
+ * @example
55
+ * // Scoped package (v9)
56
+ * parseSpecV6Plus('@babel/core@7.23.0')
57
+ * // => { name: '@babel/core', version: '7.23.0' }
58
+ *
59
+ * @example
60
+ * // With peer dependency suffix
61
+ * parseSpecV6Plus('/@babel/core@7.23.0(@types/node@20.0.0)')
62
+ * // => { name: '@babel/core', version: '7.23.0' }
63
+ *
64
+ * @example
65
+ * // With multiple peer dependencies
66
+ * parseSpecV6Plus('/@aleph-alpha/config-css@0.18.4(@unocss/core@66.5.2)(postcss@8.5.6)')
67
+ * // => { name: '@aleph-alpha/config-css', version: '0.18.4' }
68
+ *
69
+ * @example
70
+ * // Prerelease version
71
+ * parseSpecV6Plus('/unusual-pkg@1.0.0-beta.1')
72
+ * // => { name: 'unusual-pkg', version: '1.0.0-beta.1' }
73
+ *
74
+ * @example
75
+ * // Package with hyphenated name
76
+ * parseSpecV6Plus('/string-width@4.2.3')
77
+ * // => { name: 'string-width', version: '4.2.3' }
78
+ *
79
+ * @example
80
+ * // Scoped package with hyphenated name
81
+ * parseSpecV6Plus('@babel/helper-compilation-targets@7.23.6')
82
+ * // => { name: '@babel/helper-compilation-targets', version: '7.23.6' }
83
+ *
84
+ * @example
85
+ * // Complex nested peer dependencies (v9)
86
+ * parseSpecV6Plus('@testing-library/react@14.0.0(react-dom@18.2.0)(react@18.2.0)')
87
+ * // => { name: '@testing-library/react', version: '14.0.0' }
88
+ *
89
+ * @example
90
+ * // link: protocol - skipped
91
+ * parseSpecV6Plus('link:packages/my-pkg')
92
+ * // => { name: null, version: null }
93
+ *
94
+ * @example
95
+ * // file: protocol - skipped
96
+ * parseSpecV6Plus('file:../local-package')
97
+ * // => { name: null, version: null }
98
+ *
99
+ * @example
100
+ * // Null input
101
+ * parseSpecV6Plus(null)
102
+ * // => { name: null, version: null }
103
+ *
104
+ * @example
105
+ * // Build metadata version
106
+ * parseSpecV6Plus('esbuild@0.19.12+sha512.abc123')
107
+ * // => { name: 'esbuild', version: '0.19.12+sha512.abc123' }
108
+ */
109
+ export function parseSpecV6Plus(spec: string): ParsedSpec;
110
+ /**
111
+ * Check if a spec has peer dependency suffix (v6+ format).
112
+ *
113
+ * In v6+, peer dependencies are in parentheses: name@version(peer@ver)
114
+ *
115
+ * @param {string} spec - Package spec from pnpm-lock.yaml
116
+ * @returns {boolean} True if the spec has peer dependency suffix
117
+ *
118
+ * @example
119
+ * hasPeerSuffixV6Plus('/lodash@4.17.21') // => false
120
+ * hasPeerSuffixV6Plus('/@babel/core@7.23.0(@types/node@20.0.0)') // => true
121
+ * hasPeerSuffixV6Plus('lodash@4.17.21') // => false
122
+ * hasPeerSuffixV6Plus('@emotion/styled@10.0.27(react@17.0.2)') // => true
123
+ */
124
+ export function hasPeerSuffixV6Plus(spec: string): boolean;
125
+ /**
126
+ * Extract the peer dependency suffix from a v6+ spec.
127
+ *
128
+ * @param {string} spec - Package spec from pnpm-lock.yaml v6+
129
+ * @returns {string|null} The peer suffix (including parentheses) or null if none
130
+ *
131
+ * @example
132
+ * extractPeerSuffixV6Plus('/lodash@4.17.21') // => null
133
+ * extractPeerSuffixV6Plus('/@babel/core@7.23.0(@types/node@20.0.0)') // => '(@types/node@20.0.0)'
134
+ * extractPeerSuffixV6Plus('/@pkg@1.0.0(peer1@2.0.0)(peer2@3.0.0)') // => '(peer1@2.0.0)(peer2@3.0.0)'
135
+ */
136
+ export function extractPeerSuffixV6Plus(spec: string): string | null;
137
+ /**
138
+ * Parse peer dependencies from a v6+ peer suffix.
139
+ *
140
+ * @param {string} peerSuffix - The peer suffix like '(peer1@1.0.0)(peer2@2.0.0)'
141
+ * @returns {Array<{name: string, version: string}>} Array of parsed peer dependencies
142
+ *
143
+ * @example
144
+ * // Single scoped peer
145
+ * parsePeerDependencies('(@types/node@20.0.0)')
146
+ * // => [{ name: '@types/node', version: '20.0.0' }]
147
+ *
148
+ * @example
149
+ * // Multiple unscoped peers
150
+ * parsePeerDependencies('(react@18.2.0)(typescript@5.3.3)')
151
+ * // => [{ name: 'react', version: '18.2.0' }, { name: 'typescript', version: '5.3.3' }]
152
+ *
153
+ * @example
154
+ * // Single unscoped peer
155
+ * parsePeerDependencies('(lodash@4.17.21)')
156
+ * // => [{ name: 'lodash', version: '4.17.21' }]
157
+ *
158
+ * @example
159
+ * // Multiple scoped peers
160
+ * parsePeerDependencies('(@babel/core@7.23.0)(@types/react@18.2.0)')
161
+ * // => [{ name: '@babel/core', version: '7.23.0' }, { name: '@types/react', version: '18.2.0' }]
162
+ *
163
+ * @example
164
+ * // Mixed scoped and unscoped peers
165
+ * parsePeerDependencies('(react@18.2.0)(@types/react@18.2.0)')
166
+ * // => [{ name: 'react', version: '18.2.0' }, { name: '@types/react', version: '18.2.0' }]
167
+ *
168
+ * @example
169
+ * // React ecosystem peers (common pattern)
170
+ * parsePeerDependencies('(react-dom@18.2.0)(react@18.2.0)')
171
+ * // => [{ name: 'react-dom', version: '18.2.0' }, { name: 'react', version: '18.2.0' }]
172
+ *
173
+ * @example
174
+ * // Many peers (complex component library)
175
+ * parsePeerDependencies('(@unocss/core@66.5.2)(postcss@8.5.6)(typescript@5.3.3)')
176
+ * // => [{ name: '@unocss/core', version: '66.5.2' }, { name: 'postcss', version: '8.5.6' }, { name: 'typescript', version: '5.3.3' }]
177
+ *
178
+ * @example
179
+ * // Prerelease peer version
180
+ * parsePeerDependencies('(next@14.0.0-canary.0)')
181
+ * // => [{ name: 'next', version: '14.0.0-canary.0' }]
182
+ *
183
+ * @example
184
+ * // Empty/null input
185
+ * parsePeerDependencies(null)
186
+ * // => []
187
+ *
188
+ * @example
189
+ * // No parentheses (invalid)
190
+ * parsePeerDependencies('react@18.2.0')
191
+ * // => []
192
+ *
193
+ * @example
194
+ * // Deeply scoped peer
195
+ * parsePeerDependencies('(@babel/helper-compilation-targets@7.23.6)')
196
+ * // => [{ name: '@babel/helper-compilation-targets', version: '7.23.6' }]
197
+ */
198
+ export function parsePeerDependencies(peerSuffix: string): Array<{
199
+ name: string;
200
+ version: string;
201
+ }>;
202
+ export type ParsedSpec = {
203
+ /**
204
+ * - The package name (null if unparseable)
205
+ */
206
+ name: string | null;
207
+ /**
208
+ * - The package version (null if unparseable)
209
+ */
210
+ version: string | null;
211
+ };
212
+ //# sourceMappingURL=v6plus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v6plus.d.ts","sourceRoot":"","sources":["../../../src/parsers/pnpm/v6plus.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AACH,sCAzEW,MAAM,GACJ,UAAU,CAqHtB;AAED;;;;;;;;;;;;;GAaG;AACH,0CATW,MAAM,GACJ,OAAO,CAcnB;AAED;;;;;;;;;;GAUG;AACH,8CARW,MAAM,GACJ,MAAM,GAAC,IAAI,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,kDA1DW,MAAM,GACJ,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC,CAkFlD;;;;;UA1Qa,MAAM,GAAC,IAAI;;;;aACX,MAAM,GAAC,IAAI"}