@cubing/dev-config 0.6.1 → 0.6.3
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/bin/package.json.ts +103 -7
- package/package.json +1 -1
package/bin/package.json.ts
CHANGED
|
@@ -155,7 +155,7 @@ try {
|
|
|
155
155
|
break;
|
|
156
156
|
}
|
|
157
157
|
default:
|
|
158
|
-
throw new Error("Invalid
|
|
158
|
+
throw new Error("Invalid subcommand.") as never;
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -485,7 +485,7 @@ function checkPath(
|
|
|
485
485
|
break;
|
|
486
486
|
}
|
|
487
487
|
default:
|
|
488
|
-
throw new Error("Invalid
|
|
488
|
+
throw new Error("Invalid subcommand.") as never;
|
|
489
489
|
}
|
|
490
490
|
}
|
|
491
491
|
}
|
|
@@ -520,13 +520,15 @@ checkPath(["types"], { expectPrefix: ResolutionPrefix.Relative });
|
|
|
520
520
|
checkPath(["module"], { expectPrefix: ResolutionPrefix.Relative });
|
|
521
521
|
checkPath(["browser"], { expectPrefix: ResolutionPrefix.Relative });
|
|
522
522
|
|
|
523
|
-
|
|
524
|
-
|
|
523
|
+
const { exports } = packageJSON;
|
|
524
|
+
if (exports) {
|
|
525
|
+
for (const [subpath, value] of Object.entries(exports)) {
|
|
525
526
|
if (!value) {
|
|
526
527
|
// biome-ignore lint/complexity/noUselessContinue: Explicit control flow.
|
|
527
528
|
continue;
|
|
528
529
|
} else if (typeof value === "string") {
|
|
529
|
-
|
|
530
|
+
// TODO: error?
|
|
531
|
+
checkPath(["exports", [subpath]], {
|
|
530
532
|
expectPrefix: ResolutionPrefix.Relative,
|
|
531
533
|
});
|
|
532
534
|
} else if (value === null) {
|
|
@@ -537,8 +539,102 @@ if (packageJSON.exports) {
|
|
|
537
539
|
"❌ .exports — Must use an object (instead of an array).",
|
|
538
540
|
);
|
|
539
541
|
} else {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
+
const keys = Object.keys(value as Record<string, string>);
|
|
543
|
+
|
|
544
|
+
checks.push(
|
|
545
|
+
(async () => {
|
|
546
|
+
const { breadcrumbString } = traverse(["exports", [subpath]]);
|
|
547
|
+
const fixingLines = [];
|
|
548
|
+
const orderingErrorLines = [];
|
|
549
|
+
/**
|
|
550
|
+
* https://nodejs.org/api/packages.html#conditional-exports
|
|
551
|
+
*/
|
|
552
|
+
let updateKeys = false;
|
|
553
|
+
if (keys.includes("types")) {
|
|
554
|
+
if (keys[0] !== "types") {
|
|
555
|
+
switch (subcommand) {
|
|
556
|
+
case "check": {
|
|
557
|
+
orderingErrorLines.push(
|
|
558
|
+
` ↪ "types" must be the first export if present — 📝 fixable!`,
|
|
559
|
+
);
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
case "format": {
|
|
563
|
+
fixingLines.push(
|
|
564
|
+
` ↪ "types" must be the first export if present — 📝 fixing!`,
|
|
565
|
+
);
|
|
566
|
+
keys.splice(keys.indexOf("types"), 1);
|
|
567
|
+
keys.splice(0, 0, "types");
|
|
568
|
+
updateKeys = true;
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
default:
|
|
572
|
+
throw new Error("Invalid subcommand.") as never;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (keys.includes("default")) {
|
|
577
|
+
if (keys.at(-1) !== "default") {
|
|
578
|
+
switch (subcommand) {
|
|
579
|
+
case "check": {
|
|
580
|
+
orderingErrorLines.push(
|
|
581
|
+
` ↪ "default" must be the last export if present — 📝 fixable!`,
|
|
582
|
+
);
|
|
583
|
+
break;
|
|
584
|
+
}
|
|
585
|
+
case "format": {
|
|
586
|
+
fixingLines.push(
|
|
587
|
+
` ↪ "default" must be the last export if present — 📝 fixing!`,
|
|
588
|
+
);
|
|
589
|
+
keys.splice(keys.indexOf("default"), 1);
|
|
590
|
+
keys.push("default");
|
|
591
|
+
updateKeys = true;
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
default:
|
|
595
|
+
throw new Error("Invalid subcommand.") as never;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
if (updateKeys) {
|
|
600
|
+
// TODO: avoid type wrangling.
|
|
601
|
+
const newConditionalExports: Record<string, string> = {};
|
|
602
|
+
for (const key of keys) {
|
|
603
|
+
newConditionalExports[key] = (value as Record<string, string>)[
|
|
604
|
+
key
|
|
605
|
+
];
|
|
606
|
+
}
|
|
607
|
+
(exports as Record<string, Record<string, string>>)[subpath] =
|
|
608
|
+
newConditionalExports;
|
|
609
|
+
}
|
|
610
|
+
for (const key of keys) {
|
|
611
|
+
// Note `"require"` is *emphatically not allowed*.
|
|
612
|
+
if (!["types", "import", "default"].includes(key)) {
|
|
613
|
+
orderingErrorLines.push(
|
|
614
|
+
` ↪ Key must not be present: ${JSON.stringify(key)}`,
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
if (orderingErrorLines.length > 0) {
|
|
619
|
+
exitCode = 1;
|
|
620
|
+
return [
|
|
621
|
+
`❌ ${breadcrumbString} — Invalid keys:`,
|
|
622
|
+
...orderingErrorLines,
|
|
623
|
+
].join("\n");
|
|
624
|
+
} else {
|
|
625
|
+
if (fixingLines.length > 0) {
|
|
626
|
+
return [
|
|
627
|
+
`✅ ${breadcrumbString} — Fixing key ordering:`,
|
|
628
|
+
...fixingLines,
|
|
629
|
+
].join("\n");
|
|
630
|
+
} else {
|
|
631
|
+
return `✅ ${breadcrumbString} — Key set and ordering is okay.`;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
})(),
|
|
635
|
+
);
|
|
636
|
+
for (const secondaryKey of keys) {
|
|
637
|
+
checkPath(["exports", [subpath], secondaryKey], {
|
|
542
638
|
expectPrefix: ResolutionPrefix.Relative,
|
|
543
639
|
});
|
|
544
640
|
}
|