@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,240 @@
1
+ /**
2
+ * @streetjs/storage — CloudflareR2Driver (submodule `@streetjs/storage/r2`).
3
+ *
4
+ * Cloudflare R2 speaks the S3 API, so this driver is a thin **endpoint/credential
5
+ * specialization** of the shared S3-style base ({@link createS3StyleDriver} in
6
+ * `s3-base.ts`). It differs from `s3.ts` only in how the underlying client is
7
+ * built — R2 uses an account-specific endpoint
8
+ * (`https://<accountId>.r2.cloudflarestorage.com`) with `region: "auto"` — never
9
+ * in how the {@link StorageDriver} contract is satisfied.
10
+ *
11
+ * ## Two ways to obtain a driver
12
+ *
13
+ * - {@link createCloudflareR2Driver} wraps an **already-constructed, injected**
14
+ * structural {@link S3ClientLike} and returns a driver synchronously. This is
15
+ * the SDK-free path: no provider SDK is touched, so it is fully testable with
16
+ * an in-memory fake and needs no `@aws-sdk/*` install.
17
+ * - {@link connectCloudflareR2Driver} **builds its own client** from R2
18
+ * connection config. It resolves the S3-compatible SDK through a **lazy
19
+ * dynamic `import()` performed inside the function** (never at module top
20
+ * level), so the optional peer dependency is only required when this path is
21
+ * actually used. If the SDK is not installed and no client was injected, it
22
+ * throws {@link StorageConfigError} (Requirement 1.5).
23
+ *
24
+ * ## SDK isolation (Requirements 2.1, 3.3)
25
+ *
26
+ * This module imports **no provider SDK at the top level** — only this package's
27
+ * own base/types/errors. The AWS S3 SDK (which R2 uses) is referenced solely via
28
+ * a dynamic `import()` with a non-literal specifier inside
29
+ * {@link connectCloudflareR2Driver}, so `tsc` never requires the SDK to be
30
+ * present and `streetjs` stays the only runtime dependency. This driver is a
31
+ * submodule-only export (`./r2` → `dist/drivers/r2.js`); it is intentionally not
32
+ * re-exported from the package's main `index.ts`.
33
+ *
34
+ * _Requirements: 2.1, 2.3, 3.3_
35
+ */
36
+ import { StorageConfigError } from "../errors.js";
37
+ import { createS3StyleDriver, S3StyleDriver, } from "./s3-base.js";
38
+ /** The stable driver name surfaced as {@link StorageDriver.name} for R2. */
39
+ const R2_DRIVER_NAME = "r2";
40
+ /**
41
+ * The CloudflareR2 {@link StorageDriver}: the shared S3-style base pinned to the
42
+ * `"r2"` provider name. Construction is identical to the base — supply an
43
+ * {@link S3ClientLike} — the only difference is the fixed name.
44
+ */
45
+ export class CloudflareR2Driver extends S3StyleDriver {
46
+ constructor(client, options = {}) {
47
+ super(client, { ...options, name: R2_DRIVER_NAME });
48
+ }
49
+ }
50
+ /**
51
+ * Wrap an injected {@link S3ClientLike} as an R2 driver, delegating to
52
+ * {@link createS3StyleDriver} with the name `"r2"`. Synchronous and SDK-free:
53
+ * the caller supplies the client, so no provider SDK is resolved here.
54
+ */
55
+ export function createCloudflareR2Driver(client, options = {}) {
56
+ return createS3StyleDriver(client, { ...options, name: R2_DRIVER_NAME });
57
+ }
58
+ /**
59
+ * Build an R2 driver that owns its client, resolving the S3-compatible SDK
60
+ * lazily.
61
+ *
62
+ * The SDK is loaded through a dynamic `import()` with a non-literal specifier so
63
+ * it is never a static/top-level dependency: `tsc` does not require it to be
64
+ * installed, and it is only resolved when this function runs. When the SDK
65
+ * cannot be resolved, a {@link StorageConfigError} is thrown (Requirement 1.5) —
66
+ * callers that cannot install the SDK should use {@link createCloudflareR2Driver}
67
+ * with their own {@link S3ClientLike} instead.
68
+ */
69
+ export async function connectCloudflareR2Driver(config) {
70
+ const { accountId, bucket, accessKeyId, secretAccessKey } = config;
71
+ if (!accountId || !bucket || !accessKeyId || !secretAccessKey) {
72
+ throw new StorageConfigError("CloudflareR2 requires accountId, bucket, accessKeyId, and secretAccessKey.", { provider: R2_DRIVER_NAME });
73
+ }
74
+ const endpoint = config.endpoint ?? `https://${accountId}.r2.cloudflarestorage.com`;
75
+ const region = config.region ?? "auto";
76
+ // Lazy, non-literal dynamic import so the S3 SDK stays an optional peer that
77
+ // `tsc` never resolves statically and Node only loads on this path.
78
+ const specifier = "@aws-sdk/client-s3";
79
+ let sdk;
80
+ try {
81
+ sdk = (await import(specifier));
82
+ }
83
+ catch (cause) {
84
+ throw new StorageConfigError('CloudflareR2 driver requires the optional peer dependency "@aws-sdk/client-s3". ' +
85
+ "Install it, or inject your own S3ClientLike via createCloudflareR2Driver().", { provider: R2_DRIVER_NAME, cause });
86
+ }
87
+ const s3 = new sdk.S3Client({
88
+ region,
89
+ endpoint,
90
+ credentials: { accessKeyId, secretAccessKey },
91
+ forcePathStyle: true,
92
+ });
93
+ const client = adaptAwsS3Client(s3, sdk, bucket);
94
+ return createCloudflareR2Driver(client, {
95
+ clock: config.clock,
96
+ capabilities: config.capabilities,
97
+ });
98
+ }
99
+ // ── AWS S3 SDK adapter ─────────────────────────────────────────────────────────
100
+ /**
101
+ * Adapt an AWS S3 v3 client into the structural {@link S3ClientLike} the base
102
+ * depends on, binding every call to `bucket`. Only the methods the base uses are
103
+ * mapped; the AWS response shapes are narrowed through the local structural
104
+ * types below so this module never imports concrete SDK types.
105
+ */
106
+ function adaptAwsS3Client(s3, sdk, bucket) {
107
+ return {
108
+ async putObject(input) {
109
+ const res = await s3.send(new sdk.PutObjectCommand({
110
+ Bucket: bucket,
111
+ Key: input.key,
112
+ Body: input.body,
113
+ ContentType: input.contentType,
114
+ Metadata: input.metadata,
115
+ }));
116
+ return { etag: res.ETag ?? "" };
117
+ },
118
+ async getObject(input) {
119
+ let res;
120
+ try {
121
+ res = await s3.send(new sdk.GetObjectCommand({ Bucket: bucket, Key: input.key }));
122
+ }
123
+ catch (error) {
124
+ if (isNotFound(error)) {
125
+ return null;
126
+ }
127
+ throw error;
128
+ }
129
+ const body = res.Body ? await res.Body.transformToByteArray() : new Uint8Array(0);
130
+ return {
131
+ body,
132
+ contentType: res.ContentType,
133
+ etag: res.ETag,
134
+ size: res.ContentLength ?? body.byteLength,
135
+ lastModified: toEpochMs(res.LastModified),
136
+ metadata: res.Metadata,
137
+ };
138
+ },
139
+ async deleteObject(input) {
140
+ await s3.send(new sdk.DeleteObjectCommand({ Bucket: bucket, Key: input.key }));
141
+ },
142
+ async listObjects(input) {
143
+ const res = await s3.send(new sdk.ListObjectsV2Command({
144
+ Bucket: bucket,
145
+ Prefix: input.prefix,
146
+ MaxKeys: input.limit,
147
+ ContinuationToken: input.cursor,
148
+ Delimiter: input.delimiter === true ? "/" : undefined,
149
+ }));
150
+ const contents = res.Contents ?? [];
151
+ return contents.map((item) => ({
152
+ key: item.Key ?? "",
153
+ size: item.Size ?? 0,
154
+ updatedAt: toEpochMs(item.LastModified) ?? 0,
155
+ }));
156
+ },
157
+ async headObject(input) {
158
+ let res;
159
+ try {
160
+ res = await s3.send(new sdk.HeadObjectCommand({ Bucket: bucket, Key: input.key }));
161
+ }
162
+ catch (error) {
163
+ if (isNotFound(error)) {
164
+ return null;
165
+ }
166
+ throw error;
167
+ }
168
+ return {
169
+ contentType: res.ContentType,
170
+ etag: res.ETag,
171
+ size: res.ContentLength,
172
+ lastModified: toEpochMs(res.LastModified),
173
+ metadata: res.Metadata,
174
+ };
175
+ },
176
+ async createMultipartUpload(input) {
177
+ const res = await s3.send(new sdk.CreateMultipartUploadCommand({
178
+ Bucket: bucket,
179
+ Key: input.key,
180
+ ContentType: input.contentType,
181
+ Metadata: input.metadata,
182
+ }));
183
+ return { uploadId: res.UploadId ?? "" };
184
+ },
185
+ async uploadPart(input) {
186
+ const res = await s3.send(new sdk.UploadPartCommand({
187
+ Bucket: bucket,
188
+ Key: input.key,
189
+ UploadId: input.uploadId,
190
+ PartNumber: input.partNumber,
191
+ Body: input.body,
192
+ }));
193
+ return { etag: res.ETag ?? "" };
194
+ },
195
+ async completeMultipartUpload(input) {
196
+ const res = await s3.send(new sdk.CompleteMultipartUploadCommand({
197
+ Bucket: bucket,
198
+ Key: input.key,
199
+ UploadId: input.uploadId,
200
+ MultipartUpload: {
201
+ Parts: input.parts.map((part) => ({
202
+ PartNumber: part.partNumber,
203
+ ETag: part.etag,
204
+ })),
205
+ },
206
+ }));
207
+ return { etag: res.ETag ?? "" };
208
+ },
209
+ async abortMultipartUpload(input) {
210
+ await s3.send(new sdk.AbortMultipartUploadCommand({
211
+ Bucket: bucket,
212
+ Key: input.key,
213
+ UploadId: input.uploadId,
214
+ }));
215
+ },
216
+ };
217
+ }
218
+ /**
219
+ * Recognize the "no such key / not found" conditions the S3 API reports so
220
+ * `getObject`/`headObject` can return `null` (Requirement 4.2/4.10) rather than
221
+ * throwing. Matches the SDK's error `name` and the HTTP 404 status.
222
+ */
223
+ function isNotFound(error) {
224
+ if (typeof error !== "object" || error === null) {
225
+ return false;
226
+ }
227
+ const record = error;
228
+ if (record.name === "NoSuchKey" || record.name === "NotFound") {
229
+ return true;
230
+ }
231
+ if (record.Code === "NoSuchKey" || record.Code === "NotFound") {
232
+ return true;
233
+ }
234
+ return record.$metadata?.httpStatusCode === 404;
235
+ }
236
+ /** Convert an SDK `Date` (or undefined) to epoch milliseconds. */
237
+ function toEpochMs(value) {
238
+ return value instanceof Date ? value.getTime() : undefined;
239
+ }
240
+ //# sourceMappingURL=r2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2.js","sourceRoot":"","sources":["../../src/drivers/r2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAKH,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,mBAAmB,EACnB,aAAa,GASd,MAAM,cAAc,CAAC;AAEtB,4EAA4E;AAC5E,MAAM,cAAc,GAAG,IAAI,CAAC;AAuC5B;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IACnD,YAAY,MAAoB,EAAE,UAAqC,EAAE;QACvE,KAAK,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;IACtD,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAAoB,EACpB,UAAqC,EAAE;IAEvC,OAAO,mBAAmB,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,MAA0B;IAE1B,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC;IACnE,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,EAAE,CAAC;QAC9D,MAAM,IAAI,kBAAkB,CAC1B,4EAA4E,EAC5E,EAAE,QAAQ,EAAE,cAAc,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GACZ,MAAM,CAAC,QAAQ,IAAI,WAAW,SAAS,2BAA2B,CAAC;IACrE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC;IAEvC,6EAA6E;IAC7E,oEAAoE;IACpE,MAAM,SAAS,GAAG,oBAAoB,CAAC;IACvC,IAAI,GAAgB,CAAC;IACrB,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAA2B,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,kBAAkB,CAC1B,kFAAkF;YAChF,6EAA6E,EAC/E,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,CACpC,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM;QACN,QAAQ;QACR,WAAW,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE;QAC7C,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,wBAAwB,CAAC,MAAM,EAAE;QACtC,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,YAAY,EAAE,MAAM,CAAC,YAAY;KAClC,CAAC,CAAC;AACL,CAAC;AAED,kFAAkF;AAElF;;;;;GAKG;AACH,SAAS,gBAAgB,CACvB,EAAe,EACf,GAAgB,EAChB,MAAc;IAEd,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,KAAuB;YACrC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CACvB,IAAI,GAAG,CAAC,gBAAgB,CAAC;gBACvB,MAAM,EAAE,MAAM;gBACd,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC,CACH,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAClC,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,KAA+B;YAC7C,IAAI,GAAyB,CAAC;YAC9B,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CACjB,IAAI,GAAG,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAC7D,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtB,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;YAClF,OAAO;gBACL,IAAI;gBACJ,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,IAAI,EAAE,GAAG,CAAC,aAAa,IAAI,IAAI,CAAC,UAAU;gBAC1C,YAAY,EAAE,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC;gBACzC,QAAQ,EAAE,GAAG,CAAC,QAAQ;aACvB,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,KAA+B;YAChD,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACjF,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,KAAkB;YAClC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CACvB,IAAI,GAAG,CAAC,oBAAoB,CAAC;gBAC3B,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,KAAK,CAAC,KAAK;gBACpB,iBAAiB,EAAE,KAAK,CAAC,MAAM;gBAC/B,SAAS,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;aACtD,CAAC,CACH,CAAC;YACF,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;YACpC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC7B,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE;gBACnB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;gBACpB,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;aAC7C,CAAC,CAAC,CAAC;QACN,CAAC;QAED,KAAK,CAAC,UAAU,CACd,KAA+B;YAE/B,IAAI,GAA0B,CAAC;YAC/B,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CACjB,IAAI,GAAG,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAC9D,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtB,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,OAAO;gBACL,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,IAAI,EAAE,GAAG,CAAC,aAAa;gBACvB,YAAY,EAAE,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC;gBACzC,QAAQ,EAAE,GAAG,CAAC,QAAQ;aACvB,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,qBAAqB,CAAC,KAI3B;YACC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CACvB,IAAI,GAAG,CAAC,4BAA4B,CAAC;gBACnC,MAAM,EAAE,MAAM;gBACd,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC,CACH,CAAC;YACF,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC1C,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,KAKhB;YACC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CACvB,IAAI,GAAG,CAAC,iBAAiB,CAAC;gBACxB,MAAM,EAAE,MAAM;gBACd,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB,CAAC,CACH,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAClC,CAAC;QAED,KAAK,CAAC,uBAAuB,CAAC,KAI7B;YACC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CACvB,IAAI,GAAG,CAAC,8BAA8B,CAAC;gBACrC,MAAM,EAAE,MAAM;gBACd,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,eAAe,EAAE;oBACf,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;wBAChC,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;qBAChB,CAAC,CAAC;iBACJ;aACF,CAAC,CACH,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAClC,CAAC;QAED,KAAK,CAAC,oBAAoB,CAAC,KAG1B;YACC,MAAM,EAAE,CAAC,IAAI,CACX,IAAI,GAAG,CAAC,2BAA2B,CAAC;gBAClC,MAAM,EAAE,MAAM;gBACd,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC,CACH,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAG,KAId,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC,SAAS,EAAE,cAAc,KAAK,GAAG,CAAC;AAClD,CAAC;AAED,kEAAkE;AAClE,SAAS,SAAS,CAAC,KAAuB;IACxC,OAAO,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * @streetjs/storage — the shared S3-style driver base and {@link S3ClientLike}.
3
+ *
4
+ * S3-compatible providers (Amazon S3, Cloudflare R2, MinIO, and the Backblaze B2
5
+ * S3 API) share one wire shape: a small set of object operations
6
+ * (`putObject`/`getObject`/`deleteObject`/`listObjects`) plus optional
7
+ * multipart and presign calls. This module captures that shape as the structural
8
+ * {@link S3ClientLike} interface and maps the {@link StorageDriver} contract onto
9
+ * it, so `s3.ts`, `r2.ts`, `minio.ts`, and `backblaze.ts` (tasks 28.2–28.5) only
10
+ * differ in how they build/configure the client, never in how the contract is
11
+ * satisfied.
12
+ *
13
+ * ## SDK isolation (Requirements 3.1, 3.3)
14
+ *
15
+ * This module imports **no provider SDK** at the top level — only Node built-ins,
16
+ * `streetjs` (for the injected {@link Clock}), and this package's own type
17
+ * surface. The base accepts an **injected** {@link S3ClientLike}; it never
18
+ * resolves an SDK itself. The concrete submodules that *can* construct their own
19
+ * client do so with a **lazy dynamic `import()`** performed inside that submodule
20
+ * at construction time, so the optional peer SDK is resolved only when that
21
+ * submodule is actually imported. `streetjs` therefore stays the only runtime
22
+ * dependency.
23
+ *
24
+ * ## Capability delegation (Requirement 2.3)
25
+ *
26
+ * The base implements the **mandatory primitives** (`put`/`get`/`exists`/
27
+ * `delete`/`stat`/`list`/`putStream`/`getStream`) by mapping onto
28
+ * {@link S3ClientLike}, producing every {@link StorageObjectMetadata} through the
29
+ * shared metadata layer ({@link buildObjectMetadata}) so the field set is
30
+ * identical to Memory/Local, and reporting a missing key consistently
31
+ * ({@link MaybeObject} `{ found: false }` for `get`, `null` for `stat`,
32
+ * {@link NotFoundError} for `getStream`).
33
+ *
34
+ * Advanced capabilities are **delegated to the client when available, otherwise
35
+ * left `undefined` so the facade simulates them over the primitives**
36
+ * (Requirement 2, keeping behavior identical across providers):
37
+ *
38
+ * - **Multipart** is wired only when the client exposes the full SDK-shaped
39
+ * multipart method set; the base adapts those calls into a
40
+ * {@link MultipartCapability}, tracking the `uploadId → key` mapping the S3 API
41
+ * requires.
42
+ * - **Versioning / lifecycle / signed URLs** are delegated only when a native
43
+ * capability object is supplied through `options.capabilities`; otherwise they
44
+ * are left `undefined`. (A provider's presigned URLs are verified by the
45
+ * provider, not locally, so the base does not synthesize a
46
+ * {@link SignedUrlCapability} from a bare `presignUrl` — the facade's HMAC
47
+ * simulation is used instead unless a full native capability is injected.)
48
+ *
49
+ * _Requirements: 2.3, 3.1, 3.3_
50
+ */
51
+ import { type Clock } from "streetjs";
52
+ import type { MaybeObject, MultipartCapability, NodeReadable, StorageDriver, VersioningCapability, SignedUrlCapability, LifecycleCapability } from "../driver.js";
53
+ import type { ListOptions, StorageListItem, StorageObjectMetadata, WriteMetadata } from "../types.js";
54
+ /** Input to {@link S3ClientLike.putObject}. */
55
+ export interface S3PutObjectInput {
56
+ readonly key: string;
57
+ readonly body: Uint8Array;
58
+ readonly contentType?: string;
59
+ /** Provider "user metadata" (string→string), used to carry typed metadata. */
60
+ readonly metadata?: Record<string, string>;
61
+ }
62
+ /** Result of {@link S3ClientLike.putObject}. */
63
+ export interface S3PutObjectOutput {
64
+ readonly etag: string;
65
+ }
66
+ /** Result of {@link S3ClientLike.getObject} (the object body plus attributes). */
67
+ export interface S3GetObjectOutput {
68
+ readonly body: Uint8Array;
69
+ readonly contentType?: string;
70
+ readonly etag?: string;
71
+ readonly size?: number;
72
+ /** Last-modified time as epoch ms. */
73
+ readonly lastModified?: number;
74
+ readonly metadata?: Record<string, string>;
75
+ }
76
+ /** Result of {@link S3ClientLike.headObject} (attributes only, no body). */
77
+ export interface S3HeadObjectOutput {
78
+ readonly contentType?: string;
79
+ readonly etag?: string;
80
+ readonly size?: number;
81
+ readonly lastModified?: number;
82
+ readonly metadata?: Record<string, string>;
83
+ }
84
+ /** A single entry returned by {@link S3ClientLike.listObjects}. */
85
+ export interface S3ListItem {
86
+ readonly key: string;
87
+ readonly size: number;
88
+ /** Last-modified time as epoch ms. */
89
+ readonly updatedAt: number;
90
+ }
91
+ /** Options passed to {@link S3ClientLike.listObjects}. */
92
+ export interface S3ListInput {
93
+ readonly prefix: string;
94
+ readonly limit?: number;
95
+ readonly cursor?: string;
96
+ readonly delimiter?: boolean;
97
+ }
98
+ /**
99
+ * The **minimal, SDK-shaped structural interface** an S3-style driver depends on.
100
+ *
101
+ * It describes just the provider calls the driver needs — never any concrete
102
+ * SDK type — so the actual SDK stays an optional peer concern of the consumer
103
+ * (Requirement 3.1). The four object operations are mandatory; `headObject`,
104
+ * the multipart method set, and `presignUrl` are optional and unlock the
105
+ * corresponding native paths when present.
106
+ */
107
+ export interface S3ClientLike {
108
+ /** Store `body` under `key` with optional content type and user metadata. */
109
+ putObject(input: S3PutObjectInput): Promise<S3PutObjectOutput>;
110
+ /** Fetch the object at `key`, or `null` when it does not exist. */
111
+ getObject(input: {
112
+ readonly key: string;
113
+ }): Promise<S3GetObjectOutput | null>;
114
+ /** Delete the object at `key` (a no-op when it is already absent). */
115
+ deleteObject(input: {
116
+ readonly key: string;
117
+ }): Promise<void>;
118
+ /** List objects whose key begins with `prefix`. */
119
+ listObjects(input: S3ListInput): Promise<readonly S3ListItem[]>;
120
+ /** Fetch object attributes without the body, or `null` when absent (optional). */
121
+ headObject?(input: {
122
+ readonly key: string;
123
+ }): Promise<S3HeadObjectOutput | null>;
124
+ createMultipartUpload?(input: {
125
+ readonly key: string;
126
+ readonly contentType?: string;
127
+ readonly metadata?: Record<string, string>;
128
+ }): Promise<{
129
+ readonly uploadId: string;
130
+ }>;
131
+ uploadPart?(input: {
132
+ readonly key: string;
133
+ readonly uploadId: string;
134
+ readonly partNumber: number;
135
+ readonly body: Uint8Array;
136
+ }): Promise<{
137
+ readonly etag: string;
138
+ }>;
139
+ completeMultipartUpload?(input: {
140
+ readonly key: string;
141
+ readonly uploadId: string;
142
+ readonly parts: readonly {
143
+ readonly partNumber: number;
144
+ readonly etag: string;
145
+ }[];
146
+ }): Promise<{
147
+ readonly etag: string;
148
+ }>;
149
+ abortMultipartUpload?(input: {
150
+ readonly key: string;
151
+ readonly uploadId: string;
152
+ }): Promise<void>;
153
+ /**
154
+ * Mint a provider presigned URL for `key` (optional). Consumed by concrete
155
+ * provider drivers that expose native presigned URLs; the base does not build
156
+ * a {@link SignedUrlCapability} from it because provider URLs are verified by
157
+ * the provider, not locally.
158
+ */
159
+ presignUrl?(input: {
160
+ readonly key: string;
161
+ readonly op: "GET" | "PUT" | "DELETE";
162
+ readonly expiresInMs: number;
163
+ }): Promise<string>;
164
+ }
165
+ /** Native capability objects a provider driver may inject for delegation. */
166
+ export interface S3NativeCapabilities {
167
+ readonly versioning?: VersioningCapability;
168
+ readonly lifecycle?: LifecycleCapability;
169
+ readonly signedUrl?: SignedUrlCapability;
170
+ }
171
+ /** Options for {@link createS3StyleDriver} / {@link S3StyleDriver}. */
172
+ export interface S3StyleDriverOptions {
173
+ /** Stable driver name surfaced as {@link StorageDriver.name}. Default `"s3"`. */
174
+ readonly name?: string;
175
+ /** Injected clock for deterministic timestamps in tests. Default `systemClock`. */
176
+ readonly clock?: Clock;
177
+ /**
178
+ * Native capability objects to delegate to. Any capability omitted here (and
179
+ * not derivable from the client) is left `undefined` so the facade simulates
180
+ * it over the primitives.
181
+ */
182
+ readonly capabilities?: S3NativeCapabilities;
183
+ }
184
+ /**
185
+ * Maps the {@link StorageDriver} contract onto an injected {@link S3ClientLike}.
186
+ *
187
+ * This class is provider-agnostic: every S3-compatible driver (S3, R2, MinIO,
188
+ * Backblaze) is this base with a differently-constructed client. It imports no
189
+ * provider SDK; the client is supplied by the caller (typically a submodule that
190
+ * lazily `import()`s its SDK).
191
+ */
192
+ export declare class S3StyleDriver implements StorageDriver {
193
+ readonly name: string;
194
+ private readonly client;
195
+ private readonly clock;
196
+ /** Tracks the `key` for each in-flight multipart `uploadId` (S3 needs both). */
197
+ private readonly multipartKeys;
198
+ multipart?: MultipartCapability;
199
+ versioning?: VersioningCapability;
200
+ signedUrl?: SignedUrlCapability;
201
+ lifecycle?: LifecycleCapability;
202
+ constructor(client: S3ClientLike, options?: S3StyleDriverOptions);
203
+ /**
204
+ * Store `bytes` under `key`, computing size and sha-256 checksum locally and
205
+ * taking timestamps from the injected clock. When overwriting, the original
206
+ * `createdAt` is preserved (a preceding attribute read). The typed metadata is
207
+ * encoded into the provider's user-metadata map so it round-trips on read
208
+ * (Requirements 4.1, 10.1, 10.2).
209
+ */
210
+ put(key: string, bytes: Uint8Array, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
211
+ /**
212
+ * Read the object at `key`, returning a discriminated {@link MaybeObject} so
213
+ * absence is reported rather than thrown (Requirements 4.2, 2.4). Metadata is
214
+ * rebuilt from the provider attributes and encoded user metadata via the
215
+ * shared metadata layer.
216
+ */
217
+ get(key: string): Promise<MaybeObject>;
218
+ /** Report whether an object is stored under `key` (Requirement 4.3). */
219
+ exists(key: string): Promise<boolean>;
220
+ /** Delete the object at `key`; deleting a missing key is a no-op (Requirement 4.4). */
221
+ delete(key: string): Promise<void>;
222
+ /**
223
+ * Return the metadata for `key` without its content, or `null` when absent
224
+ * (Requirement 4.10). Uses `headObject` when available, else falls back to a
225
+ * body fetch.
226
+ */
227
+ stat(key: string): Promise<StorageObjectMetadata | null>;
228
+ /** List objects whose key begins with `prefix` (Requirement 4.9). */
229
+ list(prefix: string, options?: ListOptions): Promise<StorageListItem[]>;
230
+ /**
231
+ * Consume a Node {@link Readable} and persist the assembled bytes under `key`
232
+ * with the same computed metadata as {@link put} (Requirement 5.1). Chunks are
233
+ * drained through a `pipeline` (correct backpressure and error propagation),
234
+ * then handed to {@link put}.
235
+ */
236
+ putStream(key: string, stream: NodeReadable, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
237
+ /**
238
+ * Return a Node {@link Readable} of the stored bytes at `key` (Requirement
239
+ * 5.2). Throws {@link NotFoundError} for a missing key (Requirement 5.5).
240
+ */
241
+ getStream(key: string): Promise<NodeReadable>;
242
+ /**
243
+ * Best-effort read of an object's existing metadata (used to preserve
244
+ * `createdAt` on overwrite). Returns `null` when the object does not exist.
245
+ */
246
+ private readMeta;
247
+ /**
248
+ * Rebuild the typed {@link StorageObjectMetadata} field set from provider
249
+ * attributes and the encoded user-metadata map, applying the shared layer's
250
+ * canonical defaults. Provider-supplied values are used as best-effort
251
+ * fallbacks when the encoded fields are absent (e.g. an object written outside
252
+ * this base): `etag`/`size`/`lastModified` back-fill the identity/timestamp
253
+ * fields, keeping the shape consistent across providers.
254
+ */
255
+ private decodeMeta;
256
+ /**
257
+ * Adapt the client's SDK-shaped multipart calls into a
258
+ * {@link MultipartCapability}. The S3 API requires the object key on every
259
+ * part/complete/abort call, so the `uploadId → key` mapping is tracked here.
260
+ */
261
+ private buildMultipartCapability;
262
+ }
263
+ /**
264
+ * Construct an S3-style {@link StorageDriver} over an injected
265
+ * {@link S3ClientLike}. This is the entry point consumed by the concrete
266
+ * provider submodules (`s3.ts`/`r2.ts`/`minio.ts`/`backblaze.ts`), each of which
267
+ * supplies a differently-constructed client.
268
+ */
269
+ export declare function createS3StyleDriver(client: S3ClientLike, options?: S3StyleDriverOptions): StorageDriver;
270
+ //# sourceMappingURL=s3-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3-base.d.ts","sourceRoot":"","sources":["../../src/drivers/s3-base.ts"],"names":[],"mappings":"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"}