cursedbelt 4.7.0 → 5.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.
Files changed (137) hide show
  1. package/README.md +36 -0
  2. package/dist/react/chat/index.d.ts +1 -0
  3. package/dist/react/chat/index.d.ts.map +1 -1
  4. package/dist/react/chat/index.js +1 -0
  5. package/dist/react/chat/index.js.map +1 -1
  6. package/dist/react/chat/usePresence.d.ts +75 -0
  7. package/dist/react/chat/usePresence.d.ts.map +1 -0
  8. package/dist/react/chat/usePresence.js +109 -0
  9. package/dist/react/chat/usePresence.js.map +1 -0
  10. package/dist/react/components/SecretInput.d.ts +7 -2
  11. package/dist/react/components/SecretInput.d.ts.map +1 -1
  12. package/dist/react/components/SecretInput.js +5 -2
  13. package/dist/react/components/SecretInput.js.map +1 -1
  14. package/dist/react/components/TooltipImpl.d.ts.map +1 -1
  15. package/dist/react/components/TooltipImpl.js +52 -3
  16. package/dist/react/components/TooltipImpl.js.map +1 -1
  17. package/dist/react/index.d.ts +1 -0
  18. package/dist/react/index.d.ts.map +1 -1
  19. package/dist/react/index.js +1 -0
  20. package/dist/react/index.js.map +1 -1
  21. package/dist/react/master-lock/MasterLockDialog.d.ts.map +1 -1
  22. package/dist/react/master-lock/MasterLockDialog.js +2 -1
  23. package/dist/react/master-lock/MasterLockDialog.js.map +1 -1
  24. package/dist/react/master-lock/MasterLockProvider.d.ts +12 -18
  25. package/dist/react/master-lock/MasterLockProvider.d.ts.map +1 -1
  26. package/dist/react/master-lock/MasterLockProvider.js +14 -20
  27. package/dist/react/master-lock/MasterLockProvider.js.map +1 -1
  28. package/dist/react/media/MediaUploadControl.d.ts +3 -7
  29. package/dist/react/media/MediaUploadControl.d.ts.map +1 -1
  30. package/dist/react/media/MediaUploadControl.js +4 -13
  31. package/dist/react/media/MediaUploadControl.js.map +1 -1
  32. package/dist/react/media/fileUploadClient.d.ts +0 -8
  33. package/dist/react/media/fileUploadClient.d.ts.map +1 -1
  34. package/dist/react/media/fileUploadClient.js +0 -8
  35. package/dist/react/media/fileUploadClient.js.map +1 -1
  36. package/dist/react/media/hlsSource.d.ts.map +1 -1
  37. package/dist/react/media/hlsSource.js +4 -2
  38. package/dist/react/media/hlsSource.js.map +1 -1
  39. package/dist/react/media/index.d.ts +0 -4
  40. package/dist/react/media/index.d.ts.map +1 -1
  41. package/dist/react/media/index.js +0 -4
  42. package/dist/react/media/index.js.map +1 -1
  43. package/dist/react/sessionAuth.d.ts +1 -2
  44. package/dist/react/sessionAuth.d.ts.map +1 -1
  45. package/dist/react/sessionAuth.js +2 -3
  46. package/dist/react/sessionAuth.js.map +1 -1
  47. package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
  48. package/dist/styles-areas/activity-bar.css +1 -1
  49. package/dist/styles-areas/auth.css +1 -1
  50. package/dist/styles-areas/charts.css +1 -1
  51. package/dist/styles-areas/chat.css +1 -1
  52. package/dist/styles-areas/core.css +1 -1
  53. package/dist/styles-areas/data-table.css +1 -1
  54. package/dist/styles-areas/disk-usage.css +1 -1
  55. package/dist/styles-areas/fields.css +1 -1
  56. package/dist/styles-areas/master-detail.css +1 -1
  57. package/dist/styles-areas/master-lock.css +108 -2
  58. package/dist/styles-areas/media-gallery.css +1 -1
  59. package/dist/styles-areas/media.css +1 -17
  60. package/dist/styles-areas/nav.css +1 -1
  61. package/dist/styles-areas/notifications.css +1 -1
  62. package/dist/styles-areas/spreadsheet.css +1 -1
  63. package/dist/styles-areas/stats.css +1 -1
  64. package/dist/styles-areas/wizard.css +1 -1
  65. package/dist/styles-areas/workbook-viewer.css +1 -1
  66. package/dist/styles-utilities.css +0 -16
  67. package/dist/testing/_noBun.d.ts +2 -0
  68. package/dist/testing/_noBun.d.ts.map +1 -0
  69. package/dist/testing/_noBun.js +10 -0
  70. package/dist/testing/_noBun.js.map +1 -0
  71. package/package.json +42 -19
  72. package/scripts/checkAreaStyles.spec.ts +71 -0
  73. package/scripts/checkAreaStyles.ts +150 -0
  74. package/scripts/guardrailsEnforce.spec.ts +43 -0
  75. package/scripts/guardrailsEnforce.ts +46 -1
  76. package/scripts/styleAreas.ts +1 -2
  77. package/src/barrelsReachNoOptionalPeer.spec.ts +6 -3
  78. package/src/bundlerOnlyEntries.spec.ts +101 -0
  79. package/src/declaredImports.spec.ts +4 -0
  80. package/src/optionalPeersTable.spec.ts +127 -0
  81. package/src/react/chat/index.ts +8 -0
  82. package/src/react/chat/usePresence.spec.tsx +138 -0
  83. package/src/react/chat/usePresence.ts +185 -0
  84. package/src/react/components/SecretInput.tsx +12 -1
  85. package/src/react/components/TooltipImpl.tsx +54 -5
  86. package/src/react/index.ts +8 -0
  87. package/src/react/master-lock/MasterLockDialog.tsx +13 -9
  88. package/src/react/master-lock/MasterLockProvider.spec.tsx +17 -0
  89. package/src/react/master-lock/MasterLockProvider.tsx +16 -19
  90. package/src/react/media/MediaUploadControl.tsx +8 -29
  91. package/src/react/media/fileUploadClient.ts +7 -17
  92. package/src/react/media/hlsSource.ts +4 -1
  93. package/src/react/media/index.ts +0 -16
  94. package/src/react/sessionAuth.ts +2 -3
  95. package/src/scriptsResolve.spec.ts +66 -0
  96. package/src/styles-areas/activity-bar.css +1 -1
  97. package/src/styles-areas/auth.css +1 -1
  98. package/src/styles-areas/charts.css +1 -1
  99. package/src/styles-areas/chat.css +1 -1
  100. package/src/styles-areas/core.css +1 -1
  101. package/src/styles-areas/data-table.css +1 -1
  102. package/src/styles-areas/disk-usage.css +1 -1
  103. package/src/styles-areas/fields.css +1 -1
  104. package/src/styles-areas/master-detail.css +1 -1
  105. package/src/styles-areas/master-lock.css +108 -2
  106. package/src/styles-areas/media-gallery.css +1 -1
  107. package/src/styles-areas/media.css +1 -17
  108. package/src/styles-areas/nav.css +1 -1
  109. package/src/styles-areas/notifications.css +1 -1
  110. package/src/styles-areas/spreadsheet.css +1 -1
  111. package/src/styles-areas/stats.css +1 -1
  112. package/src/styles-areas/wizard.css +1 -1
  113. package/src/styles-areas/workbook-viewer.css +1 -1
  114. package/src/styles-utilities.css +0 -16
  115. package/src/testing/_noBun.ts +12 -0
  116. package/src/verifyGraph.spec.ts +11 -0
  117. package/dist/react/media/PrivateIndexView.d.ts +0 -6
  118. package/dist/react/media/PrivateIndexView.d.ts.map +0 -1
  119. package/dist/react/media/PrivateIndexView.js +0 -44
  120. package/dist/react/media/PrivateIndexView.js.map +0 -1
  121. package/dist/react/media/PrivateModeBadge.d.ts +0 -17
  122. package/dist/react/media/PrivateModeBadge.d.ts.map +0 -1
  123. package/dist/react/media/PrivateModeBadge.js +0 -24
  124. package/dist/react/media/PrivateModeBadge.js.map +0 -1
  125. package/dist/react/media/privateClient.d.ts +0 -34
  126. package/dist/react/media/privateClient.d.ts.map +0 -1
  127. package/dist/react/media/privateClient.js +0 -36
  128. package/dist/react/media/privateClient.js.map +0 -1
  129. package/dist/react/media/usePrivateUnlock.d.ts +0 -25
  130. package/dist/react/media/usePrivateUnlock.d.ts.map +0 -1
  131. package/dist/react/media/usePrivateUnlock.js +0 -68
  132. package/dist/react/media/usePrivateUnlock.js.map +0 -1
  133. package/src/react/media/PrivateIndexView.tsx +0 -113
  134. package/src/react/media/PrivateModeBadge.tsx +0 -50
  135. package/src/react/media/privateClient.spec.ts +0 -113
  136. package/src/react/media/privateClient.ts +0 -82
  137. package/src/react/media/usePrivateUnlock.ts +0 -132
