cursedbelt 1.0.0 → 2.3.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 (533) hide show
  1. package/dist/client/index.js +1 -1
  2. package/dist/core/category/index.d.ts.map +1 -1
  3. package/dist/core/category/index.js +2 -1
  4. package/dist/core/category/index.js.map +1 -1
  5. package/dist/core/category/types.js +1 -1
  6. package/dist/core/category/types.js.map +1 -1
  7. package/dist/core/file-tree/fileTreeModel.d.ts +49 -0
  8. package/dist/core/file-tree/fileTreeModel.d.ts.map +1 -1
  9. package/dist/core/file-tree/fileTreeModel.js +84 -0
  10. package/dist/core/file-tree/fileTreeModel.js.map +1 -1
  11. package/dist/core/layout/index.js +1 -1
  12. package/dist/core/layout/index.js.map +1 -1
  13. package/dist/core/media/index.js +1 -1
  14. package/dist/core/media/index.js.map +1 -1
  15. package/dist/core/media/types.js +1 -1
  16. package/dist/core/media/types.js.map +1 -1
  17. package/dist/core/media/uploadLimits.js +1 -1
  18. package/dist/core/media/uploadLimits.js.map +1 -1
  19. package/dist/core/sharing/model.d.ts +1 -1
  20. package/dist/ctgr/index.js +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/react/activity-bar/ActivityBar.d.ts +17 -0
  24. package/dist/react/activity-bar/ActivityBar.d.ts.map +1 -1
  25. package/dist/react/activity-bar/ActivityBar.js.map +1 -1
  26. package/dist/react/analytics/index.d.ts +1 -1
  27. package/dist/react/analytics/index.js +1 -1
  28. package/dist/react/chat/MessageComposer.d.ts.map +1 -1
  29. package/dist/react/chat/MessageComposer.js +5 -4
  30. package/dist/react/chat/MessageComposer.js.map +1 -1
  31. package/dist/react/components/Button.d.ts.map +1 -1
  32. package/dist/react/components/Button.js +3 -2
  33. package/dist/react/components/Button.js.map +1 -1
  34. package/dist/react/components/Checkbox.d.ts +19 -3
  35. package/dist/react/components/Checkbox.d.ts.map +1 -1
  36. package/dist/react/components/Checkbox.js +29 -12
  37. package/dist/react/components/Checkbox.js.map +1 -1
  38. package/dist/react/components/CodeArea.d.ts.map +1 -1
  39. package/dist/react/components/CodeArea.js +2 -1
  40. package/dist/react/components/CodeArea.js.map +1 -1
  41. package/dist/react/components/Collapsible.d.ts.map +1 -1
  42. package/dist/react/components/Collapsible.js +2 -1
  43. package/dist/react/components/Collapsible.js.map +1 -1
  44. package/dist/react/components/ComboboxField.d.ts.map +1 -1
  45. package/dist/react/components/ComboboxField.js +3 -2
  46. package/dist/react/components/ComboboxField.js.map +1 -1
  47. package/dist/react/components/CopyButton.d.ts.map +1 -1
  48. package/dist/react/components/CopyButton.js +2 -1
  49. package/dist/react/components/CopyButton.js.map +1 -1
  50. package/dist/react/components/DataTable/ColumnChecklist.d.ts.map +1 -1
  51. package/dist/react/components/DataTable/ColumnChecklist.js +2 -1
  52. package/dist/react/components/DataTable/ColumnChecklist.js.map +1 -1
  53. package/dist/react/components/DataTable/Pagination.d.ts.map +1 -1
  54. package/dist/react/components/DataTable/Pagination.js +2 -1
  55. package/dist/react/components/DataTable/Pagination.js.map +1 -1
  56. package/dist/react/components/DataTable/SortHeader.d.ts.map +1 -1
  57. package/dist/react/components/DataTable/SortHeader.js +2 -1
  58. package/dist/react/components/DataTable/SortHeader.js.map +1 -1
  59. package/dist/react/components/DataTable/TableFilterBuilder.d.ts +61 -0
  60. package/dist/react/components/DataTable/TableFilterBuilder.d.ts.map +1 -0
  61. package/dist/react/components/DataTable/{FilterBuilder.js → TableFilterBuilder.js} +26 -3
  62. package/dist/react/components/DataTable/TableFilterBuilder.js.map +1 -0
  63. package/dist/react/components/DataTable/Toolbar.d.ts +1 -1
  64. package/dist/react/components/DataTable/Toolbar.js +3 -3
  65. package/dist/react/components/DataTable/Toolbar.js.map +1 -1
  66. package/dist/react/components/DataTable/cells/LinkCell.d.ts.map +1 -1
  67. package/dist/react/components/DataTable/cells/LinkCell.js +2 -1
  68. package/dist/react/components/DataTable/cells/LinkCell.js.map +1 -1
  69. package/dist/react/components/DataTable/index.d.ts +1 -1
  70. package/dist/react/components/DataTable/index.d.ts.map +1 -1
  71. package/dist/react/components/DataTable/index.js +4 -1
  72. package/dist/react/components/DataTable/index.js.map +1 -1
  73. package/dist/react/components/DragHandle.d.ts.map +1 -1
  74. package/dist/react/components/DragHandle.js +2 -1
  75. package/dist/react/components/DragHandle.js.map +1 -1
  76. package/dist/react/components/EmojiField.d.ts.map +1 -1
  77. package/dist/react/components/EmojiField.js +2 -1
  78. package/dist/react/components/EmojiField.js.map +1 -1
  79. package/dist/react/components/EventTimeline.d.ts +3 -2
  80. package/dist/react/components/EventTimeline.d.ts.map +1 -1
  81. package/dist/react/components/EventTimeline.js +3 -2
  82. package/dist/react/components/EventTimeline.js.map +1 -1
  83. package/dist/react/components/IconButton.d.ts +1 -1
  84. package/dist/react/components/IconButton.js +1 -1
  85. package/dist/react/components/InfoHint.d.ts.map +1 -1
  86. package/dist/react/components/InfoHint.js +5 -4
  87. package/dist/react/components/InfoHint.js.map +1 -1
  88. package/dist/react/components/InheritBadge.js +1 -1
  89. package/dist/react/components/InheritBadge.js.map +1 -1
  90. package/dist/react/components/InlineEditableText.d.ts.map +1 -1
  91. package/dist/react/components/InlineEditableText.js +2 -1
  92. package/dist/react/components/InlineEditableText.js.map +1 -1
  93. package/dist/react/components/MeterList.d.ts.map +1 -1
  94. package/dist/react/components/MeterList.js +2 -1
  95. package/dist/react/components/MeterList.js.map +1 -1
  96. package/dist/react/components/PathText.d.ts +2 -2
  97. package/dist/react/components/PathText.d.ts.map +1 -1
  98. package/dist/react/components/PathText.js +2 -1
  99. package/dist/react/components/PathText.js.map +1 -1
  100. package/dist/react/components/RatingField.d.ts.map +1 -1
  101. package/dist/react/components/RatingField.js +2 -1
  102. package/dist/react/components/RatingField.js.map +1 -1
  103. package/dist/react/components/SecretInput.js +3 -2
  104. package/dist/react/components/SecretInput.js.map +1 -1
  105. package/dist/react/components/SegmentedControl.d.ts.map +1 -1
  106. package/dist/react/components/SegmentedControl.js +2 -1
  107. package/dist/react/components/SegmentedControl.js.map +1 -1
  108. package/dist/react/components/StarRating.d.ts.map +1 -1
  109. package/dist/react/components/StarRating.js +9 -5
  110. package/dist/react/components/StarRating.js.map +1 -1
  111. package/dist/react/components/StatStrip.d.ts.map +1 -1
  112. package/dist/react/components/StatStrip.js +2 -1
  113. package/dist/react/components/StatStrip.js.map +1 -1
  114. package/dist/react/components/StatTile.d.ts.map +1 -1
  115. package/dist/react/components/StatTile.js +3 -2
  116. package/dist/react/components/StatTile.js.map +1 -1
  117. package/dist/react/components/Tabs.d.ts.map +1 -1
  118. package/dist/react/components/Tabs.js +2 -1
  119. package/dist/react/components/Tabs.js.map +1 -1
  120. package/dist/react/components/TruncatedText.d.ts +2 -1
  121. package/dist/react/components/TruncatedText.d.ts.map +1 -1
  122. package/dist/react/components/TruncatedText.js +2 -1
  123. package/dist/react/components/TruncatedText.js.map +1 -1
  124. package/dist/react/components/calendar/MonthGrid.d.ts.map +1 -1
  125. package/dist/react/components/calendar/MonthGrid.js +2 -1
  126. package/dist/react/components/calendar/MonthGrid.js.map +1 -1
  127. package/dist/react/components/calendar/WeekView.d.ts.map +1 -1
  128. package/dist/react/components/calendar/WeekView.js +2 -1
  129. package/dist/react/components/calendar/WeekView.js.map +1 -1
  130. package/dist/react/components/revealOnHover.d.ts.map +1 -1
  131. package/dist/react/components/revealOnHover.js +2 -1
  132. package/dist/react/components/revealOnHover.js.map +1 -1
  133. package/dist/react/file-tree/FileTree.d.ts +50 -1
  134. package/dist/react/file-tree/FileTree.d.ts.map +1 -1
  135. package/dist/react/file-tree/FileTree.js +234 -6
  136. package/dist/react/file-tree/FileTree.js.map +1 -1
  137. package/dist/react/file-tree/fileTree.css +52 -0
  138. package/dist/react/filter-rail/FilterRail.d.ts.map +1 -1
  139. package/dist/react/filter-rail/FilterRail.js +5 -4
  140. package/dist/react/filter-rail/FilterRail.js.map +1 -1
  141. package/dist/react/folder-tree/FolderTreeRail.d.ts.map +1 -1
  142. package/dist/react/folder-tree/FolderTreeRail.js +2 -1
  143. package/dist/react/folder-tree/FolderTreeRail.js.map +1 -1
  144. package/dist/react/index.d.ts +5 -1
  145. package/dist/react/index.d.ts.map +1 -1
  146. package/dist/react/index.js +5 -1
  147. package/dist/react/index.js.map +1 -1
  148. package/dist/react/layoutEngine/index.js +1 -1
  149. package/dist/react/layoutEngine/index.js.map +1 -1
  150. package/dist/react/lib/field.d.ts.map +1 -1
  151. package/dist/react/lib/field.js +3 -2
  152. package/dist/react/lib/field.js.map +1 -1
  153. package/dist/react/lib/floatingStyles.d.ts.map +1 -1
  154. package/dist/react/lib/floatingStyles.js +2 -1
  155. package/dist/react/lib/floatingStyles.js.map +1 -1
  156. package/dist/react/lib/tapTarget.d.ts +96 -0
  157. package/dist/react/lib/tapTarget.d.ts.map +1 -0
  158. package/dist/react/lib/tapTarget.js +96 -0
  159. package/dist/react/lib/tapTarget.js.map +1 -0
  160. package/dist/react/media/VideoTrimmer.d.ts +1 -1
  161. package/dist/react/media/VideoTrimmer.js +1 -1
  162. package/dist/react/media/denseGallery.css +3 -3
  163. package/dist/react/media/ffmpegWasm.js +2 -2
  164. package/dist/react/media/ffmpegWasm.js.map +1 -1
  165. package/dist/react/media/videoPlayer.css +42 -0
  166. package/dist/react/namespace/NamespaceTargetCapsule.d.ts +2 -2
  167. package/dist/react/namespace/NamespaceTargetCapsule.d.ts.map +1 -1
  168. package/dist/react/nav/BreadcrumbTrail.d.ts.map +1 -1
  169. package/dist/react/nav/BreadcrumbTrail.js +4 -3
  170. package/dist/react/nav/BreadcrumbTrail.js.map +1 -1
  171. package/dist/react/nav/HubTileGrid.d.ts.map +1 -1
  172. package/dist/react/nav/HubTileGrid.js +2 -1
  173. package/dist/react/nav/HubTileGrid.js.map +1 -1
  174. package/dist/react/nav/SideNav.d.ts.map +1 -1
  175. package/dist/react/nav/SideNav.js +4 -3
  176. package/dist/react/nav/SideNav.js.map +1 -1
  177. package/dist/react/nav/SideNavCustomize.d.ts.map +1 -1
  178. package/dist/react/nav/SideNavCustomize.js +2 -1
  179. package/dist/react/nav/SideNavCustomize.js.map +1 -1
  180. package/dist/react/palette/CommandPalette.d.ts.map +1 -1
  181. package/dist/react/palette/CommandPalette.js +3 -2
  182. package/dist/react/palette/CommandPalette.js.map +1 -1
  183. package/dist/server/drivers/pooledControlStores.pg.test.js +1 -0
  184. package/dist/server/drivers/pooledControlStores.pg.test.js.map +1 -1
  185. package/dist/server/drivers/pooledIdentityStore.pg.test.js +1 -0
  186. package/dist/server/drivers/pooledIdentityStore.pg.test.js.map +1 -1
  187. package/dist/server/drivers/retentionPolicy.pg.test.js +1 -0
  188. package/dist/server/drivers/retentionPolicy.pg.test.js.map +1 -1
  189. package/dist/server/guard/argon2Binding.d.ts +1 -1
  190. package/dist/server/guard/argon2Binding.js +1 -1
  191. package/dist/server/incidents/store.d.ts +3 -3
  192. package/dist/server/index.js +1 -1
  193. package/dist/server/index.js.map +1 -1
  194. package/dist/server/master-lock/masterLock.d.ts +1 -1
  195. package/dist/server/media-bun/index.js +1 -1
  196. package/dist/server/media-bun/index.js.map +1 -1
  197. package/dist/server/paths/appDataHome.d.ts +20 -0
  198. package/dist/server/paths/appDataHome.d.ts.map +1 -0
  199. package/dist/server/paths/appDataHome.js +69 -0
  200. package/dist/server/paths/appDataHome.js.map +1 -0
  201. package/dist/server/retention/archive.d.ts +3 -4
  202. package/dist/server/retention/archive.d.ts.map +1 -1
  203. package/dist/server/retention/archive.js +20 -15
  204. package/dist/server/retention/archive.js.map +1 -1
  205. package/dist/server/retention/index.d.ts +1 -1
  206. package/dist/server/retention/index.js +1 -1
  207. package/dist/server/retention/policy.d.ts +2 -2
  208. package/dist/server/retention/policy.d.ts.map +1 -1
  209. package/dist/server/retention/policy.js +1 -1
  210. package/dist/server/retention/store.d.ts.map +1 -1
  211. package/dist/server/retention/store.js +27 -20
  212. package/dist/server/retention/store.js.map +1 -1
  213. package/dist/server/runtime/localHost.d.ts +10 -5
  214. package/dist/server/runtime/localHost.d.ts.map +1 -1
  215. package/dist/server/runtime/localHost.js +12 -8
  216. package/dist/server/runtime/localHost.js.map +1 -1
  217. package/dist/server/runtime/meterRollup.pg.test.js +1 -0
  218. package/dist/server/runtime/meterRollup.pg.test.js.map +1 -1
  219. package/dist/server/runtime/recipe.d.ts +4 -4
  220. package/dist/server/runtime/retentionJob.pg.test.js +1 -0
  221. package/dist/server/runtime/retentionJob.pg.test.js.map +1 -1
  222. package/dist/server/search/pgSearchProvider.pg.test.js +1 -0
  223. package/dist/server/search/pgSearchProvider.pg.test.js.map +1 -1
  224. package/dist/shared/errors.d.ts +1 -1
  225. package/dist/shared/errors.js +1 -1
  226. package/dist/styles-static.css +391 -0
  227. package/dist/styles.css +27 -0
  228. package/package.json +19 -167
  229. package/scripts/generateStaticStyles.ts +122 -0
  230. package/scripts/publicSurface.ts +455 -0
  231. package/scripts/testTmpRoot.ts +34 -5
  232. package/src/client/index.ts +1 -1
  233. package/src/core/category/index.ts +2 -1
  234. package/src/core/category/types.ts +1 -1
  235. package/src/core/file-tree/fileTreeModel.spec.ts +134 -0
  236. package/src/core/file-tree/fileTreeModel.ts +104 -0
  237. package/src/core/layout/index.ts +1 -1
  238. package/src/core/media/index.ts +1 -1
  239. package/src/core/media/types.ts +1 -1
  240. package/src/core/media/uploadLimits.ts +1 -1
  241. package/src/core/sharing/model.ts +1 -1
  242. package/src/ctgr/index.ts +1 -1
  243. package/src/declaredDepsAreImported.spec.ts +87 -0
  244. package/src/demoFixture.spec.ts +133 -0
  245. package/src/index.ts +1 -1
  246. package/src/lockfileIsTracked.spec.ts +50 -0
  247. package/src/namedSubpathsResolve.spec.ts +119 -0
  248. package/src/publicSurface.spec.ts +72 -0
  249. package/src/react/activity-bar/ActivityBar.tsx +17 -0
  250. package/src/react/analytics/index.ts +1 -1
  251. package/src/react/chat/MessageComposer.tsx +5 -4
  252. package/src/react/components/Button.tsx +3 -2
  253. package/src/react/components/Checkbox.spec.tsx +51 -0
  254. package/src/react/components/Checkbox.tsx +68 -26
  255. package/src/react/components/CodeArea.tsx +2 -1
  256. package/src/react/components/CodeChip.spec.tsx +2 -2
  257. package/src/react/components/Collapsible.tsx +2 -1
  258. package/src/react/components/ComboboxField.tsx +3 -2
  259. package/src/react/components/CopyButton.tsx +2 -1
  260. package/src/react/components/CopyableText.spec.tsx +1 -1
  261. package/src/react/components/DataTable/ColumnChecklist.tsx +2 -1
  262. package/src/react/components/DataTable/Pagination.tsx +2 -1
  263. package/src/react/components/DataTable/SortHeader.tsx +2 -1
  264. package/src/react/components/DataTable/{FilterBuilder.tsx → TableFilterBuilder.tsx} +33 -5
  265. package/src/react/components/DataTable/Toolbar.tsx +3 -3
  266. package/src/react/components/DataTable/cells/LinkCell.tsx +2 -1
  267. package/src/react/components/DataTable/index.ts +8 -1
  268. package/src/react/components/DragHandle.tsx +2 -1
  269. package/src/react/components/EmojiField.tsx +2 -1
  270. package/src/react/components/EventTimeline.tsx +3 -2
  271. package/src/react/components/FileLocation.spec.tsx +1 -1
  272. package/src/react/components/IconButton.tsx +1 -1
  273. package/src/react/components/InfoHint.tsx +5 -4
  274. package/src/react/components/InheritBadge.tsx +1 -1
  275. package/src/react/components/InlineEditableText.tsx +2 -1
  276. package/src/react/components/MeterList.tsx +2 -1
  277. package/src/react/components/PathText.tsx +4 -3
  278. package/src/react/components/RatingField.tsx +2 -1
  279. package/src/react/components/SecretInput.tsx +3 -3
  280. package/src/react/components/SegmentedControl.tsx +2 -2
  281. package/src/react/components/StarRating.spec.tsx +2 -2
  282. package/src/react/components/StarRating.tsx +9 -5
  283. package/src/react/components/StatStrip.tsx +2 -1
  284. package/src/react/components/StatTile.tsx +3 -3
  285. package/src/react/components/Tabs.spec.tsx +3 -2
  286. package/src/react/components/Tabs.tsx +2 -1
  287. package/src/react/components/TruncatedText.tsx +2 -1
  288. package/src/react/components/calendar/MonthGrid.spec.tsx +2 -1
  289. package/src/react/components/calendar/MonthGrid.tsx +2 -1
  290. package/src/react/components/calendar/WeekView.tsx +2 -1
  291. package/src/react/components/revealOnHover.ts +3 -2
  292. package/src/react/file-tree/FileTree.spec.tsx +248 -0
  293. package/src/react/file-tree/FileTree.tsx +304 -4
  294. package/src/react/file-tree/fileTree.css +52 -0
  295. package/src/react/file-tree/fileTreeGeometry.fixture.json +151 -0
  296. package/src/react/file-tree/fileTreeGeometry.spec.ts +33 -52
  297. package/src/react/filter-rail/FilterRail.spec.tsx +2 -1
  298. package/src/react/filter-rail/FilterRail.tsx +5 -4
  299. package/src/react/folder-tree/FolderTreeRail.tsx +2 -1
  300. package/src/react/index.ts +13 -3
  301. package/src/react/layoutEngine/index.ts +1 -1
  302. package/src/react/layoutEngine/types.ts +1 -1
  303. package/src/react/lib/field.ts +4 -2
  304. package/src/react/lib/floatingStyles.spec.ts +2 -1
  305. package/src/react/lib/floatingStyles.ts +3 -1
  306. package/src/react/lib/tapTarget.ts +100 -0
  307. package/src/react/media/MaskPainter.tsx +2 -2
  308. package/src/react/media/VideoTrimmer.tsx +1 -1
  309. package/src/react/media/denseGallery.css +3 -3
  310. package/src/react/media/ffmpegWasm.ts +2 -2
  311. package/src/react/media/videoPlayer.css +42 -0
  312. package/src/react/namespace/NamespaceTargetCapsule.tsx +2 -2
  313. package/src/react/nav/BreadcrumbTrail.tsx +4 -3
  314. package/src/react/nav/HubTileGrid.tsx +2 -1
  315. package/src/react/nav/SideNav.tsx +4 -3
  316. package/src/react/nav/SideNavCustomize.tsx +2 -1
  317. package/src/react/palette/CommandPalette.tsx +3 -2
  318. package/src/server/ctgr.ts +1 -1
  319. package/src/server/drivers/pooledControlStores.pg.test.ts +1 -0
  320. package/src/server/drivers/pooledIdentityStore.pg.test.ts +1 -0
  321. package/src/server/drivers/retentionPolicy.pg.test.ts +1 -0
  322. package/src/server/guard/argon2Binding.ts +1 -1
  323. package/src/server/incidents/store.ts +3 -3
  324. package/src/server/index.ts +1 -1
  325. package/src/server/master-lock/masterLock.spec.ts +18 -2
  326. package/src/server/master-lock/masterLock.ts +1 -1
  327. package/src/server/media-bun/image.spec.ts +1 -0
  328. package/src/server/media-bun/index.ts +1 -1
  329. package/src/server/media-bun/video.spec.ts +1 -0
  330. package/src/server/paths/appDataHome.spec.ts +87 -0
  331. package/src/server/paths/appDataHome.ts +84 -0
  332. package/src/server/retention/archive.spec.ts +26 -4
  333. package/src/server/retention/archive.ts +20 -15
  334. package/src/server/retention/index.ts +1 -1
  335. package/src/server/retention/policy.ts +2 -2
  336. package/src/server/retention/store.spec.ts +38 -10
  337. package/src/server/retention/store.ts +26 -19
  338. package/src/server/runtime/localHost.spec.ts +22 -3
  339. package/src/server/runtime/localHost.ts +12 -9
  340. package/src/server/runtime/meterRollup.pg.test.ts +1 -0
  341. package/src/server/runtime/recipe.ts +4 -4
  342. package/src/server/runtime/retentionJob.pg.test.ts +1 -0
  343. package/src/server/search/pgSearchProvider.pg.test.ts +1 -0
  344. package/src/server/storage/binaryServerProcessing.integration.spec.ts +6 -2
  345. package/src/server/storage/chunked.integration.spec.ts +5 -2
  346. package/src/server/storage/fileUploadClient-chunked.integration.spec.ts +5 -2
  347. package/src/server/storage/files/adapter.photo.display.spec.ts +1 -0
  348. package/src/server/storage/imageThumbnail.spec.ts +1 -0
  349. package/src/server/storage/transcode.integration.spec.ts +5 -2
  350. package/src/server/storage/videoProcessor.posterOnly.spec.ts +1 -0
  351. package/src/shared/errors.ts +1 -1
  352. package/src/skippedTestsAreAnswered.spec.ts +215 -0
  353. package/src/styles-static.css +391 -0
  354. package/src/styles.css +27 -0
  355. package/src/stylesStaticMatches.spec.ts +134 -0
  356. package/src/tapTargetStylesheet.spec.ts +150 -0
  357. package/src/testTmpRoot.spec.ts +102 -0
  358. package/dist/core/duplicates/index.d.ts +0 -116
  359. package/dist/core/duplicates/index.d.ts.map +0 -1
  360. package/dist/core/duplicates/index.js +0 -178
  361. package/dist/core/duplicates/index.js.map +0 -1
  362. package/dist/core/namespace/helpers.d.ts +0 -14
  363. package/dist/core/namespace/helpers.d.ts.map +0 -1
  364. package/dist/core/namespace/helpers.js +0 -29
  365. package/dist/core/namespace/helpers.js.map +0 -1
  366. package/dist/core/namespace/index.d.ts +0 -4
  367. package/dist/core/namespace/index.d.ts.map +0 -1
  368. package/dist/core/namespace/index.js +0 -6
  369. package/dist/core/namespace/index.js.map +0 -1
  370. package/dist/core/namespace/memoryStore.d.ts +0 -19
  371. package/dist/core/namespace/memoryStore.d.ts.map +0 -1
  372. package/dist/core/namespace/memoryStore.js +0 -70
  373. package/dist/core/namespace/memoryStore.js.map +0 -1
  374. package/dist/core/namespace/types.d.ts +0 -44
  375. package/dist/core/namespace/types.d.ts.map +0 -1
  376. package/dist/core/namespace/types.js +0 -8
  377. package/dist/core/namespace/types.js.map +0 -1
  378. package/dist/game/core/DisposeRegistry.d.ts +0 -42
  379. package/dist/game/core/DisposeRegistry.d.ts.map +0 -1
  380. package/dist/game/core/DisposeRegistry.js +0 -67
  381. package/dist/game/core/DisposeRegistry.js.map +0 -1
  382. package/dist/game/core/drawBudget.d.ts +0 -26
  383. package/dist/game/core/drawBudget.d.ts.map +0 -1
  384. package/dist/game/core/drawBudget.js +0 -55
  385. package/dist/game/core/drawBudget.js.map +0 -1
  386. package/dist/game/core/fixedTimestep.d.ts +0 -38
  387. package/dist/game/core/fixedTimestep.d.ts.map +0 -1
  388. package/dist/game/core/fixedTimestep.js +0 -47
  389. package/dist/game/core/fixedTimestep.js.map +0 -1
  390. package/dist/game/core/index.d.ts +0 -9
  391. package/dist/game/core/index.d.ts.map +0 -1
  392. package/dist/game/core/index.js +0 -8
  393. package/dist/game/core/index.js.map +0 -1
  394. package/dist/game/core/inputCollector.d.ts +0 -82
  395. package/dist/game/core/inputCollector.d.ts.map +0 -1
  396. package/dist/game/core/inputCollector.js +0 -176
  397. package/dist/game/core/inputCollector.js.map +0 -1
  398. package/dist/game/core/resizeCanvas.d.ts +0 -19
  399. package/dist/game/core/resizeCanvas.d.ts.map +0 -1
  400. package/dist/game/core/resizeCanvas.js +0 -29
  401. package/dist/game/core/resizeCanvas.js.map +0 -1
  402. package/dist/game/react/index.d.ts +0 -3
  403. package/dist/game/react/index.d.ts.map +0 -1
  404. package/dist/game/react/index.js +0 -5
  405. package/dist/game/react/index.js.map +0 -1
  406. package/dist/game/react/useGameEngine.d.ts +0 -64
  407. package/dist/game/react/useGameEngine.d.ts.map +0 -1
  408. package/dist/game/react/useGameEngine.js +0 -78
  409. package/dist/game/react/useGameEngine.js.map +0 -1
  410. package/dist/react/canvas/CanvasNavHUD.d.ts +0 -64
  411. package/dist/react/canvas/CanvasNavHUD.d.ts.map +0 -1
  412. package/dist/react/canvas/CanvasNavHUD.js +0 -58
  413. package/dist/react/canvas/CanvasNavHUD.js.map +0 -1
  414. package/dist/react/canvas/fitLabel.d.ts +0 -53
  415. package/dist/react/canvas/fitLabel.d.ts.map +0 -1
  416. package/dist/react/canvas/fitLabel.js +0 -104
  417. package/dist/react/canvas/fitLabel.js.map +0 -1
  418. package/dist/react/canvas/index.d.ts +0 -4
  419. package/dist/react/canvas/index.d.ts.map +0 -1
  420. package/dist/react/canvas/index.js +0 -4
  421. package/dist/react/canvas/index.js.map +0 -1
  422. package/dist/react/canvas/lod.d.ts +0 -40
  423. package/dist/react/canvas/lod.d.ts.map +0 -1
  424. package/dist/react/canvas/lod.js +0 -37
  425. package/dist/react/canvas/lod.js.map +0 -1
  426. package/dist/react/components/DataTable/FilterBuilder.d.ts +0 -38
  427. package/dist/react/components/DataTable/FilterBuilder.d.ts.map +0 -1
  428. package/dist/react/components/DataTable/FilterBuilder.js.map +0 -1
  429. package/dist/react/seo/HeadProvider.d.ts +0 -14
  430. package/dist/react/seo/HeadProvider.d.ts.map +0 -1
  431. package/dist/react/seo/HeadProvider.js +0 -44
  432. package/dist/react/seo/HeadProvider.js.map +0 -1
  433. package/dist/react/seo/applyHeadToDocument.d.ts +0 -3
  434. package/dist/react/seo/applyHeadToDocument.d.ts.map +0 -1
  435. package/dist/react/seo/applyHeadToDocument.js +0 -66
  436. package/dist/react/seo/applyHeadToDocument.js.map +0 -1
  437. package/dist/react/seo/index.d.ts +0 -3
  438. package/dist/react/seo/index.d.ts.map +0 -1
  439. package/dist/react/seo/index.js +0 -7
  440. package/dist/react/seo/index.js.map +0 -1
  441. package/dist/react/timeline/ClipView.d.ts +0 -29
  442. package/dist/react/timeline/ClipView.d.ts.map +0 -1
  443. package/dist/react/timeline/ClipView.js +0 -53
  444. package/dist/react/timeline/ClipView.js.map +0 -1
  445. package/dist/react/timeline/Playhead.d.ts +0 -16
  446. package/dist/react/timeline/Playhead.d.ts.map +0 -1
  447. package/dist/react/timeline/Playhead.js +0 -26
  448. package/dist/react/timeline/Playhead.js.map +0 -1
  449. package/dist/react/timeline/TimeRuler.d.ts +0 -21
  450. package/dist/react/timeline/TimeRuler.d.ts.map +0 -1
  451. package/dist/react/timeline/TimeRuler.js +0 -31
  452. package/dist/react/timeline/TimeRuler.js.map +0 -1
  453. package/dist/react/timeline/TimelineSurface.d.ts +0 -29
  454. package/dist/react/timeline/TimelineSurface.d.ts.map +0 -1
  455. package/dist/react/timeline/TimelineSurface.js +0 -56
  456. package/dist/react/timeline/TimelineSurface.js.map +0 -1
  457. package/dist/react/timeline/TrackLane.d.ts +0 -31
  458. package/dist/react/timeline/TrackLane.d.ts.map +0 -1
  459. package/dist/react/timeline/TrackLane.js +0 -32
  460. package/dist/react/timeline/TrackLane.js.map +0 -1
  461. package/dist/react/timeline/index.d.ts +0 -6
  462. package/dist/react/timeline/index.d.ts.map +0 -1
  463. package/dist/react/timeline/index.js +0 -12
  464. package/dist/react/timeline/index.js.map +0 -1
  465. package/dist/server/private-media/index.d.ts +0 -7
  466. package/dist/server/private-media/index.d.ts.map +0 -1
  467. package/dist/server/private-media/index.js +0 -13
  468. package/dist/server/private-media/index.js.map +0 -1
  469. package/dist/server/seo/index.d.ts +0 -3
  470. package/dist/server/seo/index.d.ts.map +0 -1
  471. package/dist/server/seo/index.js +0 -6
  472. package/dist/server/seo/index.js.map +0 -1
  473. package/dist/server/seo/mountSeoRoutes.d.ts +0 -9
  474. package/dist/server/seo/mountSeoRoutes.d.ts.map +0 -1
  475. package/dist/server/seo/mountSeoRoutes.js +0 -19
  476. package/dist/server/seo/mountSeoRoutes.js.map +0 -1
  477. package/dist/server/seo/serveHeadInjectedIndex.d.ts +0 -9
  478. package/dist/server/seo/serveHeadInjectedIndex.d.ts.map +0 -1
  479. package/dist/server/seo/serveHeadInjectedIndex.js +0 -20
  480. package/dist/server/seo/serveHeadInjectedIndex.js.map +0 -1
  481. package/dist/upload.d.ts +0 -148
  482. package/dist/upload.d.ts.map +0 -1
  483. package/dist/upload.js +0 -159
  484. package/dist/upload.js.map +0 -1
  485. package/dist/verify/runtime/index.d.ts +0 -16
  486. package/dist/verify/runtime/index.d.ts.map +0 -1
  487. package/dist/verify/runtime/index.js +0 -16
  488. package/dist/verify/runtime/index.js.map +0 -1
  489. package/scripts/demoCheck.ts +0 -42
  490. package/src/core/duplicates/index.spec.ts +0 -116
  491. package/src/core/duplicates/index.ts +0 -203
  492. package/src/core/namespace/helpers.ts +0 -31
  493. package/src/core/namespace/index.ts +0 -12
  494. package/src/core/namespace/memoryStore.ts +0 -77
  495. package/src/core/namespace/namespace.spec.ts +0 -117
  496. package/src/core/namespace/types.ts +0 -53
  497. package/src/game/core/DisposeRegistry.spec.ts +0 -53
  498. package/src/game/core/DisposeRegistry.ts +0 -70
  499. package/src/game/core/drawBudget.spec.ts +0 -51
  500. package/src/game/core/drawBudget.ts +0 -75
  501. package/src/game/core/fixedTimestep.spec.ts +0 -91
  502. package/src/game/core/fixedTimestep.ts +0 -79
  503. package/src/game/core/index.ts +0 -16
  504. package/src/game/core/inputCollector.spec.ts +0 -29
  505. package/src/game/core/inputCollector.ts +0 -245
  506. package/src/game/core/resizeCanvas.ts +0 -31
  507. package/src/game/react/index.ts +0 -10
  508. package/src/game/react/useGameEngine.ts +0 -125
  509. package/src/react/canvas/CanvasNavHUD.spec.tsx +0 -62
  510. package/src/react/canvas/CanvasNavHUD.tsx +0 -210
  511. package/src/react/canvas/fitLabel.spec.ts +0 -82
  512. package/src/react/canvas/fitLabel.ts +0 -150
  513. package/src/react/canvas/index.ts +0 -15
  514. package/src/react/canvas/lod.ts +0 -53
  515. package/src/react/seo/HeadProvider.tsx +0 -67
  516. package/src/react/seo/applyHeadToDocument.ts +0 -73
  517. package/src/react/seo/index.ts +0 -12
  518. package/src/react/seo/seo.spec.tsx +0 -101
  519. package/src/react/timeline/ClipView.tsx +0 -146
  520. package/src/react/timeline/Playhead.tsx +0 -63
  521. package/src/react/timeline/TimeRuler.tsx +0 -85
  522. package/src/react/timeline/TimelineSurface.tsx +0 -157
  523. package/src/react/timeline/TrackLane.tsx +0 -87
  524. package/src/react/timeline/index.ts +0 -12
  525. package/src/react/timeline/timeline.spec.tsx +0 -175
  526. package/src/server/private-media/index.ts +0 -45
  527. package/src/server/seo/index.ts +0 -8
  528. package/src/server/seo/mountSeoRoutes.ts +0 -37
  529. package/src/server/seo/seo.spec.ts +0 -128
  530. package/src/server/seo/serveHeadInjectedIndex.ts +0 -36
  531. package/src/upload.spec.ts +0 -300
  532. package/src/upload.ts +0 -288
  533. package/src/verify/runtime/index.ts +0 -64
