@openrails/contentkit-ui 0.0.0-stage → 0.68.1

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 (367) hide show
  1. package/README.md +470 -2
  2. package/dist/appearance.d.ts +38 -0
  3. package/dist/appearance.js +15 -0
  4. package/dist/appearance.js.map +1 -0
  5. package/dist/assets/hash.worker-BYfo-7MQ.js.map +1 -0
  6. package/dist/client/aspect.d.ts +6 -0
  7. package/dist/client/aspect.js +17 -0
  8. package/dist/client/aspect.js.map +1 -0
  9. package/dist/client/client.d.ts +53 -0
  10. package/dist/client/client.js +36 -0
  11. package/dist/client/client.js.map +1 -0
  12. package/dist/client/codes.d.ts +12 -0
  13. package/dist/client/codes.js +19 -0
  14. package/dist/client/codes.js.map +1 -0
  15. package/dist/client/content/bans.d.ts +15 -0
  16. package/dist/client/content/bans.js +40 -0
  17. package/dist/client/content/bans.js.map +1 -0
  18. package/dist/client/content/comments.d.ts +36 -0
  19. package/dist/client/content/comments.js +95 -0
  20. package/dist/client/content/comments.js.map +1 -0
  21. package/dist/client/content/favorites.d.ts +14 -0
  22. package/dist/client/content/favorites.js +42 -0
  23. package/dist/client/content/favorites.js.map +1 -0
  24. package/dist/client/content/moderation.d.ts +18 -0
  25. package/dist/client/content/moderation.js +37 -0
  26. package/dist/client/content/moderation.js.map +1 -0
  27. package/dist/client/content/polls.d.ts +47 -0
  28. package/dist/client/content/polls.js +151 -0
  29. package/dist/client/content/polls.js.map +1 -0
  30. package/dist/client/content/posts.d.ts +44 -0
  31. package/dist/client/content/posts.js +92 -0
  32. package/dist/client/content/posts.js.map +1 -0
  33. package/dist/client/content/reactions.d.ts +12 -0
  34. package/dist/client/content/reactions.js +36 -0
  35. package/dist/client/content/reactions.js.map +1 -0
  36. package/dist/client/content/types.d.ts +91 -0
  37. package/dist/client/content/types.js +8 -0
  38. package/dist/client/content/types.js.map +1 -0
  39. package/dist/client/crop.d.ts +32 -0
  40. package/dist/client/crop.js +103 -0
  41. package/dist/client/crop.js.map +1 -0
  42. package/dist/client/errors.d.ts +54 -0
  43. package/dist/client/errors.js +80 -0
  44. package/dist/client/errors.js.map +1 -0
  45. package/dist/client/gallery.d.ts +43 -0
  46. package/dist/client/gallery.js +86 -0
  47. package/dist/client/gallery.js.map +1 -0
  48. package/dist/client/generated/error-codes.d.ts +5 -0
  49. package/dist/client/generated/error-codes.js +131 -0
  50. package/dist/client/generated/error-codes.js.map +1 -0
  51. package/dist/client/generated/routes.d.ts +1086 -0
  52. package/dist/client/generated/routes.js +1400 -0
  53. package/dist/client/generated/routes.js.map +1 -0
  54. package/dist/client/generated/wire.d.ts +630 -0
  55. package/dist/client/generated/wire.js +6 -0
  56. package/dist/client/generated/wire.js.map +1 -0
  57. package/dist/client/http.d.ts +83 -0
  58. package/dist/client/http.js +82 -0
  59. package/dist/client/http.js.map +1 -0
  60. package/dist/client/image.d.ts +24 -0
  61. package/dist/client/image.js +65 -0
  62. package/dist/client/image.js.map +1 -0
  63. package/dist/client/index.d.ts +33 -0
  64. package/dist/client/media/api.d.ts +36 -0
  65. package/dist/client/media/api.js +61 -0
  66. package/dist/client/media/api.js.map +1 -0
  67. package/dist/client/media/client.d.ts +247 -0
  68. package/dist/client/media/client.js +407 -0
  69. package/dist/client/media/client.js.map +1 -0
  70. package/dist/client/media/encode.d.ts +3 -0
  71. package/dist/client/media/encode.js +8 -0
  72. package/dist/client/media/encode.js.map +1 -0
  73. package/dist/client/media/hash-stream.d.ts +6 -0
  74. package/dist/client/media/hash-stream.js +16 -0
  75. package/dist/client/media/hash-stream.js.map +1 -0
  76. package/dist/client/media/hash.d.ts +12 -0
  77. package/dist/client/media/hash.js +48 -0
  78. package/dist/client/media/hash.js.map +1 -0
  79. package/dist/client/media/hash.worker-inline.js +18 -0
  80. package/dist/client/media/hash.worker-inline.js.map +1 -0
  81. package/dist/client/media/pacer.d.ts +21 -0
  82. package/dist/client/media/pacer.js +25 -0
  83. package/dist/client/media/pacer.js.map +1 -0
  84. package/dist/client/media/queue.d.ts +112 -0
  85. package/dist/client/media/queue.js +274 -0
  86. package/dist/client/media/queue.js.map +1 -0
  87. package/dist/client/media/ref.d.ts +6 -0
  88. package/dist/client/media/ref.js +10 -0
  89. package/dist/client/media/ref.js.map +1 -0
  90. package/dist/client/media/rules.d.ts +54 -0
  91. package/dist/client/media/rules.js +143 -0
  92. package/dist/client/media/rules.js.map +1 -0
  93. package/dist/client/media/transport.d.ts +13 -0
  94. package/dist/client/media/transport.js +33 -0
  95. package/dist/client/media/transport.js.map +1 -0
  96. package/dist/client/media/windows.d.ts +15 -0
  97. package/dist/client/media/windows.js +39 -0
  98. package/dist/client/media/windows.js.map +1 -0
  99. package/dist/client/playback.d.ts +200 -0
  100. package/dist/client/playback.js +142 -0
  101. package/dist/client/playback.js.map +1 -0
  102. package/dist/client/player.d.ts +102 -0
  103. package/dist/client/player.js +155 -0
  104. package/dist/client/player.js.map +1 -0
  105. package/dist/client/public.d.ts +25 -0
  106. package/dist/client/public.js +18 -0
  107. package/dist/client/public.js.map +1 -0
  108. package/dist/client/rendition.d.ts +19 -0
  109. package/dist/client/rendition.js +16 -0
  110. package/dist/client/rendition.js.map +1 -0
  111. package/dist/client/route.d.ts +39 -0
  112. package/dist/client/route.js +31 -0
  113. package/dist/client/route.js.map +1 -0
  114. package/dist/client/taxonomy.d.ts +30 -0
  115. package/dist/client/taxonomy.js +77 -0
  116. package/dist/client/taxonomy.js.map +1 -0
  117. package/dist/client.js +33 -0
  118. package/dist/components/encode-progress.d.ts +15 -0
  119. package/dist/components/encode-progress.js +49 -0
  120. package/dist/components/encode-progress.js.map +1 -0
  121. package/dist/components/hover-preview.d.ts +29 -0
  122. package/dist/components/hover-preview.js +49 -0
  123. package/dist/components/hover-preview.js.map +1 -0
  124. package/dist/components/image-crop-dialog.d.ts +48 -0
  125. package/dist/components/image-crop-dialog.js +359 -0
  126. package/dist/components/image-crop-dialog.js.map +1 -0
  127. package/dist/components/lazy-mount.d.ts +10 -0
  128. package/dist/components/lazy-mount.js +22 -0
  129. package/dist/components/lazy-mount.js.map +1 -0
  130. package/dist/components/media-folder-editor.d.ts +59 -0
  131. package/dist/components/media-folder-editor.js +611 -0
  132. package/dist/components/media-folder-editor.js.map +1 -0
  133. package/dist/components/media-gallery.d.ts +54 -0
  134. package/dist/components/media-gallery.js +597 -0
  135. package/dist/components/media-gallery.js.map +1 -0
  136. package/dist/components/media-readiness-notice.d.ts +24 -0
  137. package/dist/components/media-readiness-notice.js +61 -0
  138. package/dist/components/media-readiness-notice.js.map +1 -0
  139. package/dist/components/player-controls.d.ts +71 -0
  140. package/dist/components/player-controls.js +264 -0
  141. package/dist/components/player-controls.js.map +1 -0
  142. package/dist/components/progress.d.ts +5 -0
  143. package/dist/components/progress.js +14 -0
  144. package/dist/components/progress.js.map +1 -0
  145. package/dist/components/rendition-img.d.ts +34 -0
  146. package/dist/components/rendition-img.js +78 -0
  147. package/dist/components/rendition-img.js.map +1 -0
  148. package/dist/components/slot-editor.d.ts +95 -0
  149. package/dist/components/slot-editor.js +182 -0
  150. package/dist/components/slot-editor.js.map +1 -0
  151. package/dist/components/slot-image.d.ts +23 -0
  152. package/dist/components/slot-image.js +48 -0
  153. package/dist/components/slot-image.js.map +1 -0
  154. package/dist/components/slot-upload.d.ts +41 -0
  155. package/dist/components/slot-upload.js +215 -0
  156. package/dist/components/slot-upload.js.map +1 -0
  157. package/dist/components/social/bans.d.ts +42 -0
  158. package/dist/components/social/bans.js +300 -0
  159. package/dist/components/social/bans.js.map +1 -0
  160. package/dist/components/social/comments.d.ts +42 -0
  161. package/dist/components/social/comments.js +517 -0
  162. package/dist/components/social/comments.js.map +1 -0
  163. package/dist/components/social/engagement.d.ts +45 -0
  164. package/dist/components/social/engagement.js +129 -0
  165. package/dist/components/social/engagement.js.map +1 -0
  166. package/dist/components/social/index.d.ts +6 -0
  167. package/dist/components/social/moderation.d.ts +32 -0
  168. package/dist/components/social/moderation.js +383 -0
  169. package/dist/components/social/moderation.js.map +1 -0
  170. package/dist/components/social/parts.d.ts +50 -0
  171. package/dist/components/social/parts.js +106 -0
  172. package/dist/components/social/parts.js.map +1 -0
  173. package/dist/components/social/poll-editor.d.ts +34 -0
  174. package/dist/components/social/poll-editor.js +567 -0
  175. package/dist/components/social/poll-editor.js.map +1 -0
  176. package/dist/components/social/poll.d.ts +30 -0
  177. package/dist/components/social/poll.js +252 -0
  178. package/dist/components/social/poll.js.map +1 -0
  179. package/dist/components/sortable-list.d.ts +29 -0
  180. package/dist/components/sortable-list.js +121 -0
  181. package/dist/components/sortable-list.js.map +1 -0
  182. package/dist/components/video-mini-player.d.ts +35 -0
  183. package/dist/components/video-mini-player.js +236 -0
  184. package/dist/components/video-mini-player.js.map +1 -0
  185. package/dist/components/video-player.d.ts +146 -0
  186. package/dist/components/video-player.js +630 -0
  187. package/dist/components/video-player.js.map +1 -0
  188. package/dist/components/video-poster-picker.d.ts +59 -0
  189. package/dist/components/video-poster-picker.js +335 -0
  190. package/dist/components/video-poster-picker.js.map +1 -0
  191. package/dist/components/video-poster.d.ts +24 -0
  192. package/dist/components/video-poster.js +46 -0
  193. package/dist/components/video-poster.js.map +1 -0
  194. package/dist/i18n/context.d.ts +4 -0
  195. package/dist/i18n/context.js +11 -0
  196. package/dist/i18n/context.js.map +1 -0
  197. package/dist/i18n/messages.d.ts +40 -0
  198. package/dist/i18n/messages.js +94 -0
  199. package/dist/i18n/messages.js.map +1 -0
  200. package/dist/index.d.ts +23 -0
  201. package/dist/index.js +41 -0
  202. package/dist/locales/de.d.ts +2 -0
  203. package/dist/locales/de.js +271 -0
  204. package/dist/locales/de.js.map +1 -0
  205. package/dist/locales/en.d.ts +457 -0
  206. package/dist/locales/en.js +271 -0
  207. package/dist/locales/en.js.map +1 -0
  208. package/dist/locales/es.d.ts +2 -0
  209. package/dist/locales/es.js +271 -0
  210. package/dist/locales/es.js.map +1 -0
  211. package/dist/locales/ja.d.ts +2 -0
  212. package/dist/locales/ja.js +271 -0
  213. package/dist/locales/ja.js.map +1 -0
  214. package/dist/locales/ko.d.ts +2 -0
  215. package/dist/locales/ko.js +271 -0
  216. package/dist/locales/ko.js.map +1 -0
  217. package/dist/locales/social/de.d.ts +2 -0
  218. package/dist/locales/social/de.js +198 -0
  219. package/dist/locales/social/de.js.map +1 -0
  220. package/dist/locales/social/en.d.ts +195 -0
  221. package/dist/locales/social/en.js +198 -0
  222. package/dist/locales/social/en.js.map +1 -0
  223. package/dist/locales/social/es.d.ts +2 -0
  224. package/dist/locales/social/es.js +198 -0
  225. package/dist/locales/social/es.js.map +1 -0
  226. package/dist/locales/social/ja.d.ts +2 -0
  227. package/dist/locales/social/ja.js +198 -0
  228. package/dist/locales/social/ja.js.map +1 -0
  229. package/dist/locales/social/ko.d.ts +2 -0
  230. package/dist/locales/social/ko.js +198 -0
  231. package/dist/locales/social/ko.js.map +1 -0
  232. package/dist/locales/social/zh.d.ts +2 -0
  233. package/dist/locales/social/zh.js +198 -0
  234. package/dist/locales/social/zh.js.map +1 -0
  235. package/dist/locales/zh.d.ts +2 -0
  236. package/dist/locales/zh.js +271 -0
  237. package/dist/locales/zh.js.map +1 -0
  238. package/dist/provider.d.ts +22 -0
  239. package/dist/provider.js +59 -0
  240. package/dist/provider.js.map +1 -0
  241. package/dist/react/canonical.d.ts +33 -0
  242. package/dist/react/canonical.js +78 -0
  243. package/dist/react/canonical.js.map +1 -0
  244. package/dist/react/comments.d.ts +82 -0
  245. package/dist/react/comments.js +155 -0
  246. package/dist/react/comments.js.map +1 -0
  247. package/dist/react/config.d.ts +13 -0
  248. package/dist/react/config.js +14 -0
  249. package/dist/react/config.js.map +1 -0
  250. package/dist/react/context.d.ts +55 -0
  251. package/dist/react/context.js +42 -0
  252. package/dist/react/context.js.map +1 -0
  253. package/dist/react/crop.d.ts +49 -0
  254. package/dist/react/crop.js +107 -0
  255. package/dist/react/crop.js.map +1 -0
  256. package/dist/react/engagement.d.ts +38 -0
  257. package/dist/react/engagement.js +88 -0
  258. package/dist/react/engagement.js.map +1 -0
  259. package/dist/react/folder.d.ts +103 -0
  260. package/dist/react/folder.js +240 -0
  261. package/dist/react/folder.js.map +1 -0
  262. package/dist/react/gallery.d.ts +140 -0
  263. package/dist/react/gallery.js +477 -0
  264. package/dist/react/gallery.js.map +1 -0
  265. package/dist/react/index.d.ts +21 -0
  266. package/dist/react/inline-preview.d.ts +24 -0
  267. package/dist/react/inline-preview.js +76 -0
  268. package/dist/react/inline-preview.js.map +1 -0
  269. package/dist/react/player.d.ts +70 -0
  270. package/dist/react/player.js +214 -0
  271. package/dist/react/player.js.map +1 -0
  272. package/dist/react/polls.d.ts +74 -0
  273. package/dist/react/polls.js +176 -0
  274. package/dist/react/polls.js.map +1 -0
  275. package/dist/react/posts.d.ts +59 -0
  276. package/dist/react/posts.js +149 -0
  277. package/dist/react/posts.js.map +1 -0
  278. package/dist/react/provider.d.ts +27 -0
  279. package/dist/react/provider.js +49 -0
  280. package/dist/react/provider.js.map +1 -0
  281. package/dist/react/public.d.ts +39 -0
  282. package/dist/react/public.js +70 -0
  283. package/dist/react/public.js.map +1 -0
  284. package/dist/react/read.d.ts +52 -0
  285. package/dist/react/read.js +144 -0
  286. package/dist/react/read.js.map +1 -0
  287. package/dist/react/resources.d.ts +73 -0
  288. package/dist/react/resources.js +247 -0
  289. package/dist/react/resources.js.map +1 -0
  290. package/dist/react/slot.d.ts +104 -0
  291. package/dist/react/slot.js +185 -0
  292. package/dist/react/slot.js.map +1 -0
  293. package/dist/react/store.d.ts +51 -0
  294. package/dist/react/store.js +165 -0
  295. package/dist/react/store.js.map +1 -0
  296. package/dist/react/upload.d.ts +86 -0
  297. package/dist/react/upload.js +155 -0
  298. package/dist/react/upload.js.map +1 -0
  299. package/dist/react/use-resource.d.ts +44 -0
  300. package/dist/react/use-resource.js +74 -0
  301. package/dist/react/use-resource.js.map +1 -0
  302. package/dist/react/video.d.ts +118 -0
  303. package/dist/react/video.js +184 -0
  304. package/dist/react/video.js.map +1 -0
  305. package/dist/react/viewport.d.ts +19 -0
  306. package/dist/react/viewport.js +30 -0
  307. package/dist/react/viewport.js.map +1 -0
  308. package/dist/react.js +21 -0
  309. package/dist/scope.d.ts +14 -0
  310. package/dist/scope.js +30 -0
  311. package/dist/scope.js.map +1 -0
  312. package/dist/styles.css +3 -0
  313. package/dist/ui/alert-dialog.d.ts +18 -0
  314. package/dist/ui/alert-dialog.js +86 -0
  315. package/dist/ui/alert-dialog.js.map +1 -0
  316. package/dist/ui/alert.d.ts +10 -0
  317. package/dist/ui/alert.js +38 -0
  318. package/dist/ui/alert.js.map +1 -0
  319. package/dist/ui/avatar.d.ts +11 -0
  320. package/dist/ui/avatar.js +31 -0
  321. package/dist/ui/avatar.js.map +1 -0
  322. package/dist/ui/badge.d.ts +7 -0
  323. package/dist/ui/badge.js +31 -0
  324. package/dist/ui/badge.js.map +1 -0
  325. package/dist/ui/button.d.ts +8 -0
  326. package/dist/ui/button.js +46 -0
  327. package/dist/ui/button.js.map +1 -0
  328. package/dist/ui/dialog.d.ts +17 -0
  329. package/dist/ui/dialog.js +91 -0
  330. package/dist/ui/dialog.js.map +1 -0
  331. package/dist/ui/dropdown-menu.d.ts +15 -0
  332. package/dist/ui/dropdown-menu.js +105 -0
  333. package/dist/ui/dropdown-menu.js.map +1 -0
  334. package/dist/ui/input.d.ts +3 -0
  335. package/dist/ui/input.js +17 -0
  336. package/dist/ui/input.js.map +1 -0
  337. package/dist/ui/label.d.ts +3 -0
  338. package/dist/ui/label.js +15 -0
  339. package/dist/ui/label.js.map +1 -0
  340. package/dist/ui/progress.d.ts +7 -0
  341. package/dist/ui/progress.js +31 -0
  342. package/dist/ui/progress.js.map +1 -0
  343. package/dist/ui/select.d.ts +15 -0
  344. package/dist/ui/select.js +98 -0
  345. package/dist/ui/select.js.map +1 -0
  346. package/dist/ui/skeleton.d.ts +2 -0
  347. package/dist/ui/skeleton.js +14 -0
  348. package/dist/ui/skeleton.js.map +1 -0
  349. package/dist/ui/slider.d.ts +3 -0
  350. package/dist/ui/slider.js +35 -0
  351. package/dist/ui/slider.js.map +1 -0
  352. package/dist/ui/switch.d.ts +5 -0
  353. package/dist/ui/switch.js +20 -0
  354. package/dist/ui/switch.js.map +1 -0
  355. package/dist/ui/tabs.d.ts +10 -0
  356. package/dist/ui/tabs.js +47 -0
  357. package/dist/ui/tabs.js.map +1 -0
  358. package/dist/ui/textarea.d.ts +3 -0
  359. package/dist/ui/textarea.js +15 -0
  360. package/dist/ui/textarea.js.map +1 -0
  361. package/dist/ui/toggle-group.d.ts +5 -0
  362. package/dist/ui/toggle-group.js +23 -0
  363. package/dist/ui/toggle-group.js.map +1 -0
  364. package/dist/urls/index.d.ts +100 -0
  365. package/dist/urls.js +118 -0
  366. package/dist/urls.js.map +1 -0
  367. package/package.json +120 -3