@@ -5,8 +5,7 @@
5
5
  *
6
6
  * Shaped as a plain function (not a hook) so it can be passed straight to helpers
7
7
  * that expect an `authHeaders: () => Record<string, string>` callback
8
- * (`revealPrivateWithToken`, `privateHlsUrlWithToken`, …) and spread into a
9
- * `fetch` init's headers.
8
+ * (`createFileUploadClient`'s, for one) and spread into a `fetch` init's headers.
10
9
  */
11
10
  export declare function sessionAuthHeaders(): Record<string, string>;
12
11
  //# sourceMappingURL=sessionAuth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessionAuth.d.ts","sourceRoot":"","sources":["../../src/react/sessionAuth.ts"],"names":[],"mappings":"AAcA;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK3D"}
1
+ {"version":3,"file":"sessionAuth.d.ts","sourceRoot":"","sources":["../../src/react/sessionAuth.ts"],"names":[],"mappings":"AAcA;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK3D"}
@@ -1,6 +1,6 @@
1
1
  // ── Session auth headers (hook-free) ────────────────────────────────────────
2
2
  // One source of truth for "turn the browser session into a Bearer header". Plugins
3
- // that call guarded endpoints (uploads, the private-media client, RPC over fetch)
3
+ // that call guarded endpoints (uploads, RPC over fetch)
4
4
  // all need the same header shape; before this they each re-rolled the cookie read.
5
5
  //
6
6
  // NOTE (genapp-34): a generated app's `session` cookie is now `HttpOnly`, so this
@@ -18,8 +18,7 @@
18
18
  *
19
19
  * Shaped as a plain function (not a hook) so it can be passed straight to helpers
20
20
  * that expect an `authHeaders: () => Record<string, string>` callback
21
- * (`revealPrivateWithToken`, `privateHlsUrlWithToken`, …) and spread into a
22
- * `fetch` init's headers.
21
+ * (`createFileUploadClient`'s, for one) and spread into a `fetch` init's headers.
23
22
  */
24
23
  export function sessionAuthHeaders() {
25
24
  const token = (typeof document !== 'undefined' && document.cookie.match(/session=([^;]+)/)?.[1]) ||
@@ -1 +1 @@
1
- {"version":3,"file":"sessionAuth.js","sourceRoot":"","sources":["../../src/react/sessionAuth.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mFAAmF;AACnF,kFAAkF;AAClF,mFAAmF;AACnF,EAAE;AACF,kFAAkF;AAClF,8EAA8E;AAC9E,2EAA2E;AAC3E,0EAA0E;AAC1E,kFAAkF;AAClF,2EAA2E;AAC3E,yEAAyE;AACzE,8DAA8D;AAE9D;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,KAAK,GACT,CAAC,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClF,WAAW,CAAC;IACd,OAAO,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"sessionAuth.js","sourceRoot":"","sources":["../../src/react/sessionAuth.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mFAAmF;AACnF,wDAAwD;AACxD,mFAAmF;AACnF,EAAE;AACF,kFAAkF;AAClF,8EAA8E;AAC9E,2EAA2E;AAC3E,0EAA0E;AAC1E,kFAAkF;AAClF,2EAA2E;AAC3E,yEAAyE;AACzE,8DAA8D;AAE9D;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,KAAK,GACT,CAAC,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClF,WAAW,CAAC;IACd,OAAO,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;AAC9C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"guardrailsEnforce.d.ts","sourceRoot":"","sources":["../../scripts/guardrailsEnforce.ts"],"names":[],"mappings":";AA0LA,UAAU,SAAS;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,IAAI;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;CACzD;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CA6B9D;AA+4BD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEpE;AAweD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAkBtC,CAAC;AASF,eAAO,MAAM,uBAAuB,aAAkD,CAAC;AAGvF,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED;2FAC2F;AAC3F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA0C3F;AAED,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAmGhC,wBAAgB,0BAA0B,CAAC,SAAS,GAAE,MAAwB,GAAG,MAAM,EAAE,CAyBxF"}
1
+ {"version":3,"file":"guardrailsEnforce.d.ts","sourceRoot":"","sources":["../../scripts/guardrailsEnforce.ts"],"names":[],"mappings":";AA8LA,UAAU,SAAS;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,IAAI;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;CACzD;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CA6B9D;AA+4BD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAEpE;AAghBD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAmBtC,CAAC;AASF,eAAO,MAAM,uBAAuB,aAAkD,CAAC;AAGvF,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb;AAED;2FAC2F;AAC3F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA0C3F;AAED,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAmGhC,wBAAgB,0BAA0B,CAAC,SAAS,GAAE,MAAwB,GAAG,MAAM,EAAE,CAyBxF"}
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 72 candidate(s) scanned.
18
+ * when this file is stale. 71 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 300 candidate(s) scanned.
18
+ * when this file is stale. 303 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 463 candidate(s) scanned.
18
+ * when this file is stale. 462 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 348 candidate(s) scanned.
18
+ * when this file is stale. 388 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
15
15
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
16
- * when this file is stale. 5187 candidate(s) scanned.
16
+ * when this file is stale. 5197 candidate(s) scanned.
17
17
  *
18
18
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
19
19
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 1349 candidate(s) scanned.
18
+ * when this file is stale. 1350 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 290 candidate(s) scanned.
18
+ * when this file is stale. 289 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 613 candidate(s) scanned.
18
+ * when this file is stale. 616 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 195 candidate(s) scanned.
18
+ * when this file is stale. 198 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,12 +15,118 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 147 candidate(s) scanned.
18
+ * when this file is stale. 189 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
22
22
  * import closures rather than a hand-written list, is scripts/styleAreas.ts.
23
23
  */
24
24
  /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
25
+ @layer properties;
25
26
  @layer theme, base, components, utilities;
26
- @layer utilities;
27
+ @layer utilities {
28
+ .self-stretch {
29
+ align-self: stretch;
30
+ }
31
+ .focus-within\:border-field-ring:focus-within {
32
+ border-color: var(--field-ring);
33
+ }
34
+ .focus-within\:ring-2:focus-within {
35
+ --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
36
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
37
+ }
38
+ .focus-within\:ring-field-ring\/30:focus-within {
39
+ --tw-ring-color: var(--field-ring);
40
+ @supports (color: color-mix(in lab, red, red)) {
41
+ --tw-ring-color: color-mix(in oklab, var(--field-ring) 30%, transparent);
42
+ }
43
+ }
44
+ .has-\[\[aria-invalid\=true\]\]\:border-field-error:has(:is([aria-invalid=true])) {
45
+ border-color: var(--field-error);
46
+ }
47
+ }
48
+ @property --tw-shadow {
49
+ syntax: "*";
50
+ inherits: false;
51
+ initial-value: 0 0 #0000;
52
+ }
53
+ @property --tw-shadow-color {
54
+ syntax: "*";
55
+ inherits: false;
56
+ }
57
+ @property --tw-shadow-alpha {
58
+ syntax: "<percentage>";
59
+ inherits: false;
60
+ initial-value: 100%;
61
+ }
62
+ @property --tw-inset-shadow {
63
+ syntax: "*";
64
+ inherits: false;
65
+ initial-value: 0 0 #0000;
66
+ }
67
+ @property --tw-inset-shadow-color {
68
+ syntax: "*";
69
+ inherits: false;
70
+ }
71
+ @property --tw-inset-shadow-alpha {
72
+ syntax: "<percentage>";
73
+ inherits: false;
74
+ initial-value: 100%;
75
+ }
76
+ @property --tw-ring-color {
77
+ syntax: "*";
78
+ inherits: false;
79
+ }
80
+ @property --tw-ring-shadow {
81
+ syntax: "*";
82
+ inherits: false;
83
+ initial-value: 0 0 #0000;
84
+ }
85
+ @property --tw-inset-ring-color {
86
+ syntax: "*";
87
+ inherits: false;
88
+ }
89
+ @property --tw-inset-ring-shadow {
90
+ syntax: "*";
91
+ inherits: false;
92
+ initial-value: 0 0 #0000;
93
+ }
94
+ @property --tw-ring-inset {
95
+ syntax: "*";
96
+ inherits: false;
97
+ }
98
+ @property --tw-ring-offset-width {
99
+ syntax: "<length>";
100
+ inherits: false;
101
+ initial-value: 0px;
102
+ }
103
+ @property --tw-ring-offset-color {
104
+ syntax: "*";
105
+ inherits: false;
106
+ initial-value: #fff;
107
+ }
108
+ @property --tw-ring-offset-shadow {
109
+ syntax: "*";
110
+ inherits: false;
111
+ initial-value: 0 0 #0000;
112
+ }
113
+ @layer properties {
114
+ @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
115
+ *, ::before, ::after, ::backdrop {
116
+ --tw-shadow: 0 0 #0000;
117
+ --tw-shadow-color: initial;
118
+ --tw-shadow-alpha: 100%;
119
+ --tw-inset-shadow: 0 0 #0000;
120
+ --tw-inset-shadow-color: initial;
121
+ --tw-inset-shadow-alpha: 100%;
122
+ --tw-ring-color: initial;
123
+ --tw-ring-shadow: 0 0 #0000;
124
+ --tw-inset-ring-color: initial;
125
+ --tw-inset-ring-shadow: 0 0 #0000;
126
+ --tw-ring-inset: initial;
127
+ --tw-ring-offset-width: 0px;
128
+ --tw-ring-offset-color: #fff;
129
+ --tw-ring-offset-shadow: 0 0 #0000;
130
+ }
131
+ }
132
+ }
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 2162 candidate(s) scanned.
18
+ * when this file is stale. 2159 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 2849 candidate(s) scanned.
18
+ * when this file is stale. 2777 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -156,9 +156,6 @@
156
156
  border-block-style: var(--tw-border-style);
157
157
  border-block-width: 2px;
158
158
  }
159
- .border-\[color\:var\(--border-strong\)\] {
160
- border-color: var(--border-strong);
161
- }
162
159
  .border-accent {
163
160
  border-color: var(--accent);
164
161
  }
@@ -171,12 +168,6 @@
171
168
  border-color: color-mix(in oklab, var(--color-white) 90%, transparent);
172
169
  }
173
170
  }
