@streetjs/storage 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +719 -0
  3. package/dist/access.d.ts +95 -0
  4. package/dist/access.d.ts.map +1 -0
  5. package/dist/access.js +114 -0
  6. package/dist/access.js.map +1 -0
  7. package/dist/cli/commands.d.ts +88 -0
  8. package/dist/cli/commands.d.ts.map +1 -0
  9. package/dist/cli/commands.js +369 -0
  10. package/dist/cli/commands.js.map +1 -0
  11. package/dist/cli/generators.d.ts +41 -0
  12. package/dist/cli/generators.d.ts.map +1 -0
  13. package/dist/cli/generators.js +119 -0
  14. package/dist/cli/generators.js.map +1 -0
  15. package/dist/directory.d.ts +88 -0
  16. package/dist/directory.d.ts.map +1 -0
  17. package/dist/directory.js +148 -0
  18. package/dist/directory.js.map +1 -0
  19. package/dist/driver.d.ts +83 -0
  20. package/dist/driver.d.ts.map +1 -0
  21. package/dist/driver.js +16 -0
  22. package/dist/driver.js.map +1 -0
  23. package/dist/drivers/azure.d.ts +239 -0
  24. package/dist/drivers/azure.d.ts.map +1 -0
  25. package/dist/drivers/azure.js +476 -0
  26. package/dist/drivers/azure.js.map +1 -0
  27. package/dist/drivers/backblaze.d.ts +105 -0
  28. package/dist/drivers/backblaze.d.ts.map +1 -0
  29. package/dist/drivers/backblaze.js +279 -0
  30. package/dist/drivers/backblaze.js.map +1 -0
  31. package/dist/drivers/gcs.d.ts +239 -0
  32. package/dist/drivers/gcs.d.ts.map +1 -0
  33. package/dist/drivers/gcs.js +454 -0
  34. package/dist/drivers/gcs.js.map +1 -0
  35. package/dist/drivers/local.d.ts +126 -0
  36. package/dist/drivers/local.d.ts.map +1 -0
  37. package/dist/drivers/local.js +321 -0
  38. package/dist/drivers/local.js.map +1 -0
  39. package/dist/drivers/memory.d.ts +104 -0
  40. package/dist/drivers/memory.d.ts.map +1 -0
  41. package/dist/drivers/memory.js +197 -0
  42. package/dist/drivers/memory.js.map +1 -0
  43. package/dist/drivers/minio.d.ts +90 -0
  44. package/dist/drivers/minio.d.ts.map +1 -0
  45. package/dist/drivers/minio.js +276 -0
  46. package/dist/drivers/minio.js.map +1 -0
  47. package/dist/drivers/r2.d.ts +100 -0
  48. package/dist/drivers/r2.d.ts.map +1 -0
  49. package/dist/drivers/r2.js +240 -0
  50. package/dist/drivers/r2.js.map +1 -0
  51. package/dist/drivers/s3-base.d.ts +270 -0
  52. package/dist/drivers/s3-base.d.ts.map +1 -0
  53. package/dist/drivers/s3-base.js +436 -0
  54. package/dist/drivers/s3-base.js.map +1 -0
  55. package/dist/drivers/s3.d.ts +111 -0
  56. package/dist/drivers/s3.d.ts.map +1 -0
  57. package/dist/drivers/s3.js +311 -0
  58. package/dist/drivers/s3.js.map +1 -0
  59. package/dist/drivers/supabase.d.ts +246 -0
  60. package/dist/drivers/supabase.d.ts.map +1 -0
  61. package/dist/drivers/supabase.js +502 -0
  62. package/dist/drivers/supabase.js.map +1 -0
  63. package/dist/errors.d.ts +115 -0
  64. package/dist/errors.d.ts.map +1 -0
  65. package/dist/errors.js +131 -0
  66. package/dist/errors.js.map +1 -0
  67. package/dist/examples/storage-demo.d.ts +53 -0
  68. package/dist/examples/storage-demo.d.ts.map +1 -0
  69. package/dist/examples/storage-demo.js +242 -0
  70. package/dist/examples/storage-demo.js.map +1 -0
  71. package/dist/facade.d.ts +192 -0
  72. package/dist/facade.d.ts.map +1 -0
  73. package/dist/facade.js +898 -0
  74. package/dist/facade.js.map +1 -0
  75. package/dist/image.d.ts +94 -0
  76. package/dist/image.d.ts.map +1 -0
  77. package/dist/image.js +224 -0
  78. package/dist/image.js.map +1 -0
  79. package/dist/index.d.ts +47 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +53 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/integrations/events.d.ts +108 -0
  84. package/dist/integrations/events.d.ts.map +1 -0
  85. package/dist/integrations/events.js +111 -0
  86. package/dist/integrations/events.js.map +1 -0
  87. package/dist/integrations/queue.d.ts +89 -0
  88. package/dist/integrations/queue.d.ts.map +1 -0
  89. package/dist/integrations/queue.js +91 -0
  90. package/dist/integrations/queue.js.map +1 -0
  91. package/dist/integrations/realtime.d.ts +95 -0
  92. package/dist/integrations/realtime.d.ts.map +1 -0
  93. package/dist/integrations/realtime.js +90 -0
  94. package/dist/integrations/realtime.js.map +1 -0
  95. package/dist/lifecycle.d.ts +137 -0
  96. package/dist/lifecycle.d.ts.map +1 -0
  97. package/dist/lifecycle.js +240 -0
  98. package/dist/lifecycle.js.map +1 -0
  99. package/dist/metadata.d.ts +109 -0
  100. package/dist/metadata.d.ts.map +1 -0
  101. package/dist/metadata.js +139 -0
  102. package/dist/metadata.js.map +1 -0
  103. package/dist/multipart.d.ts +108 -0
  104. package/dist/multipart.d.ts.map +1 -0
  105. package/dist/multipart.js +200 -0
  106. package/dist/multipart.js.map +1 -0
  107. package/dist/observability.d.ts +82 -0
  108. package/dist/observability.d.ts.map +1 -0
  109. package/dist/observability.js +175 -0
  110. package/dist/observability.js.map +1 -0
  111. package/dist/plugin.d.ts +82 -0
  112. package/dist/plugin.d.ts.map +1 -0
  113. package/dist/plugin.js +100 -0
  114. package/dist/plugin.js.map +1 -0
  115. package/dist/resumable.d.ts +118 -0
  116. package/dist/resumable.d.ts.map +1 -0
  117. package/dist/resumable.js +223 -0
  118. package/dist/resumable.js.map +1 -0
  119. package/dist/search.d.ts +57 -0
  120. package/dist/search.d.ts.map +1 -0
  121. package/dist/search.js +172 -0
  122. package/dist/search.js.map +1 -0
  123. package/dist/signed-url.d.ts +110 -0
  124. package/dist/signed-url.d.ts.map +1 -0
  125. package/dist/signed-url.js +237 -0
  126. package/dist/signed-url.js.map +1 -0
  127. package/dist/testing/index.d.ts +219 -0
  128. package/dist/testing/index.d.ts.map +1 -0
  129. package/dist/testing/index.js +393 -0
  130. package/dist/testing/index.js.map +1 -0
  131. package/dist/tests/access.test.d.ts +2 -0
  132. package/dist/tests/access.test.d.ts.map +1 -0
  133. package/dist/tests/access.test.js +270 -0
  134. package/dist/tests/access.test.js.map +1 -0
  135. package/dist/tests/azure-driver.test.d.ts +2 -0
  136. package/dist/tests/azure-driver.test.d.ts.map +1 -0
  137. package/dist/tests/azure-driver.test.js +183 -0
  138. package/dist/tests/azure-driver.test.js.map +1 -0
  139. package/dist/tests/backblaze-driver.test.d.ts +2 -0
  140. package/dist/tests/backblaze-driver.test.d.ts.map +1 -0
  141. package/dist/tests/backblaze-driver.test.js +185 -0
  142. package/dist/tests/backblaze-driver.test.js.map +1 -0
  143. package/dist/tests/bridge-degradation.test.d.ts +2 -0
  144. package/dist/tests/bridge-degradation.test.d.ts.map +1 -0
  145. package/dist/tests/bridge-degradation.test.js +138 -0
  146. package/dist/tests/bridge-degradation.test.js.map +1 -0
  147. package/dist/tests/cli.test.d.ts +2 -0
  148. package/dist/tests/cli.test.d.ts.map +1 -0
  149. package/dist/tests/cli.test.js +127 -0
  150. package/dist/tests/cli.test.js.map +1 -0
  151. package/dist/tests/contract.d.ts +131 -0
  152. package/dist/tests/contract.d.ts.map +1 -0
  153. package/dist/tests/contract.js +222 -0
  154. package/dist/tests/contract.js.map +1 -0
  155. package/dist/tests/contract.test.d.ts +2 -0
  156. package/dist/tests/contract.test.d.ts.map +1 -0
  157. package/dist/tests/contract.test.js +110 -0
  158. package/dist/tests/contract.test.js.map +1 -0
  159. package/dist/tests/directory.test.d.ts +2 -0
  160. package/dist/tests/directory.test.d.ts.map +1 -0
  161. package/dist/tests/directory.test.js +125 -0
  162. package/dist/tests/directory.test.js.map +1 -0
  163. package/dist/tests/errors.test.d.ts +2 -0
  164. package/dist/tests/errors.test.d.ts.map +1 -0
  165. package/dist/tests/errors.test.js +93 -0
  166. package/dist/tests/errors.test.js.map +1 -0
  167. package/dist/tests/events-bridge.test.d.ts +2 -0
  168. package/dist/tests/events-bridge.test.d.ts.map +1 -0
  169. package/dist/tests/events-bridge.test.js +228 -0
  170. package/dist/tests/events-bridge.test.js.map +1 -0
  171. package/dist/tests/example-smoke.test.d.ts +2 -0
  172. package/dist/tests/example-smoke.test.d.ts.map +1 -0
  173. package/dist/tests/example-smoke.test.js +34 -0
  174. package/dist/tests/example-smoke.test.js.map +1 -0
  175. package/dist/tests/gcs-driver.test.d.ts +2 -0
  176. package/dist/tests/gcs-driver.test.d.ts.map +1 -0
  177. package/dist/tests/gcs-driver.test.js +197 -0
  178. package/dist/tests/gcs-driver.test.js.map +1 -0
  179. package/dist/tests/image.test.d.ts +2 -0
  180. package/dist/tests/image.test.d.ts.map +1 -0
  181. package/dist/tests/image.test.js +102 -0
  182. package/dist/tests/image.test.js.map +1 -0
  183. package/dist/tests/lifecycle.test.d.ts +2 -0
  184. package/dist/tests/lifecycle.test.d.ts.map +1 -0
  185. package/dist/tests/lifecycle.test.js +171 -0
  186. package/dist/tests/lifecycle.test.js.map +1 -0
  187. package/dist/tests/local-driver.test.d.ts +2 -0
  188. package/dist/tests/local-driver.test.d.ts.map +1 -0
  189. package/dist/tests/local-driver.test.js +153 -0
  190. package/dist/tests/local-driver.test.js.map +1 -0
  191. package/dist/tests/local-streaming.test.d.ts +2 -0
  192. package/dist/tests/local-streaming.test.d.ts.map +1 -0
  193. package/dist/tests/local-streaming.test.js +121 -0
  194. package/dist/tests/local-streaming.test.js.map +1 -0
  195. package/dist/tests/memory-driver.test.d.ts +2 -0
  196. package/dist/tests/memory-driver.test.d.ts.map +1 -0
  197. package/dist/tests/memory-driver.test.js +180 -0
  198. package/dist/tests/memory-driver.test.js.map +1 -0
  199. package/dist/tests/memory-streaming.test.d.ts +2 -0
  200. package/dist/tests/memory-streaming.test.d.ts.map +1 -0
  201. package/dist/tests/memory-streaming.test.js +92 -0
  202. package/dist/tests/memory-streaming.test.js.map +1 -0
  203. package/dist/tests/minio-driver.test.d.ts +2 -0
  204. package/dist/tests/minio-driver.test.d.ts.map +1 -0
  205. package/dist/tests/minio-driver.test.js +146 -0
  206. package/dist/tests/minio-driver.test.js.map +1 -0
  207. package/dist/tests/non-s3-integration.test.d.ts +2 -0
  208. package/dist/tests/non-s3-integration.test.d.ts.map +1 -0
  209. package/dist/tests/non-s3-integration.test.js +201 -0
  210. package/dist/tests/non-s3-integration.test.js.map +1 -0
  211. package/dist/tests/observability.registration.test.d.ts +2 -0
  212. package/dist/tests/observability.registration.test.d.ts.map +1 -0
  213. package/dist/tests/observability.registration.test.js +103 -0
  214. package/dist/tests/observability.registration.test.js.map +1 -0
  215. package/dist/tests/observability.test.d.ts +2 -0
  216. package/dist/tests/observability.test.d.ts.map +1 -0
  217. package/dist/tests/observability.test.js +240 -0
  218. package/dist/tests/observability.test.js.map +1 -0
  219. package/dist/tests/plugin.test.d.ts +2 -0
  220. package/dist/tests/plugin.test.d.ts.map +1 -0
  221. package/dist/tests/plugin.test.js +112 -0
  222. package/dist/tests/plugin.test.js.map +1 -0
  223. package/dist/tests/prop-concurrent.test.d.ts +2 -0
  224. package/dist/tests/prop-concurrent.test.d.ts.map +1 -0
  225. package/dist/tests/prop-concurrent.test.js +59 -0
  226. package/dist/tests/prop-concurrent.test.js.map +1 -0
  227. package/dist/tests/prop-copy.test.d.ts +2 -0
  228. package/dist/tests/prop-copy.test.d.ts.map +1 -0
  229. package/dist/tests/prop-copy.test.js +63 -0
  230. package/dist/tests/prop-copy.test.js.map +1 -0
  231. package/dist/tests/prop-delete.test.d.ts +2 -0
  232. package/dist/tests/prop-delete.test.d.ts.map +1 -0
  233. package/dist/tests/prop-delete.test.js +35 -0
  234. package/dist/tests/prop-delete.test.js.map +1 -0
  235. package/dist/tests/prop-directory.test.d.ts +2 -0
  236. package/dist/tests/prop-directory.test.d.ts.map +1 -0
  237. package/dist/tests/prop-directory.test.js +118 -0
  238. package/dist/tests/prop-directory.test.js.map +1 -0
  239. package/dist/tests/prop-driver-conformance.test.d.ts +2 -0
  240. package/dist/tests/prop-driver-conformance.test.d.ts.map +1 -0
  241. package/dist/tests/prop-driver-conformance.test.js +110 -0
  242. package/dist/tests/prop-driver-conformance.test.js.map +1 -0
  243. package/dist/tests/prop-driver-equivalence.test.d.ts +2 -0
  244. package/dist/tests/prop-driver-equivalence.test.d.ts.map +1 -0
  245. package/dist/tests/prop-driver-equivalence.test.js +163 -0
  246. package/dist/tests/prop-driver-equivalence.test.js.map +1 -0
  247. package/dist/tests/prop-lifecycle.test.d.ts +2 -0
  248. package/dist/tests/prop-lifecycle.test.d.ts.map +1 -0
  249. package/dist/tests/prop-lifecycle.test.js +83 -0
  250. package/dist/tests/prop-lifecycle.test.js.map +1 -0
  251. package/dist/tests/prop-list.test.d.ts +2 -0
  252. package/dist/tests/prop-list.test.d.ts.map +1 -0
  253. package/dist/tests/prop-list.test.js +53 -0
  254. package/dist/tests/prop-list.test.js.map +1 -0
  255. package/dist/tests/prop-metadata.test.d.ts +2 -0
  256. package/dist/tests/prop-metadata.test.d.ts.map +1 -0
  257. package/dist/tests/prop-metadata.test.js +87 -0
  258. package/dist/tests/prop-metadata.test.js.map +1 -0
  259. package/dist/tests/prop-move.test.d.ts +2 -0
  260. package/dist/tests/prop-move.test.d.ts.map +1 -0
  261. package/dist/tests/prop-move.test.js +67 -0
  262. package/dist/tests/prop-move.test.js.map +1 -0
  263. package/dist/tests/prop-multipart-abort.test.d.ts +2 -0
  264. package/dist/tests/prop-multipart-abort.test.d.ts.map +1 -0
  265. package/dist/tests/prop-multipart-abort.test.js +48 -0
  266. package/dist/tests/prop-multipart-abort.test.js.map +1 -0
  267. package/dist/tests/prop-multipart.test.d.ts +2 -0
  268. package/dist/tests/prop-multipart.test.d.ts.map +1 -0
  269. package/dist/tests/prop-multipart.test.js +65 -0
  270. package/dist/tests/prop-multipart.test.js.map +1 -0
  271. package/dist/tests/prop-resumable.test.d.ts +2 -0
  272. package/dist/tests/prop-resumable.test.d.ts.map +1 -0
  273. package/dist/tests/prop-resumable.test.js +78 -0
  274. package/dist/tests/prop-resumable.test.js.map +1 -0
  275. package/dist/tests/prop-search.test.d.ts +2 -0
  276. package/dist/tests/prop-search.test.d.ts.map +1 -0
  277. package/dist/tests/prop-search.test.js +120 -0
  278. package/dist/tests/prop-search.test.js.map +1 -0
  279. package/dist/tests/prop-signed-url.test.d.ts +2 -0
  280. package/dist/tests/prop-signed-url.test.d.ts.map +1 -0
  281. package/dist/tests/prop-signed-url.test.js +74 -0
  282. package/dist/tests/prop-signed-url.test.js.map +1 -0
  283. package/dist/tests/prop-streaming.test.d.ts +2 -0
  284. package/dist/tests/prop-streaming.test.d.ts.map +1 -0
  285. package/dist/tests/prop-streaming.test.js +34 -0
  286. package/dist/tests/prop-streaming.test.js.map +1 -0
  287. package/dist/tests/prop-upload-download.test.d.ts +2 -0
  288. package/dist/tests/prop-upload-download.test.d.ts.map +1 -0
  289. package/dist/tests/prop-upload-download.test.js +30 -0
  290. package/dist/tests/prop-upload-download.test.js.map +1 -0
  291. package/dist/tests/prop-validation.test.d.ts +2 -0
  292. package/dist/tests/prop-validation.test.d.ts.map +1 -0
  293. package/dist/tests/prop-validation.test.js +50 -0
  294. package/dist/tests/prop-validation.test.js.map +1 -0
  295. package/dist/tests/prop-versioning.test.d.ts +2 -0
  296. package/dist/tests/prop-versioning.test.d.ts.map +1 -0
  297. package/dist/tests/prop-versioning.test.js +74 -0
  298. package/dist/tests/prop-versioning.test.js.map +1 -0
  299. package/dist/tests/queue-bridge.test.d.ts +2 -0
  300. package/dist/tests/queue-bridge.test.d.ts.map +1 -0
  301. package/dist/tests/queue-bridge.test.js +111 -0
  302. package/dist/tests/queue-bridge.test.js.map +1 -0
  303. package/dist/tests/r2-driver.test.d.ts +2 -0
  304. package/dist/tests/r2-driver.test.d.ts.map +1 -0
  305. package/dist/tests/r2-driver.test.js +143 -0
  306. package/dist/tests/r2-driver.test.js.map +1 -0
  307. package/dist/tests/realtime-bridge.test.d.ts +2 -0
  308. package/dist/tests/realtime-bridge.test.d.ts.map +1 -0
  309. package/dist/tests/realtime-bridge.test.js +106 -0
  310. package/dist/tests/realtime-bridge.test.js.map +1 -0
  311. package/dist/tests/resumable.test.d.ts +2 -0
  312. package/dist/tests/resumable.test.d.ts.map +1 -0
  313. package/dist/tests/resumable.test.js +104 -0
  314. package/dist/tests/resumable.test.js.map +1 -0
  315. package/dist/tests/s3-base.test.d.ts +2 -0
  316. package/dist/tests/s3-base.test.d.ts.map +1 -0
  317. package/dist/tests/s3-base.test.js +289 -0
  318. package/dist/tests/s3-base.test.js.map +1 -0
  319. package/dist/tests/s3-integration.test.d.ts +2 -0
  320. package/dist/tests/s3-integration.test.d.ts.map +1 -0
  321. package/dist/tests/s3-integration.test.js +270 -0
  322. package/dist/tests/s3-integration.test.js.map +1 -0
  323. package/dist/tests/s3.test.d.ts +2 -0
  324. package/dist/tests/s3.test.d.ts.map +1 -0
  325. package/dist/tests/s3.test.js +203 -0
  326. package/dist/tests/s3.test.js.map +1 -0
  327. package/dist/tests/scaffold.test.d.ts +2 -0
  328. package/dist/tests/scaffold.test.d.ts.map +1 -0
  329. package/dist/tests/scaffold.test.js +13 -0
  330. package/dist/tests/scaffold.test.js.map +1 -0
  331. package/dist/tests/search.test.d.ts +2 -0
  332. package/dist/tests/search.test.d.ts.map +1 -0
  333. package/dist/tests/search.test.js +106 -0
  334. package/dist/tests/search.test.js.map +1 -0
  335. package/dist/tests/supabase-driver.test.d.ts +2 -0
  336. package/dist/tests/supabase-driver.test.d.ts.map +1 -0
  337. package/dist/tests/supabase-driver.test.js +196 -0
  338. package/dist/tests/supabase-driver.test.js.map +1 -0
  339. package/dist/tests/testing-utilities.test.d.ts +2 -0
  340. package/dist/tests/testing-utilities.test.d.ts.map +1 -0
  341. package/dist/tests/testing-utilities.test.js +138 -0
  342. package/dist/tests/testing-utilities.test.js.map +1 -0
  343. package/dist/tests/validation.test.d.ts +2 -0
  344. package/dist/tests/validation.test.d.ts.map +1 -0
  345. package/dist/tests/validation.test.js +135 -0
  346. package/dist/tests/validation.test.js.map +1 -0
  347. package/dist/tests/versioning.test.d.ts +2 -0
  348. package/dist/tests/versioning.test.d.ts.map +1 -0
  349. package/dist/tests/versioning.test.js +128 -0
  350. package/dist/tests/versioning.test.js.map +1 -0
  351. package/dist/types.d.ts +232 -0
  352. package/dist/types.d.ts.map +1 -0
  353. package/dist/types.js +23 -0
  354. package/dist/types.js.map +1 -0
  355. package/dist/validation.d.ts +105 -0
  356. package/dist/validation.d.ts.map +1 -0
  357. package/dist/validation.js +225 -0
  358. package/dist/validation.js.map +1 -0
  359. package/dist/versioning.d.ts +100 -0
  360. package/dist/versioning.d.ts.map +1 -0
  361. package/dist/versioning.js +179 -0
  362. package/dist/versioning.js.map +1 -0
  363. package/package.json +137 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @streetjs/storage — the Events integration bridge.
