@patchstack/connect 0.2.4 → 0.2.6
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/README.md +6 -3
- package/dist/cli.js +597 -24
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +482 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +478 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/parsers/index.ts
|
|
2
2
|
import { access } from "fs/promises";
|
|
3
|
-
import
|
|
3
|
+
import path4 from "path";
|
|
4
4
|
|
|
5
5
|
// src/types.ts
|
|
6
6
|
var PatchstackError = class extends Error {
|
|
@@ -207,9 +207,452 @@ async function isPlainDirectory(dir) {
|
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
// src/parsers/pnpm.ts
|
|
211
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
212
|
+
async function parsePnpmLockfile(lockfilePath) {
|
|
213
|
+
let raw;
|
|
214
|
+
try {
|
|
215
|
+
raw = await readFile3(lockfilePath, "utf8");
|
|
216
|
+
} catch (cause) {
|
|
217
|
+
throw new PatchstackError(
|
|
218
|
+
`Could not read lockfile at ${lockfilePath}`,
|
|
219
|
+
"LOCKFILE_NOT_FOUND",
|
|
220
|
+
cause
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
const lines = raw.split(/\r?\n/);
|
|
224
|
+
const directNames = collectDirectDepNames(lines);
|
|
225
|
+
const packageKeys = collectPackagesBlockKeys(lines);
|
|
226
|
+
if (packageKeys.length === 0) {
|
|
227
|
+
throw new PatchstackError(
|
|
228
|
+
`Lockfile at ${lockfilePath} has no "packages" entries`,
|
|
229
|
+
"LOCKFILE_PARSE_ERROR"
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
const entries = [];
|
|
233
|
+
for (const key of packageKeys) {
|
|
234
|
+
const parsed = parsePackageKey(key);
|
|
235
|
+
if (parsed === null) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
entries.push({
|
|
239
|
+
name: parsed.name,
|
|
240
|
+
version: parsed.version,
|
|
241
|
+
direct: directNames.has(parsed.name)
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
return entries;
|
|
245
|
+
}
|
|
246
|
+
function parsePackageKey(rawKey) {
|
|
247
|
+
let k = rawKey.trim();
|
|
248
|
+
if (k.length === 0) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
if (k.startsWith("'") && k.endsWith("'") || k.startsWith('"') && k.endsWith('"')) {
|
|
252
|
+
k = k.slice(1, -1);
|
|
253
|
+
}
|
|
254
|
+
if (k.startsWith("/")) {
|
|
255
|
+
k = k.slice(1);
|
|
256
|
+
}
|
|
257
|
+
const parenIdx = k.indexOf("(");
|
|
258
|
+
if (parenIdx >= 0) {
|
|
259
|
+
k = k.slice(0, parenIdx);
|
|
260
|
+
}
|
|
261
|
+
let scopePrefix = "";
|
|
262
|
+
let body = k;
|
|
263
|
+
if (k.startsWith("@")) {
|
|
264
|
+
const firstSlash = k.indexOf("/");
|
|
265
|
+
if (firstSlash <= 0) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
scopePrefix = k.slice(0, firstSlash + 1);
|
|
269
|
+
body = k.slice(firstSlash + 1);
|
|
270
|
+
}
|
|
271
|
+
const slashIdx = body.indexOf("/");
|
|
272
|
+
const atIdx = body.indexOf("@");
|
|
273
|
+
let sepIdx;
|
|
274
|
+
if (slashIdx < 0 && atIdx < 0) {
|
|
275
|
+
return null;
|
|
276
|
+
} else if (slashIdx < 0) {
|
|
277
|
+
sepIdx = atIdx;
|
|
278
|
+
} else if (atIdx < 0) {
|
|
279
|
+
sepIdx = slashIdx;
|
|
280
|
+
} else {
|
|
281
|
+
sepIdx = Math.min(slashIdx, atIdx);
|
|
282
|
+
}
|
|
283
|
+
const name = scopePrefix + body.slice(0, sepIdx);
|
|
284
|
+
let version = body.slice(sepIdx + 1);
|
|
285
|
+
const underscoreIdx = version.indexOf("_");
|
|
286
|
+
if (underscoreIdx >= 0) {
|
|
287
|
+
version = version.slice(0, underscoreIdx);
|
|
288
|
+
}
|
|
289
|
+
if (name.length === 0 || version.length === 0) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
return { name, version };
|
|
293
|
+
}
|
|
294
|
+
function indentOf(line) {
|
|
295
|
+
let i = 0;
|
|
296
|
+
while (i < line.length && line[i] === " ") {
|
|
297
|
+
i++;
|
|
298
|
+
}
|
|
299
|
+
return i;
|
|
300
|
+
}
|
|
301
|
+
function isBlankOrComment(line) {
|
|
302
|
+
const trimmed = line.trim();
|
|
303
|
+
return trimmed.length === 0 || trimmed.startsWith("#");
|
|
304
|
+
}
|
|
305
|
+
function collectPackagesBlockKeys(lines) {
|
|
306
|
+
const keys = [];
|
|
307
|
+
let inBlock = false;
|
|
308
|
+
let childIndent = null;
|
|
309
|
+
for (const line of lines) {
|
|
310
|
+
if (isBlankOrComment(line)) {
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const indent = indentOf(line);
|
|
314
|
+
if (!inBlock) {
|
|
315
|
+
if (indent === 0 && line.trim() === "packages:") {
|
|
316
|
+
inBlock = true;
|
|
317
|
+
}
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (indent === 0) {
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
if (childIndent === null) {
|
|
324
|
+
childIndent = indent;
|
|
325
|
+
}
|
|
326
|
+
if (indent !== childIndent) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const content = line.slice(indent);
|
|
330
|
+
if (!content.endsWith(":")) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
keys.push(content.slice(0, -1));
|
|
334
|
+
}
|
|
335
|
+
return keys;
|
|
336
|
+
}
|
|
337
|
+
function collectDirectDepNames(lines) {
|
|
338
|
+
const names = /* @__PURE__ */ new Set();
|
|
339
|
+
collectFromImporters(lines, names);
|
|
340
|
+
for (const section of ["dependencies", "devDependencies", "optionalDependencies"]) {
|
|
341
|
+
collectFromTopLevelSection(lines, section, names);
|
|
342
|
+
}
|
|
343
|
+
return names;
|
|
344
|
+
}
|
|
345
|
+
var DEP_SECTIONS = /* @__PURE__ */ new Set([
|
|
346
|
+
"dependencies",
|
|
347
|
+
"devDependencies",
|
|
348
|
+
"optionalDependencies"
|
|
349
|
+
]);
|
|
350
|
+
function collectFromImporters(lines, out) {
|
|
351
|
+
let inImporters = false;
|
|
352
|
+
let importerIndent = null;
|
|
353
|
+
let inDepSection = false;
|
|
354
|
+
let depSectionIndent = null;
|
|
355
|
+
let leafIndent = null;
|
|
356
|
+
for (const line of lines) {
|
|
357
|
+
if (isBlankOrComment(line)) {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
const indent = indentOf(line);
|
|
361
|
+
const trimmed = line.trim();
|
|
362
|
+
if (!inImporters) {
|
|
363
|
+
if (indent === 0 && trimmed === "importers:") {
|
|
364
|
+
inImporters = true;
|
|
365
|
+
}
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (indent === 0) {
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
if (importerIndent === null) {
|
|
372
|
+
importerIndent = indent;
|
|
373
|
+
}
|
|
374
|
+
if (indent === importerIndent) {
|
|
375
|
+
inDepSection = false;
|
|
376
|
+
depSectionIndent = null;
|
|
377
|
+
leafIndent = null;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (!inDepSection) {
|
|
381
|
+
const key = stripTrailingColon(trimmed);
|
|
382
|
+
if (key !== null && DEP_SECTIONS.has(key)) {
|
|
383
|
+
inDepSection = true;
|
|
384
|
+
depSectionIndent = indent;
|
|
385
|
+
}
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
if (depSectionIndent !== null && indent <= depSectionIndent) {
|
|
389
|
+
inDepSection = false;
|
|
390
|
+
depSectionIndent = null;
|
|
391
|
+
leafIndent = null;
|
|
392
|
+
const key = stripTrailingColon(trimmed);
|
|
393
|
+
if (key !== null && DEP_SECTIONS.has(key)) {
|
|
394
|
+
inDepSection = true;
|
|
395
|
+
depSectionIndent = indent;
|
|
396
|
+
}
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (leafIndent === null) {
|
|
400
|
+
leafIndent = indent;
|
|
401
|
+
}
|
|
402
|
+
if (indent !== leafIndent) {
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
const name = extractLeafName(trimmed);
|
|
406
|
+
if (name !== null) {
|
|
407
|
+
out.add(name);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
function collectFromTopLevelSection(lines, section, out) {
|
|
412
|
+
let inSection = false;
|
|
413
|
+
let leafIndent = null;
|
|
414
|
+
for (const line of lines) {
|
|
415
|
+
if (isBlankOrComment(line)) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
const indent = indentOf(line);
|
|
419
|
+
const trimmed = line.trim();
|
|
420
|
+
if (!inSection) {
|
|
421
|
+
if (indent === 0 && trimmed === `${section}:`) {
|
|
422
|
+
inSection = true;
|
|
423
|
+
}
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
if (indent === 0) {
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
if (leafIndent === null) {
|
|
430
|
+
leafIndent = indent;
|
|
431
|
+
}
|
|
432
|
+
if (indent !== leafIndent) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const name = extractLeafName(trimmed);
|
|
436
|
+
if (name !== null) {
|
|
437
|
+
out.add(name);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function stripTrailingColon(s) {
|
|
442
|
+
if (!s.endsWith(":")) {
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
return s.slice(0, -1).trim();
|
|
446
|
+
}
|
|
447
|
+
function extractLeafName(trimmed) {
|
|
448
|
+
const colonIdx = trimmed.indexOf(":");
|
|
449
|
+
if (colonIdx < 0) {
|
|
450
|
+
return null;
|
|
451
|
+
}
|
|
452
|
+
let name = trimmed.slice(0, colonIdx).trim();
|
|
453
|
+
if (name.length === 0) {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
if (name.startsWith("'") && name.endsWith("'") || name.startsWith('"') && name.endsWith('"')) {
|
|
457
|
+
name = name.slice(1, -1);
|
|
458
|
+
}
|
|
459
|
+
return name.length > 0 ? name : null;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// src/parsers/yarn.ts
|
|
463
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
464
|
+
import path3 from "path";
|
|
465
|
+
async function parseYarnLockfile(lockfilePath) {
|
|
466
|
+
let raw;
|
|
467
|
+
try {
|
|
468
|
+
raw = await readFile4(lockfilePath, "utf8");
|
|
469
|
+
} catch (cause) {
|
|
470
|
+
throw new PatchstackError(
|
|
471
|
+
`Could not read lockfile at ${lockfilePath}`,
|
|
472
|
+
"LOCKFILE_NOT_FOUND",
|
|
473
|
+
cause
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
const blocks = parseBlocks(raw);
|
|
477
|
+
if (blocks.length === 0) {
|
|
478
|
+
throw new PatchstackError(
|
|
479
|
+
`Lockfile at ${lockfilePath} contains no package entries`,
|
|
480
|
+
"LOCKFILE_PARSE_ERROR"
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
const directNames = await readDirectDepNames(path3.dirname(lockfilePath));
|
|
484
|
+
const entries = [];
|
|
485
|
+
const seen = /* @__PURE__ */ new Set();
|
|
486
|
+
for (const block of blocks) {
|
|
487
|
+
if (block.version.length === 0 || block.names.size === 0) {
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
for (const name of block.names) {
|
|
491
|
+
const dedupKey = `${name}@${block.version}`;
|
|
492
|
+
if (seen.has(dedupKey)) {
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
seen.add(dedupKey);
|
|
496
|
+
entries.push({
|
|
497
|
+
name,
|
|
498
|
+
version: block.version,
|
|
499
|
+
direct: directNames.has(name)
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return entries;
|
|
504
|
+
}
|
|
505
|
+
function parseBlocks(raw) {
|
|
506
|
+
const lines = raw.split(/\r?\n/);
|
|
507
|
+
const blocks = [];
|
|
508
|
+
let current = null;
|
|
509
|
+
const finalize = () => {
|
|
510
|
+
if (current !== null && current.version.length > 0 && current.names.size > 0) {
|
|
511
|
+
blocks.push(current);
|
|
512
|
+
}
|
|
513
|
+
current = null;
|
|
514
|
+
};
|
|
515
|
+
for (const line of lines) {
|
|
516
|
+
const trimmed = line.trim();
|
|
517
|
+
if (trimmed.length === 0 || trimmed.startsWith("#")) {
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
const indent = countLeadingSpaces(line);
|
|
521
|
+
if (indent === 0) {
|
|
522
|
+
finalize();
|
|
523
|
+
if (!trimmed.endsWith(":")) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
const keyLine = trimmed.slice(0, -1);
|
|
527
|
+
const names = /* @__PURE__ */ new Set();
|
|
528
|
+
for (const spec of splitDescriptors(keyLine)) {
|
|
529
|
+
const name = extractName(spec);
|
|
530
|
+
if (name !== null) {
|
|
531
|
+
names.add(name);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
current = { names, version: "" };
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
if (current === null) {
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
const version = parseVersionField(trimmed);
|
|
541
|
+
if (version !== null) {
|
|
542
|
+
current.version = version;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
finalize();
|
|
546
|
+
return blocks;
|
|
547
|
+
}
|
|
548
|
+
function countLeadingSpaces(line) {
|
|
549
|
+
let i = 0;
|
|
550
|
+
while (i < line.length && line[i] === " ") {
|
|
551
|
+
i++;
|
|
552
|
+
}
|
|
553
|
+
return i;
|
|
554
|
+
}
|
|
555
|
+
function splitDescriptors(keyLine) {
|
|
556
|
+
const parts = [];
|
|
557
|
+
let current = "";
|
|
558
|
+
let quote = null;
|
|
559
|
+
for (let i = 0; i < keyLine.length; i++) {
|
|
560
|
+
const c = keyLine[i];
|
|
561
|
+
if (quote !== null) {
|
|
562
|
+
current += c;
|
|
563
|
+
if (c === quote) {
|
|
564
|
+
quote = null;
|
|
565
|
+
}
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
if (c === '"' || c === "'") {
|
|
569
|
+
quote = c;
|
|
570
|
+
current += c;
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
if (c === ",") {
|
|
574
|
+
const piece = current.trim();
|
|
575
|
+
if (piece.length > 0) {
|
|
576
|
+
parts.push(piece);
|
|
577
|
+
}
|
|
578
|
+
current = "";
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
current += c;
|
|
582
|
+
}
|
|
583
|
+
const tail = current.trim();
|
|
584
|
+
if (tail.length > 0) {
|
|
585
|
+
parts.push(tail);
|
|
586
|
+
}
|
|
587
|
+
return parts;
|
|
588
|
+
}
|
|
589
|
+
function extractName(rawSpec) {
|
|
590
|
+
let s = rawSpec.trim();
|
|
591
|
+
if (s.length === 0) {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
|
|
595
|
+
s = s.slice(1, -1);
|
|
596
|
+
}
|
|
597
|
+
const atIdx = s.lastIndexOf("@");
|
|
598
|
+
if (atIdx <= 0) {
|
|
599
|
+
return null;
|
|
600
|
+
}
|
|
601
|
+
const name = s.slice(0, atIdx);
|
|
602
|
+
return name.length > 0 ? name : null;
|
|
603
|
+
}
|
|
604
|
+
function parseVersionField(content) {
|
|
605
|
+
if (!content.startsWith("version")) {
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
const after = content.slice("version".length);
|
|
609
|
+
const firstChar = after.charAt(0);
|
|
610
|
+
if (firstChar !== " " && firstChar !== " " && firstChar !== ":") {
|
|
611
|
+
return null;
|
|
612
|
+
}
|
|
613
|
+
let rest = firstChar === ":" ? after.slice(1) : after;
|
|
614
|
+
rest = rest.trim();
|
|
615
|
+
if (rest.length === 0) {
|
|
616
|
+
return null;
|
|
617
|
+
}
|
|
618
|
+
if (rest.startsWith('"') && rest.endsWith('"') || rest.startsWith("'") && rest.endsWith("'")) {
|
|
619
|
+
rest = rest.slice(1, -1);
|
|
620
|
+
}
|
|
621
|
+
return rest.length > 0 ? rest : null;
|
|
622
|
+
}
|
|
623
|
+
async function readDirectDepNames(cwd) {
|
|
624
|
+
const names = /* @__PURE__ */ new Set();
|
|
625
|
+
let raw;
|
|
626
|
+
try {
|
|
627
|
+
raw = await readFile4(path3.join(cwd, "package.json"), "utf8");
|
|
628
|
+
} catch {
|
|
629
|
+
return names;
|
|
630
|
+
}
|
|
631
|
+
let parsed;
|
|
632
|
+
try {
|
|
633
|
+
parsed = JSON.parse(raw);
|
|
634
|
+
} catch {
|
|
635
|
+
return names;
|
|
636
|
+
}
|
|
637
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
638
|
+
return names;
|
|
639
|
+
}
|
|
640
|
+
const obj = parsed;
|
|
641
|
+
for (const field of ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"]) {
|
|
642
|
+
const section = obj[field];
|
|
643
|
+
if (typeof section !== "object" || section === null) {
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
for (const name of Object.keys(section)) {
|
|
647
|
+
names.add(name);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return names;
|
|
651
|
+
}
|
|
652
|
+
|
|
210
653
|
// src/parsers/index.ts
|
|
211
654
|
async function detectLockfile(cwd) {
|
|
212
|
-
const npmLock =
|
|
655
|
+
const npmLock = path4.join(cwd, "package-lock.json");
|
|
213
656
|
if (await exists(npmLock)) {
|
|
214
657
|
return {
|
|
215
658
|
ecosystem: "npm",
|
|
@@ -218,7 +661,7 @@ async function detectLockfile(cwd) {
|
|
|
218
661
|
strategy: "npm-lockfile"
|
|
219
662
|
};
|
|
220
663
|
}
|
|
221
|
-
const bunLock =
|
|
664
|
+
const bunLock = path4.join(cwd, "bun.lock");
|
|
222
665
|
if (await exists(bunLock)) {
|
|
223
666
|
return {
|
|
224
667
|
ecosystem: "npm",
|
|
@@ -227,7 +670,7 @@ async function detectLockfile(cwd) {
|
|
|
227
670
|
strategy: "node-modules-walk"
|
|
228
671
|
};
|
|
229
672
|
}
|
|
230
|
-
const bunLockB =
|
|
673
|
+
const bunLockB = path4.join(cwd, "bun.lockb");
|
|
231
674
|
if (await exists(bunLockB)) {
|
|
232
675
|
return {
|
|
233
676
|
ecosystem: "npm",
|
|
@@ -236,19 +679,23 @@ async function detectLockfile(cwd) {
|
|
|
236
679
|
strategy: "node-modules-walk"
|
|
237
680
|
};
|
|
238
681
|
}
|
|
239
|
-
const
|
|
240
|
-
if (await exists(yarnLock)) {
|
|
241
|
-
throw new PatchstackError(
|
|
242
|
-
"yarn.lock detected but not yet supported. Run `npm install` to generate a package-lock.json, or open an issue at github.com/patchstack/connect.",
|
|
243
|
-
"LOCKFILE_UNSUPPORTED"
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
const pnpmLock = path3.join(cwd, "pnpm-lock.yaml");
|
|
682
|
+
const pnpmLock = path4.join(cwd, "pnpm-lock.yaml");
|
|
247
683
|
if (await exists(pnpmLock)) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
684
|
+
return {
|
|
685
|
+
ecosystem: "npm",
|
|
686
|
+
filePath: pnpmLock,
|
|
687
|
+
filename: "pnpm-lock.yaml",
|
|
688
|
+
strategy: "pnpm-lockfile"
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
const yarnLock = path4.join(cwd, "yarn.lock");
|
|
692
|
+
if (await exists(yarnLock)) {
|
|
693
|
+
return {
|
|
694
|
+
ecosystem: "npm",
|
|
695
|
+
filePath: yarnLock,
|
|
696
|
+
filename: "yarn.lock",
|
|
697
|
+
strategy: "yarn-lockfile"
|
|
698
|
+
};
|
|
252
699
|
}
|
|
253
700
|
throw new PatchstackError(
|
|
254
701
|
`No lockfile found in ${cwd}. Expected one of: package-lock.json, bun.lock, bun.lockb, yarn.lock, pnpm-lock.yaml.`,
|
|
@@ -264,6 +711,10 @@ async function runStrategy(detected, cwd) {
|
|
|
264
711
|
switch (detected.strategy) {
|
|
265
712
|
case "npm-lockfile":
|
|
266
713
|
return parseNpmLockfile(detected.filePath);
|
|
714
|
+
case "pnpm-lockfile":
|
|
715
|
+
return parsePnpmLockfile(detected.filePath);
|
|
716
|
+
case "yarn-lockfile":
|
|
717
|
+
return parseYarnLockfile(detected.filePath);
|
|
267
718
|
case "node-modules-walk":
|
|
268
719
|
return walkNodeModules(cwd);
|
|
269
720
|
}
|
|
@@ -380,12 +831,16 @@ function compareSegments(a, b) {
|
|
|
380
831
|
}
|
|
381
832
|
|
|
382
833
|
// src/client.ts
|
|
383
|
-
var DEFAULT_ENDPOINT = "
|
|
834
|
+
var DEFAULT_ENDPOINT = "https://api.patchstack.com/monitor/pulse/manifest";
|
|
384
835
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
385
836
|
function buildEndpointUrl(base, siteUuid) {
|
|
386
837
|
const trimmed = base.replace(/\/$/, "");
|
|
387
838
|
return siteUuid !== void 0 && siteUuid !== null && siteUuid.length > 0 ? `${trimmed}/${encodeURIComponent(siteUuid)}` : trimmed;
|
|
388
839
|
}
|
|
840
|
+
function buildClaimUrl(endpoint, siteUuid) {
|
|
841
|
+
const origin = new URL(endpoint).origin;
|
|
842
|
+
return `${origin}/monitor/claim?site=${encodeURIComponent(siteUuid)}`;
|
|
843
|
+
}
|
|
389
844
|
async function postManifest(config, payload) {
|
|
390
845
|
const url = buildEndpointUrl(config.endpoint, config.siteUuid);
|
|
391
846
|
const timeoutMs = config.timeoutMs;
|
|
@@ -453,8 +908,8 @@ function isTimeoutError(cause) {
|
|
|
453
908
|
}
|
|
454
909
|
|
|
455
910
|
// src/config.ts
|
|
456
|
-
import { readFile as
|
|
457
|
-
import
|
|
911
|
+
import { readFile as readFile5, writeFile } from "fs/promises";
|
|
912
|
+
import path5 from "path";
|
|
458
913
|
var CONFIG_FILENAME = ".patchstackrc.json";
|
|
459
914
|
async function resolveConfig(options) {
|
|
460
915
|
const fromFile = await readConfigFile(options.cwd);
|
|
@@ -481,7 +936,7 @@ async function resolveConfig(options) {
|
|
|
481
936
|
};
|
|
482
937
|
}
|
|
483
938
|
async function writeConfigFile(cwd, config) {
|
|
484
|
-
const target =
|
|
939
|
+
const target = path5.join(cwd, CONFIG_FILENAME);
|
|
485
940
|
const content = JSON.stringify(config, null, 2) + "\n";
|
|
486
941
|
await writeFile(target, content, "utf8");
|
|
487
942
|
return target;
|
|
@@ -491,10 +946,10 @@ async function persistSiteUuid(cwd, siteUuid) {
|
|
|
491
946
|
return writeConfigFile(cwd, { ...existing, siteUuid });
|
|
492
947
|
}
|
|
493
948
|
async function readConfigFile(cwd) {
|
|
494
|
-
const target =
|
|
949
|
+
const target = path5.join(cwd, CONFIG_FILENAME);
|
|
495
950
|
let raw;
|
|
496
951
|
try {
|
|
497
|
-
raw = await
|
|
952
|
+
raw = await readFile5(target, "utf8");
|
|
498
953
|
} catch (err) {
|
|
499
954
|
if (err.code === "ENOENT") {
|
|
500
955
|
return {};
|
|
@@ -559,6 +1014,7 @@ async function scanAndReport(options = {}) {
|
|
|
559
1014
|
export {
|
|
560
1015
|
DEFAULT_ENDPOINT,
|
|
561
1016
|
PatchstackError,
|
|
1017
|
+
buildClaimUrl,
|
|
562
1018
|
buildEndpointUrl,
|
|
563
1019
|
buildWirePayload,
|
|
564
1020
|
compareVersions,
|