package/dist/upload.js DELETED
@@ -1,159 +0,0 @@
1
- // cursedbelt/upload — framework-agnostic upload primitive
2
- //
3
- // Sits above the transport (fileUploadClient) and below the UI layer. Provides:
4
- // • Client-side validation (MIME type + byte size)
5
- // • Progress events during upload
6
- // • Drag-and-drop drop-zone wiring (pure DOM, no React)
7
- // • HEIC/HEIF mobile-photo detection (conversion is server-side)
8
- // • Typed UploadResult contract consumed by MediaUploadControl and app plugins
9
- //
10
- // Consumers that want the raw transport client import createFileUploadClient from
11
- // 'cursedbelt/react/media'; this module layers validation + progress on top.
12
- // ── MIME / HEIC ──────────────────────────────────────────────────────────────
13
- /** True for iPhone HEIC/HEIF images — the server converts these to JPEG. */
14
- export function isHeicFile(file) {
15
- const mime = file.type.toLowerCase();
16
- if (mime === 'image/heic' || mime === 'image/heif')
17
- return true;
18
- const name = file.name.toLowerCase();
19
- return name.endsWith('.heic') || name.endsWith('.heif');
20
- }
21
- function mimeMatches(mime, pattern) {
22
- if (pattern === mime)
23
- return true;
24
- if (pattern.endsWith('/*')) {
25
- return mime.startsWith(pattern.slice(0, -1));
26
- }
27
- return false;
28
- }
29
- export function validateFile(file, constraints) {
30
- if (constraints.accept?.length) {
31
- const mime = file.type || 'application/octet-stream';
32
- const ok = constraints.accept.some((p) => mimeMatches(mime, p));
33
- if (!ok)
34
- return {
35
- ok: false,
36
- error: { kind: 'type', file: file.name, mime, accept: constraints.accept },
37
- };
38
- }
39
- if (constraints.maxBytes !== undefined && file.size > constraints.maxBytes) {
40
- return {
41
- ok: false,
42
- error: { kind: 'size', file: file.name, bytes: file.size, maxBytes: constraints.maxBytes },
43
- };
44
- }
45
- return { ok: true };
46
- }
47
- export function formatValidationError(error) {
48
- if (error.kind === 'type') {
49
- return `"${error.file}" is not an accepted file type (${error.mime}). Accepted: ${error.accept.join(', ')}.`;
50
- }
51
- return `"${error.file}" is too large (${(error.bytes / 1024 / 1024).toFixed(1)} MB). Max: ${(error.maxBytes / 1024 / 1024).toFixed(1)} MB.`;
52
- }
53
- export async function uploadFile(file, opts) {
54
- const { transport, constraints = {}, tags, onProgress } = opts;
55
- const emit = (p) => {
56
- onProgress?.(p);
57
- };
58
- emit({ phase: 'validating' });
59
- const validation = validateFile(file, constraints);
60
- if (!validation.ok) {
61
- const msg = formatValidationError(validation.error);
62
- emit({ phase: 'error', message: msg });
63
- return { ok: false, error: msg, validationError: validation.error };
64
- }
65
- emit({ phase: 'uploading', loaded: 0, total: file.size });
66
- const heic = isHeicFile(file);
67
- const res = await transport.uploadAuto(file, { tags }).catch((e) => ({
68
- ok: false,
69
- error: e instanceof Error ? e.message : 'upload failed',
70
- }));
71
- if (!res.ok) {
72
- emit({ phase: 'error', message: res.error });
73
- return { ok: false, error: res.error };
74
- }
75
- const f = res.file;
76
- if (!f) {
77
- emit({ phase: 'error', message: 'upload succeeded but no file record returned' });
78
- return { ok: false, error: 'upload succeeded but no file record returned' };
79
- }
80
- emit({ phase: 'done' });
81
- return {
82
- ok: true,
83
- file: {
84
- id: f.id,
85
- name: f.name,
86
- mime: f.mime,
87
- size: f.size,
88
- fileType: f.fileType,
89
- tags: f.tags,
90
- processingStatus: f.processingStatus,
91
- heicConverted: heic,
92
- },
93
- };
94
- }
95
- /** Upload multiple files sequentially, stopping on the first error. */
96
- export async function uploadFiles(files, opts) {
97
- const results = [];
98
- for (const file of files) {
99
- const result = await uploadFile(file, opts);
100
- results.push(result);
101
- if (!result.ok)
102
- return { results, firstError: result.error };
103
- }
104
- return { results, firstError: null };
105
- }
106
- /**
107
- * Returns plain event handler objects that wire a DOM element as a drop zone.
108
- * Attach them with addEventListener or pass to a React component's onDrag* props.
109
- *
110
- * @example
111
- * const { onDragOver, onDragLeave, onDrop } = createDropZoneHandlers({ onFiles });
112
- * el.addEventListener('dragover', onDragOver);
113
- * el.addEventListener('dragleave', onDragLeave);
114
- * el.addEventListener('drop', onDrop);
115
- */
116
- export function createDropZoneHandlers(opts) {
117
- const { onFiles, onEnter, onLeave, accept } = opts;
118
- const onDragOver = (e) => {
119
- e.preventDefault();
120
- onEnter?.();
121
- };
122
- const onDragLeave = (e) => {
123
- e.preventDefault();
124
- onLeave?.();
125
- };
126
- const onDrop = (e) => {
127
- e.preventDefault();
128
- onLeave?.();
129
- const items = e.dataTransfer?.files;
130
- if (!items?.length)
131
- return;
132
- let files = Array.from(items);
133
- if (accept?.length) {
134
- files = files.filter((f) => accept.some((p) => mimeMatches(f.type || '', p)));
135
- }
136
- if (files.length)
137
- onFiles(files);
138
- };
139
- return { onDragOver, onDragLeave, onDrop };
140
- }
141
- /**
142
- * Mount a drop zone on `el`, returning an unmount function.
143
- *
144
- * @example
145
- * const unmount = mountDropZone(containerEl, { onFiles, accept: ['image/*'] });
146
- * // later: unmount();
147
- */
148
- export function mountDropZone(el, opts) {
149
- const { onDragOver, onDragLeave, onDrop } = createDropZoneHandlers(opts);
150
- el.addEventListener('dragover', onDragOver);
151
- el.addEventListener('dragleave', onDragLeave);
152
- el.addEventListener('drop', onDrop);
153
- return () => {
154
- el.removeEventListener('dragover', onDragOver);
155
- el.removeEventListener('dragleave', onDragLeave);
156
- el.removeEventListener('drop', onDrop);
157
- };
158
- }
159
- //# sourceMappingURL=upload.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"upload.js","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"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"}
@@ -1,16 +0,0 @@
1
- /**
2
- * `cursedbelt/verify/runtime` — V7: verify-mode boot, the probe suite, and the
3
- * PID jail that guarantees a run leaves nothing behind (04 §2 V7, §5.7).
4
- *
5
- * Server-side only (Bun + Hono); the static V0–V6 compiler in `cursedbelt/verify`
6
- * has no runtime dependencies and runs anywhere.
7
- */
8
- export { type CliOptions, type CliResult, type CorpusFailure, parseArgs, runCli, runCorpus, writeArtifacts, } from './cli';
9
- export { type HostProbeOptions, probeHostCapabilities } from './hostCapabilities';
10
- export { createFakeSpawn, createVerifyContext, createVerifyGuard, createVerifyExec, createVerifyJobBroker, createVerifyCognitiveDriver, createVerifyStorage, createVerifyTelemetry, VERIFY_COMMANDS, type VerifyContext, type VerifyContextOptions, type VerifyGuard, } from './verifyContext';
11
- export { createVerifyAssetService, createVerifyDevService, createVerifyGuardService, createVerifyKnowledgeService, createVerifySystemService, PRIVATE_ITEM_IDS, PUBLIC_ITEM_IDS, } from './verifyServices';
12
- export { CORE_PROBES, crossTabLockProbe, deepLinkTenantProbe, eventLoopGuardProbe, execJailProbe, injectionGuardProbe, instanceIsolationProbe, integrityTamperProbe, lastGoodProbe, layoutProbe, lifecycleProbe, type Probe, type ProbeContext, privateModeProbe, rbacProbe, reconnectProbe, routeSurfaceProbe, securityHeaderProbe, wireSmokeProbe, } from './probes';
13
- export { isPortBound, ProcessJail, runJailed, type SweepReport, type TrackedChild } from './processJail';
14
- export { type ProbeRunResult, type RunProbesOptions, runVerifyProbes, VERIFY_TIMEOUT_MS } from './runner';
15
- export { createVerifyServer, type Role, type VerifyClaims, type VerifyServer, type VerifyServerOptions } from './verifyServer';
16
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/verify/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,SAAS,EACT,MAAM,EACN,SAAS,EACT,cAAc,GACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,cAAc,EACd,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,GACf,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC1G,OAAO,EAAE,kBAAkB,EAAE,KAAK,IAAI,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,16 +0,0 @@
1
- /**
2
- * `cursedbelt/verify/runtime` — V7: verify-mode boot, the probe suite, and the
3
- * PID jail that guarantees a run leaves nothing behind (04 §2 V7, §5.7).
4
- *
5
- * Server-side only (Bun + Hono); the static V0–V6 compiler in `cursedbelt/verify`
6
- * has no runtime dependencies and runs anywhere.
7
- */
8
- export { parseArgs, runCli, runCorpus, writeArtifacts, } from './cli';
9
- export { probeHostCapabilities } from './hostCapabilities';
10
- export { createFakeSpawn, createVerifyContext, createVerifyGuard, createVerifyExec, createVerifyJobBroker, createVerifyCognitiveDriver, createVerifyStorage, createVerifyTelemetry, VERIFY_COMMANDS, } from './verifyContext';
11
- export { createVerifyAssetService, createVerifyDevService, createVerifyGuardService, createVerifyKnowledgeService, createVerifySystemService, PRIVATE_ITEM_IDS, PUBLIC_ITEM_IDS, } from './verifyServices';
12
- export { CORE_PROBES, crossTabLockProbe, deepLinkTenantProbe, eventLoopGuardProbe, execJailProbe, injectionGuardProbe, instanceIsolationProbe, integrityTamperProbe, lastGoodProbe, layoutProbe, lifecycleProbe, privateModeProbe, rbacProbe, reconnectProbe, routeSurfaceProbe, securityHeaderProbe, wireSmokeProbe, } from './probes';
13
- export { isPortBound, ProcessJail, runJailed } from './processJail';
14
- export { runVerifyProbes, VERIFY_TIMEOUT_MS } from './runner';
15
- export { createVerifyServer } from './verifyServer';
16
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/verify/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAIL,SAAS,EACT,MAAM,EACN,SAAS,EACT,cAAc,GACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAyB,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,GAIhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,cAAc,EAGd,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,GACf,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAuC,MAAM,eAAe,CAAC;AACzG,OAAO,EAA8C,eAAe,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC1G,OAAO,EAAE,kBAAkB,EAA6E,MAAM,gBAAgB,CAAC"}
@@ -1,42 +0,0 @@
1
- /**
2
- * Typechecks the kitchen-sink demo (`demo/`) as part of cursedbelt's own gate — the
3
- * demo is the component proof surface an e2e suite drives, so its tsc debt must not
4
- * be able to silently regrow (cbux-71).
5
- *
6
- * `demo/` is intentionally NOT a root workspace member (see demo/package.json's
7
- * `cursedbelt` dependency: a relative `file:..` — worktree-safe, resolves to
8
- * WHICHEVER checkout this script runs from, never the primary). That means it has
9
- * its own `node_modules`/`bun.lock`, so a completely fresh clone/worktree needs one
10
- * `bun install` here before `tsc` can resolve anything. Only pay for that install
11
- * when it's actually missing: a demo install pulls cursedbelt's full dependency
12
- * tree (400+ packages, individually file-symlinked — see the `file:` link note in
13
- * demo/package.json) and reliably takes 60–120s even when nothing changed, so
14
- * re-running it on every gate invocation would make `bun run done` unusable.
15
- * `bun run setup` (repo root) also installs this proactively so a fresh worktree's
16
- * FIRST gate run isn't the one paying that cost.
17
- */
18
- import { existsSync } from "node:fs";
19
- import { resolve } from "node:path";
20
-
21
- const demoDir = resolve(import.meta.dir, "..", "demo");
22
-
23
- async function run(cmd: string[], cwd: string): Promise<number> {
24
- const proc = Bun.spawn(cmd, { cwd, stdout: "inherit", stderr: "inherit" });
25
- return await proc.exited;
26
- }
27
-
28
- if (!existsSync(resolve(demoDir, "node_modules", "cursedbelt"))) {
29
- console.log("• demo: node_modules missing/stale — installing…");
30
- const installExit = await run(["bun", "install"], demoDir);
31
- if (installExit !== 0) {
32
- console.error("✗ demo install failed — see output above.");
33
- process.exit(installExit);
34
- }
35
- }
36
-
37
- const tscExit = await run(["bunx", "tsc", "--noEmit", "-p", "tsconfig.json"], demoDir);
38
- if (tscExit !== 0) {
39
- console.error("✗ demo typecheck failed — see output above.");
40
- process.exit(tscExit);
41
- }
42
- console.log("✓ demo typecheck clean");
@@ -1,116 +0,0 @@
1
- /**
2
- * The shared duplicate rules, proved against the cases that produced them.
3
- *
4
- * Every assertion here is a measured incident from `binary-server` or `music`, not an
5
- * invented example — see the module header for which.
6
- */
7
- import { describe, expect, it } from "bun:test";
8
- import {
9
- DURATION_TOLERANCE,
10
- durationsClose,
11
- isGenericName,
12
- likelyTheSameFile,
13
- normalizeName,
14
- SIZE_TOLERANCE,
15
- sizesClose,
16
- } from "./index";
17
-
18
- describe("normalizeName", () => {
19
- it("reduces the marks a copy picks up to the same stem", () => {
20
- expect(normalizeName("My Video (1).mp4")).toBe("myvideo");
21
- expect(normalizeName("my_video.MP4")).toBe("myvideo");
22
- expect(normalizeName("My-Video copy 2.mov")).toBe("myvideo");
23
- });
24
-
25
- it("strips the extension, so a re-encode still pairs with its source", () => {
26
- expect(normalizeName("Song.wma")).toBe(normalizeName("Song.mp3"));
27
- });
28
-
29
- it("🔴 keeps a four-digit camera sequence — the 2026-08-14 flood", () => {
30
- // `IMG_4595` and `IMG_4646` must NOT collapse onto each other.
31
- expect(normalizeName("IMG_4595.MOV")).not.toBe(normalizeName("IMG_4646.MOV"));
32
- // …while a two-digit copy marker still does.
33
- expect(normalizeName("mix_2.mp3")).toBe(normalizeName("mix.mp3"));
34
- });
35
-
36
- it("drops the directory", () => {
37
- expect(normalizeName("Main 1/rap/Song.mp3")).toBe("song");
38
- });
39
- });
40
-
41
- describe("isGenericName", () => {
42
- it("rejects the stems that name a device rather than a file", () => {
43
- expect(isGenericName(normalizeName("IMG_1.MOV"))).toBe(true);
44
- expect(isGenericName(normalizeName("Track01.mp3"))).toBe(true);
45
- expect(isGenericName(normalizeName("Between U.mp3"))).toBe(false);
46
- });
47
- });
48
-
49
- describe("sizesClose", () => {
50
- it("accepts a re-encode and refuses a different file", () => {
51
- expect(sizesClose(10_000_000, 10_400_000)).toBe(true);
52
- expect(sizesClose(10_000_000, 20_000_000)).toBe(false);
53
- });
54
-
55
- it("🔴 two zero-byte files are not close — nothing is known about either", () => {
56
- expect(sizesClose(0, 0)).toBe(false);
57
- });
58
-
59
- it("is bounded by the exported tolerance", () => {
60
- expect(sizesClose(100, 100 * (1 + SIZE_TOLERANCE))).toBe(true);
61
- expect(sizesClose(100, 100 * (1 + SIZE_TOLERANCE * 2))).toBe(false);
62
- });
63
- });
64
-
65
- describe("durationsClose", () => {
66
- it("🔴 answers null when nobody has measured, never false", () => {
67
- expect(durationsClose(null, 200)).toBeNull();
68
- expect(durationsClose(0, 200)).toBeNull();
69
- expect(durationsClose(undefined, undefined)).toBeNull();
70
- });
71
-
72
- it("refuses the owner's 3:56-vs-1:52 pair", () => {
73
- expect(durationsClose(236, 112)).toBe(false);
74
- expect(durationsClose(236, 236 * (1 + DURATION_TOLERANCE / 2))).toBe(true);
75
- });
76
- });
77
-
78
- describe("likelyTheSameFile", () => {
79
- const facts = (name: string, sizeBytes: number, duration?: number | null) => ({
80
- name,
81
- sizeBytes,
82
- ...(duration === undefined ? {} : { duration }),
83
- });
84
-
85
- it("pairs a re-encode of the same song", () => {
86
- const verdict = likelyTheSameFile(
87
- facts("Between U.mp3", 8_000_000, 312),
88
- facts("Between U.wma", 7_800_000, 312),
89
- );
90
- expect(verdict.match).toBe(true);
91
- expect(verdict.reason).toContain("same name");
92
- });
93
-
94
- it("does not pair two different songs of a similar size", () => {
95
- expect(likelyTheSameFile(facts("A.mp3", 8_000_000), facts("B.mp3", 8_010_000)).match).toBe(
96
- false,
97
- );
98
- });
99
-
100
- it("🔴 a length that disagrees kills a name+size match", () => {
101
- expect(
102
- likelyTheSameFile(facts("Set.mp3", 8_000_000, 236), facts("Set.mp3", 8_100_000, 112)).match,
103
- ).toBe(false);
104
- });
105
-
106
- it("🔴 an unmeasured length does not — that would find nothing in an unprobed library", () => {
107
- expect(
108
- likelyTheSameFile(facts("Set.mp3", 8_000_000, null), facts("Set.mp3", 8_100_000, null)).match,
109
- ).toBe(true);
110
- });
111
-
112
- it("refuses a generic stem, and refuses two nameless files", () => {
113
- expect(likelyTheSameFile(facts("IMG_1.MOV", 500), facts("IMG_1.MOV", 500)).match).toBe(false);
114
- expect(likelyTheSameFile(facts("", 500), facts("", 500)).match).toBe(false);
115
- });
116
- });
@@ -1,203 +0,0 @@
1
- /**
2
- * "Are these two files the same thing?" — the fleet's ONE answer, with no I/O in it.
3
- *
4
- * ── Why this is here and not in an app ──────────────────────────────────────────────────
5
- * `binary-server` wrote these rules first (2026-08-13, the owner: *"make strategy to always
6
- * check for duplicate binaries in same app for same user … mark likely the duplicates for
7
- * users to confirm"*), and they were measured against a real store: the copy-counter cap, the
8
- * camera-generic stem list and the 5% size window each exist because a wider rule proposed
9
- * thousands of pairs nobody could ever review. `music` then needed the same question asked of
10
- * a 5,400-track library — *"I want to see a duplicate next to the file that it is a possible
11
- * duplicate of … The 'binary-server' app (bs) already has this feature for checking duplicate
12
- * files. We can reuse it and enhance the customizability if needed so the main strategy is
13
- * shared."*
14
- *
15
- * So the strategy lives once, here, and both consume it. What each app keeps for itself is the
16
- * evidence only it has: bs's perceptual frame hashes, music's artist/title key.
17
- *
18
- * ── What is NOT here, deliberately ──────────────────────────────────────────────────────
19
- * Anything that needs a database, a filesystem, a fetch or a picture decoder. This module is
20
- * pure so both consumers can prove their behaviour with `bun test` instead of against a live
21
- * store, and so a browser bundle may import it (music renders the pair side by side).
22
- */
23
-
24
- /**
25
- * How far two sizes may differ and still be called the same thing.
26
- *
27
- * A re-encode at a different quality is the case this exists for, and those land within a few
28
- * percent. Zero would make a name match a strict subset of "same name AND same size", which
29
- * misses precisely the files worth asking about; much larger starts pairing a clip with its
30
- * own trailer.
31
- */
32
- export const SIZE_TOLERANCE = 0.05;
33
-
34
- /**
35
- * How far two playing times may differ and still be the same recording.
36
- *
37
- * Wide enough for a re-encode (a trim of a trailing black frame, a container that rounds), far
38
- * too narrow for the owner's 2026-08-14 report of a 3:56 video paired with a 1:52 one.
39
- */
40
- export const DURATION_TOLERANCE = 0.05;
41
-
42
- /**
43
- * The name to compare, reduced to what a human means by "the same file".
44
- *
45
- * Strips the directory, the extension, and the marks a copy picks up along the way —
46
- * `Finder`'s ` copy`/` copy 2`, a browser's ` (1)`, a script's `_1`/`-1` — then collapses
47
- * everything that is not a letter or a digit. `My Video (1).mp4`, `my_video.MP4` and
48
- * `My-Video copy 2.mov` all reduce to `myvideo`.
49
- *
50
- * 🔴 The extension is stripped ON PURPOSE, so a re-encode (`.mov` → `.mp4`, `.wma` → `.mp3`)
51
- * still pairs with its source. That is the single most common likely-duplicate in this fleet's
52
- * stores and a rule that kept the extension would never see one.
53
- *
54
- * 🔴 **The copy-counter strip is capped at two digits**, and that cap is a measured bug fix
55
- * (bs, 2026-08-14). It used to be `[-_]\d+$`, which eats a CAMERA SEQUENCE as readily as a copy
56
- * marker: `IMG_4595` and `IMG_4646` both reduced to `img`, so every iPhone capture in a tenant
57
- * shared one bucket and paired with every other one whose size was within 5%. `_1`…`_99` is
58
- * what a copy marker actually looks like; four digits is a photo's identity, and it must
59
- * survive.
60
- */
61
- export function normalizeName(name: string | null | undefined): string {
62
- if (!name) return "";
63
- const leaf = name.split(/[\\/]/).pop() ?? "";
64
- const stem = leaf.replace(/\.[a-z0-9]{1,5}$/i, "");
65
- return stem
66
- .toLowerCase()
67
- .replace(/\s*\(\d+\)\s*$/, "")
68
- .replace(/\s+copy(\s+\d+)?\s*$/, "")
69
- .replace(/[-_]\d{1,2}\s*$/, "")
70
- .replace(/[^a-z0-9]+/g, "");
71
- }
72
-
73
- /**
74
- * Stems that name a CAMERA, not a file.
75
- *
76
- * `IMG`, `DSC`, `PXL`, `VID` are what a device calls everything it produces; two files whose
77
- * names reduce to one of these have told us nothing except that they came from a phone. Even
78
- * with the counter cap above, `IMG_1.MOV` still reduces to `img`, and a bucket called "img" is
79
- * every photo the owner has ever taken.
80
- *
81
- * 🔴 This rejects a MATCH, never a file. Both copies stay wherever they are, and an
82
- * identical-bytes pair is unaffected — a checksum match never consults the name.
83
- */
84
- export const GENERIC_STEMS: ReadonlySet<string> = new Set([
85
- "img",
86
- "image",
87
- "images",
88
- "dsc",
89
- "dscf",
90
- "dscn",
91
- "pxl",
92
- "vid",
93
- "video",
94
- "movie",
95
- "mov",
96
- "photo",
97
- "pic",
98
- "picture",
99
- "screenshot",
100
- "screenrecording",
101
- "untitled",
102
- "unknown",
103
- "file",
104
- "download",
105
- "scan",
106
- "capture",
107
- "copy",
108
- "new",
109
- "temp",
110
- "tmp",
111
- // Music's own version of the same problem: an untagged rip is called this by every ripper
112
- // ever written, and `track01` from two albums is two different songs.
113
- "track",
114
- "audiotrack",
115
- "unknownartist",
116
- ]);
117
-
118
- /**
119
- * A name that could belong to any file from that device tells us nothing about identity.
120
- *
121
- * 🔴 The trailing digit run is stripped BEFORE the lookup, and only here — never in
122
- * {@link normalizeName}, where removing it is what made every camera capture one bucket. The
123
- * two are asked at different moments: `normalizeName` decides whether two names are the SAME
124
- * (so `img4595` and `img4646` must stay apart), and this decides whether a name that already
125
- * matched is worth anything (so two files both called `Track01` have told us nothing, and a
126
- * ripper names half a library that).
127
- */
128
- export const isGenericName = (normalized: string): boolean =>
129
- normalized.length < 3 ||
130
- GENERIC_STEMS.has(normalized) ||
131
- GENERIC_STEMS.has(normalized.replace(/\d+$/, ""));
132
-
133
- /** Within {@link SIZE_TOLERANCE} of each other. Two zero-byte files are not "close" — they
134
- * are two files nothing is known about. */
135
- export function sizesClose(a: number, b: number, tolerance = SIZE_TOLERANCE): boolean {
136
- if (a === b && a > 0) return true;
137
- const larger = Math.max(a, b);
138
- if (larger <= 0) return false;
139
- return Math.abs(a - b) / larger <= tolerance;
140
- }
141
-
142
- /**
143
- * Within {@link DURATION_TOLERANCE} of each other.
144
- *
145
- * 🔴 A missing or zero duration answers `null`, never `false`: "nobody has measured this yet"
146
- * and "these are different lengths" are opposite answers, and collapsing them makes an
147
- * unprobed library look like a library with no duplicates in it.
148
- */
149
- export function durationsClose(
150
- a: number | null | undefined,
151
- b: number | null | undefined,
152
- tolerance = DURATION_TOLERANCE,
153
- ): boolean | null {
154
- if (!a || !b || a <= 0 || b <= 0) return null;
155
- return Math.abs(a - b) / Math.max(a, b) <= tolerance;
156
- }
157
-
158
- /** One file, reduced to what this module can reason about. Units are the caller's — pass
159
- * both durations in the same unit or not at all. */
160
- export interface NamedFileFacts {
161
- /** The name a person would recognise: a display title, else the last path segment. */
162
- name: string | null | undefined;
163
- sizeBytes: number;
164
- /** Playing time, in whatever unit the caller uses consistently. Null = never measured. */
165
- duration?: number | null;
166
- }
167
-
168
- export interface NameMatchVerdict {
169
- match: boolean;
170
- /** Written for the owner reading a review queue, never for a log. Empty when `match` is
171
- * false — a non-match has nothing to explain. */
172
- reason: string;
173
- }
174
-
175
- /**
176
- * The shared "these look like the same thing" test: the NAME agrees after normalization, the
177
- * sizes are close, and nothing about the length says otherwise.
178
- *
179
- * It is deliberately a QUESTION and never an action. Both consumers act only on a checksum,
180
- * which is proof; this decides what is worth showing a person side by side.
181
- */
182
- export function likelyTheSameFile(a: NamedFileFacts, b: NamedFileFacts): NameMatchVerdict {
183
- const na = normalizeName(a.name);
184
- const nb = normalizeName(b.name);
185
- // Two empty names are not a match with each other — it means neither file has a name worth
186
- // comparing (a bare digest key, an untitled upload), and pairing those proposes every
187
- // unnamed object as a duplicate of every other.
188
- if (!na || na !== nb) return { match: false, reason: "" };
189
- if (isGenericName(na)) return { match: false, reason: "" };
190
- if (!sizesClose(a.sizeBytes, b.sizeBytes)) return { match: false, reason: "" };
191
- if (durationsClose(a.duration, b.duration) === false) return { match: false, reason: "" };
192
-
193
- const pct = Math.round(
194
- (Math.abs(a.sizeBytes - b.sizeBytes) / Math.max(a.sizeBytes, b.sizeBytes, 1)) * 100,
195
- );
196
- return {
197
- match: true,
198
- reason:
199
- a.sizeBytes === b.sizeBytes
200
- ? "same name, same size, different bytes"
201
- : `same name, size within ${pct}%, different bytes`,
202
- };
203
- }
@@ -1,31 +0,0 @@
1
- import type { Namespace } from './types';
2
-
3
- /** Irrational angle (in degrees) whose repeated steps around a 360° wheel
4
- * never re-align on a short cycle, so successive hues stay maximally spread
5
- * regardless of how many namespaces already exist. */
6
- const GOLDEN_ANGLE = 137.50776405003785;
7
-
8
- /**
9
- * Picks the next hue (0–359) for a new namespace by stepping around the color
10
- * wheel by the golden angle once per existing namespace, then nudging past
11
- * any exact collision with a hue already in use. Golden-angle stepping keeps
12
- * consecutive hues far apart without tracking gaps explicitly.
13
- */
14
- export function nextHue(existing: Namespace[]): number {
15
- const used = new Set(existing.map((n) => n.hue));
16
- let hue = Math.round((existing.length * GOLDEN_ANGLE) % 360);
17
- while (used.has(hue)) {
18
- hue = (hue + 1) % 360;
19
- }
20
- return hue;
21
- }
22
-
23
- /**
24
- * Trims and collapses internal whitespace in a namespace label, caps it at 40
25
- * characters, and rejects a label that is empty/blank after normalization.
26
- */
27
- export function normalizeNamespaceLabel(label: string): string {
28
- const normalized = label.trim().replace(/\s+/g, ' ').slice(0, 40);
29
- if (!normalized) throw new Error('namespace label must not be empty');
30
- return normalized;
31
- }
@@ -1,12 +0,0 @@
1
- // `cursedbelt/namespace` — reusable flat namespace/workspace model. Pure and
2
- // React-free (the switcher/picker UI lives in the consuming app), so servers
3
- // can import the contract + store without pulling any UI runtime.
4
-
5
- export type {
6
- Namespace,
7
- NamespaceCreateInput,
8
- NamespaceStore,
9
- NamespaceUpdateInput,
10
- } from './types';
11
- export { nextHue, normalizeNamespaceLabel } from './helpers';
12
- export { createMemoryNamespaceStore } from './memoryStore';