3
+ *
4
+ * This module publishes typed storage lifecycle events (`storage.uploaded`,
5
+ * `storage.deleted`, `storage.updated`, `storage.moved`, `storage.restored`,
6
+ * `storage.expired`) through an events layer, each payload carrying the affected
7
+ * object key and (when available) its {@link StorageObjectMetadata}
8
+ * (Requirements 18.1, 18.2). Lifecycle-rule actions publish through this same
9
+ * bridge (Requirement 13.4).
10
+ *
11
+ * Following the events package's structural-interface pattern, the bridge
12
+ * depends only on the minimal {@link EventsLike} shape declared in `types.ts`
13
+ * (any object exposing `publish(event, payload)`), never on the concrete
14
+ * `@streetjs/events` package, so there is no hard dependency and no circular
15
+ * dependency (Requirements 18.3, 28.3). {@link EventsLike} is re-exported here
16
+ * for convenience; it is intentionally the single definition that lives in
17
+ * `types.ts`.
18
+ *
19
+ * **Never throws into the operation path.** Every publish is wrapped so that a
20
+ * synchronous throw or an asynchronous rejection from the underlying events
21
+ * layer is swallowed: a publish failure must never break the storage operation
22
+ * that triggered it. This mirrors the graceful-degradation guarantee the Queue
23
+ * and Realtime bridges also uphold.
24
+ *
25
+ * The facade constructs a {@link StorageEventPublisher} via
26
+ * {@link bridgeStorageEvents} only when `config.bridges?.events` is provided;
27
+ * when it is absent the facade holds no publisher and event publication is a
28
+ * complete no-op.
29
+ *
30
+ * _Requirements: 13.4, 18.1, 18.2, 18.3, 28.3_
31
+ */
32
+ /**
33
+ * Map an applied {@link LifecycleOutcome} action onto its typed storage event
34
+ * name. `archived` is surfaced as `storage.moved` because archiving relocates
35
+ * the object under the reserved archive prefix; the original action is retained
36
+ * in the payload so listeners can still tell the two apart.
37
+ */
38
+ const LIFECYCLE_EVENT_BY_ACTION = {
39
+ deleted: "storage.deleted",
40
+ expired: "storage.expired",
41
+ moved: "storage.moved",
42
+ archived: "storage.moved",
43
+ };
44
+ /**
45
+ * Isolate a single publish call. A synchronous throw is caught; a returned
46
+ * promise has its rejection swallowed. Either way nothing propagates back to the
47
+ * storage operation that triggered the event, satisfying the "never throw into
48
+ * the operation path" guarantee.
49
+ */
50
+ function safePublish(events, event, payload) {
51
+ try {
52
+ const result = events.publish(event, payload);
53
+ if (result !== undefined && result !== null && typeof result.then === "function") {
54
+ // Fire-and-forget: absorb any asynchronous rejection.
55
+ result.then(undefined, () => {
56
+ /* swallow — a publish failure must not break the storage op */
57
+ });
58
+ }
59
+ }
60
+ catch {
61
+ // swallow — a publish failure must not break the storage op
62
+ }
63
+ }
64
+ /**
65
+ * Create a {@link StorageEventPublisher} that publishes typed storage events
66
+ * through the supplied structural {@link EventsLike} bridge.
67
+ *
68
+ * The returned publisher is what the facade wires into its object operations
69
+ * (`put` → uploaded/updated, `delete` → deleted, `move`/`rename` → moved,
70
+ * `restoreVersion` → restored) and its lifecycle evaluation (`applyLifecycle`
71
+ * → deleted/expired/moved via {@link StorageEventPublisher.lifecycle}). Every
72
+ * method is guaranteed never to throw into the caller.
73
+ *
74
+ * ```ts
75
+ * const publisher = bridgeStorageEvents(events);
76
+ * publisher.uploaded(metadata); // publishes "storage.uploaded" — never throws
77
+ * ```
78
+ */
79
+ export function bridgeStorageEvents(events) {
80
+ const publish = (event, payload) => {
81
+ safePublish(events, event, payload);
82
+ };
83
+ return {
84
+ publish,
85
+ uploaded(metadata) {
86
+ publish("storage.uploaded", { key: metadata.key, metadata });
87
+ },
88
+ updated(metadata) {
89
+ publish("storage.updated", { key: metadata.key, metadata });
90
+ },
91
+ deleted(key, metadata) {
92
+ publish("storage.deleted", { key, metadata });
93
+ },
94
+ moved(metadata) {
95
+ publish("storage.moved", { key: metadata.key, metadata });
96
+ },
97
+ restored(metadata) {
98
+ publish("storage.restored", { key: metadata.key, metadata });
99
+ },
100
+ expired(key, metadata) {
101
+ publish("storage.expired", { key, metadata });
102
+ },
103
+ lifecycle(outcome) {
104
+ publish(LIFECYCLE_EVENT_BY_ACTION[outcome.action], {
105
+ key: outcome.key,
106
+ action: outcome.action,
107
+ });
108
+ },
109
+ };
110
+ }
111
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/integrations/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAmFH;;;;;GAKG;AACH,MAAM,yBAAyB,GAAmE;IAChG,OAAO,EAAE,iBAAiB;IAC1B,OAAO,EAAE,iBAAiB;IAC1B,KAAK,EAAE,eAAe;IACtB,QAAQ,EAAE,eAAe;CAC1B,CAAC;AAEF;;;;;GAKG;AACH,SAAS,WAAW,CAAC,MAAkB,EAAE,KAAuB,EAAE,OAA4B;IAC5F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC9C,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,OAAQ,MAAwB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACpG,sDAAsD;YACrD,MAAwB,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;gBAC7C,+DAA+D;YACjE,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,4DAA4D;IAC9D,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAkB;IACpD,MAAM,OAAO,GAAG,CAAC,KAAuB,EAAE,OAA4B,EAAQ,EAAE;QAC9E,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC,CAAC;IAEF,OAAO;QACL,OAAO;QACP,QAAQ,CAAC,QAAQ;YACf,OAAO,CAAC,kBAAkB,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,CAAC,QAAQ;YACd,OAAO,CAAC,iBAAiB,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,QAAQ;YACnB,OAAO,CAAC,iBAAiB,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,KAAK,CAAC,QAAQ;YACZ,OAAO,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,QAAQ,CAAC,QAAQ;YACf,OAAO,CAAC,kBAAkB,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,QAAQ;YACnB,OAAO,CAAC,iBAAiB,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,SAAS,CAAC,OAAO;YACf,OAAO,CAAC,yBAAyB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;gBACjD,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @streetjs/storage — the Queue integration bridge.
3
+ *
4
+ * This module hands heavy, out-of-band work off to a background queue so that
5
+ * storage operations never block on it: thumbnail generation, virus scanning,
6
+ * OCR, PDF processing, transcoding, image optimization, and archive creation
7
+ * (Requirement 17.1). Each job is dispatched through the minimal
8
+ * {@link QueueLike} shape declared in `types.ts` (any object exposing
9
+ * `dispatch(job, payload)`), never through the concrete `@streetjs/queue`
10
+ * package, so there is no hard dependency and no circular dependency
11
+ * (Requirements 17.2, 28.3). {@link QueueLike} is re-exported here for
12
+ * convenience; it is intentionally the single definition that lives in
13
+ * `types.ts`.
14
+ *
15
+ * **Never throws into the operation path.** Every dispatch is wrapped so that a
16
+ * synchronous throw or an asynchronous rejection from the underlying queue is
17
+ * swallowed: a dispatch failure must never break the storage operation that
18
+ * triggered it (Requirement 17.4). Equally, when no queue bridge is configured
19
+ * the facade holds no publisher and job dispatch is a complete no-op — storage
20
+ * operations proceed unaffected (Requirement 17.3). This mirrors the
21
+ * graceful-degradation guarantee the Events and Realtime bridges also uphold.
22
+ *
23
+ * The facade constructs a {@link StorageQueuePublisher} via
24
+ * {@link bridgeStorageQueue} only when `config.bridges?.queue` is provided.
25
+ *
26
+ * _Requirements: 17.1, 17.2, 17.3, 17.4, 28.3_
27
+ */
28
+ import type { QueueLike } from "../types.js";
29
+ export type { QueueLike } from "../types.js";
30
+ /**
31
+ * The exhaustive set of background job names the storage framework dispatches
32
+ * (Requirement 17.1). Every heavy, out-of-band task maps onto exactly one of
33
+ * these names.
34
+ */
35
+ export type StorageJobName = "storage.thumbnail" | "storage.virus-scan" | "storage.ocr" | "storage.pdf-process" | "storage.transcode" | "storage.image-optimize" | "storage.archive";
36
+ /**
37
+ * The payload dispatched with every storage job. It always carries the affected
38
+ * object `key` and, when the triggering operation has it in hand, arbitrary
39
+ * job-specific `options` the worker uses to perform the task.
40
+ */
41
+ export interface StorageJobPayload {
42
+ /** The affected object key (always present). */
43
+ readonly key: string;
44
+ /** Job-specific options passed through to the worker (optional). */
45
+ readonly options?: Record<string, unknown>;
46
+ }
47
+ /**
48
+ * The publisher the facade holds and can call to hand heavy work to the queue.
49
+ * Every method is fire-and-forget and guaranteed never to throw into the
50
+ * caller: the underlying dispatch is isolated so a failing (or absent) queue
51
+ * cannot break a storage operation (Requirements 17.3, 17.4).
52
+ */
53
+ export interface StorageQueuePublisher {
54
+ /**
55
+ * Dispatch an already-named background job with the given payload. Never
56
+ * throws. The typed convenience methods below are thin wrappers over this.
57
+ */
58
+ dispatch(job: StorageJobName, payload: StorageJobPayload): void;
59
+ /** Dispatch a thumbnail-generation job for an object. */
60
+ thumbnail(key: string, options?: Record<string, unknown>): void;
61
+ /** Dispatch a virus-scan job for an object. */
62
+ virusScan(key: string, options?: Record<string, unknown>): void;
63
+ /** Dispatch an OCR (text-extraction) job for an object. */
64
+ ocr(key: string, options?: Record<string, unknown>): void;
65
+ /** Dispatch a PDF-processing job for an object. */
66
+ pdfProcess(key: string, options?: Record<string, unknown>): void;
67
+ /** Dispatch a media-transcoding job for an object. */
68
+ transcode(key: string, options?: Record<string, unknown>): void;
69
+ /** Dispatch an image-optimization job for an object. */
70
+ imageOptimize(key: string, options?: Record<string, unknown>): void;
71
+ /** Dispatch an archive-creation job for an object. */
72
+ archive(key: string, options?: Record<string, unknown>): void;
73
+ }
74
+ /**
75
+ * Create a {@link StorageQueuePublisher} that dispatches background jobs through
76
+ * the supplied structural {@link QueueLike} bridge.
77
+ *
78
+ * The returned publisher is what the facade wires into any heavy, out-of-band
79
+ * work (thumbnail generation, virus scanning, OCR, PDF processing, transcoding,
80
+ * image optimization, archive creation). Every method is guaranteed never to
81
+ * throw into the caller.
82
+ *
83
+ * ```ts
84
+ * const publisher = bridgeStorageQueue(queue);
85
+ * publisher.thumbnail("photo.png"); // dispatches "storage.thumbnail" — never throws
86
+ * ```
87
+ */
88
+ export declare function bridgeStorageQueue(queue: QueueLike): StorageQueuePublisher;
89
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/integrations/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;GAIG;AACH,MAAM,MAAM,cAAc,GACtB,mBAAmB,GACnB,oBAAoB,GACpB,aAAa,GACb,qBAAqB,GACrB,mBAAmB,GACnB,wBAAwB,GACxB,iBAAiB,CAAC;AAEtB;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5C;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAEhE,yDAAyD;IACzD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAEhE,+CAA+C;IAC/C,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAEhE,2DAA2D;IAC3D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAE1D,mDAAmD;IACnD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAEjE,sDAAsD;IACtD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAEhE,wDAAwD;IACxD,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAEpE,sDAAsD;IACtD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC/D;AAsBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,qBAAqB,CA6B1E"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @streetjs/storage — the Queue integration bridge.
3
+ *
4
+ * This module hands heavy, out-of-band work off to a background queue so that
5
+ * storage operations never block on it: thumbnail generation, virus scanning,
6
+ * OCR, PDF processing, transcoding, image optimization, and archive creation
7
+ * (Requirement 17.1). Each job is dispatched through the minimal
8
+ * {@link QueueLike} shape declared in `types.ts` (any object exposing
9
+ * `dispatch(job, payload)`), never through the concrete `@streetjs/queue`
10
+ * package, so there is no hard dependency and no circular dependency
11
+ * (Requirements 17.2, 28.3). {@link QueueLike} is re-exported here for
12
+ * convenience; it is intentionally the single definition that lives in
13
+ * `types.ts`.
14
+ *
15
+ * **Never throws into the operation path.** Every dispatch is wrapped so that a
16
+ * synchronous throw or an asynchronous rejection from the underlying queue is
17
+ * swallowed: a dispatch failure must never break the storage operation that
18
+ * triggered it (Requirement 17.4). Equally, when no queue bridge is configured
19
+ * the facade holds no publisher and job dispatch is a complete no-op — storage
20
+ * operations proceed unaffected (Requirement 17.3). This mirrors the
21
+ * graceful-degradation guarantee the Events and Realtime bridges also uphold.
22
+ *
23
+ * The facade constructs a {@link StorageQueuePublisher} via
24
+ * {@link bridgeStorageQueue} only when `config.bridges?.queue` is provided.
25
+ *
26
+ * _Requirements: 17.1, 17.2, 17.3, 17.4, 28.3_
27
+ */
28
+ /**
29
+ * Isolate a single dispatch call. A synchronous throw is caught; a returned
30
+ * promise has its rejection swallowed. Either way nothing propagates back to the
31
+ * storage operation that triggered the job, satisfying the "never throw into the
32
+ * operation path" guarantee (Requirement 17.4).
33
+ */
34
+ function safeDispatch(queue, job, payload) {
35
+ try {
36
+ const result = queue.dispatch(job, payload);
37
+ if (result !== undefined && result !== null && typeof result.then === "function") {
38
+ // Fire-and-forget: absorb any asynchronous rejection.
39
+ result.then(undefined, () => {
40
+ /* swallow — a dispatch failure must not break the storage op */
41
+ });
42
+ }
43
+ }
44
+ catch {
45
+ // swallow — a dispatch failure must not break the storage op
46
+ }
47
+ }
48
+ /**
49
+ * Create a {@link StorageQueuePublisher} that dispatches background jobs through
50
+ * the supplied structural {@link QueueLike} bridge.
51
+ *
52
+ * The returned publisher is what the facade wires into any heavy, out-of-band
53
+ * work (thumbnail generation, virus scanning, OCR, PDF processing, transcoding,
54
+ * image optimization, archive creation). Every method is guaranteed never to
55
+ * throw into the caller.
56
+ *
57
+ * ```ts
58
+ * const publisher = bridgeStorageQueue(queue);
59
+ * publisher.thumbnail("photo.png"); // dispatches "storage.thumbnail" — never throws
60
+ * ```
61
+ */
62
+ export function bridgeStorageQueue(queue) {
63
+ const dispatch = (job, payload) => {
64
+ safeDispatch(queue, job, payload);
65
+ };
66
+ return {
67
+ dispatch,
68
+ thumbnail(key, options) {
69
+ dispatch("storage.thumbnail", { key, options });
70
+ },
71
+ virusScan(key, options) {
72
+ dispatch("storage.virus-scan", { key, options });
73
+ },
74
+ ocr(key, options) {
75
+ dispatch("storage.ocr", { key, options });
76
+ },
77
+ pdfProcess(key, options) {
78
+ dispatch("storage.pdf-process", { key, options });
79
+ },
80
+ transcode(key, options) {
81
+ dispatch("storage.transcode", { key, options });
82
+ },
83
+ imageOptimize(key, options) {
84
+ dispatch("storage.image-optimize", { key, options });
85
+ },
86
+ archive(key, options) {
87
+ dispatch("storage.archive", { key, options });
88
+ },
89
+ };
90
+ }
91
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/integrations/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAsEH;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAgB,EAAE,GAAmB,EAAE,OAA0B;IACrF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC5C,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,OAAQ,MAAwB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACpG,sDAAsD;YACrD,MAAwB,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;gBAC7C,gEAAgE;YAClE,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;IAC/D,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAgB;IACjD,MAAM,QAAQ,GAAG,CAAC,GAAmB,EAAE,OAA0B,EAAQ,EAAE;QACzE,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC;IAEF,OAAO;QACL,QAAQ;QACR,SAAS,CAAC,GAAG,EAAE,OAAO;YACpB,QAAQ,CAAC,mBAAmB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,SAAS,CAAC,GAAG,EAAE,OAAO;YACpB,QAAQ,CAAC,oBAAoB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,GAAG,CAAC,GAAG,EAAE,OAAO;YACd,QAAQ,CAAC,aAAa,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,UAAU,CAAC,GAAG,EAAE,OAAO;YACrB,QAAQ,CAAC,qBAAqB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,SAAS,CAAC,GAAG,EAAE,OAAO;YACpB,QAAQ,CAAC,mBAAmB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,aAAa,CAAC,GAAG,EAAE,OAAO;YACxB,QAAQ,CAAC,wBAAwB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,OAAO;YAClB,QAAQ,CAAC,iBAAiB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @streetjs/storage — the Realtime integration bridge.
3
+ *
4
+ * This module broadcasts live upload-lifecycle events — `upload.started`,
5
+ * `upload.progress`, `upload.completed`, `upload.failed` — as an upload changes
6
+ * state, so connected clients can display live progress (Requirement 19.1).
7
+ * Each broadcast goes out through the minimal {@link RealtimeLike} shape
8
+ * declared in `types.ts` (any object exposing
9
+ * `broadcast(channel, event, payload)`), never through the concrete
10
+ * `@streetjs/realtime` package, so there is no hard dependency and no circular
11
+ * dependency (Requirements 19.2, 28.3). {@link RealtimeLike} is re-exported here
12
+ * for convenience; it is intentionally the single definition that lives in
13
+ * `types.ts`.
14
+ *
15
+ * **Never throws into the operation path.** Every broadcast is wrapped so that a
16
+ * synchronous throw or an asynchronous rejection from the underlying realtime
17
+ * layer is swallowed: a broadcast failure must never break the upload that
18
+ * triggered it (Requirement 19.3). Equally, when no realtime bridge is
19
+ * configured the facade holds no publisher and broadcasting is a complete no-op
20
+ * — uploads proceed unaffected (Requirement 19.3). This mirrors the
21
+ * graceful-degradation guarantee the Events and Queue bridges also uphold.
22
+ *
23
+ * The facade constructs a {@link StorageRealtimePublisher} via
24
+ * {@link bridgeStorageRealtime} only when `config.bridges?.realtime` is
25
+ * provided.
26
+ *
27
+ * _Requirements: 19.1, 19.2, 19.3, 28.3_
28
+ */
29
+ import type { RealtimeLike } from "../types.js";
30
+ export type { RealtimeLike } from "../types.js";
31
+ /**
32
+ * The channel every upload-lifecycle event is broadcast on. A single channel
33
+ * keeps the client subscription surface simple; the typed
34
+ * {@link StorageRealtimeEventName} distinguishes the state transitions, and the
35
+ * payload's `key` distinguishes the upload.
36
+ */
37
+ export declare const STORAGE_UPLOAD_CHANNEL: "storage.uploads";
38
+ /**
39
+ * The exhaustive set of upload-lifecycle event names the storage framework
40
+ * broadcasts (Requirement 19.1). Every upload state transition maps onto
41
+ * exactly one of these names.
42
+ */
43
+ export type StorageRealtimeEventName = "upload.started" | "upload.progress" | "upload.completed" | "upload.failed";
44
+ /**
45
+ * The payload broadcast with every upload-lifecycle event. It always carries the
46
+ * affected object `key` and, depending on the transition, optional progress
47
+ * counters or an error description.
48
+ */
49
+ export interface StorageRealtimeEventPayload {
50
+ /** The affected object key (always present). */
51
+ readonly key: string;
52
+ /** Bytes transferred so far, present on `upload.progress`. */
53
+ readonly bytesTransferred?: number;
54
+ /** Total expected bytes when known, present on `upload.progress`. */
55
+ readonly totalBytes?: number;
56
+ /** A human-readable failure reason, present on `upload.failed`. */
57
+ readonly error?: string;
58
+ }
59
+ /**
60
+ * The publisher the facade holds and calls at each upload state transition.
61
+ * Every method is fire-and-forget and guaranteed never to throw into the caller:
62
+ * the underlying broadcast is isolated so a failing (or absent) realtime layer
63
+ * cannot break an upload (Requirement 19.3).
64
+ */
65
+ export interface StorageRealtimePublisher {
66
+ /**
67
+ * Broadcast an already-named upload event with the given payload. Never
68
+ * throws. The typed convenience methods below are thin wrappers over this.
69
+ */
70
+ broadcast(event: StorageRealtimeEventName, payload: StorageRealtimeEventPayload): void;
71
+ /** Broadcast `upload.started` when an upload begins. */
72
+ started(key: string): void;
73
+ /** Broadcast `upload.progress` as bytes transfer. */
74
+ progress(key: string, bytesTransferred: number, totalBytes?: number): void;
75
+ /** Broadcast `upload.completed` when an upload finishes successfully. */
76
+ completed(key: string): void;
77
+ /** Broadcast `upload.failed` when an upload errors out. */
78
+ failed(key: string, error?: string): void;
79
+ }
80
+ /**
81
+ * Create a {@link StorageRealtimePublisher} that broadcasts upload-lifecycle
82
+ * events through the supplied structural {@link RealtimeLike} bridge.
83
+ *
84
+ * The returned publisher is what the facade wires into its streaming/resumable
85
+ * upload paths (`putStream`/`resumeUpload` → started/completed, and failed on
86
+ * error). Every method is guaranteed never to throw into the caller.
87
+ *
88
+ * ```ts
89
+ * const publisher = bridgeStorageRealtime(realtime);
90
+ * publisher.started("video.mp4"); // broadcasts "upload.started" — never throws
91
+ * publisher.completed("video.mp4"); // broadcasts "upload.completed" — never throws
92
+ * ```
93
+ */
94
+ export declare function bridgeStorageRealtime(realtime: RealtimeLike): StorageRealtimePublisher;
95
+ //# sourceMappingURL=realtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../src/integrations/realtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKhD,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAG,iBAA0B,CAAC;AAEjE;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAChC,gBAAgB,GAChB,iBAAiB,GACjB,kBAAkB,GAClB,eAAe,CAAC;AAEpB;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,qEAAqE;IACrE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,wBAAwB,EAAE,OAAO,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAEvF,wDAAwD;IACxD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,qDAAqD;IACrD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3E,yEAAyE;IACzE,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B,2DAA2D;IAC3D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AA0BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,wBAAwB,CAoBtF"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * @streetjs/storage — the Realtime integration bridge.
3
+ *
4
+ * This module broadcasts live upload-lifecycle events — `upload.started`,
5
+ * `upload.progress`, `upload.completed`, `upload.failed` — as an upload changes
6
+ * state, so connected clients can display live progress (Requirement 19.1).
7
+ * Each broadcast goes out through the minimal {@link RealtimeLike} shape
8
+ * declared in `types.ts` (any object exposing
9
+ * `broadcast(channel, event, payload)`), never through the concrete
10
+ * `@streetjs/realtime` package, so there is no hard dependency and no circular
11
+ * dependency (Requirements 19.2, 28.3). {@link RealtimeLike} is re-exported here
12
+ * for convenience; it is intentionally the single definition that lives in
13
+ * `types.ts`.
14
+ *
15
+ * **Never throws into the operation path.** Every broadcast is wrapped so that a
16
+ * synchronous throw or an asynchronous rejection from the underlying realtime
17
+ * layer is swallowed: a broadcast failure must never break the upload that
18
+ * triggered it (Requirement 19.3). Equally, when no realtime bridge is
19
+ * configured the facade holds no publisher and broadcasting is a complete no-op
20
+ * — uploads proceed unaffected (Requirement 19.3). This mirrors the
21
+ * graceful-degradation guarantee the Events and Queue bridges also uphold.
22
+ *
23
+ * The facade constructs a {@link StorageRealtimePublisher} via
24
+ * {@link bridgeStorageRealtime} only when `config.bridges?.realtime` is
25
+ * provided.
26
+ *
27
+ * _Requirements: 19.1, 19.2, 19.3, 28.3_
28
+ */
29
+ /**
30
+ * The channel every upload-lifecycle event is broadcast on. A single channel
31
+ * keeps the client subscription surface simple; the typed
32
+ * {@link StorageRealtimeEventName} distinguishes the state transitions, and the
33
+ * payload's `key` distinguishes the upload.
34
+ */
35
+ export const STORAGE_UPLOAD_CHANNEL = "storage.uploads";
36
+ /**
37
+ * Isolate a single broadcast call. A synchronous throw is caught; a returned
38
+ * promise has its rejection swallowed. Either way nothing propagates back to the
39
+ * upload that triggered the event, satisfying the "never throw into the
40
+ * operation path" guarantee (Requirement 19.3).
41
+ */
42
+ function safeBroadcast(realtime, event, payload) {
43
+ try {
44
+ const result = realtime.broadcast(STORAGE_UPLOAD_CHANNEL, event, payload);
45
+ if (result !== undefined && result !== null && typeof result.then === "function") {
46
+ // Fire-and-forget: absorb any asynchronous rejection.
47
+ result.then(undefined, () => {
48
+ /* swallow — a broadcast failure must not break the upload */
49
+ });
50
+ }
51
+ }
52
+ catch {
53
+ // swallow — a broadcast failure must not break the upload
54
+ }
55
+ }
56
+ /**
57
+ * Create a {@link StorageRealtimePublisher} that broadcasts upload-lifecycle
58
+ * events through the supplied structural {@link RealtimeLike} bridge.
59
+ *
60
+ * The returned publisher is what the facade wires into its streaming/resumable
61
+ * upload paths (`putStream`/`resumeUpload` → started/completed, and failed on
62
+ * error). Every method is guaranteed never to throw into the caller.
63
+ *
64
+ * ```ts
65
+ * const publisher = bridgeStorageRealtime(realtime);
66
+ * publisher.started("video.mp4"); // broadcasts "upload.started" — never throws
67
+ * publisher.completed("video.mp4"); // broadcasts "upload.completed" — never throws
68
+ * ```
69
+ */
70
+ export function bridgeStorageRealtime(realtime) {
71
+ const broadcast = (event, payload) => {
72
+ safeBroadcast(realtime, event, payload);
73
+ };
74
+ return {
75
+ broadcast,
76
+ started(key) {
77
+ broadcast("upload.started", { key });
78
+ },
79
+ progress(key, bytesTransferred, totalBytes) {
80
+ broadcast("upload.progress", { key, bytesTransferred, totalBytes });
81
+ },
82
+ completed(key) {
83
+ broadcast("upload.completed", { key });
84
+ },
85
+ failed(key, error) {
86
+ broadcast("upload.failed", { key, error });
87
+ },
88
+ };
89
+ }
90
+ //# sourceMappingURL=realtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../../src/integrations/realtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AASH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAA0B,CAAC;AAuDjE;;;;;GAKG;AACH,SAAS,aAAa,CACpB,QAAsB,EACtB,KAA+B,EAC/B,OAAoC;IAEpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,sBAAsB,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1E,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,OAAQ,MAAwB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACpG,sDAAsD;YACrD,MAAwB,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;gBAC7C,6DAA6D;YAC/D,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;IAC5D,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAsB;IAC1D,MAAM,SAAS,GAAG,CAAC,KAA+B,EAAE,OAAoC,EAAQ,EAAE;QAChG,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC,CAAC;IAEF,OAAO;QACL,SAAS;QACT,OAAO,CAAC,GAAG;YACT,SAAS,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,CAAC;QACD,QAAQ,CAAC,GAAG,EAAE,gBAAgB,EAAE,UAAU;YACxC,SAAS,CAAC,iBAAiB,EAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,SAAS,CAAC,GAAG;YACX,SAAS,CAAC,kBAAkB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,CAAC,GAAG,EAAE,KAAK;YACf,SAAS,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * @streetjs/storage — the lifecycle engine.
3
+ *
4
+ * Lifecycle rules act on objects automatically based on their age or state, so
5
+ * stored objects are cleaned up, archived, or tiered over time (Requirement
6
+ * 13). {@link LifecycleEngine} evaluates a single {@link LifecycleRule} and
7
+ * applies its action to every qualifying object in a **provider-agnostic** way:
8
+ *
9
+ * - When the backing {@link StorageDriver} implements the optional native
10
+ * `lifecycle` capability, the engine delegates evaluation to the driver so a
11
+ * provider with first-class lifecycle policies (e.g. S3 lifecycle
12
+ * configuration) is used directly.
13
+ * - Otherwise the engine **simulates** the rule over the mandatory driver
14
+ * primitives (`list`/`stat`/`get`/`put`/`delete`). It enumerates candidate
15
+ * keys with `list`, reads each object's `createdAt` with `stat`, computes the
16
+ * object's age relative to the injected {@link Clock}, and applies the rule's
17
+ * action to the objects whose age meets the rule's threshold. This is what
18
+ * lets the zero-dependency drivers simulate lifecycle entirely in memory /
19
+ * over the local filesystem (Requirement 13.3).
20
+ *
21
+ * Supported rule types (Requirement 13.1):
22
+ * - `delete-after-days` — delete objects older than `days`.
23
+ * - `archive-after-months` — archive objects older than `months` by relocating
24
+ * them under the reserved {@link ARCHIVE_KEY_PREFIX}.
25
+ * - `expire-temp-uploads` — delete transient multipart-part / resumable-session
26
+ * state older than `afterMs` (the reserved temp-upload key spaces).
27
+ * - `move-to-cold` — relocate objects older than `afterDays` under `coldPrefix`.
28
+ *
29
+ * **Exactly-once (Requirement 13.2).** Each action removes the qualifying object
30
+ * from the space that a subsequent evaluation scans: `delete`/`expire` remove
31
+ * the object outright, and `archive`/`move-to-cold` relocate it to a prefix that
32
+ * the scan excludes (the reserved archive prefix, or `coldPrefix`). Because the
33
+ * relocated copy is written with a fresh `createdAt` at the evaluation instant,
34
+ * it is also too young to re-qualify at the same `now`. The net effect is that a
35
+ * second evaluation produces no further action on an already-actioned object.
36
+ *
37
+ * The module depends only on the driver contract, the shared type surface, the
38
+ * metadata layer, and the core `Clock`, keeping the dependency direction
39
+ * acyclic. Event publication for applied actions (Requirement 13.4) is wired
40
+ * separately by the Events bridge (task 21.1); this engine only performs the
41
+ * actions and returns their {@link LifecycleOutcome} descriptors.
42
+ *
43
+ * _Requirements: 13.1, 13.2, 13.3_
44
+ */
45
+ import { type Clock } from "streetjs";
46
+ import type { StorageDriver } from "./driver.js";
47
+ import type { LifecycleOutcome, LifecycleRule } from "./types.js";
48
+ /**
49
+ * Reserved key prefix under which objects archived by an `archive-after-months`
50
+ * rule are relocated. An archived `<key>` lives at `${ARCHIVE_KEY_PREFIX}<key>`.
51
+ * The prefix is excluded from every lifecycle scan so an archived object is
52
+ * never re-actioned (Requirement 13.2).
53
+ */
54
+ export declare const ARCHIVE_KEY_PREFIX = ".archive/";
55
+ /** Options for constructing a {@link LifecycleEngine}. */
56
+ export interface LifecycleEngineOptions {
57
+ /** The driver every action is delegated to or simulated over. */
58
+ readonly driver: StorageDriver;
59
+ /**
60
+ * Injected clock used to compute object age at evaluation time. Default
61
+ * `systemClock`, so time is deterministic in tests (Requirement 13.3).
62
+ */
63
+ readonly clock?: Clock;
64
+ }
65
+ /**
66
+ * Provider-agnostic lifecycle engine built on the driver contract.
67
+ *
68
+ * A single instance is held by the facade and bound to one {@link StorageDriver}
69
+ * for its lifetime, so the native-vs-simulated decision (based on whether the
70
+ * driver exposes a `lifecycle` capability) is stable across every call.
71
+ */
72
+ export declare class LifecycleEngine {
73
+ /** The driver every action is delegated to or simulated over. */
74
+ private readonly driver;
75
+ /** Injected clock used to compute object age at evaluation time. */
76
+ private readonly clock;
77
+ constructor(options: LifecycleEngineOptions);
78
+ /** The driver's native lifecycle capability, when present. */
79
+ private get native();
80
+ /**
81
+ * Evaluate `rule` against the current object set and apply its action to every
82
+ * qualifying object, returning one {@link LifecycleOutcome} per actioned
83
+ * object (Requirements 13.1, 13.2). Object age is measured relative to `now`,
84
+ * which defaults to the injected clock. When the driver exposes a native
85
+ * `lifecycle` capability the evaluation is delegated to it; otherwise the rule
86
+ * is simulated over the driver primitives.
87
+ */
88
+ apply(rule: LifecycleRule, now?: number): Promise<LifecycleOutcome[]>;
89
+ /**
90
+ * Delete every managed object under `prefix` whose age is at least
91
+ * `thresholdMs`. The deletion removes the object from the scanned space, so a
92
+ * repeated evaluation finds nothing further to delete (Requirement 13.2).
93
+ */
94
+ private applyDelete;
95
+ /**
96
+ * Archive every managed object under `prefix` whose age is at least
97
+ * `thresholdMs` by relocating it under {@link ARCHIVE_KEY_PREFIX}. The archive
98
+ * prefix is excluded from the scan, so an archived object is never re-archived
99
+ * (Requirement 13.2).
100
+ */
101
+ private applyArchive;
102
+ /**
103
+ * Expire (delete) transient upload state older than `afterMs` across the
104
+ * reserved temp-upload key spaces (multipart parts and resumable session
105
+ * bytes). Because expiration deletes the state, a repeated evaluation finds
106
+ * nothing further to expire (Requirement 13.2).
107
+ */
108
+ private applyExpire;
109
+ /**
110
+ * Relocate every managed object under `prefix` whose age is at least
111
+ * `thresholdMs` to `${coldPrefix}<key>`. Keys already residing under
112
+ * `coldPrefix` are excluded from the scan, so a repeated evaluation does not
113
+ * move an already-tiered object again (Requirement 13.2).
114
+ */
115
+ private applyMoveToCold;
116
+ /**
117
+ * List candidate keys under `prefix`, keep those accepted by `accept`, and
118
+ * return the subset whose age (`now - createdAt`, read via `stat`) is at least
119
+ * `thresholdMs`. Keys that vanish between `list` and `stat` are skipped.
120
+ */
121
+ private collectQualifying;
122
+ /**
123
+ * Move the object at `sourceKey` to `destinationKey` over the driver
124
+ * primitives: the content and preserved write-time metadata are written to the
125
+ * destination and the source is then removed. Returns `false` without writing
126
+ * when the source has vanished.
127
+ */
128
+ private relocate;
129
+ /**
130
+ * Report whether `key` is an application-visible object (as opposed to
131
+ * internal bookkeeping such as version snapshots, multipart parts, resumable
132
+ * session bytes, or already-archived copies). Age-based rules act only on
133
+ * managed keys.
134
+ */
135
+ private isManagedKey;
136
+ }
137
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAEnD,OAAO,KAAK,EAAuB,aAAa,EAAE,MAAM,aAAa,CAAC;AAEtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAalE;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAwB9C,0DAA0D;AAC1D,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED;;;;;;GAMG;AACH,qBAAa,eAAe;IAC1B,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IAEvC,oEAAoE;IACpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;gBAElB,OAAO,EAAE,sBAAsB;IAK3C,8DAA8D;IAC9D,OAAO,KAAK,MAAM,GAEjB;IAED;;;;;;;OAOG;IACG,KAAK,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,GAAE,MAAqB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAsBzF;;;;OAIG;YACW,WAAW;IAgBzB;;;;;OAKG;YACW,YAAY;IAkB1B;;;;;OAKG;YACW,WAAW;IAczB;;;;;OAKG;YACW,eAAe;IAsB7B;;;;OAIG;YACW,iBAAiB;IAuB/B;;;;;OAKG;YACW,QAAQ;IAUtB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;CAGrB"}