@crbroughton/recul 0.1.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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -0
  3. package/dist/bin/recul.d.ts +3 -0
  4. package/dist/bin/recul.d.ts.map +1 -0
  5. package/dist/bin/recul.js +96 -0
  6. package/dist/bin/recul.js.map +1 -0
  7. package/dist/src/adapters/npm.d.ts +10 -0
  8. package/dist/src/adapters/npm.d.ts.map +1 -0
  9. package/dist/src/adapters/npm.js +26 -0
  10. package/dist/src/adapters/npm.js.map +1 -0
  11. package/dist/src/adapters/pnpm.d.ts +34 -0
  12. package/dist/src/adapters/pnpm.d.ts.map +1 -0
  13. package/dist/src/adapters/pnpm.js +97 -0
  14. package/dist/src/adapters/pnpm.js.map +1 -0
  15. package/dist/src/audit.d.ts +19 -0
  16. package/dist/src/audit.d.ts.map +1 -0
  17. package/dist/src/audit.js +65 -0
  18. package/dist/src/audit.js.map +1 -0
  19. package/dist/src/config.d.ts +23 -0
  20. package/dist/src/config.d.ts.map +1 -0
  21. package/dist/src/config.js +67 -0
  22. package/dist/src/config.js.map +1 -0
  23. package/dist/src/index.d.ts +6 -0
  24. package/dist/src/index.d.ts.map +1 -0
  25. package/dist/src/index.js +5 -0
  26. package/dist/src/index.js.map +1 -0
  27. package/dist/src/init.d.ts +2 -0
  28. package/dist/src/init.d.ts.map +1 -0
  29. package/dist/src/init.js +113 -0
  30. package/dist/src/init.js.map +1 -0
  31. package/dist/src/lockfile.d.ts +24 -0
  32. package/dist/src/lockfile.d.ts.map +1 -0
  33. package/dist/src/lockfile.js +54 -0
  34. package/dist/src/lockfile.js.map +1 -0
  35. package/dist/src/output.d.ts +13 -0
  36. package/dist/src/output.d.ts.map +1 -0
  37. package/dist/src/output.js +198 -0
  38. package/dist/src/output.js.map +1 -0
  39. package/dist/src/resolve.d.ts +25 -0
  40. package/dist/src/resolve.d.ts.map +1 -0
  41. package/dist/src/resolve.js +55 -0
  42. package/dist/src/resolve.js.map +1 -0
  43. package/dist/src/semver.d.ts +29 -0
  44. package/dist/src/semver.d.ts.map +1 -0
  45. package/dist/src/semver.js +39 -0
  46. package/dist/src/semver.js.map +1 -0
  47. package/dist/src/types.d.ts +70 -0
  48. package/dist/src/types.d.ts.map +1 -0
  49. package/dist/src/types.js +2 -0
  50. package/dist/src/types.js.map +1 -0
  51. package/package.json +66 -0