@@ -0,0 +1,247 @@
1
+ import { CommitBody, Edit, FileInfo, Op, PresetRule, ReadResult, RefBody } from '../generated/wire.js';
2
+ import { Http } from '../http.js';
3
+ import { MediaApi, ReadOptions } from './api.js';
4
+ import { Transport } from './transport.js';
5
+ /** Upload tuning for the media module. */
6
+ export interface MediaOptions {
7
+ /** Sends presigned PUTs. Default XMLHttpRequest (upload progress), else fetch. */
8
+ transport?: Transport;
9
+ /** Parallel parts per multipart upload (the pacer may run fewer). Default 4. */
10
+ concurrency?: number;
11
+ /** Retries per part and per idempotent API call. Default 5. */
12
+ retries?: number;
13
+ /** Delay before retry attempt (0-based); retryAfter is the server's hint in seconds. */
14
+ retryDelay?: (attempt: number, retryAfter?: number) => number;
15
+ /** Seconds one part should take. Default 30. */
16
+ targetPartSeconds?: number;
17
+ }
18
+ export interface Progress {
19
+ /** processing: committed, waiting for the worker (put). */
20
+ phase: "hashing" | "uploading" | "completing" | "processing";
21
+ loaded: number;
22
+ total: number;
23
+ }
24
+ export interface UploadOptions {
25
+ ref: RefBody;
26
+ /** The upload path: a literal ("cover") or under a pattern ("originals/001.png"); the server cleans it and adds the extension. */
27
+ path: string;
28
+ /** Content type; default the file's. */
29
+ type?: string;
30
+ /** Aborting pauses: a multipart upload stays resumable from the last state. */
31
+ signal?: AbortSignal;
32
+ onProgress?: (p: Progress) => void;
33
+ /** State saved from onState, to resume a multipart upload of the same file. */
34
+ resume?: UploadState;
35
+ /** Resumable state after every change; null once the upload completed. Persist it to survive a reload. */
36
+ onState?: (s: UploadState | null) => void;
37
+ }
38
+ /** An upload, ready for a put op. */
39
+ export interface UploadedFile {
40
+ /** The path to commit: cleaned, with an extension, named by the server for a Named upload. */
41
+ path: string;
42
+ /**
43
+ * The name to commit: the folder's identical blob ("sha256-{hex}-{uuid}") when
44
+ * exists, else the staged upload ("u-{uuid}") the worker hashes and places
45
+ * after the commit.
46
+ */
47
+ blob: string;
48
+ type: string;
49
+ size: number;
50
+ /** The identical file was already in the item's folder; nothing was sent. */
51
+ exists: boolean;
52
+ /** The host processes files on upload: commit it unattached now (the queue does). */
53
+ processOnUpload?: boolean;
54
+ }
55
+ /** The put op's fields besides path and blob. */
56
+ export interface PutOptions {
57
+ /** Refuse to replace an existing upload. Default false. */
58
+ createOnly?: boolean;
59
+ edit?: Edit | null;
60
+ meta?: Record<string, unknown>;
61
+ index?: number;
62
+ /** Wait until the worker processed the upload (waitFor). Default true. */
63
+ wait?: boolean;
64
+ /** How long to wait, ms. */
65
+ timeout?: number;
66
+ /** The upload, before the commit. */
67
+ onUploaded?: (up: UploadedFile) => void;
68
+ }
69
+ export interface WaitOptions {
70
+ signal?: AbortSignal;
71
+ /** Poll interval, ms. Default 1000. */
72
+ interval?: number;
73
+ /** ms; then render_timeout. Default 120000. */
74
+ timeout?: number;
75
+ }
76
+ export interface PlannedPart {
77
+ number: number;
78
+ offset: number;
79
+ size: number;
80
+ sha256?: string;
81
+ }
82
+ /** A multipart upload in flight; JSON-serializable. */
83
+ export interface UploadState {
84
+ ticket: string;
85
+ path: string;
86
+ /** The staged upload ("u-{uuid}") the parts write. */
87
+ blob: string;
88
+ type: string;
89
+ size: number;
90
+ ref: RefBody;
91
+ file: {
92
+ name?: string;
93
+ lastModified?: number;
94
+ size: number;
95
+ };
96
+ limits: {
97
+ minPartSize: number;
98
+ maxPartSize: number;
99
+ maxParts: number;
100
+ };
101
+ parts: PlannedPart[];
102
+ processOnUpload?: boolean;
103
+ }
104
+ /** An upload to a server-named (Named) path: a post's or poll's image. */
105
+ export interface NamedOptions {
106
+ /** The requested path; the server names the file. Default the file's name. */
107
+ path?: string;
108
+ signal?: AbortSignal;
109
+ onProgress?: (p: Progress) => void;
110
+ /** Wait until the worker processed it. Default true. */
111
+ wait?: boolean;
112
+ /** How long to wait, ms. */
113
+ timeout?: number;
114
+ }
115
+ /** An upload to a Named path, committed. */
116
+ export interface NamedUpload {
117
+ /** The server's name for it ("i-{uuid}"), which content routes take. */
118
+ name: string;
119
+ path: string;
120
+ file: FileInfo;
121
+ }
122
+ /** The media kinds of post and poll folders (content.Media.PostKind and PollKind). */
123
+ export interface ContentFolders {
124
+ /** Default "post". */
125
+ post?: string;
126
+ /** Default "poll". */
127
+ poll?: string;
128
+ }
129
+ /** A file to upload again when its blob is gone at commit; type defaults to the file's. */
130
+ export type CommitSource = Blob | {
131
+ file: Blob;
132
+ type?: string;
133
+ };
134
+ export interface CommitOptions {
135
+ signal?: AbortSignal;
136
+ /** UUID for this complete batch. Keep it with unchanged ops for a later retry; default a new UUID. */
137
+ operationID?: string;
138
+ /** Persist the active batch before sending it, including any replacement after re-upload. Resume with its ops and operation_id. */
139
+ onState?: (batch: CommitBody) => void;
140
+ /** Blob ("sha256-…") → the file it was uploaded from. */
141
+ sources?: Record<string, CommitSource>;
142
+ }
143
+ type Uploadable = Blob & {
144
+ name?: string;
145
+ lastModified?: number;
146
+ };
147
+ /** A path names a file by its full path or, for an upload, its stem ("cover" for "cover.png"). */
148
+ export declare const samePath: (file: string, path: string) => boolean;
149
+ /** The path without its extension. */
150
+ export declare const stem: (path: string) => string;
151
+ /** The media module: uploads, commits, reads, frames and HLS. */
152
+ export declare class MediaClient {
153
+ private readonly http;
154
+ readonly api: MediaApi;
155
+ private readonly transport;
156
+ private readonly concurrency;
157
+ private readonly retries;
158
+ private readonly delay;
159
+ private readonly targetSeconds;
160
+ private presetList?;
161
+ private readonly folders;
162
+ constructor(http: Http, o?: MediaOptions, folders?: ContentFolders);
163
+ /**
164
+ * Uploads file to the item's folder: it hashes the whole file (off the
165
+ * main thread) and presigns {path, type, size, sha256}, then sends nothing
166
+ * (the folder holds the identical blob), or stages it: one checksum-bound
167
+ * PUT up to 64 MiB, resumable multipart above. A refused presign throws
168
+ * before any bytes move. Commit the result with a put op (or use put());
169
+ * the worker then places a staged upload at the hash of its bytes.
170
+ */
171
+ upload(file: Uploadable, o: UploadOptions): Promise<UploadedFile>;
172
+ /**
173
+ * Uploads file and commits it as a put to its path (with edit, meta and
174
+ * index), then by default waits until the worker processed it; resolves
175
+ * with the upload as an editor reads it.
176
+ */
177
+ put(file: Uploadable, o: UploadOptions & PutOptions): Promise<FileInfo>;
178
+ /**
179
+ * Applies ops to the item in one conditional write; returns its uploads as
180
+ * an editor reads them. With sources (blob → the file uploaded as it), a
181
+ * not_uploaded refusal (the blob expired or is due for cleanup) uploads
182
+ * the affected files again and retries the commit once.
183
+ */
184
+ commit(ref: RefBody, ops: Op[], o?: CommitOptions): Promise<FileInfo[]>;
185
+ /** The read API: the item's files under prefix in manifest order, with signed URLs for what this viewer may have. */
186
+ read(ref: RefBody, o?: ReadOptions & {
187
+ signal?: AbortSignal;
188
+ }): Promise<ReadResult>;
189
+ /**
190
+ * Polls an editor read until the upload at path (or with that stem) is
191
+ * processed: placed (not staged), nothing pending and its blob present (a
192
+ * frame grabbed).
193
+ * Rejects with its failure, not_found once it is gone, too_large while the
194
+ * item is full (nothing is processed until uploads are removed),
195
+ * render_timeout after the timeout.
196
+ */
197
+ waitFor(ref: RefBody, path: string, o?: WaitOptions): Promise<FileInfo>;
198
+ /**
199
+ * The upload's editor view, for re-cropping: its URL and the upload's
200
+ * oriented size. Waits while it renders (an editor read asks for it);
201
+ * not_found when the path has no upload, render_timeout after the timeout
202
+ * (default 30 s).
203
+ */
204
+ editorView(ref: RefBody, path: string, o?: WaitOptions): Promise<{
205
+ url: string;
206
+ width: number;
207
+ height: number;
208
+ edit?: Edit;
209
+ }>;
210
+ /**
211
+ * Every kind's public presets, fetched once per client: crop bounds,
212
+ * widths and default images. An item's current image is in its read's
213
+ * `public`, never built from a preset. Shared by every caller, so it takes
214
+ * no signal; a failed fetch is retried on the next call.
215
+ */
216
+ presets(): Promise<PresetRule[]>;
217
+ /** A JPEG still of the video upload at path, t seconds in, w pixels wide (default the frame's). */
218
+ getFrame(ref: RefBody, path: string, t: number, w?: number, signal?: AbortSignal): Promise<Blob>;
219
+ /** The folder of an HLS ladder from a read's `hls`: `{media}/{kind}/{id}/hls/{dir}`; master.m3u8 and sprite.vtt resolve under it. */
220
+ hlsBase(ref: RefBody, dir: string): string;
221
+ /** hls.js `xhrSetup` for playlists on the API (the client's token and credentials); pass it to players as is. */
222
+ get xhrSetup(): (xhr: XMLHttpRequest, url: string) => Promise<void>;
223
+ /**
224
+ * Uploads an image to the item's server-named upload path and commits it
225
+ * (by default waiting until it is processed); resolves with the name content
226
+ * routes take: a poll or option image, a post cover.
227
+ */
228
+ uploadNamed(ref: RefBody, file: Uploadable, o?: NamedOptions): Promise<NamedUpload>;
229
+ /** An image for a post's rich-text body: uploaded to the post's folder; resolves with the URL to place in the body. */
230
+ uploadInline(post: string, file: Uploadable, o?: NamedOptions): Promise<NamedUpload & {
231
+ url: string;
232
+ }>;
233
+ /** The media folder of a post. */
234
+ postRef(id: string): RefBody;
235
+ /** The media folder of a poll. */
236
+ pollRef(id: string): RefBody;
237
+ /** Discards a paused multipart upload. */
238
+ discard(state: UploadState): Promise<void>;
239
+ private resumeMultipart;
240
+ private multipart;
241
+ private complete;
242
+ private retry;
243
+ }
244
+ /** Exponential backoff from 1 s to 30 s with jitter, or the server's Retry-After. */
245
+ export declare function backoff(attempt: number, retryAfter?: number): number;
246
+ export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
247
+ export {};
@@ -0,0 +1,407 @@
1
+ import { ContentKitError as e, aborted as t, failureError as n, throwIfAborted as r, toContentKitError as i } from "../errors.js";
2
+ import { call as a } from "../route.js";
3
+ import { MediaApi as o } from "./api.js";
4
+ import { sha256Hex as s } from "./hash.js";
5
+ import { Pacer as c } from "./pacer.js";
6
+ import { defaultTransport as l } from "./transport.js";
7
+ //#region src/client/media/client.ts
8
+ var u = /^i-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, d = (e, t) => e === t || f(e) === t, f = (e) => {
9
+ let t = e.lastIndexOf(".");
10
+ return t > e.lastIndexOf("/") + 1 ? e.slice(0, t) : e;
11
+ }, p = class {
12
+ http;
13
+ api;
14
+ transport;
15
+ concurrency;
16
+ retries;
17
+ delay;
18
+ targetSeconds;
19
+ presetList;
20
+ folders;
21
+ constructor(e, t = {}, n = {}) {
22
+ this.http = e, this.folders = {
23
+ post: n.post ?? "post",
24
+ poll: n.poll ?? "poll"
25
+ }, this.api = new o(e), this.transport = t.transport ?? l, this.concurrency = t.concurrency ?? 4, this.retries = t.retries ?? 5, this.delay = t.retryDelay ?? h, this.targetSeconds = t.targetPartSeconds ?? 30;
26
+ }
27
+ async upload(t, n) {
28
+ let i = n.type || t.type;
29
+ if (!i) throw new e("invalid_request", "the file has no content type");
30
+ if (r(n.signal), n.resume) return this.resumeMultipart(t, n.resume, n);
31
+ let a = t.size, o = await s(t, {
32
+ signal: n.signal,
33
+ onProgress: (e) => n.onProgress?.({
34
+ phase: "hashing",
35
+ loaded: e,
36
+ total: a
37
+ })
38
+ }), c = () => this.api.presign({
39
+ ref: n.ref,
40
+ path: n.path,
41
+ type: i,
42
+ size: a,
43
+ sha256: o
44
+ }, n.signal), l = await c(), u = (e) => ({
45
+ path: e.path,
46
+ blob: e.blob,
47
+ type: i,
48
+ size: a,
49
+ exists: !!e.exists,
50
+ processOnUpload: !!e.process_on_upload
51
+ });
52
+ if (l.exists) return u(l);
53
+ if (l.multipart) {
54
+ let e = l.multipart, r = {
55
+ ticket: e.ticket,
56
+ path: l.path,
57
+ blob: l.blob,
58
+ type: i,
59
+ size: a,
60
+ ref: n.ref,
61
+ file: m(t),
62
+ limits: {
63
+ minPartSize: e.min_part_size,
64
+ maxPartSize: e.max_part_size,
65
+ maxParts: e.max_parts
66
+ },
67
+ parts: [],
68
+ processOnUpload: !!l.process_on_upload
69
+ };
70
+ return this.multipart(t, r, /* @__PURE__ */ new Set(), n);
71
+ }
72
+ return await this.retry(async () => {
73
+ l.exists || await this.transport(l.put, t, {
74
+ signal: n.signal,
75
+ onProgress: (e) => n.onProgress?.({
76
+ phase: "uploading",
77
+ loaded: e,
78
+ total: a
79
+ })
80
+ });
81
+ }, n.signal, async (e) => {
82
+ e.code === "storage" && e.status === 403 && (l = await c());
83
+ }), u(l);
84
+ }
85
+ async put(e, t) {
86
+ let n = await this.upload(e, t);
87
+ t.onUploaded?.(n);
88
+ let r = {
89
+ op: "put",
90
+ path: n.path,
91
+ blob: n.blob
92
+ };
93
+ t.createOnly && (r.create_id = crypto.randomUUID()), t.edit && (r.edit = t.edit), t.meta && (r.meta = t.meta), t.index !== void 0 && (r.index = t.index);
94
+ let i = await this.commit(t.ref, [r], {
95
+ signal: t.signal,
96
+ sources: { [n.blob]: {
97
+ file: e,
98
+ type: n.type
99
+ } }
100
+ });
101
+ return t.wait === !1 ? i.find((e) => e.path === n.path) ?? {
102
+ path: n.path,
103
+ type: n.type
104
+ } : (t.onProgress?.({
105
+ phase: "processing",
106
+ loaded: n.size,
107
+ total: n.size
108
+ }), this.waitFor(t.ref, n.path, {
109
+ signal: t.signal,
110
+ timeout: t.timeout
111
+ }));
112
+ }
113
+ async commit(t, n, r = {}) {
114
+ let i = this.http.captureChanges(), a = structuredClone({
115
+ ref: t,
116
+ ops: n,
117
+ operation_id: r.operationID ?? crypto.randomUUID()
118
+ });
119
+ r.onState?.(structuredClone(a));
120
+ let o;
121
+ try {
122
+ o = (await this.retry(() => this.api.commit(a, r.signal), r.signal)).files;
123
+ } catch (t) {
124
+ if (!(t instanceof e) || t.code !== "not_uploaded") throw t;
125
+ let n = r.sources ?? {}, i = a.ops.filter((e) => e.op === "put" && e.blob && e.blob in n), s = [...new Set(i.map((e) => e.blob))].filter((e) => !t.blobs || t.blobs.includes(e));
126
+ if (s.length === 0) throw t;
127
+ let c = /* @__PURE__ */ new Map();
128
+ for (let e of s) {
129
+ let t = n[e], o = t instanceof Blob ? t : t.file, s = t instanceof Blob ? void 0 : t.type, l = i.find((t) => t.blob === e);
130
+ c.set(e, (await this.upload(o, {
131
+ ref: a.ref,
132
+ path: l.path,
133
+ type: s,
134
+ signal: r.signal
135
+ })).blob);
136
+ }
137
+ let l = a.ops.map((e) => e.blob && c.has(e.blob) ? {
138
+ ...e,
139
+ blob: c.get(e.blob)
140
+ } : e), u = {
141
+ ref: a.ref,
142
+ ops: l,
143
+ operation_id: crypto.randomUUID()
144
+ };
145
+ r.onState?.(structuredClone(u)), o = (await this.retry(() => this.api.commit(u, r.signal), r.signal)).files;
146
+ }
147
+ return i({
148
+ type: "media.committed",
149
+ ref: {
150
+ kind: t.kind,
151
+ id: t.id
152
+ },
153
+ files: o
154
+ }), o;
155
+ }
156
+ async read(e, t = {}) {
157
+ return this.api.itemURL(e), this.retry(() => this.api.read(e, t, t.signal), t.signal);
158
+ }
159
+ async waitFor(t, r, i = {}) {
160
+ let a = this.http.captureChanges(), o = Date.now() + (i.timeout ?? 12e4);
161
+ for (;;) {
162
+ let s = await this.read(t, {
163
+ editor: !0,
164
+ prefix: f(r),
165
+ signal: i.signal
166
+ }), c = s.files.find((e) => e.upload && d(e.path, r));
167
+ if (!c) throw new e("not_found", `no upload ${r}`, { status: 404 });
168
+ if (c.failed) throw n(c.failed);
169
+ if (!c.pending?.length && !c.staged && (c.size ?? 0) > 0) return a({
170
+ type: "media.processed",
171
+ ref: {
172
+ kind: t.kind,
173
+ id: t.id
174
+ },
175
+ file: c
176
+ }), c;
177
+ if (s.full) throw new e("too_large", `${r} waits: the item is full; remove uploads to process more`, { status: 413 });
178
+ if (Date.now() >= o) throw new e("render_timeout", `${r} is still processing`);
179
+ await g(i.interval ?? 1e3, i.signal);
180
+ }
181
+ }
182
+ async editorView(t, r, i = {}) {
183
+ let a = Date.now() + (i.timeout ?? 3e4);
184
+ for (;;) {
185
+ let o = (await this.read(t, {
186
+ editor: !0,
187
+ prefix: f(r),
188
+ signal: i.signal
189
+ })).files.find((e) => e.upload && d(e.path, r));
190
+ if (!o) throw new e("not_found", `no upload ${r}`, { status: 404 });
191
+ if (o.editor_url && o.w && o.h) return {
192
+ url: o.editor_url,
193
+ width: o.w,
194
+ height: o.h,
195
+ ...o.edit ? { edit: o.edit } : {}
196
+ };
197
+ if (o.failed) throw n(o.failed);
198
+ if (Date.now() >= a) throw new e("render_timeout", `the editor view of ${r} is still rendering`);
199
+ await g(i.interval ?? 1e3, i.signal);
200
+ }
201
+ }
202
+ presets() {
203
+ return this.presetList ??= this.retry(() => this.api.presets()).catch((e) => {
204
+ throw this.presetList = void 0, e;
205
+ }), this.presetList;
206
+ }
207
+ getFrame(e, t, n, r, i) {
208
+ return this.retry(() => this.api.frame(e, t, n, r, i), i);
209
+ }
210
+ hlsBase(e, t) {
211
+ return `${this.api.itemURL(e)}/hls/${t}`;
212
+ }
213
+ get xhrSetup() {
214
+ return this.http.xhrSetup;
215
+ }
216
+ async uploadNamed(t, n, r = {}) {
217
+ let i = await this.put(n, {
218
+ ref: t,
219
+ path: r.path ?? (n.name || "image"),
220
+ signal: r.signal,
221
+ onProgress: r.onProgress,
222
+ wait: r.wait,
223
+ timeout: r.timeout
224
+ }), a = f(i.path.slice(i.path.lastIndexOf("/") + 1));
225
+ if (!u.test(a)) throw new e("invalid_request", `${i.path} is not a server-named upload path of ${t.kind}`);
226
+ return {
227
+ name: a,
228
+ path: i.path,
229
+ file: i
230
+ };
231
+ }
232
+ async uploadInline(e, t, n = {}) {
233
+ let r = await this.uploadNamed(this.postRef(e), t, n), i = await a(this.http, "POST", "/posts/{id}/images", {
234
+ params: { id: e },
235
+ body: { image: r.name },
236
+ signal: n.signal
237
+ });
238
+ return {
239
+ ...r,
240
+ url: i.url
241
+ };
242
+ }
243
+ postRef(e) {
244
+ return {
245
+ kind: this.folders.post,
246
+ id: e
247
+ };
248
+ }
249
+ pollRef(e) {
250
+ return {
251
+ kind: this.folders.poll,
252
+ id: e
253
+ };
254
+ }
255
+ async discard(e) {
256
+ await this.api.abort(e.ref, { ticket: e.ticket });
257
+ }
258
+ async resumeMultipart(t, n, r) {
259
+ let i = m(t);
260
+ if (i.size !== n.size || i.name !== n.file.name || i.lastModified !== n.file.lastModified) throw new e("resume_mismatch", "the saved upload is for a different file");
261
+ let a;
262
+ try {
263
+ a = await this.retry(() => this.api.listParts(n.ref, { ticket: n.ticket }, r.signal), r.signal);
264
+ } catch (t) {
265
+ if (t instanceof e && t.code === "not_found") return this.complete(n, r);
266
+ throw t;
267
+ }
268
+ let o = /* @__PURE__ */ new Set();
269
+ for (let e of a.parts) {
270
+ let i = n.parts.find((t) => t.number === e.number);
271
+ if (!i || i.size !== e.size || e.sha256 && i.sha256 !== e.sha256) return await this.discard(n).catch(() => {}), r.onState?.(null), this.upload(t, {
272
+ ...r,
273
+ resume: void 0
274
+ });
275
+ o.add(e.number);
276
+ }
277
+ return this.multipart(t, structuredClone(n), o, r);
278
+ }
279
+ async multipart(e, n, r, i) {
280
+ let a = new c({
281
+ ...n.limits,
282
+ maxConcurrency: this.concurrency,
283
+ targetSeconds: this.targetSeconds
284
+ }), o = () => i.onState?.(structuredClone(n)), l = /* @__PURE__ */ new Map(), u = n.parts.filter((e) => r.has(e.number)).reduce((e, t) => e + t.size, 0), d = () => {
285
+ let e = u;
286
+ for (let t of l.values()) e += t;
287
+ i.onProgress?.({
288
+ phase: "uploading",
289
+ loaded: e,
290
+ total: n.size
291
+ });
292
+ }, f = n.parts.filter((e) => !r.has(e.number)), p = n.parts.reduce((e, t) => Math.max(e, t.offset + t.size), 0), m = () => {
293
+ let e = f.shift();
294
+ if (e || p >= n.size) return e;
295
+ let t = {
296
+ number: n.parts.length + 1,
297
+ offset: p,
298
+ size: Math.min(a.partSize(), n.size - p)
299
+ };
300
+ return p += t.size, n.parts.push(t), t;
301
+ }, h = new AbortController(), g = i.signal ? AbortSignal.any([i.signal, h.signal]) : h.signal, _ = 0, v = [], y = () => new Promise((e, n) => {
302
+ let r = () => {
303
+ g.removeEventListener("abort", i), _++, e();
304
+ }, i = () => {
305
+ v.splice(v.indexOf(r) >>> 0, 1), n(t(g));
306
+ };
307
+ if (_ < a.concurrency) return r();
308
+ if (g.aborted) return n(t(g));
309
+ g.addEventListener("abort", i, { once: !0 }), v.push(r);
310
+ }), b = () => {
311
+ for (_--; _ < a.concurrency && v.length;) v.shift()();
312
+ }, x = async (t) => {
313
+ let r = e.slice(t.offset, t.offset + t.size);
314
+ await this.retry(async () => {
315
+ t.sha256 || (t.sha256 = await s(r, { signal: g }), o());
316
+ let { parts: e } = await this.api.parts(n.ref, {
317
+ ticket: n.ticket,
318
+ parts: [{
319
+ number: t.number,
320
+ size: t.size,
321
+ sha256: t.sha256
322
+ }]
323
+ }, g), i = e[0]?.request;
324
+ await y();
325
+ let c = performance.now(), f = _;
326
+ try {
327
+ await this.transport(i, r, {
328
+ signal: g,
329
+ onProgress: (e) => {
330
+ l.set(t.number, e), d();
331
+ }
332
+ });
333
+ } finally {
334
+ l.delete(t.number), b();
335
+ }
336
+ a.record(t.size, performance.now() - c, f), u += t.size, d();
337
+ }, g);
338
+ };
339
+ o(), d();
340
+ let S = /* @__PURE__ */ new Set(), C;
341
+ for (;;) {
342
+ let e;
343
+ for (; C === void 0 && S.size < a.concurrency + 2 && (e = m());) {
344
+ o();
345
+ let t = x(e).then(() => void S.delete(t), (e) => {
346
+ S.delete(t), C === void 0 && (C = e, h.abort());
347
+ });
348
+ S.add(t);
349
+ }
350
+ if (S.size === 0) break;
351
+ await Promise.race(S);
352
+ }
353
+ if (C !== void 0) throw i.signal?.aborted ? t(i.signal) : C;
354
+ return this.complete(n, i);
355
+ }
356
+ async complete(e, t) {
357
+ t.onProgress?.({
358
+ phase: "completing",
359
+ loaded: e.size,
360
+ total: e.size
361
+ });
362
+ let n = await this.retry(() => this.api.complete(e.ref, { ticket: e.ticket }, t.signal), t.signal);
363
+ return t.onState?.(null), {
364
+ path: e.path,
365
+ blob: n.blob,
366
+ type: n.type,
367
+ size: n.size,
368
+ exists: !1,
369
+ processOnUpload: e.processOnUpload
370
+ };
371
+ }
372
+ async retry(e, n, r) {
373
+ for (let a = 0;; a++) try {
374
+ return await e();
375
+ } catch (e) {
376
+ let o = i(e);
377
+ if (n?.aborted) throw t(n);
378
+ if (!o.transient || a >= this.retries) throw o;
379
+ await g(this.delay(a, o.retryAfter), n), await r?.(o);
380
+ }
381
+ }
382
+ };
383
+ function m(e) {
384
+ return {
385
+ name: e.name,
386
+ lastModified: e.lastModified,
387
+ size: e.size
388
+ };
389
+ }
390
+ function h(e, t) {
391
+ return t ? t * 1e3 : Math.min(3e4, 1e3 * 2 ** e) * (.75 + Math.random() * .5);
392
+ }
393
+ function g(e, n) {
394
+ return new Promise((r, i) => {
395
+ if (n?.aborted) return i(t(n));
396
+ let a = setTimeout(() => {
397
+ n?.removeEventListener("abort", o), r();
398
+ }, e), o = () => {
399
+ clearTimeout(a), i(t(n));
400
+ };
401
+ n?.addEventListener("abort", o, { once: !0 });
402
+ });
403
+ }
404
+ //#endregion
405
+ export { p as MediaClient, h as backoff, d as samePath, g as sleep, f as stem };
406
+
407
+ //# sourceMappingURL=client.js.map