@seorii/libcollect 0.1.0 → 1.0.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.
- package/include-deps.mjs +274 -71
- package/include-deps.test.mjs +437 -0
- package/package.json +1507 -5
package/include-deps.mjs
CHANGED
|
@@ -6,10 +6,12 @@ import process from "node:process";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import semver from "semver";
|
|
8
8
|
|
|
9
|
-
const DEFAULT_CONCURRENCY =
|
|
9
|
+
const DEFAULT_CONCURRENCY = 50;
|
|
10
10
|
const DEFAULT_SOURCE_SECTIONS = ["dependencies", "optionalDependencies", "peerDependencies"];
|
|
11
11
|
const DEFAULT_INCLUDE_TYPES = ["peerDependency", "optionalDependency", "bundledDependency"];
|
|
12
12
|
const REGISTRY_BASE = "https://registry.npmjs.org";
|
|
13
|
+
const FETCH_RETRY_COUNT = 3;
|
|
14
|
+
const FETCH_RETRY_BASE_DELAY_MS = 250;
|
|
13
15
|
|
|
14
16
|
function createLimiter(maxConcurrency) {
|
|
15
17
|
let activeCount = 0;
|
|
@@ -38,7 +40,13 @@ function createLimiter(maxConcurrency) {
|
|
|
38
40
|
};
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
function
|
|
43
|
+
function sleep(ms) {
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
setTimeout(resolve, ms);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function createRegistryContext(concurrency = DEFAULT_CONCURRENCY, logger = null) {
|
|
42
50
|
const safeConcurrency =
|
|
43
51
|
Number.isFinite(concurrency) && concurrency > 0 ? Math.floor(concurrency) : DEFAULT_CONCURRENCY;
|
|
44
52
|
|
|
@@ -47,20 +55,42 @@ function createRegistryContext(concurrency = DEFAULT_CONCURRENCY) {
|
|
|
47
55
|
fetchLimit: createLimiter(safeConcurrency),
|
|
48
56
|
metaCache: new Map(),
|
|
49
57
|
resolvedCache: new Map(),
|
|
58
|
+
warnings: [],
|
|
59
|
+
logger,
|
|
50
60
|
};
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
async function fetchJson(url, registryContext) {
|
|
54
64
|
return registryContext.fetchLimit(async () => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
});
|
|
65
|
+
for (let attempt = 0; attempt <= FETCH_RETRY_COUNT; attempt += 1) {
|
|
66
|
+
let failureMessage = null;
|
|
58
67
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
try {
|
|
69
|
+
const res = await fetch(url, {
|
|
70
|
+
headers: { accept: "application/json" },
|
|
71
|
+
});
|
|
62
72
|
|
|
63
|
-
|
|
73
|
+
if (res.ok) {
|
|
74
|
+
return res.json();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
failureMessage = `HTTP ${res.status} for ${url}`;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
failureMessage = error instanceof Error ? error.message : String(error);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (attempt === FETCH_RETRY_COUNT) {
|
|
83
|
+
throw new Error(failureMessage);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const delayMs = FETCH_RETRY_BASE_DELAY_MS * 2 ** attempt;
|
|
87
|
+
if (typeof registryContext.logger === "function") {
|
|
88
|
+
registryContext.logger(
|
|
89
|
+
`[libcollect] registry fetch failed, retrying ${attempt + 1}/${FETCH_RETRY_COUNT} in ${delayMs}ms: ${failureMessage}`,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
await sleep(delayMs);
|
|
93
|
+
}
|
|
64
94
|
});
|
|
65
95
|
}
|
|
66
96
|
|
|
@@ -99,12 +129,87 @@ function rangeMentionsPrerelease(range) {
|
|
|
99
129
|
return /-\w/.test(String(range || ""));
|
|
100
130
|
}
|
|
101
131
|
|
|
132
|
+
function splitDisjunctiveRange(range) {
|
|
133
|
+
return String(range || "")
|
|
134
|
+
.split("||")
|
|
135
|
+
.map((part) => part.trim())
|
|
136
|
+
.filter(Boolean);
|
|
137
|
+
}
|
|
138
|
+
|
|
102
139
|
function getAllVersions(meta) {
|
|
103
140
|
return Object.keys(meta.versions || {})
|
|
104
141
|
.filter((version) => !!semver.valid(version))
|
|
105
142
|
.sort(semver.rcompare);
|
|
106
143
|
}
|
|
107
144
|
|
|
145
|
+
function getPrereleaseChannel(version) {
|
|
146
|
+
const prerelease = semver.prerelease(version);
|
|
147
|
+
if (!prerelease || prerelease.length === 0) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return String(prerelease[0] || "")
|
|
152
|
+
.split("-")[0]
|
|
153
|
+
.trim() || null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function findFallbackVersionFromMeta(meta, wanted) {
|
|
157
|
+
const target = String(wanted || "").trim();
|
|
158
|
+
if (!semver.valid(target)) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const targetChannel = getPrereleaseChannel(target);
|
|
163
|
+
if (!targetChannel) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
getAllVersions(meta).find((version) => {
|
|
169
|
+
if (!semver.prerelease(version)) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
semver.major(version) === semver.major(target) &&
|
|
175
|
+
semver.minor(version) === semver.minor(target) &&
|
|
176
|
+
semver.patch(version) === semver.patch(target) &&
|
|
177
|
+
getPrereleaseChannel(version) === targetChannel
|
|
178
|
+
);
|
|
179
|
+
}) || null
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function versionSatisfiesWanted(version, wanted, meta) {
|
|
184
|
+
const target = String(wanted || "latest").trim() || "latest";
|
|
185
|
+
const distTags = meta["dist-tags"] || {};
|
|
186
|
+
|
|
187
|
+
if (target === "latest" || target === "*") {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const parts = splitDisjunctiveRange(target);
|
|
192
|
+
if (parts.length > 1) {
|
|
193
|
+
return parts.some((part) => versionSatisfiesWanted(version, part, meta));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (distTags[target]) {
|
|
197
|
+
return version === distTags[target];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (meta.versions?.[target]) {
|
|
201
|
+
return version === target;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!semver.validRange(target)) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return semver.satisfies(version, target, {
|
|
209
|
+
includePrerelease: rangeMentionsPrerelease(target),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
108
213
|
function pickVersionFromMeta(meta, wanted) {
|
|
109
214
|
const versions = getAllVersions(meta);
|
|
110
215
|
const distTags = meta["dist-tags"] || {};
|
|
@@ -122,13 +227,7 @@ function pickVersionFromMeta(meta, wanted) {
|
|
|
122
227
|
return target;
|
|
123
228
|
}
|
|
124
229
|
|
|
125
|
-
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return semver.maxSatisfying(versions, target, {
|
|
130
|
-
includePrerelease: rangeMentionsPrerelease(target),
|
|
131
|
-
});
|
|
230
|
+
return versions.find((version) => versionSatisfiesWanted(version, target, meta)) || null;
|
|
132
231
|
}
|
|
133
232
|
|
|
134
233
|
async function resolveVersion(name, wanted, registryContext) {
|
|
@@ -157,6 +256,14 @@ async function resolveVersion(name, wanted, registryContext) {
|
|
|
157
256
|
const resolvedVersion = pickVersionFromMeta(meta, wanted);
|
|
158
257
|
|
|
159
258
|
if (!resolvedVersion) {
|
|
259
|
+
const fallbackVersion = findFallbackVersionFromMeta(meta, wanted);
|
|
260
|
+
if (fallbackVersion) {
|
|
261
|
+
registryContext.warnings.push(
|
|
262
|
+
`${name}: requested ${wanted} is unavailable in the registry, using nearest published ${fallbackVersion} instead.`,
|
|
263
|
+
);
|
|
264
|
+
return fallbackVersion;
|
|
265
|
+
}
|
|
266
|
+
|
|
160
267
|
throw new Error(`Cannot resolve version: ${name}@${wanted || "latest"}`);
|
|
161
268
|
}
|
|
162
269
|
|
|
@@ -280,36 +387,44 @@ async function walkNode(name, wanted, edgeType, parent, registryContext, visited
|
|
|
280
387
|
return makeSkippedNode(name, wanted, edgeType, parent, "non-registry spec");
|
|
281
388
|
}
|
|
282
389
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
390
|
+
try {
|
|
391
|
+
const alias = parseAliasSpec(wanted);
|
|
392
|
+
if (alias) {
|
|
393
|
+
const resolvedAlias = await resolveVersion(name, wanted, registryContext);
|
|
394
|
+
return buildNodeFromPackage(
|
|
395
|
+
resolvedAlias.actualName,
|
|
396
|
+
name,
|
|
397
|
+
wanted,
|
|
398
|
+
resolvedAlias.version,
|
|
399
|
+
edgeType,
|
|
400
|
+
parent,
|
|
401
|
+
registryContext,
|
|
402
|
+
visited,
|
|
403
|
+
{
|
|
404
|
+
actualName: resolvedAlias.actualName,
|
|
405
|
+
aliased: true,
|
|
406
|
+
},
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const resolvedVersion = await resolveVersion(name, wanted, registryContext);
|
|
286
411
|
return buildNodeFromPackage(
|
|
287
|
-
|
|
412
|
+
name,
|
|
288
413
|
name,
|
|
289
414
|
wanted,
|
|
290
|
-
|
|
415
|
+
resolvedVersion,
|
|
291
416
|
edgeType,
|
|
292
417
|
parent,
|
|
293
418
|
registryContext,
|
|
294
419
|
visited,
|
|
295
|
-
{
|
|
296
|
-
actualName: resolvedAlias.actualName,
|
|
297
|
-
aliased: true,
|
|
298
|
-
},
|
|
299
420
|
);
|
|
300
|
-
}
|
|
421
|
+
} catch (error) {
|
|
422
|
+
if (edgeType !== "root" && isVersionResolutionError(error)) {
|
|
423
|
+
return makeSkippedNode(name, wanted, edgeType, parent, "unresolvable version");
|
|
424
|
+
}
|
|
301
425
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
name,
|
|
305
|
-
name,
|
|
306
|
-
wanted,
|
|
307
|
-
resolvedVersion,
|
|
308
|
-
edgeType,
|
|
309
|
-
parent,
|
|
310
|
-
registryContext,
|
|
311
|
-
visited,
|
|
312
|
-
);
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
313
428
|
}
|
|
314
429
|
|
|
315
430
|
function flattenTree(tree) {
|
|
@@ -354,7 +469,8 @@ function flattenTree(tree) {
|
|
|
354
469
|
}
|
|
355
470
|
|
|
356
471
|
async function collectNpmDeps(rootName, rootVersion = "latest", options = {}) {
|
|
357
|
-
const registryContext =
|
|
472
|
+
const registryContext =
|
|
473
|
+
options.registryContext || createRegistryContext(options.concurrency, options.logger);
|
|
358
474
|
const visited = new Set();
|
|
359
475
|
const tree = await walkNode(rootName, rootVersion, "root", null, registryContext, visited);
|
|
360
476
|
const flat = flattenTree(tree);
|
|
@@ -375,6 +491,26 @@ function dedupe(items) {
|
|
|
375
491
|
return [...new Set(items.filter(Boolean))];
|
|
376
492
|
}
|
|
377
493
|
|
|
494
|
+
function logProgress(logger, message) {
|
|
495
|
+
if (typeof logger !== "function") {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
logger(`[libcollect] ${message}`);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function shouldLogStep(index, total, step = 25) {
|
|
503
|
+
return index === 1 || index === total || index % step === 0;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function isVersionResolutionError(error) {
|
|
507
|
+
return (
|
|
508
|
+
error instanceof Error &&
|
|
509
|
+
(error.message.startsWith("Cannot resolve version:") ||
|
|
510
|
+
error.message.startsWith("Missing version metadata:"))
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
378
514
|
function getLibcollectConfig(pkg) {
|
|
379
515
|
const raw = pkg.libcollect && typeof pkg.libcollect === "object" ? pkg.libcollect : {};
|
|
380
516
|
|
|
@@ -475,34 +611,57 @@ function addCandidate(candidates, node, extra = {}) {
|
|
|
475
611
|
if (node.aliased || extra.aliased) candidate.aliased = true;
|
|
476
612
|
}
|
|
477
613
|
|
|
478
|
-
async function collectCandidates(pkg, config, registryContext) {
|
|
614
|
+
async function collectCandidates(pkg, config, registryContext, logger) {
|
|
479
615
|
const { roots, manualDependencies } = buildSourceRoots(pkg, config);
|
|
480
616
|
const candidates = new Map();
|
|
481
617
|
const warnings = [];
|
|
482
618
|
const includeTypeSet = new Set(config.includeDependencyTypes);
|
|
483
619
|
|
|
484
|
-
|
|
620
|
+
logProgress(
|
|
621
|
+
logger,
|
|
622
|
+
`collecting dependency graph from ${roots.length} root(s) with concurrency ${registryContext.concurrency}`,
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
for (const [index, root] of roots.entries()) {
|
|
626
|
+
const rootProgress = `${index + 1}/${roots.length}`;
|
|
627
|
+
logProgress(logger, `root ${rootProgress}: ${root.name}@${root.range} (${root.sourceSection})`);
|
|
628
|
+
|
|
485
629
|
if (root.sourceSection !== "dependencies") {
|
|
486
630
|
if (isNonRegistrySpec(root.range)) {
|
|
487
631
|
warnings.push(
|
|
488
632
|
`${root.name}: ${root.sourceSection}에 있는 non-registry spec(${root.range})은 dependencies로 자동 승격하지 않았습니다.`,
|
|
489
633
|
);
|
|
490
634
|
} else {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
635
|
+
try {
|
|
636
|
+
const resolvedRoot = await resolveVersion(root.name, root.range, registryContext);
|
|
637
|
+
addCandidate(
|
|
638
|
+
candidates,
|
|
639
|
+
{
|
|
640
|
+
name: root.name,
|
|
641
|
+
requested: root.range,
|
|
642
|
+
version: typeof resolvedRoot === "string" ? resolvedRoot : resolvedRoot.version,
|
|
643
|
+
actualName: typeof resolvedRoot === "string" ? null : resolvedRoot.actualName || null,
|
|
644
|
+
dependencyType: "sourceSection",
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
sourceSection: root.sourceSection,
|
|
648
|
+
aliased: !!(typeof resolvedRoot !== "string" && resolvedRoot.actualName),
|
|
649
|
+
},
|
|
650
|
+
);
|
|
651
|
+
} catch (error) {
|
|
652
|
+
if (!isVersionResolutionError(error)) {
|
|
653
|
+
throw error;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
warnings.push(
|
|
657
|
+
`${root.name}: ${root.sourceSection}에 있는 spec(${root.range})을 registry에서 찾지 못해 자동 승격하지 않았습니다.`,
|
|
658
|
+
);
|
|
659
|
+
logProgress(
|
|
660
|
+
logger,
|
|
661
|
+
`root ${rootProgress} skipped source-section promotion: unresolved version ${root.range}`,
|
|
662
|
+
);
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
506
665
|
}
|
|
507
666
|
}
|
|
508
667
|
|
|
@@ -510,13 +669,30 @@ async function collectCandidates(pkg, config, registryContext) {
|
|
|
510
669
|
warnings.push(
|
|
511
670
|
`${root.name}: root spec(${root.range})는 registry 기반이 아니어서 하위 dep 탐색을 건너뛰었습니다.`,
|
|
512
671
|
);
|
|
672
|
+
logProgress(logger, `root ${rootProgress} skipped graph walk: non-registry spec ${root.range}`);
|
|
513
673
|
continue;
|
|
514
674
|
}
|
|
515
675
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
676
|
+
let result;
|
|
677
|
+
|
|
678
|
+
try {
|
|
679
|
+
result = await collectNpmDeps(root.name, root.range, {
|
|
680
|
+
registryContext,
|
|
681
|
+
concurrency: config.concurrency,
|
|
682
|
+
});
|
|
683
|
+
} catch (error) {
|
|
684
|
+
if (!isVersionResolutionError(error)) {
|
|
685
|
+
throw error;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
warnings.push(
|
|
689
|
+
`${root.name}: root spec(${root.range})을 registry에서 찾지 못해 하위 dep 탐색을 건너뛰었습니다.`,
|
|
690
|
+
);
|
|
691
|
+
logProgress(logger, `root ${rootProgress} skipped graph walk: unresolved version ${root.range}`);
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
const candidateCountBefore = candidates.size;
|
|
520
696
|
|
|
521
697
|
for (const node of result.flat) {
|
|
522
698
|
if (node.skipped) {
|
|
@@ -532,6 +708,13 @@ async function collectCandidates(pkg, config, registryContext) {
|
|
|
532
708
|
|
|
533
709
|
addCandidate(candidates, node);
|
|
534
710
|
}
|
|
711
|
+
|
|
712
|
+
logProgress(
|
|
713
|
+
logger,
|
|
714
|
+
`root ${rootProgress} done: walked ${result.flat.length} node(s), ${
|
|
715
|
+
candidates.size - candidateCountBefore
|
|
716
|
+
} new candidate(s)`,
|
|
717
|
+
);
|
|
535
718
|
}
|
|
536
719
|
|
|
537
720
|
return { candidates, warnings, manualDependencies, roots };
|
|
@@ -548,14 +731,11 @@ async function resolvePreferredSpec(name, candidate, pkg, config, registryContex
|
|
|
548
731
|
|
|
549
732
|
const meta = await getPackageMeta(targetName, registryContext);
|
|
550
733
|
const versions = getAllVersions(meta);
|
|
551
|
-
const includePrerelease = normalizedRanges.some(rangeMentionsPrerelease);
|
|
552
734
|
|
|
553
735
|
const commonVersion = versions.find((version) =>
|
|
554
736
|
normalizedRanges.every((range) => {
|
|
555
737
|
if (range === "latest" || range === "*") return true;
|
|
556
|
-
|
|
557
|
-
if (!semver.validRange(range)) return false;
|
|
558
|
-
return semver.satisfies(version, range, { includePrerelease });
|
|
738
|
+
return versionSatisfiesWanted(version, range, meta);
|
|
559
739
|
}),
|
|
560
740
|
);
|
|
561
741
|
|
|
@@ -594,27 +774,46 @@ function diffKeys(beforeObj, afterObj) {
|
|
|
594
774
|
|
|
595
775
|
export async function includeDependencies(
|
|
596
776
|
packageJsonPath = path.resolve(process.cwd(), "package.json"),
|
|
777
|
+
options = {},
|
|
597
778
|
) {
|
|
779
|
+
const logger = typeof options.logger === "function" ? options.logger : null;
|
|
780
|
+
logProgress(logger, `reading ${packageJsonPath}`);
|
|
781
|
+
|
|
598
782
|
const rawText = await fs.readFile(packageJsonPath, "utf8");
|
|
599
783
|
const pkg = JSON.parse(rawText);
|
|
600
784
|
const config = getLibcollectConfig(pkg);
|
|
601
|
-
const registryContext = createRegistryContext(config.concurrency);
|
|
785
|
+
const registryContext = createRegistryContext(config.concurrency, logger);
|
|
602
786
|
const beforeDependencies = { ...pkg.dependencies };
|
|
603
787
|
|
|
788
|
+
logProgress(
|
|
789
|
+
logger,
|
|
790
|
+
`config loaded: source sections [${config.sourceSections.join(", ")}], include types [${config.includeDependencyTypes.join(", ")}]`,
|
|
791
|
+
);
|
|
792
|
+
|
|
604
793
|
const { candidates, warnings, manualDependencies, roots } = await collectCandidates(
|
|
605
794
|
pkg,
|
|
606
795
|
config,
|
|
607
796
|
registryContext,
|
|
797
|
+
logger,
|
|
608
798
|
);
|
|
609
799
|
|
|
610
800
|
const autoIncludedDependencies = {};
|
|
611
801
|
const versionConflictWarnings = [];
|
|
802
|
+
const pendingCandidates = [...candidates.entries()]
|
|
803
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
804
|
+
.filter(([name]) => !manualDependencies[name]);
|
|
612
805
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
806
|
+
logProgress(
|
|
807
|
+
logger,
|
|
808
|
+
`selecting preferred specs for ${pendingCandidates.length} auto-include candidate(s)`,
|
|
809
|
+
);
|
|
810
|
+
|
|
811
|
+
for (const [index, [name, candidate]] of pendingCandidates.entries()) {
|
|
812
|
+
if (shouldLogStep(index + 1, pendingCandidates.length)) {
|
|
813
|
+
logProgress(
|
|
814
|
+
logger,
|
|
815
|
+
`spec selection ${index + 1}/${pendingCandidates.length}: ${name}`,
|
|
816
|
+
);
|
|
618
817
|
}
|
|
619
818
|
|
|
620
819
|
const spec = await resolvePreferredSpec(name, candidate, pkg, config, registryContext);
|
|
@@ -643,7 +842,9 @@ export async function includeDependencies(
|
|
|
643
842
|
exactVersions: config.exactVersions,
|
|
644
843
|
};
|
|
645
844
|
|
|
845
|
+
logProgress(logger, `writing backup to ${packageJsonPath}.bak`);
|
|
646
846
|
await fs.writeFile(`${packageJsonPath}.bak`, rawText, "utf8");
|
|
847
|
+
logProgress(logger, `writing updated package.json`);
|
|
647
848
|
await fs.writeFile(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf8");
|
|
648
849
|
|
|
649
850
|
const { added, removed } = diffKeys(beforeDependencies, nextDependencies);
|
|
@@ -654,7 +855,7 @@ export async function includeDependencies(
|
|
|
654
855
|
roots,
|
|
655
856
|
added,
|
|
656
857
|
removed,
|
|
657
|
-
warnings: [...warnings, ...versionConflictWarnings],
|
|
858
|
+
warnings: [...warnings, ...versionConflictWarnings, ...registryContext.warnings],
|
|
658
859
|
autoIncludedCount: Object.keys(autoIncludedDependencies).length,
|
|
659
860
|
dependencyCount: Object.keys(nextDependencies).length,
|
|
660
861
|
};
|
|
@@ -684,7 +885,9 @@ async function runCli() {
|
|
|
684
885
|
}
|
|
685
886
|
|
|
686
887
|
try {
|
|
687
|
-
const result = await includeDependencies(
|
|
888
|
+
const result = await includeDependencies(undefined, {
|
|
889
|
+
logger: (message) => console.log(message),
|
|
890
|
+
});
|
|
688
891
|
console.log(
|
|
689
892
|
`[libcollect] roots: ${result.roots.map((x) => `${x.name}@${x.range}`).join(", ")}`,
|
|
690
893
|
);
|