@@ -0,0 +1,67 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { parseJSONC } from 'confbox';
4
+ const VALID_RANGE = new Set(['exact', 'caret', 'tilde']);
5
+ function isRangeSpecifier(value) {
6
+ return VALID_RANGE.has(value);
7
+ }
8
+ const CONFIG_FILE = 'recul.config.jsonc';
9
+ /**
10
+ * Load the config file from `dir`.
11
+ * Returns the parsed config, or null if no config file was found.
12
+ */
13
+ export function loadConfigFile(dir) {
14
+ const path = resolve(dir, CONFIG_FILE);
15
+ if (existsSync(path)) {
16
+ try {
17
+ const src = readFileSync(path, 'utf8');
18
+ const raw = parseJSONC(src);
19
+ if (raw === null || typeof raw !== 'object')
20
+ return null;
21
+ return raw;
22
+ }
23
+ catch (err) {
24
+ const message = err instanceof Error ? err.message : String(err);
25
+ console.error(`error: could not parse ${path}: ${message}`);
26
+ return null;
27
+ }
28
+ }
29
+ return null;
30
+ }
31
+ /** Resolve the directory to search for the config file, based on --file if provided. */
32
+ export function resolveConfigDir({ file, cwd }) {
33
+ return file !== undefined ? resolve(cwd, dirname(file)) : cwd;
34
+ }
35
+ export const DEFAULTS = {
36
+ lag: 2,
37
+ file: 'package.json',
38
+ pm: 'npm',
39
+ ignore: [],
40
+ behindBehavior: 'ignore',
41
+ rangeSpecifier: 'exact',
42
+ preReleaseFilter: ['-alpha', '-beta', '-rc', '-next', '-canary'],
43
+ };
44
+ /**
45
+ * Resolve the effective RangeSpecifier for a specific package.
46
+ * When config is a string it applies to all packages.
47
+ * When config is a record, looks up by name, then "default", then falls back to "exact".
48
+ */
49
+ export function resolveRangeSpecifier({ config, name }) {
50
+ if (typeof config === 'string')
51
+ return config;
52
+ const specific = config[name];
53
+ if (specific !== undefined && isRangeSpecifier(specific))
54
+ return specific;
55
+ const fallback = config.default;
56
+ if (fallback !== undefined && isRangeSpecifier(fallback))
57
+ return fallback;
58
+ return 'exact';
59
+ }
60
+ export function rangePrefix(specifier) {
61
+ switch (specifier) {
62
+ case 'caret': return '^';
63
+ case 'tilde': return '~';
64
+ case 'exact': return '';
65
+ }
66
+ }
67
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEpC,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AAE7E,SAAS,gBAAgB,CAAC,KAAa;IACrC,OAAO,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,WAAW,GAAG,oBAAoB,CAAA;AAExC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;IACtC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACtC,MAAM,GAAG,GAAG,UAAU,CAAoB,GAAG,CAAC,CAAA;YAC9C,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;gBACzC,OAAO,IAAI,CAAA;YACb,OAAO,GAAG,CAAA;QACZ,CAAC;QACD,OAAO,GAAG,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChE,OAAO,CAAC,KAAK,CAAC,0BAA0B,IAAI,KAAK,OAAO,EAAE,CAAC,CAAA;YAC3D,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,gBAAgB,CAAC,EAAE,IAAI,EAAE,GAAG,EAAkC;IAC5E,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AAC/D,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAW;IAC9B,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,cAAc;IACpB,EAAE,EAAE,KAAK;IACT,MAAM,EAAE,EAAE;IACV,cAAc,EAAE,QAAQ;IACxB,cAAc,EAAE,OAAO;IACvB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC;CACjE,CAAA;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAkD;IACpG,IAAI,OAAO,MAAM,KAAK,QAAQ;QAC5B,OAAO,MAAM,CAAA;IACf,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;IAC7B,IAAI,QAAQ,KAAK,SAAS,IAAI,gBAAgB,CAAC,QAAQ,CAAC;QACtD,OAAO,QAAQ,CAAA;IACjB,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAA;IAC/B,IAAI,QAAQ,KAAK,SAAS,IAAI,gBAAgB,CAAC,QAAQ,CAAC;QACtD,OAAO,QAAQ,CAAA;IACjB,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAyB;IACnD,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,OAAO,CAAC,CAAC,OAAO,GAAG,CAAA;QACxB,KAAK,OAAO,CAAC,CAAC,OAAO,GAAG,CAAA;QACxB,KAAK,OAAO,CAAC,CAAC,OAAO,EAAE,CAAA;IACzB,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { auditDeps } from './audit.js';
2
+ export { DEFAULTS, loadConfigFile, rangePrefix, resolveConfigDir, resolveRangeSpecifier } from './config.js';
3
+ export { printResults } from './output.js';
4
+ export { computeTarget, fetchStableVersions, resolvePackage } from './resolve.js';
5
+ export type { AuditResult, AuditStatus, BehindBehavior, Config, ConfigFile, InstalledVersionMap, PackageJson, PackageManager, RangeSpecifier, RangeSpecifierConfig, ResolvedPackage, } from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAC5G,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACjF,YAAY,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,MAAM,EACN,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,5 @@
1
+ export { auditDeps } from './audit.js';
2
+ export { DEFAULTS, loadConfigFile, rangePrefix, resolveConfigDir, resolveRangeSpecifier } from './config.js';
3
+ export { printResults } from './output.js';
4
+ export { computeTarget, fetchStableVersions, resolvePackage } from './resolve.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAC5G,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare function runInit(cwd: string): void;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/init.ts"],"names":[],"mappings":"AA2EA,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,QA2ClC"}
@@ -0,0 +1,113 @@
1
+ import { existsSync, writeFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ const CONFIG_FILENAME = 'recul.config.jsonc';
4
+ const TEMPLATE = `{
5
+ // How many versions to stay behind the latest published release.
6
+ // Counted in releases, not semver increments; a major bump counts as one.
7
+ //
8
+ // 1 → days to weeks (fast-moving projects, minimal buffer)
9
+ // 2 → weeks (balanced default, recommended)
10
+ // 3 → weeks to months (cautious teams, slower release cadences)
11
+ // 5+ → months (regulated environments, high-security contexts)
12
+ "lag": 2,
13
+
14
+ // Package manager used in this project.
15
+ // Controls the phrasing of generated install commands and lockfile detection.
16
+ // "npm" | "pnpm"
17
+ "packageManager": "npm",
18
+
19
+ // Path to the package.json file to audit, relative to this config file.
20
+ "packageFile": "package.json",
21
+
22
+ // How to handle packages that are already older than the lag target
23
+ // (e.g. you pinned something much older than the window).
24
+ //
25
+ // "ignore" → treat as ok, no output (default)
26
+ // "report" → surface them with a safe upgrade-to-target command
27
+ "behindBehavior": "ignore",
28
+
29
+ // Version prefix used in generated install commands.
30
+ // Also controls two things simultaneously:
31
+ //
32
+ // 1. Mismatch detection; flags packages declared with a different prefix
33
+ // than configured (e.g. "^1.2.3" declared but "exact" configured).
34
+ //
35
+ // 2. Lag comparison depth; how strictly the installed version must match
36
+ // the lag target before a pin-back is triggered:
37
+ // exact → all three parts compared (1.2.3 must equal 1.2.3)
38
+ // tilde → major + minor compared (1.2.x is ok if target is 1.2.0)
39
+ // caret → major only compared (1.x.x is ok if target is 1.0.0)
40
+ //
41
+ // Setting "react": "tilde" relaxes both checks for that package; patch
42
+ // differences will not trigger a pin-back and will not be flagged as mismatches.
43
+ //
44
+ // Can be a single value applied to all packages:
45
+ // "exact" → 1.3.4 (recommended; audits are reliable)
46
+ // "caret" → ^1.3.4 (allows minor/patch drift; audit may be imprecise)
47
+ // "tilde" → ~1.3.4 (allows patch drift only; audit may be imprecise)
48
+ //
49
+ // Or a per-package map (use "default" as the fallback):
50
+ // { "default": "exact", "react": "tilde", "some-pkg": "caret" }
51
+ "rangeSpecifier": "exact",
52
+
53
+ // Packages to skip entirely during the audit.
54
+ // Useful for tools where you intentionally stay on an older version
55
+ // for reasons unrelated to the lag policy (e.g. peer dep constraints).
56
+ "ignore": [],
57
+
58
+ // Minimum number of days a version must have been published before it
59
+ // is considered eligible as a lag target. Versions newer than this
60
+ // threshold are excluded from the candidate list entirely.
61
+ //
62
+ // Combine with "lag" for defence-in-depth:
63
+ // lag: 2 + minimumReleaseAge: 3 → at least 2 versions old AND published 3+ days ago
64
+ //
65
+ // Omit or set to 0 to disable (default).
66
+ "minimumReleaseAge": 3,
67
+
68
+ // Version strings containing any of these substrings are excluded from
69
+ // the candidate list and treated as pre-releases.
70
+ "preReleaseFilter": ["-alpha", "-beta", "-rc", "-next", "-canary"]
71
+ }
72
+ `;
73
+ export function runInit(cwd) {
74
+ const dest = resolve(cwd, CONFIG_FILENAME);
75
+ if (existsSync(dest)) {
76
+ console.log(`\nrecul init\n`);
77
+ console.log(`config file already exists: ${dest}`);
78
+ console.log(`delete it first if you want to regenerate.\n`);
79
+ process.exit(1);
80
+ }
81
+ writeFileSync(dest, TEMPLATE, 'utf8');
82
+ console.log(`\nrecul init\n`);
83
+ console.log(`created: ${dest}\n`);
84
+ console.log(`configuration options:\n`);
85
+ console.log(` lag How many versions behind latest to stay.`);
86
+ console.log(` Default 2 (weeks of vetting window).`);
87
+ console.log(``);
88
+ console.log(` packageManager Controls generated install command phrasing.`);
89
+ console.log(` npm | pnpm`);
90
+ console.log(``);
91
+ console.log(` packageFile Path to the package.json to audit.`);
92
+ console.log(` Relative to this config file.`);
93
+ console.log(``);
94
+ console.log(` behindBehavior What to do with packages older than the lag target.`);
95
+ console.log(` ignore (default); silent. report; show upgrade command.`);
96
+ console.log(``);
97
+ console.log(` rangeSpecifier Controls mismatch detection and lag comparison depth.`);
98
+ console.log(` exact (recommended); pin-back if any part differs`);
99
+ console.log(` tilde ; pin-back only if major or minor differs`);
100
+ console.log(` caret ; pin-back only if major differs`);
101
+ console.log(` Per-package map: { "default": "exact", "react": "tilde" }`);
102
+ console.log(``);
103
+ console.log(` ignore Array of package names to skip entirely.`);
104
+ console.log(``);
105
+ console.log(` minimumReleaseAge Minimum days a version must be published before it is eligible.`);
106
+ console.log(` Omit or set to 0 to disable.`);
107
+ console.log(``);
108
+ console.log(` preReleaseFilter Substrings that mark a version as a pre-release.`);
109
+ console.log(` Any version containing one of these strings is excluded.`);
110
+ console.log(``);
111
+ console.log(`CLI flags always override config file values.\n`);
112
+ }
113
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,MAAM,eAAe,GAAG,oBAAoB,CAAA;AAE5C,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoEhB,CAAA;AAED,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;IAE1C,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QAC7B,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,EAAE,CAAC,CAAA;QAClD,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAA;QAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;IAErC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAC7B,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,CAAA;IACjC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAA;IACvC,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAA;IAC1E,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAA;IACtE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAA;IAC9E,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAA;IAE5C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAA;IACpE,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAA;IAC/D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAA;IACrF,OAAO,CAAC,GAAG,CAAC,4EAA4E,CAAC,CAAA;IACzF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,0EAA0E,CAAC,CAAA;IACvF,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAA;IACnF,OAAO,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAA;IAC9F,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAA;IACrF,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAA;IAC3F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAA;IAC1E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,sFAAsF,CAAC,CAAA;IACnG,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAA;IAChE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAA;IACpF,OAAO,CAAC,GAAG,CAAC,+EAA+E,CAAC,CAAA;IAC5F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAA;AAChE,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { InstalledVersionMap, PackageManager } from './types.js';
2
+ export { npmAdapter, parseNpmLock } from './adapters/npm.js';
3
+ export { loadPnpmCatalog, parsePnpmLock, pnpmAdapter, resolveCatalogRefs, updatePnpmCatalog } from './adapters/pnpm.js';
4
+ export interface LockfileAdapter {
5
+ /** Filename to look for relative to the package.json directory. */
6
+ filename: string;
7
+ /** Parse lockfile content into a name → version map. */
8
+ parse: (content: string) => InstalledVersionMap;
9
+ }
10
+ /**
11
+ * Try each adapter in order, returning the first successfully parsed map.
12
+ * Returns null if no matching lockfile is found.
13
+ */
14
+ export declare function loadLockfile({ dir, adapters, }: {
15
+ dir: string;
16
+ adapters: LockfileAdapter[];
17
+ }): InstalledVersionMap | null;
18
+ /**
19
+ * Detect the package manager used in `dir` by checking for known lockfiles,
20
+ * then falling back to the `packageManager` field in `package.json`.
21
+ * Returns null if detection fails.
22
+ */
23
+ export declare function detectPackageManager(dir: string): PackageManager | null;
24
+ //# sourceMappingURL=lockfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../../src/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKrE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAEvH,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,mBAAmB,CAAA;CAChD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,QAAQ,GACT,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,eAAe,EAAE,CAAA;CAC5B,GAAG,mBAAmB,GAAG,IAAI,CAe7B;AAOD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAkBvE"}
@@ -0,0 +1,54 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { destr } from 'destr';
4
+ export { npmAdapter, parseNpmLock } from './adapters/npm.js';
5
+ export { loadPnpmCatalog, parsePnpmLock, pnpmAdapter, resolveCatalogRefs, updatePnpmCatalog } from './adapters/pnpm.js';
6
+ /**
7
+ * Try each adapter in order, returning the first successfully parsed map.
8
+ * Returns null if no matching lockfile is found.
9
+ */
10
+ export function loadLockfile({ dir, adapters, }) {
11
+ for (const adapter of adapters) {
12
+ const path = resolve(dir, adapter.filename);
13
+ if (!existsSync(path))
14
+ continue;
15
+ try {
16
+ return adapter.parse(readFileSync(path, 'utf8'));
17
+ }
18
+ catch (err) {
19
+ const message = err instanceof Error ? err.message : String(err);
20
+ console.error(`error: could not parse ${path}: ${message}`);
21
+ return null;
22
+ }
23
+ }
24
+ return null;
25
+ }
26
+ const PM_LOCKFILES = [
27
+ ['pnpm-lock.yaml', 'pnpm'],
28
+ ['package-lock.json', 'npm'],
29
+ ];
30
+ /**
31
+ * Detect the package manager used in `dir` by checking for known lockfiles,
32
+ * then falling back to the `packageManager` field in `package.json`.
33
+ * Returns null if detection fails.
34
+ */
35
+ export function detectPackageManager(dir) {
36
+ for (const [filename, pm] of PM_LOCKFILES) {
37
+ if (existsSync(resolve(dir, filename)))
38
+ return pm;
39
+ }
40
+ const pkgPath = resolve(dir, 'package.json');
41
+ if (existsSync(pkgPath)) {
42
+ const pkg = destr(readFileSync(pkgPath, 'utf8'));
43
+ if (typeof pkg === 'object' && pkg !== null && 'packageManager' in pkg) {
44
+ const field = pkg.packageManager;
45
+ if (typeof field === 'string') {
46
+ const name = field.split('@')[0];
47
+ if (name === 'npm' || name === 'pnpm')
48
+ return name;
49
+ }
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+ //# sourceMappingURL=lockfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../../src/lockfile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAE7B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AASvH;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,GAAG,EACH,QAAQ,GAIT;IACC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,SAAQ;QACV,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QAClD,CAAC;QACD,OAAO,GAAG,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChE,OAAO,CAAC,KAAK,CAAC,0BAA0B,IAAI,KAAK,OAAO,EAAE,CAAC,CAAA;YAC3D,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,YAAY,GAAoC;IACpD,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAC1B,CAAC,mBAAmB,EAAE,KAAK,CAAC;CAC7B,CAAA;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,KAAK,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,YAAY,EAAE,CAAC;QAC1C,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACpC,OAAO,EAAE,CAAA;IACb,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IAC5C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAA;QAChD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,gBAAgB,IAAI,GAAG,EAAE,CAAC;YACvE,MAAM,KAAK,GAAI,GAA+B,CAAC,cAAc,CAAA;YAC7D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;gBAChC,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM;oBACnC,OAAO,IAAI,CAAA;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { AuditResult, BehindBehavior, PackageManager, RangeSpecifierConfig } from './types.js';
2
+ export interface PrintResultsOptions {
3
+ results: AuditResult[];
4
+ lag: number;
5
+ pm: PackageManager;
6
+ behindBehavior: BehindBehavior;
7
+ rangeSpecifier: RangeSpecifierConfig;
8
+ minimumReleaseAge?: number;
9
+ workspaceFile?: string;
10
+ fixed?: string[];
11
+ }
12
+ export declare function printResults({ results, lag, pm, behindBehavior, rangeSpecifier, minimumReleaseAge, workspaceFile, fixed }: PrintResultsOptions): void;
13
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAkB,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAkInH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,EAAE,cAAc,CAAA;IAClB,cAAc,EAAE,cAAc,CAAA;IAC9B,cAAc,EAAE,oBAAoB,CAAA;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,mBAAmB,GAAG,IAAI,CAqIrJ"}
@@ -0,0 +1,198 @@
1
+ import { rangePrefix } from './config.js';
2
+ const COL = { name: 20, version: 16, status: 22 };
3
+ function pad(str, len) {
4
+ return str.padEnd(len);
5
+ }
6
+ function installCmd({ pm, packages, versionFn, exact = false, }) {
7
+ const pkgs = packages.map(r => `${r.name}@${versionFn(r)}`).join(' ');
8
+ const e = exact ? ' -E' : '';
9
+ switch (pm) {
10
+ case 'pnpm': return `pnpm add${e} ${pkgs}`;
11
+ case 'npm': return `npm install${e} ${pkgs}`;
12
+ }
13
+ }
14
+ /**
15
+ * Generate install command(s) for a set of packages, grouping exact and
16
+ * non-exact packages separately so the -E flag applies only where needed.
17
+ */
18
+ function installCmds({ pm, packages, versionTarget, }) {
19
+ const ver = (r, specifier) => `${rangePrefix(specifier)}${versionTarget === 'current' ? r.current : r.target ?? ''}`;
20
+ const exact = packages.filter(r => r.rangeSpecifier === 'exact');
21
+ const nonExact = packages.filter(r => r.rangeSpecifier !== 'exact');
22
+ const cmds = [];
23
+ if (exact.length > 0) {
24
+ cmds.push(installCmd({ pm, packages: exact, versionFn: r => ver(r, 'exact'), exact: true }));
25
+ }
26
+ if (nonExact.length > 0) {
27
+ cmds.push(installCmd({ pm, packages: nonExact, versionFn: r => ver(r, r.rangeSpecifier) }));
28
+ }
29
+ return cmds;
30
+ }
31
+ function formatRangeConfig(config) {
32
+ if (typeof config === 'string')
33
+ return config;
34
+ const def = config.default ?? 'exact';
35
+ const overrides = Object.entries(config)
36
+ .filter(([k]) => k !== 'default')
37
+ .map(([k, v]) => `${k} → ${v}`)
38
+ .join(', ');
39
+ return overrides ? `${def} (default), ${overrides}` : def;
40
+ }
41
+ function printSettings({ lag, pm, behindBehavior, rangeSpecifier, minimumReleaseAge, }) {
42
+ const behindDesc = behindBehavior === 'report'
43
+ ? 'report packages behind target'
44
+ : 'ignore packages behind target';
45
+ const rangeDesc = {
46
+ exact: 'pin exact versions',
47
+ caret: 'allow minor/patch drift (^)',
48
+ tilde: 'allow patch drift (~)',
49
+ };
50
+ const rangeVal = formatRangeConfig(rangeSpecifier);
51
+ const hasOverrides = typeof rangeSpecifier !== 'string'
52
+ && Object.keys(rangeSpecifier).some(k => k !== 'default');
53
+ const effectiveDefault = typeof rangeSpecifier === 'string'
54
+ ? rangeSpecifier
55
+ : (rangeSpecifier.default ?? 'exact');
56
+ const rangeNote = hasOverrides ? 'per-package specifiers configured' : rangeDesc[effectiveDefault];
57
+ const col = (s) => s.padEnd(10);
58
+ console.log('settings');
59
+ console.log(` ${col('lag')}${col(String(lag))}; stay ${lag} version${lag === 1 ? '' : 's'} behind latest`);
60
+ console.log(` ${col('pm')}${col(pm)}; the chosen package manager`);
61
+ console.log(` ${col('behind')}${col(behindBehavior)}; ${behindDesc}`);
62
+ console.log(` ${col('range')}${rangeVal}; ${rangeNote}`);
63
+ if (minimumReleaseAge !== undefined) {
64
+ console.log(` ${col('minAge')}${col(String(minimumReleaseAge))}; skip versions published within the last ${minimumReleaseAge} day${minimumReleaseAge === 1 ? '' : 's'}`);
65
+ }
66
+ }
67
+ function printCatalogEdits({ packages, versionTarget, workspaceFile = 'pnpm-workspace.yaml', label, }) {
68
+ const heading = label
69
+ ?? (versionTarget === 'target' ? 'to pin back (update catalog in' : 'to re-pin (update catalog in');
70
+ console.log(`\n${heading} ${workspaceFile}):`);
71
+ for (const r of packages) {
72
+ const ver = versionTarget === 'target' ? r.target : r.current;
73
+ if (ver)
74
+ console.log(` ${r.name}: ${ver}`);
75
+ }
76
+ console.log(`\n or run with --fix to apply automatically`);
77
+ }
78
+ export function printResults({ results, lag, pm, behindBehavior, rangeSpecifier, minimumReleaseAge, workspaceFile, fixed }) {
79
+ const violations = results.filter(r => r.status === 'pin');
80
+ const behind = results.filter(r => r.status === 'behind');
81
+ const unresolved = results.filter(r => r.status === 'unresolved');
82
+ const mismatches = results.filter(r => r.specifierMismatch);
83
+ // Exclude violations from re-pin — the pin-back command already covers them.
84
+ const mismatchesOnly = mismatches.filter(r => r.status !== 'pin');
85
+ const catalogViolations = violations.filter(r => r.fromCatalog);
86
+ const standardViolations = violations.filter(r => !r.fromCatalog);
87
+ const catalogMismatches = mismatchesOnly.filter(r => r.fromCatalog);
88
+ const standardMismatches = mismatchesOnly.filter(r => !r.fromCatalog);
89
+ const hasActions = violations.length > 0 || (behindBehavior === 'report' && behind.length > 0);
90
+ const hasInstalled = results.some(r => r.installed !== null);
91
+ console.log(`\nrecul staying ${lag} version${lag === 1 ? '' : 's'} behind latest\n`);
92
+ printSettings({ lag, pm, behindBehavior, rangeSpecifier, ...(minimumReleaseAge !== undefined ? { minimumReleaseAge } : {}) });
93
+ console.log();
94
+ // Column order: package · declared · → target · installed · latest · status
95
+ const versionCols = hasInstalled ? 4 : 3;
96
+ const divider = '─'.repeat(COL.name + COL.version * versionCols + COL.status + 4);
97
+ const header = `${pad('package', COL.name)
98
+ + pad('declared', COL.version)
99
+ + pad('→ target', COL.version)
100
+ + (hasInstalled ? pad('installed', COL.version) : '')
101
+ + pad('latest', COL.version)}status`;
102
+ console.log(header);
103
+ console.log(divider);
104
+ const sorted = [...results].sort((a, b) => a.name.localeCompare(b.name));
105
+ for (const r of sorted) {
106
+ let statusLabel;
107
+ if (r.status === 'pin')
108
+ statusLabel = '↓ will pin back';
109
+ else if (r.status === 'ok')
110
+ statusLabel = '✓ ok';
111
+ else if (r.status === 'behind' && behindBehavior === 'report')
112
+ statusLabel = '↑ safe to upgrade';
113
+ else if (r.status === 'behind')
114
+ statusLabel = '✓ ok';
115
+ else
116
+ statusLabel = '✗ unresolved';
117
+ if (r.specifierMismatch) {
118
+ statusLabel += ` ⚠ declared ${r.declaredSpecifier}`;
119
+ }
120
+ console.log(pad(r.name, COL.name)
121
+ + pad(r.declared, COL.version)
122
+ + pad(r.target ?? '—', COL.version)
123
+ + (hasInstalled ? pad(r.installed ?? '—', COL.version) : '')
124
+ + pad(r.latest ?? '—', COL.version)
125
+ + statusLabel);
126
+ }
127
+ if (unresolved.length > 0) {
128
+ console.log('\nunresolved:');
129
+ for (const r of unresolved) {
130
+ console.log(` ${r.name}: ${r.error}`);
131
+ }
132
+ }
133
+ if (mismatches.length > 0) {
134
+ console.log();
135
+ const names = mismatches.map(r => r.name).join(', ');
136
+ console.log(`⚠ specifier mismatch on: ${names}`);
137
+ console.log(` These packages are declared with a different range than configured.`);
138
+ if (mismatchesOnly.length > 0)
139
+ console.log(` Re-pin command included below.`);
140
+ }
141
+ if (!hasActions && mismatches.length === 0) {
142
+ console.log('\nall audited packages are within the lag policy ✓\n');
143
+ return;
144
+ }
145
+ if (!hasActions && mismatchesOnly.length > 0) {
146
+ if (standardMismatches.length > 0) {
147
+ for (const cmd of installCmds({ pm, packages: standardMismatches, versionTarget: 'current' })) {
148
+ console.log(`\nto re-pin:\n ${cmd}`);
149
+ }
150
+ }
151
+ if (catalogMismatches.length > 0) {
152
+ printCatalogEdits({ packages: catalogMismatches, versionTarget: 'current', ...(workspaceFile !== undefined ? { workspaceFile } : {}) });
153
+ }
154
+ console.log();
155
+ return;
156
+ }
157
+ if (standardViolations.length > 0) {
158
+ const cmds = installCmds({ pm, packages: standardViolations, versionTarget: 'target' });
159
+ console.log(`\nto pin back:`);
160
+ for (const cmd of cmds)
161
+ console.log(` ${cmd}`);
162
+ }
163
+ if (catalogViolations.length > 0) {
164
+ if (fixed !== undefined && fixed.length > 0) {
165
+ const file = workspaceFile ?? 'pnpm-workspace.yaml';
166
+ console.log(`\ncatalog updated in ${file}:`);
167
+ for (const name of fixed)
168
+ console.log(` ${name}`);
169
+ }
170
+ else {
171
+ printCatalogEdits({ packages: catalogViolations, versionTarget: 'target', ...(workspaceFile !== undefined ? { workspaceFile } : {}) });
172
+ }
173
+ }
174
+ if (behindBehavior === 'report' && behind.length > 0) {
175
+ const catalogBehind = behind.filter(r => r.fromCatalog);
176
+ const standardBehind = behind.filter(r => !r.fromCatalog);
177
+ if (standardBehind.length > 0) {
178
+ const cmds = installCmds({ pm, packages: standardBehind, versionTarget: 'target' });
179
+ console.log(`\nsafe to upgrade (currently behind lag target):`);
180
+ for (const cmd of cmds)
181
+ console.log(` ${cmd}`);
182
+ }
183
+ if (catalogBehind.length > 0) {
184
+ printCatalogEdits({ packages: catalogBehind, versionTarget: 'target', label: 'safe to upgrade (update catalog in', ...(workspaceFile !== undefined ? { workspaceFile } : {}) });
185
+ }
186
+ }
187
+ if (standardMismatches.length > 0) {
188
+ const cmds = installCmds({ pm, packages: standardMismatches, versionTarget: 'current' });
189
+ console.log(`\nto re-pin:`);
190
+ for (const cmd of cmds)
191
+ console.log(` ${cmd}`);
192
+ }
193
+ if (catalogMismatches.length > 0) {
194
+ printCatalogEdits({ packages: catalogMismatches, versionTarget: 'current', ...(workspaceFile !== undefined ? { workspaceFile } : {}) });
195
+ }
196
+ console.log();
197
+ }
198
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { ResolvedPackage } from './types.js';
2
+ /**
3
+ * Fetch all published versions for a package from the npm registry.
4
+ * Returns them in publish order (oldest → newest), stable only.
5
+ * When minimumReleaseAge is set (days), versions published more recently are excluded.
6
+ */
7
+ export declare function fetchStableVersions(name: string, minimumReleaseAge?: number, preReleaseFilter?: string[]): Promise<string[]>;
8
+ /**
9
+ * Given a list of stable versions (oldest → newest) and a lag value,
10
+ * return the target version to pin to.
11
+ *
12
+ * If the package has fewer releases than the lag, pins to the oldest.
13
+ */
14
+ export declare function computeTarget({ versions, lag }: {
15
+ versions: string[];
16
+ lag: number;
17
+ }): string | null;
18
+ /** Resolve lag target for a single package. */
19
+ export declare function resolvePackage({ name, lag, minimumReleaseAge, preReleaseFilter }: {
20
+ name: string;
21
+ lag: number;
22
+ minimumReleaseAge?: number;
23
+ preReleaseFilter?: string[];
24
+ }): Promise<ResolvedPackage>;
25
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAqBjD;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,EAAE,gBAAgB,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBtI;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAMnG;AAED,+CAA+C;AAC/C,wBAAsB,cAAc,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,iBAAiB,EAAE,gBAAqB,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAK9M"}
@@ -0,0 +1,55 @@
1
+ import { semverCompare } from './semver.js';
2
+ const REGISTRY = 'https://registry.npmjs.org';
3
+ const DAY_MS = 86_400_000;
4
+ function isPackument(value) {
5
+ return (typeof value === 'object'
6
+ && value !== null
7
+ && 'versions' in value
8
+ && typeof value.versions === 'object');
9
+ }
10
+ /**
11
+ * Fetch all published versions for a package from the npm registry.
12
+ * Returns them in publish order (oldest → newest), stable only.
13
+ * When minimumReleaseAge is set (days), versions published more recently are excluded.
14
+ */
15
+ export async function fetchStableVersions(name, minimumReleaseAge, preReleaseFilter = []) {
16
+ const res = await fetch(`${REGISTRY}/${encodeURIComponent(name)}`);
17
+ if (!res.ok) {
18
+ throw new Error(`registry fetch failed for "${name}": ${res.status} ${res.statusText}`);
19
+ }
20
+ const data = await res.json();
21
+ if (!isPackument(data)) {
22
+ throw new Error(`unexpected registry response shape for "${name}"`);
23
+ }
24
+ const stable = Object.keys(data.versions).filter(v => !preReleaseFilter.some(tag => v.includes(tag)));
25
+ if (minimumReleaseAge === undefined || minimumReleaseAge <= 0)
26
+ return stable;
27
+ const cutoff = Date.now() - minimumReleaseAge * DAY_MS;
28
+ return stable.filter((v) => {
29
+ const published = data.time?.[v];
30
+ if (published === undefined)
31
+ return true;
32
+ return new Date(published).getTime() <= cutoff;
33
+ });
34
+ }
35
+ /**
36
+ * Given a list of stable versions (oldest → newest) and a lag value,
37
+ * return the target version to pin to.
38
+ *
39
+ * If the package has fewer releases than the lag, pins to the oldest.
40
+ */
41
+ export function computeTarget({ versions, lag }) {
42
+ if (versions.length === 0)
43
+ return null;
44
+ const idx = versions.length - 1 - lag;
45
+ const version = versions[Math.max(0, idx)];
46
+ return version ?? null;
47
+ }
48
+ /** Resolve lag target for a single package. */
49
+ export async function resolvePackage({ name, lag, minimumReleaseAge, preReleaseFilter = [] }) {
50
+ const stableVersions = (await fetchStableVersions(name, minimumReleaseAge, preReleaseFilter)).sort((versionA, versionB) => semverCompare({ versionA, versionB }));
51
+ const latest = stableVersions.at(-1) ?? null;
52
+ const target = computeTarget({ versions: stableVersions, lag });
53
+ return { name, stableVersions, latest, target };
54
+ }
55
+ //# sourceMappingURL=resolve.js.map