174
- .bg-\[color\:color-mix\(in_srgb\,var\(--accent-solid\)_8\%\,transparent\)\] {
175
- background-color: var(--accent-solid);
176
- @supports (color: color-mix(in lab, red, red)) {
177
- background-color: color-mix(in srgb,var(--accent-solid) 8%,transparent);
178
- }
179
- }
180
171
  .bg-accent\/15 {
181
172
  background-color: var(--accent);
182
173
  @supports (color: color-mix(in lab, red, red)) {
@@ -283,9 +274,6 @@
283
274
  .text-\[color\:var\(--accent\)\] {
284
275
  color: var(--accent);
285
276
  }
286
- .text-\[color\:var\(--muted-foreground\)\] {
287
- color: var(--muted-foreground);
288
- }
289
277
  .accent-white {
290
278
  accent-color: var(--color-white);
291
279
  }
@@ -322,10 +310,6 @@
322
310
  .group-focus-within\:opacity-100:is(:where(.group):focus-within *) {
323
311
  opacity: 100%;
324
312
  }
325
- .last\:border-b-0:last-child {
326
- border-bottom-style: var(--tw-border-style);
327
- border-bottom-width: 0px;
328
- }
329
313
  .focus-within\:opacity-100:focus-within {
330
314
  opacity: 100%;
331
315
  }
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 800 candidate(s) scanned.
18
+ * when this file is stale. 799 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 232 candidate(s) scanned.
18
+ * when this file is stale. 231 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 166 candidate(s) scanned.
18
+ * when this file is stale. 165 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 361 candidate(s) scanned.
18
+ * when this file is stale. 360 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 389 candidate(s) scanned.
18
+ * when this file is stale. 392 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 247 candidate(s) scanned.
18
+ * when this file is stale. 246 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -1591,9 +1591,6 @@
1591
1591
  --tw-border-style: solid;
1592
1592
  border-style: solid;
1593
1593
  }
1594
- .border-\[color\:var\(--border-strong\)\] {
1595
- border-color: var(--border-strong);
1596
- }
1597
1594
  .border-\[var\(--border\)\] {
1598
1595
  border-color: var(--border);
1599
1596
  }
@@ -1741,12 +1738,6 @@
1741
1738
  .border-l-warning {
1742
1739
  border-left-color: var(--warning);
1743
1740
  }
1744
- .bg-\[color\:color-mix\(in_srgb\,var\(--accent-solid\)_8\%\,transparent\)\] {
1745
- background-color: var(--accent-solid);
1746
- @supports (color: color-mix(in lab, red, red)) {
1747
- background-color: color-mix(in srgb,var(--accent-solid) 8%,transparent);
1748
- }
1749
- }
1750
1741
  .bg-\[var\(--accent\)\]\/12 {
1751
1742
  background-color: var(--accent);
1752
1743
  @supports (color: color-mix(in lab, red, red)) {
@@ -2626,9 +2617,6 @@
2626
2617
  .text-\[color\:var\(--accent\)\] {
2627
2618
  color: var(--accent);
2628
2619
  }
2629
- .text-\[color\:var\(--muted-foreground\)\] {
2630
- color: var(--muted-foreground);
2631
- }
2632
2620
  .text-\[var\(--danger\)\] {
2633
2621
  color: var(--danger);
2634
2622
  }
@@ -3299,10 +3287,6 @@
3299
3287
  border-right-style: var(--tw-border-style);
3300
3288
  border-right-width: 0px;
3301
3289
  }
3302
- .last\:border-b-0:last-child {
3303
- border-bottom-style: var(--tw-border-style);
3304
- border-bottom-width: 0px;
3305
- }
3306
3290
  .last\:pr-1:last-child {
3307
3291
  padding-right: var(--spacing);
3308
3292
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=_noBun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_noBun.d.ts","sourceRoot":"","sources":["../../src/testing/_noBun.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ // Loaded only on non-Bun runtimes (task 2087). The `cursedbelt/testing` export map routes the
2
+ // real module to Bun (the `bun` condition) and everything else here, so importing these helpers
3
+ // from Node fails with a sentence instead of `Named export 'waitFor' not found` — which is what
4
+ // Node said about `@testing-library/react`, a CommonJS module its ESM loader cannot name-import.
5
+ // Same shape as `cwip/testing`'s `_noBun`, and `tools/proveInstall.ts` excuses exactly this: a
6
+ // `bun` condition plus a plain `Error` of the package's own making.
7
+ throw new Error('cursedbelt/testing requires the Bun runtime — it drives @testing-library/react under bun:test + happy-dom. ' +
8
+ 'Import it only from specs run with `bun test`.');
9
+ export {};
10
+ //# sourceMappingURL=_noBun.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_noBun.js","sourceRoot":"","sources":["../../src/testing/_noBun.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,gGAAgG;AAChG,gGAAgG;AAChG,iGAAiG;AACjG,+FAA+F;AAC/F,oEAAoE;AACpE,MAAM,IAAI,KAAK,CACb,6GAA6G;IAC3G,gDAAgD,CACnD,CAAC;AAEF,OAAO,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt",
3
- "version": "4.7.0",
3
+ "version": "5.0.0",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
@@ -13,12 +13,41 @@
13
13
  "typecheck": "typecheck",
14
14
  "e2e": "e2e",
15
15
  "build": "build"
16
- },
17
- "extraCommands": {
18
- "format": "format"
19
16
  }
20
17
  }
21
18
  },
