@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,279 @@
1
+ /**
2
+ * @streetjs/storage — the Backblaze B2 driver submodule (`@streetjs/storage/backblaze`).
3
+ *
4
+ * Backblaze B2 exposes a **fully S3-compatible API**, so this driver is a thin
5
+ * specialization of the shared S3-style base ({@link createS3StyleDriver} in
6
+ * `s3-base.ts`): it only differs in how the underlying client is
7
+ * built/configured (a B2 S3 endpoint and B2 application-key credentials), never
8
+ * in how the {@link StorageDriver} contract is satisfied. The driver name is
9
+ * fixed to `"backblaze"`.
10
+ *
11
+ * ## SDK isolation (Requirements 3.1, 3.3)
12
+ *
13
+ * This module imports **no provider SDK at the top level** — only this package's
14
+ * own type surface and the shared S3-style base. It supports two construction
15
+ * modes:
16
+ *
17
+ * 1. **Injected structural client** — the caller passes an {@link S3ClientLike}
18
+ * (the minimal, SDK-shaped structural interface the base depends on). The SDK
19
+ * is then entirely a concern of the caller; this package resolves nothing.
20
+ * ({@link createBackblazeB2Driver} with a client, synchronous.)
21
+ * 2. **Self-built client from connection config** — the driver constructs its own
22
+ * S3-compatible client for the B2 endpoint using a **lazy dynamic `import()`**
23
+ * performed inside the factory at construction time (never at module top
24
+ * level), so `@aws-sdk/client-s3` is resolved only when this submodule is
25
+ * actually used to build a client. If that optional peer SDK is absent (and no
26
+ * client was injected), a descriptive {@link StorageConfigError} is thrown.
27
+ * ({@link createBackblazeB2Driver} with a config, asynchronous.)
28
+ *
29
+ * Because this driver lives behind the `./backblaze` subpath export and the base
30
+ * package never imports it, `streetjs` stays the only runtime dependency and the
31
+ * B2/S3 SDK remains an optional peer dependency.
32
+ *
33
+ * _Requirements: 2.1, 2.3, 3.3_
34
+ */
35
+ import { Buffer } from "node:buffer";
36
+ import { systemClock } from "streetjs";
37
+ import { StorageConfigError } from "../errors.js";
38
+ import { createS3StyleDriver, S3StyleDriver, } from "./s3-base.js";
39
+ /** The stable driver name surfaced as {@link StorageDriver.name}. */
40
+ export const BACKBLAZE_DRIVER_NAME = "backblaze";
41
+ /** Peer SDK specifier resolved lazily when the driver builds its own client. */
42
+ const BACKBLAZE_SDK_SPECIFIER = "@aws-sdk/client-s3";
43
+ export function createBackblazeB2Driver(clientOrConfig, options = {}) {
44
+ if (isS3ClientLike(clientOrConfig)) {
45
+ return buildDriver(clientOrConfig, options);
46
+ }
47
+ return buildFromConnectionConfig(clientOrConfig);
48
+ }
49
+ /**
50
+ * A Backblaze B2 driver as a concrete class over an injected {@link S3ClientLike},
51
+ * for callers who prefer `new` construction. Equivalent to
52
+ * {@link createBackblazeB2Driver} with an injected client; the name defaults to
53
+ * `"backblaze"`.
54
+ */
55
+ export class BackblazeB2Driver extends S3StyleDriver {
56
+ constructor(client, options = {}) {
57
+ super(client, {
58
+ name: options.name ?? BACKBLAZE_DRIVER_NAME,
59
+ clock: options.clock ?? systemClock,
60
+ capabilities: options.capabilities,
61
+ });
62
+ }
63
+ }
64
+ // ── Internal construction helpers ───────────────────────────────────────────
65
+ /** Delegate to the shared S3-style base, fixing the name to `"backblaze"`. */
66
+ function buildDriver(client, options) {
67
+ return createS3StyleDriver(client, {
68
+ name: options.name ?? BACKBLAZE_DRIVER_NAME,
69
+ clock: options.clock ?? systemClock,
70
+ capabilities: options.capabilities,
71
+ });
72
+ }
73
+ /**
74
+ * Build a B2 S3-compatible client via a lazy dynamic `import()` of the optional
75
+ * peer SDK, then wrap it in {@link S3ClientLike} and hand it to the base. Throws
76
+ * a descriptive {@link StorageConfigError} when the SDK cannot be resolved.
77
+ */
78
+ async function buildFromConnectionConfig(config) {
79
+ const client = await buildBackblazeS3Client(config);
80
+ return buildDriver(client, config);
81
+ }
82
+ /**
83
+ * Structural guard distinguishing an injected {@link S3ClientLike} from a
84
+ * connection config: only a client exposes the mandatory `putObject` method.
85
+ */
86
+ function isS3ClientLike(value) {
87
+ return typeof value.putObject === "function";
88
+ }
89
+ // ── The lazily-built S3-compatible client for Backblaze B2 ──────────────────────
90
+ /**
91
+ * Resolve `@aws-sdk/client-s3` lazily and adapt it into an {@link S3ClientLike}
92
+ * bound to the B2 bucket/endpoint. The specifier is held in a variable so the
93
+ * static build never requires the optional peer dependency to be installed; it
94
+ * is resolved only at call time.
95
+ */
96
+ async function buildBackblazeS3Client(config) {
97
+ // Lazy dynamic import — never a top-level import. An indirection variable keeps
98
+ // the specifier non-literal so the module is not required at build time.
99
+ const specifier = BACKBLAZE_SDK_SPECIFIER;
100
+ let sdk;
101
+ try {
102
+ sdk = (await import(specifier));
103
+ }
104
+ catch (cause) {
105
+ throw new StorageConfigError(`The Backblaze B2 driver requires the optional peer dependency "${BACKBLAZE_SDK_SPECIFIER}". ` +
106
+ `Install it, or pass a pre-constructed S3ClientLike to createBackblazeB2Driver().`, { provider: BACKBLAZE_DRIVER_NAME, cause });
107
+ }
108
+ const bucket = config.bucket;
109
+ const raw = new sdk.S3Client({
110
+ endpoint: config.endpoint,
111
+ region: config.region ?? "auto",
112
+ credentials: {
113
+ accessKeyId: config.credentials.accessKeyId,
114
+ secretAccessKey: config.credentials.secretAccessKey,
115
+ },
116
+ forcePathStyle: config.forcePathStyle ?? false,
117
+ });
118
+ const send = (command) => raw.send(command);
119
+ return {
120
+ async putObject(input) {
121
+ const result = await send(new sdk.PutObjectCommand({
122
+ Bucket: bucket,
123
+ Key: input.key,
124
+ Body: input.body,
125
+ ContentType: input.contentType,
126
+ Metadata: input.metadata,
127
+ }));
128
+ return { etag: normalizeEtag(result.ETag) };
129
+ },
130
+ async getObject({ key }) {
131
+ let result;
132
+ try {
133
+ result = await send(new sdk.GetObjectCommand({ Bucket: bucket, Key: key }));
134
+ }
135
+ catch (error) {
136
+ if (isNotFound(error)) {
137
+ return null;
138
+ }
139
+ throw error;
140
+ }
141
+ const body = await collectBody(result.Body);
142
+ return {
143
+ body,
144
+ contentType: result.ContentType,
145
+ etag: normalizeEtag(result.ETag),
146
+ size: result.ContentLength ?? body.byteLength,
147
+ lastModified: toEpochMs(result.LastModified),
148
+ metadata: result.Metadata,
149
+ };
150
+ },
151
+ async headObject({ key }) {
152
+ let result;
153
+ try {
154
+ result = await send(new sdk.HeadObjectCommand({ Bucket: bucket, Key: key }));
155
+ }
156
+ catch (error) {
157
+ if (isNotFound(error)) {
158
+ return null;
159
+ }
160
+ throw error;
161
+ }
162
+ return {
163
+ contentType: result.ContentType,
164
+ etag: normalizeEtag(result.ETag),
165
+ size: result.ContentLength,
166
+ lastModified: toEpochMs(result.LastModified),
167
+ metadata: result.Metadata,
168
+ };
169
+ },
170
+ async deleteObject({ key }) {
171
+ await send(new sdk.DeleteObjectCommand({ Bucket: bucket, Key: key }));
172
+ },
173
+ async listObjects({ prefix, limit, cursor, delimiter }) {
174
+ const result = await send(new sdk.ListObjectsV2Command({
175
+ Bucket: bucket,
176
+ Prefix: prefix,
177
+ MaxKeys: limit,
178
+ ContinuationToken: cursor,
179
+ Delimiter: delimiter === true ? "/" : undefined,
180
+ }));
181
+ const contents = result.Contents ?? [];
182
+ return contents.map((entry) => ({
183
+ key: entry.Key ?? "",
184
+ size: entry.Size ?? 0,
185
+ updatedAt: toEpochMs(entry.LastModified) ?? 0,
186
+ }));
187
+ },
188
+ async createMultipartUpload({ key, contentType, metadata }) {
189
+ const result = await send(new sdk.CreateMultipartUploadCommand({
190
+ Bucket: bucket,
191
+ Key: key,
192
+ ContentType: contentType,
193
+ Metadata: metadata,
194
+ }));
195
+ if (typeof result.UploadId !== "string") {
196
+ throw new StorageConfigError("Backblaze B2 did not return an upload id for the multipart upload.", {
197
+ provider: BACKBLAZE_DRIVER_NAME,
198
+ });
199
+ }
200
+ return { uploadId: result.UploadId };
201
+ },
202
+ async uploadPart({ key, uploadId, partNumber, body }) {
203
+ const result = await send(new sdk.UploadPartCommand({
204
+ Bucket: bucket,
205
+ Key: key,
206
+ UploadId: uploadId,
207
+ PartNumber: partNumber,
208
+ Body: body,
209
+ }));
210
+ return { etag: normalizeEtag(result.ETag) };
211
+ },
212
+ async completeMultipartUpload({ key, uploadId, parts }) {
213
+ const result = await send(new sdk.CompleteMultipartUploadCommand({
214
+ Bucket: bucket,
215
+ Key: key,
216
+ UploadId: uploadId,
217
+ MultipartUpload: {
218
+ Parts: parts.map((part) => ({ PartNumber: part.partNumber, ETag: part.etag })),
219
+ },
220
+ }));
221
+ return { etag: normalizeEtag(result.ETag) };
222
+ },
223
+ async abortMultipartUpload({ key, uploadId }) {
224
+ await send(new sdk.AbortMultipartUploadCommand({ Bucket: bucket, Key: key, UploadId: uploadId }));
225
+ },
226
+ };
227
+ }
228
+ // ── Adapter utilities ───────────────────────────────────────────────────────
229
+ /** Strip the surrounding quotes S3 wraps around ETags; tolerate an absent value. */
230
+ function normalizeEtag(etag) {
231
+ if (typeof etag !== "string") {
232
+ return "";
233
+ }
234
+ return etag.replace(/^"|"$/g, "");
235
+ }
236
+ /** Coerce an S3 `LastModified` (Date or epoch ms) into epoch ms, if present. */
237
+ function toEpochMs(value) {
238
+ if (value === undefined) {
239
+ return undefined;
240
+ }
241
+ return value instanceof Date ? value.getTime() : value;
242
+ }
243
+ /** `true` when an AWS SDK error represents a missing key (404 / NoSuchKey / NotFound). */
244
+ function isNotFound(error) {
245
+ if (typeof error !== "object" || error === null) {
246
+ return false;
247
+ }
248
+ const err = error;
249
+ if (err.name === "NoSuchKey" || err.name === "NotFound") {
250
+ return true;
251
+ }
252
+ return err.$metadata?.httpStatusCode === 404;
253
+ }
254
+ /**
255
+ * Collect an AWS SDK response body (a streaming blob) into a `Uint8Array`,
256
+ * supporting the SDK's `transformToByteArray()` helper as well as Node streams
257
+ * and already-buffered values.
258
+ */
259
+ async function collectBody(body) {
260
+ if (body === undefined || body === null) {
261
+ return new Uint8Array(0);
262
+ }
263
+ const maybe = body;
264
+ if (typeof maybe.transformToByteArray === "function") {
265
+ return maybe.transformToByteArray();
266
+ }
267
+ if (body instanceof Uint8Array) {
268
+ return body;
269
+ }
270
+ if (typeof maybe[Symbol.asyncIterator] === "function") {
271
+ const chunks = [];
272
+ for await (const chunk of body) {
273
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
274
+ }
275
+ return new Uint8Array(Buffer.concat(chunks));
276
+ }
277
+ return new Uint8Array(Buffer.from(body));
278
+ }
279
+ //# sourceMappingURL=backblaze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backblaze.js","sourceRoot":"","sources":["../../src/drivers/backblaze.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * @streetjs/storage — GoogleCloudStorageDriver (submodule `@streetjs/storage/gcs`).
3
+ *
4
+ * Google Cloud Storage is **not** an S3-wire-compatible provider — its SDK
5
+ * exposes a bucket/file object model (`bucket.file(name).save/download/delete/
6
+ * exists/getMetadata`, `bucket.getFiles({ prefix })`) rather than the
7
+ * `putObject`/`getObject` verbs the S3-style base is built on. So, unlike
8
+ * `r2.ts`/`minio.ts`/`backblaze.ts`, this driver does **not** extend the shared
9
+ * S3 base ({@link ../drivers/s3-base}); it maps the {@link StorageDriver}
10
+ * contract directly onto a purpose-built structural {@link GcsClientLike} that
11
+ * mirrors just the GCS calls it needs.
12
+ *
13
+ * ## Two ways to obtain a driver
14
+ *
15
+ * - {@link createGoogleCloudStorageDriver} wraps an **already-constructed,
16
+ * injected** {@link GcsClientLike} and returns a driver synchronously. This is
17
+ * the SDK-free path: no provider SDK is touched, so it is fully testable with
18
+ * an in-memory fake and needs no `@google-cloud/storage` install.
19
+ * - {@link connectGoogleCloudStorageDriver} **builds its own client** from GCS
20
+ * connection config. It resolves `@google-cloud/storage` through a **lazy
21
+ * dynamic `import()` performed inside the function** (never at module top
22
+ * level), so the optional peer dependency is only required when this path is
23
+ * actually used. If the SDK is not installed and no client was injected, it
24
+ * throws {@link StorageConfigError} (Requirement 1.5).
25
+ *
26
+ * ## Capability delegation (Requirement 2.3)
27
+ *
28
+ * The driver implements only the **mandatory primitives** (`put`/`get`/`exists`/
29
+ * `delete`/`stat`/`list`/`putStream`/`getStream`), producing every
30
+ * {@link StorageObjectMetadata} through the shared metadata layer
31
+ * ({@link buildObjectMetadata}) so the field set is identical to Memory/Local/S3,
32
+ * and reporting a missing key consistently ({@link MaybeObject} `{ found: false }`
33
+ * for `get`, `null` for `stat`, {@link NotFoundError} for `getStream`). Advanced
34
+ * capabilities (`multipart`/`resumable`/`versioning`/`signedUrl`/`lifecycle`) are
35
+ * intentionally left `undefined` so the facade simulates them over the
36
+ * primitives, keeping behavior identical across providers.
37
+ *
38
+ * ## SDK isolation (Requirements 2.1, 3.3)
39
+ *
40
+ * This module imports **no provider SDK at the top level** — only Node built-ins,
41
+ * `streetjs` (for the injected {@link Clock}), and this package's own type
42
+ * surface. `@google-cloud/storage` is referenced solely via a dynamic `import()`
43
+ * with a non-literal specifier inside {@link connectGoogleCloudStorageDriver}, so
44
+ * `tsc` never requires the SDK to be present and `streetjs` stays the only
45
+ * runtime dependency. This driver is a submodule-only export
46
+ * (`./gcs` → `dist/drivers/gcs.js`); it is intentionally not re-exported from the
47
+ * package's main `index.ts`.
48
+ *
49
+ * _Requirements: 2.1, 2.3, 3.3_
50
+ */
51
+ import { type Clock } from "streetjs";
52
+ import type { MaybeObject, NodeReadable, StorageDriver } from "../driver.js";
53
+ import type { ListOptions, StorageListItem, StorageObjectMetadata, WriteMetadata } from "../types.js";
54
+ /**
55
+ * Object attributes as surfaced by the GCS object model (`file.getMetadata()` /
56
+ * entries from `bucket.getFiles`). Every field is optional and loosely typed
57
+ * because GCS returns `size` as a numeric string and timestamps as RFC-3339
58
+ * strings; the driver normalizes them. Caller-supplied user metadata lives under
59
+ * the nested {@link metadata} map (GCS's "custom metadata").
60
+ */
61
+ export interface GcsObjectAttributes {
62
+ /** Byte length. GCS returns this as a numeric string; a number is tolerated. */
63
+ readonly size?: number | string;
64
+ /** Declared content type. */
65
+ readonly contentType?: string;
66
+ /** Entity tag. */
67
+ readonly etag?: string;
68
+ /** Base64 MD5 hash of the content, when present. */
69
+ readonly md5Hash?: string;
70
+ /** Creation time as an RFC-3339 / ISO-8601 string. */
71
+ readonly timeCreated?: string;
72
+ /** Last-updated time as an RFC-3339 / ISO-8601 string. */
73
+ readonly updated?: string;
74
+ /** Caller-supplied custom metadata (string→string), GCS's "metadata" map. */
75
+ readonly metadata?: Record<string, string>;
76
+ }
77
+ /** Options accepted by {@link GcsClientLike.save}. */
78
+ export interface GcsSaveOptions {
79
+ /** Content type to persist alongside the object. */
80
+ readonly contentType?: string;
81
+ /** Custom metadata (string→string) to persist as GCS object metadata. */
82
+ readonly metadata?: Record<string, string>;
83
+ }
84
+ /** Options accepted by {@link GcsClientLike.getFiles}. */
85
+ export interface GcsListInput {
86
+ /** Only list objects whose name begins with this prefix. */
87
+ readonly prefix: string;
88
+ /** When set, collapse results on this delimiter (GCS directory semantics). */
89
+ readonly delimiter?: string;
90
+ /** Best-effort maximum number of results the caller wants. */
91
+ readonly maxResults?: number;
92
+ }
93
+ /** A single object entry returned by {@link GcsClientLike.getFiles}. */
94
+ export interface GcsFileEntry {
95
+ /** The object name (full key). */
96
+ readonly name: string;
97
+ /** The entry's attributes, when the listing includes them. */
98
+ readonly attributes?: GcsObjectAttributes;
99
+ }
100
+ /**
101
+ * The **minimal, GCS-shaped structural interface** this driver depends on.
102
+ *
103
+ * It is bucket-scoped (the concrete adapter binds a bucket) and describes just
104
+ * the object operations the driver needs — never any concrete
105
+ * `@google-cloud/storage` type — so the SDK stays an optional peer concern of the
106
+ * consumer (Requirement 3.1). `download`/`getMetadata` return `null` for a
107
+ * missing object so not-found maps to the contract's consistent semantics rather
108
+ * than a thrown error.
109
+ */
110
+ export interface GcsClientLike {
111
+ /** Store `bytes` under `name` with optional content type and custom metadata. */
112
+ save(name: string, bytes: Uint8Array, options?: GcsSaveOptions): Promise<void>;
113
+ /** Download the object's bytes, or `null` when it does not exist. */
114
+ download(name: string): Promise<Uint8Array | null>;
115
+ /** Delete the object at `name` (a no-op when it is already absent). */
116
+ delete(name: string): Promise<void>;
117
+ /** Report whether an object exists at `name`. */
118
+ exists(name: string): Promise<boolean>;
119
+ /** Fetch the object's attributes, or `null` when it does not exist. */
120
+ getMetadata(name: string): Promise<GcsObjectAttributes | null>;
121
+ /** List objects whose name begins with `input.prefix`. */
122
+ getFiles(input: GcsListInput): Promise<readonly GcsFileEntry[]>;
123
+ }
124
+ /**
125
+ * Options for the GCS driver. The provider name is fixed to `"gcs"` and is not
126
+ * caller-configurable, so provider identity stays stable.
127
+ */
128
+ export interface GoogleCloudStorageDriverOptions {
129
+ /** Injected clock for deterministic timestamps in tests. Default `systemClock`. */
130
+ readonly clock?: Clock;
131
+ }
132
+ /**
133
+ * Maps the {@link StorageDriver} contract onto an injected {@link GcsClientLike}.
134
+ *
135
+ * Object identity fields (`etag`/`checksum`/`size`) and timestamps are computed
136
+ * locally at write time — the checksum/etag are the sha-256 hex digest of the
137
+ * stored bytes, the size is the byte length, and timestamps come from the
138
+ * injected {@link Clock} — then encoded into the object's custom metadata so they
139
+ * round-trip on read. Advanced capabilities are left `undefined` for facade
140
+ * simulation.
141
+ */
142
+ export declare class GoogleCloudStorageDriver implements StorageDriver {
143
+ /** Stable driver name. */
144
+ readonly name = "gcs";
145
+ private readonly client;
146
+ private readonly clock;
147
+ constructor(client: GcsClientLike, options?: GoogleCloudStorageDriverOptions);
148
+ /**
149
+ * Store `bytes` under `key`, computing size and sha-256 checksum locally and
150
+ * taking timestamps from the injected clock. When overwriting, the original
151
+ * `createdAt` is preserved (a preceding attribute read). The typed metadata is
152
+ * encoded into the object's custom-metadata map so it round-trips on read
153
+ * (Requirements 4.1, 10.1, 10.2).
154
+ */
155
+ put(key: string, bytes: Uint8Array, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
156
+ /**
157
+ * Read the object at `key`, returning a discriminated {@link MaybeObject} so
158
+ * absence is reported rather than thrown (Requirements 4.2, 2.4). Metadata is
159
+ * rebuilt from the object's attributes and encoded custom metadata via the
160
+ * shared metadata layer.
161
+ */
162
+ get(key: string): Promise<MaybeObject>;
163
+ /** Report whether an object is stored under `key` (Requirement 4.3). */
164
+ exists(key: string): Promise<boolean>;
165
+ /** Delete the object at `key`; deleting a missing key is a no-op (Requirement 4.4). */
166
+ delete(key: string): Promise<void>;
167
+ /**
168
+ * Return the metadata for `key` without its content, or `null` when absent
169
+ * (Requirement 4.10).
170
+ */
171
+ stat(key: string): Promise<StorageObjectMetadata | null>;
172
+ /**
173
+ * List objects whose key begins with `prefix`, sorted by key for deterministic
174
+ * ordering (Requirement 4.9). Honors optional `cursor` (exclusive resume
175
+ * point), `limit`, and `delimiter` (collapse to immediate children on `/`).
176
+ */
177
+ list(prefix: string, options?: ListOptions): Promise<StorageListItem[]>;
178
+ /**
179
+ * Consume a Node {@link Readable} and persist the assembled bytes under `key`
180
+ * with the same computed metadata as {@link put} (Requirement 5.1). Chunks are
181
+ * drained through a `pipeline` (correct backpressure and error propagation),
182
+ * then handed to {@link put}.
183
+ */
184
+ putStream(key: string, stream: NodeReadable, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
185
+ /**
186
+ * Return a Node {@link Readable} of the stored bytes at `key` (Requirement
187
+ * 5.2). Throws {@link NotFoundError} for a missing key (Requirement 5.5).
188
+ */
189
+ getStream(key: string): Promise<NodeReadable>;
190
+ /**
191
+ * Rebuild the typed {@link StorageObjectMetadata} field set from the object's
192
+ * attributes and the encoded custom-metadata map, applying the shared layer's
193
+ * canonical defaults. Provider-supplied values are used as best-effort
194
+ * fallbacks when the encoded fields are absent (e.g. an object written outside
195
+ * this driver): `etag`/`md5Hash`/`timeCreated`/`updated` back-fill the
196
+ * identity/timestamp fields, keeping the shape consistent across providers.
197
+ */
198
+ private decodeMeta;
199
+ }
200
+ /**
201
+ * Wrap an injected {@link GcsClientLike} as a GCS driver. Synchronous and
202
+ * SDK-free: the caller supplies the client, so no provider SDK is resolved here.
203
+ *
204
+ * @throws {StorageConfigError} when no client is injected — use
205
+ * {@link connectGoogleCloudStorageDriver} to build a client from connection
206
+ * options instead.
207
+ */
208
+ export declare function createGoogleCloudStorageDriver(client: GcsClientLike, options?: GoogleCloudStorageDriverOptions): StorageDriver;
209
+ /**
210
+ * Connection configuration for {@link connectGoogleCloudStorageDriver}. These are
211
+ * forwarded to the `@google-cloud/storage` `Storage` constructor (except
212
+ * `bucket`, which scopes the resulting client).
213
+ */
214
+ export interface GoogleCloudStorageConfig extends GoogleCloudStorageDriverOptions {
215
+ /** The GCS bucket the driver operates within (required). */
216
+ readonly bucket: string;
217
+ /** GCP project id. */
218
+ readonly projectId?: string;
219
+ /** Path to a service-account key file. */
220
+ readonly keyFilename?: string;
221
+ /** Inline service-account credentials. */
222
+ readonly credentials?: Record<string, unknown>;
223
+ /** Custom API endpoint (e.g. a fake/emulator host). */
224
+ readonly apiEndpoint?: string;
225
+ }
226
+ /**
227
+ * Build a GCS driver that owns its client, resolving `@google-cloud/storage`
228
+ * lazily.
229
+ *
230
+ * The SDK is loaded through a dynamic `import()` with a non-literal specifier so
231
+ * it is never a static/top-level dependency: `tsc` does not require it to be
232
+ * installed, and it is only resolved when this function runs. When the SDK
233
+ * cannot be resolved, a {@link StorageConfigError} is thrown (Requirement 1.5) —
234
+ * callers that cannot install the SDK should use
235
+ * {@link createGoogleCloudStorageDriver} with their own {@link GcsClientLike}
236
+ * instead.
237
+ */
238
+ export declare function connectGoogleCloudStorageDriver(config: GoogleCloudStorageConfig): Promise<StorageDriver>;
239
+ //# sourceMappingURL=gcs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcs.d.ts","sourceRoot":"","sources":["../../src/drivers/gcs.ts"],"names":[],"mappings":"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"}