@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.
Files changed (2) hide show
  1. package/bin/package.json.ts +103 -7
  2. package/package.json +1 -1
@@ -155,7 +155,7 @@ try {
155
155
  break;
156
156
  }
157
157
  default:
158
- throw new Error("Invalid command.") as never;
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 command.") as never;
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
- if (packageJSON.exports) {
524
- for (const [exportPath, value] of Object.entries(packageJSON.exports)) {
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
- checkPath(["exports", [exportPath]], {
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
- for (const secondaryKey of Object.keys(value as Record<string, string>)) {
541
- checkPath(["exports", [exportPath], secondaryKey], {
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cubing/dev-config",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Common dev configs for projects.",
5
5
  "author": {
6
6
  "name": "Lucas Garron",