19
+ "bundlerOnly": {
20
+ "why": "Entries that load only through a bundler (Vite, Bun), never under plain Node, and why. `css`: they import a stylesheet — their own or a dependency's — so Node refuses them with ERR_UNKNOWN_FILE_EXTENSION \".css\" by design. `directoryImport`: they reach @atlaskit/pragmatic-drag-and-drop, which ships nested package.json directories and no exports map, so Node ESM refuses its subpaths with ERR_UNSUPPORTED_DIR_IMPORT (importing its dist files directly would load a second copy of the drag engine under a bundler). This is the declaration tools/proveInstall.ts reads to excuse exactly that error for exactly these subpaths (task 2087); src/bundlerOnlyEntries.spec.ts fails when a list and the code disagree, in either direction.",
21
+ "css": [
22
+ "./react",
23
+ "./react/activity-bar",
24
+ "./react/dashboard-grid",
25
+ "./react/diff-viewer",
26
+ "./react/file-tree",
27
+ "./react/markdown-doc",
28
+ "./react/media",
29
+ "./react/media-gallery",
30
+ "./react/media/player-strip",
31
+ "./react/media/video-player",
32
+ "./react/pdf-viewer",
33
+ "./react/rich-text",
34
+ "./react/spreadsheet",
35
+ "./react/workbook-viewer"
36
+ ],
37
+ "directoryImport": [
38
+ "./react",
39
+ "./react/disk-usage"
40
+ ]
41
+ },
42
+ "unpeered": {
43
+ "why": "Packages some subpaths import that are deliberately NOT in peerDependencies, because npm cannot resolve them beside this package's own peers: npm checks an optional peer's OWN peer ranges even when nobody installs it, so `npm install cursedbelt` failed ERESOLVE (task 2087, measured on 4.7.0 and on packed probes). @glideapps/glide-data-grid@6 peers react <=18 and marked ^4 (this package: react ^19, marked >=14); @emoji-mart/react@1 peers react <=18; @hookform/resolvers@5 dragged zod 3 against zod ^4. lodash is glide's own peer, which glide does not declare as a dependency. An app that renders ./react/spreadsheet, ./react/workbook-viewer or ./react/media-gallery installs glide + lodash itself; EmojiPicker and makeFormConfig load theirs lazily and name the package when it is missing. Bun installs these without complaint; npm needs --legacy-peer-deps for them, which is the truth about those packages rather than about this one.",
44
+ "packages": {
45
+ "@emoji-mart/react": ">=1",
46
+ "@glideapps/glide-data-grid": ">=6",
47
+ "@hookform/resolvers": ">=5",
48
+ "lodash": ">=4.17.19"
49
+ }
50
+ },
22
51
  "scripts": {
23
52
  "typecheck": "bun run typecheck:root && bun run typecheck:specs && bun run typecheck:scripts",
24
53
  "typecheck:root": "tsc --noEmit",
@@ -26,8 +55,8 @@
26
55
  "typecheck:scripts": "tsc --noEmit --project tsconfig.scripts.json",
27
56
  "demo:check": "tsc --noEmit --project demo/tsconfig.json",
28
57
  "demo:paths": "bun run demo/generatePaths.ts --write",
29
- "guardrails:report": "bun run scripts/guardrailsEnforce.ts no-raw-action-button,no-raw-overflow,no-raw-inputs,no-hardcoded-colors,no-raw-modal-footer,no-unguarded-editing-modal,control-height-tokens,no-raw-zindex,no-raw-data-table,no-tailwind-palette,no-raw-title-attr,micro-typography-floor,choice-needs-empty-state,no-select-as-action-menu,no-native-dialog,no-fast-tooltip --scope cursedbelt src/react src/styles.css",
30
- "format": "biome format --write .",
58
+ "guardrails:report": "bun run scripts/guardrailsEnforce.ts no-raw-action-button,no-raw-overflow,no-raw-inputs,no-hardcoded-colors,no-raw-modal-footer,no-unguarded-editing-modal,control-height-tokens,no-raw-zindex,no-raw-data-table,no-tailwind-palette,no-raw-title-attr,micro-typography-floor,choice-needs-empty-state,no-select-as-action-menu,no-native-dialog,no-fast-tooltip,no-raw-password --scope cursedbelt src/react src/styles.css",
59
+ "lint": "biome lint src e2e demo scripts",
31
60
  "styles": "bun run styles:static && bun run styles:utilities && bun run styles:areas",
32
61
  "styles:static": "bun run scripts/generateStaticStyles.ts",
33
62
  "styles:utilities": "bun run scripts/generateUtilityStyles.ts",
@@ -404,7 +433,7 @@
404
433
  "types": "./dist/testing/tooltip.d.ts",
405
434
  "bun": "./src/testing/tooltip.ts",
406
435
  "source": "./src/testing/tooltip.ts",
407
- "import": "./dist/testing/tooltip.js"
436
+ "default": "./dist/testing/_noBun.js"
408
437
  },
409
438
  "./theme.css": "./src/theme.css",
410
439
  "./workspace.css": "./src/workspace.css"
@@ -432,12 +461,9 @@
432
461
  "@codemirror/state": ">=6",
433
462
  "@codemirror/view": ">=6",
434
463
  "@emoji-mart/data": ">=1",
435
- "@emoji-mart/react": ">=1",
436
464
  "@ffmpeg/ffmpeg": ">=0.12",
437
465
  "@ffmpeg/util": ">=0.12",
438
466
  "@git-diff-view/react": ">=0.1.6",
439
- "@glideapps/glide-data-grid": ">=6",
440
- "@hookform/resolvers": ">=5",
441
467
  "@lezer/highlight": ">=1",
442
468
  "@tanstack/react-query": ">=5",
443
469
  "@testing-library/react": ">=16",
@@ -500,9 +526,6 @@
500
526
  "@emoji-mart/data": {
501
527
  "optional": true
502
528
  },
503
- "@emoji-mart/react": {
504
- "optional": true
505
- },
506
529
  "@ffmpeg/ffmpeg": {
507
530
  "optional": true
508
531
  },
@@ -512,12 +535,6 @@
512
535
  "@git-diff-view/react": {
513
536
  "optional": true
514
537
  },
515
- "@glideapps/glide-data-grid": {
516
- "optional": true
517
- },
518
- "@hookform/resolvers": {
519
- "optional": true
520
- },
521
538
  "@lezer/highlight": {
522
539
  "optional": true
523
540
  },
@@ -730,6 +747,12 @@
730
747
  {
731
748
  "script": "demo:check"
732
749
  },
750
+ {
751
+ "script": "lint"
752
+ },
753
+ {
754
+ "script": "guardrails:report"
755
+ },
733
756
  {
734
757
  "script": "styles"
735
758
  },
@@ -0,0 +1,71 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { checkAreaStyles, classesInCss, readBeltSheets, tokensInJs } from './checkAreaStyles';
6
+
7
+ const BELT = {
8
+ union: `@layer utilities { .flex { display: flex } .rounded-full { border-radius: 9999px } .hover\\:bg-muted { &:hover { @media (hover: hover) { background: var(--muted) } } } .recharts-tip { opacity: .5; } }`,
9
+ areas: {
10
+ core: `.flex { display: flex } .hover\\:bg-muted:hover { background: x }`,
11
+ charts: `.recharts-tip { opacity: .5 }`,
12
+ chat: `.rounded-full { border-radius: 9999px }`,
13
+ },
14
+ };
15
+
16
+ describe('classesInCss', () => {
17
+ test('unescapes Tailwind selectors and ignores numbers inside declarations', () => {
18
+ const names = classesInCss(`.hover\\:bg-muted:hover{a:b} .\\32 xl\\:grid{x:y} .w-\\[1\\.5rem\\]{width:1.5rem} .a{opacity:.5}`);
19
+ expect([...names].sort()).toEqual(['2xl:grid', 'a', 'hover:bg-muted', 'w-[1.5rem]']);
20
+ });
21
+
22
+ test("reads the real union — cursedbelt's own styles-utilities.css", () => {
23
+ const { union, areas } = readBeltSheets();
24
+ const names = classesInCss(union);
25
+ expect(names.size).toBeGreaterThan(500);
26
+ expect(names.has('truncate')).toBe(true);
27
+ expect(Object.keys(areas)).toContain('core');
28
+ });
29
+ });
30
+
31
+ describe('checkAreaStyles', () => {
32
+ test('🔴 a class the JS uses that the CSS does not style is reported WITH its area — the under-selected case', () => {
33
+ const js = [`const a="flex rounded-full";const b=\`recharts-tip \${x}\`;`];
34
+ const css = [`.flex{display:flex}.rounded-full{border-radius:9999px}`];
35
+ const result = checkAreaStyles({ js, css }, BELT);
36
+ expect(result.missing).toEqual([{ className: 'recharts-tip', area: 'charts' }]);
37
+ expect(result.referenced).toBe(3);
38
+ });
39
+
40
+ test('complete when every referenced class has a rule; a word that is no belt class is ignored', () => {
41
+ const js = [`x("flex hover:bg-muted"), y("not-a-belt-class")`];
42
+ const css = [`.flex{display:flex}.hover\\:bg-muted:hover{background:red}`];
43
+ expect(checkAreaStyles({ js, css }, BELT).missing).toEqual([]);
44
+ });
45
+
46
+ test('tokensInJs splits on whitespace, quotes and backticks only', () => {
47
+ expect([...tokensInJs(`a="[&>*]:w-full p-2" b='x'`)]).toContain('[&>*]:w-full');
48
+ });
49
+
50
+ test('the CLI exits 2 on a directory with nothing to compare, 1 on a miss, 0 when complete', () => {
51
+ const dir = mkdtempSync(join(tmpdir(), 'belt-area-check-'));
52
+ try {
53
+ const run = () =>
54
+ Bun.spawnSync(['bun', join(import.meta.dir, 'checkAreaStyles.ts'), dir], { stdout: 'pipe', stderr: 'pipe' });
55
+ expect(run().exitCode).toBe(2);
56
+ const { union } = readBeltSheets();
57
+ // `truncate` is a core utility in every build of the union.
58
+ expect(classesInCss(union).has('truncate')).toBe(true);
59
+ mkdirSync(join(dir, 'assets'));
60
+ writeFileSync(join(dir, 'assets', 'index.js'), 'const c="truncate";');
61
+ writeFileSync(join(dir, 'assets', 'index.css'), '.app{color:red}');
62
+ const miss = run();
63
+ expect(miss.exitCode).toBe(1);
64
+ expect(miss.stderr.toString()).toContain('truncate');
65
+ writeFileSync(join(dir, 'assets', 'index.css'), '.truncate{overflow:hidden}');
66
+ expect(run().exitCode).toBe(0);
67
+ } finally {
68
+ rmSync(dir, { recursive: true, force: true });
69
+ }
70
+ });
71
+ });