@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,185 @@
1
+ // Unit tests for the Backblaze B2 driver submodule (task 28.5).
2
+ //
3
+ // Backblaze B2 exposes a fully S3-compatible API, so the driver is a thin
4
+ // specialization of the shared S3-style base: it fixes the driver name to
5
+ // "backblaze" and either accepts an injected S3ClientLike or builds its own
6
+ // client from connection config via a lazy dynamic import() of the optional
7
+ // peer SDK. These tests exercise the injected-client path with an in-memory
8
+ // fake (no external service, no SDK), assert the name/contract behavior, and
9
+ // confirm the self-built path throws StorageConfigError when the SDK is absent.
10
+ //
11
+ // Requirements: 2.1, 2.3, 3.3
12
+ import test from "node:test";
13
+ import assert from "node:assert/strict";
14
+ import { BackblazeB2Driver, createBackblazeB2Driver, BACKBLAZE_DRIVER_NAME, } from "../drivers/backblaze.js";
15
+ import { StorageConfigError } from "../errors.js";
16
+ import { NotFoundError } from "../errors.js";
17
+ import { registerStorageDriverContractTests } from "./contract.js";
18
+ const FIXED_NOW = 1_700_000_000_000;
19
+ const fixedClock = () => FIXED_NOW;
20
+ function bytes(str) {
21
+ return new TextEncoder().encode(str);
22
+ }
23
+ /** A minimal in-memory S3ClientLike standing in for the B2 S3 endpoint. */
24
+ function makeFakeClient({ withMultipart = true } = {}) {
25
+ const objects = new Map();
26
+ const uploads = new Map();
27
+ let seed = 0;
28
+ const client = {
29
+ async putObject({ key, body, contentType, metadata }) {
30
+ objects.set(key, {
31
+ body: body.slice(),
32
+ contentType,
33
+ metadata: metadata ? { ...metadata } : undefined,
34
+ });
35
+ return { etag: `${key}-etag` };
36
+ },
37
+ async getObject({ key }) {
38
+ const obj = objects.get(key);
39
+ if (obj === undefined)
40
+ return null;
41
+ return {
42
+ body: obj.body.slice(),
43
+ contentType: obj.contentType,
44
+ etag: `${key}-etag`,
45
+ size: obj.body.byteLength,
46
+ lastModified: FIXED_NOW,
47
+ metadata: obj.metadata,
48
+ };
49
+ },
50
+ async headObject({ key }) {
51
+ const obj = objects.get(key);
52
+ if (obj === undefined)
53
+ return null;
54
+ return {
55
+ contentType: obj.contentType,
56
+ etag: `${key}-etag`,
57
+ size: obj.body.byteLength,
58
+ lastModified: FIXED_NOW,
59
+ metadata: obj.metadata,
60
+ };
61
+ },
62
+ async deleteObject({ key }) {
63
+ objects.delete(key);
64
+ },
65
+ async listObjects({ prefix }) {
66
+ return [...objects.entries()]
67
+ .filter(([key]) => key.startsWith(prefix))
68
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
69
+ .map(([key, obj]) => ({ key, size: obj.body.byteLength, updatedAt: FIXED_NOW }));
70
+ },
71
+ };
72
+ if (withMultipart) {
73
+ client.createMultipartUpload = async ({ key, contentType, metadata }) => {
74
+ const uploadId = `upload-${(seed += 1)}`;
75
+ uploads.set(uploadId, { key, contentType, metadata, parts: new Map() });
76
+ return { uploadId };
77
+ };
78
+ client.uploadPart = async ({ uploadId, partNumber, body }) => {
79
+ uploads.get(uploadId).parts.set(partNumber, body.slice());
80
+ return { etag: `${uploadId}-${partNumber}` };
81
+ };
82
+ client.completeMultipartUpload = async ({ uploadId, parts }) => {
83
+ const session = uploads.get(uploadId);
84
+ const ordered = [...parts].sort((a, b) => a.partNumber - b.partNumber);
85
+ const buffers = ordered.map((p) => Buffer.from(session.parts.get(p.partNumber)));
86
+ objects.set(session.key, {
87
+ body: new Uint8Array(Buffer.concat(buffers)),
88
+ contentType: session.contentType,
89
+ metadata: session.metadata,
90
+ });
91
+ uploads.delete(uploadId);
92
+ return { etag: `${session.key}-etag` };
93
+ };
94
+ client.abortMultipartUpload = async ({ uploadId }) => {
95
+ uploads.delete(uploadId);
96
+ };
97
+ }
98
+ return { client, objects, uploads };
99
+ }
100
+ // ── name ────────────────────────────────────────────────────────────────────
101
+ test("driver name is fixed to 'backblaze'", () => {
102
+ const { client } = makeFakeClient();
103
+ const driver = createBackblazeB2Driver(client, { clock: fixedClock });
104
+ assert.equal(driver.name, BACKBLAZE_DRIVER_NAME);
105
+ assert.equal(driver.name, "backblaze");
106
+ });
107
+ test("BackblazeB2Driver class constructs with name 'backblaze'", () => {
108
+ const { client } = makeFakeClient();
109
+ const driver = new BackblazeB2Driver(client, { clock: fixedClock });
110
+ assert.equal(driver.name, "backblaze");
111
+ });
112
+ test("injected-client factory is synchronous (returns a driver, not a promise)", () => {
113
+ const { client } = makeFakeClient();
114
+ const driver = createBackblazeB2Driver(client);
115
+ assert.equal(typeof driver.put, "function");
116
+ assert.notEqual(typeof driver.then, "function");
117
+ });
118
+ // ── primitives round-trip through the injected client ──────────────────────────
119
+ test("put/get round-trips bytes and typed metadata", async () => {
120
+ const { client } = makeFakeClient();
121
+ const driver = createBackblazeB2Driver(client, { clock: fixedClock });
122
+ const content = bytes("backblaze payload");
123
+ await driver.put("docs/file.txt", content, {
124
+ contentType: "text/plain",
125
+ owner: "user-1",
126
+ accessLevel: "public",
127
+ custom: { label: "invoice" },
128
+ });
129
+ const result = await driver.get("docs/file.txt");
130
+ assert.equal(result.found, true);
131
+ assert.deepEqual(result.bytes, content);
132
+ assert.equal(result.metadata.contentType, "text/plain");
133
+ assert.equal(result.metadata.owner, "user-1");
134
+ assert.equal(result.metadata.accessLevel, "public");
135
+ assert.deepEqual(result.metadata.custom, { label: "invoice" });
136
+ });
137
+ test("get/stat report a missing key consistently", async () => {
138
+ const { client } = makeFakeClient();
139
+ const driver = createBackblazeB2Driver(client, { clock: fixedClock });
140
+ assert.deepEqual(await driver.get("missing"), { found: false });
141
+ assert.equal(await driver.stat("missing"), null);
142
+ await assert.rejects(() => driver.getStream("missing"), NotFoundError);
143
+ });
144
+ test("native multipart delegates through the client when available", async () => {
145
+ const { client } = makeFakeClient({ withMultipart: true });
146
+ const driver = createBackblazeB2Driver(client, { clock: fixedClock });
147
+ assert.notEqual(driver.multipart, undefined);
148
+ const mp = driver.multipart;
149
+ const uploadId = await mp.create("big/file.bin", {});
150
+ const p1 = await mp.uploadPart(uploadId, 1, bytes("part-one-"));
151
+ const p2 = await mp.uploadPart(uploadId, 2, bytes("part-two"));
152
+ await mp.complete(uploadId, [p1, p2]);
153
+ const result = await driver.get("big/file.bin");
154
+ assert.equal(result.found, true);
155
+ assert.deepEqual(result.bytes, bytes("part-one-part-two"));
156
+ });
157
+ test("native capabilities are delegated when injected via options", () => {
158
+ const { client } = makeFakeClient();
159
+ const versioning = { snapshot: async () => null, list: async () => [], restore: async () => ({}), deleteVersion: async () => { } };
160
+ const lifecycle = { apply: async () => [] };
161
+ const signedUrl = { sign: async () => "url", verify: () => ({ valid: true }) };
162
+ const driver = createBackblazeB2Driver(client, {
163
+ clock: fixedClock,
164
+ capabilities: { versioning, lifecycle, signedUrl },
165
+ });
166
+ assert.equal(driver.versioning, versioning);
167
+ assert.equal(driver.lifecycle, lifecycle);
168
+ assert.equal(driver.signedUrl, signedUrl);
169
+ });
170
+ // ── self-built client path (lazy dynamic import of an absent optional SDK) ──────
171
+ test("building own client without the SDK installed throws StorageConfigError", async () => {
172
+ await assert.rejects(() => createBackblazeB2Driver({
173
+ bucket: "my-bucket",
174
+ endpoint: "https://s3.us-west-002.backblazeb2.com",
175
+ region: "us-west-002",
176
+ credentials: { accessKeyId: "keyId", secretAccessKey: "appKey" },
177
+ }), (error) => {
178
+ assert.ok(error instanceof StorageConfigError);
179
+ assert.equal(error.provider, "backblaze");
180
+ return true;
181
+ });
182
+ });
183
+ // ── shared contract-conformance suite ───────────────────────────────────────────
184
+ registerStorageDriverContractTests("backblaze", () => createBackblazeB2Driver(makeFakeClient().client, { clock: fixedClock }), test);
185
+ //# sourceMappingURL=backblaze-driver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backblaze-driver.test.js","sourceRoot":"","sources":["../../src/tests/backblaze-driver.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bridge-degradation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-degradation.test.d.ts","sourceRoot":"","sources":["../../src/tests/bridge-degradation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,138 @@
1
+ // Cross-bridge graceful-degradation unit tests for the storage facade
2
+ // (task 21.4).
3
+ //
4
+ // Tasks 21.1/21.2/21.3 each proved a single bridge degrades gracefully in
5
+ // isolation (events-bridge.test.js, queue-bridge.test.js,
6
+ // realtime-bridge.test.js). This file adds the focused CROSS-bridge coverage
7
+ // that specifically satisfies task 21.4's intent: with the Events, Queue AND
8
+ // Realtime bridges wired simultaneously, object and upload operations must
9
+ // still succeed whether every bridge is ABSENT or every bridge THROWS, and the
10
+ // events published must carry the affected key + metadata.
11
+ //
12
+ // Covered:
13
+ // - all three bridges absent → put/get/delete/putStream/resumeUpload succeed
14
+ // (17.3, 19.3).
15
+ // - all three bridges throwing simultaneously → the same operations still
16
+ // succeed and return correct results (17.4, 19.3).
17
+ // - with a live (recording) events bridge alongside a throwing queue + throwing
18
+ // realtime bridge, the published events still carry key + metadata; asserted
19
+ // for storage.uploaded (key + full metadata) and storage.deleted (key)
20
+ // (18.2).
21
+ //
22
+ // Uses the Node.js built-in test runner (node:test); executed via
23
+ // `node --test dist/tests/*.test.js`.
24
+ //
25
+ // Requirements: 17.3, 17.4, 18.2, 19.3
26
+ import test from "node:test";
27
+ import assert from "node:assert/strict";
28
+ import { Readable } from "node:stream";
29
+ import { createStorage } from "../index.js";
30
+ /** A bridge trio whose every method throws synchronously on use. */
31
+ function throwingBridges() {
32
+ return {
33
+ events: {
34
+ publish() {
35
+ throw new Error("events bus down");
36
+ },
37
+ },
38
+ queue: {
39
+ dispatch() {
40
+ throw new Error("queue down");
41
+ },
42
+ },
43
+ realtime: {
44
+ broadcast() {
45
+ throw new Error("realtime down");
46
+ },
47
+ },
48
+ };
49
+ }
50
+ /** A recording EventsLike double capturing every published (event, payload). */
51
+ function recordingEvents() {
52
+ const published = [];
53
+ return {
54
+ published,
55
+ publish(event, payload) {
56
+ published.push({ event, payload: payload });
57
+ },
58
+ };
59
+ }
60
+ test("with NO bridges configured, object + upload operations all succeed (Req 17.3, 19.3)", async () => {
61
+ const storage = createStorage({ provider: "memory" });
62
+ // Object operations.
63
+ const meta = await storage.put("k", "v");
64
+ assert.equal(meta.key, "k");
65
+ const got = await storage.get("k");
66
+ assert.equal(got.found, true);
67
+ await storage.delete("k");
68
+ assert.equal(await storage.exists("k"), false);
69
+ // Streaming upload.
70
+ const streamed = await storage.putStream("s", Readable.from([Buffer.from("stream-bytes")]));
71
+ assert.equal(streamed.key, "s");
72
+ assert.equal(await storage.exists("s"), true);
73
+ // Resumable upload.
74
+ const sessionId = await storage.startUpload("r");
75
+ const resumed = await storage.resumeUpload(sessionId, Readable.from([Buffer.from("resumed")]));
76
+ assert.equal(resumed.key, "r");
77
+ assert.equal(await storage.exists("r"), true);
78
+ });
79
+ test("with ALL THREE bridges throwing simultaneously, object operations still succeed (Req 17.4, 19.3)", async () => {
80
+ const storage = createStorage({ provider: "memory", bridges: throwingBridges() });
81
+ // put on a new key succeeds and returns metadata despite every bridge throwing.
82
+ const meta = await storage.put("k", "v", { contentType: "text/plain" });
83
+ assert.equal(meta.key, "k");
84
+ // get returns the stored bytes.
85
+ const got = await storage.get("k");
86
+ assert.equal(got.found, true);
87
+ // put overwriting (storage.updated path) still succeeds.
88
+ const updated = await storage.put("k", "v2");
89
+ assert.equal(updated.key, "k");
90
+ // delete succeeds and removes the object.
91
+ await storage.delete("k");
92
+ assert.equal(await storage.exists("k"), false);
93
+ });
94
+ test("with ALL THREE bridges throwing simultaneously, streaming + resumable uploads still succeed (Req 17.4, 19.3)", async () => {
95
+ const storage = createStorage({ provider: "memory", bridges: throwingBridges() });
96
+ // putStream broadcasts started/completed through a throwing realtime bridge —
97
+ // the upload must still complete.
98
+ const streamed = await storage.putStream("s", Readable.from([Buffer.from("stream-bytes")]));
99
+ assert.equal(streamed.key, "s");
100
+ assert.equal(await storage.exists("s"), true);
101
+ // resumeUpload likewise broadcasts through the throwing realtime bridge.
102
+ const sessionId = await storage.startUpload("r");
103
+ const resumed = await storage.resumeUpload(sessionId, Readable.from([Buffer.from("resumed")]));
104
+ assert.equal(resumed.key, "r");
105
+ assert.equal(await storage.exists("r"), true);
106
+ });
107
+ test("published events carry key + metadata even while queue + realtime bridges throw (Req 18.2)", async () => {
108
+ const events = recordingEvents();
109
+ const storage = createStorage({
110
+ provider: "memory",
111
+ bridges: {
112
+ events,
113
+ queue: {
114
+ dispatch() {
115
+ throw new Error("queue down");
116
+ },
117
+ },
118
+ realtime: {
119
+ broadcast() {
120
+ throw new Error("realtime down");
121
+ },
122
+ },
123
+ },
124
+ });
125
+ await storage.put("photo.png", "bytes", { contentType: "image/png" });
126
+ await storage.delete("photo.png");
127
+ assert.deepEqual(events.published.map((e) => e.event), ["storage.uploaded", "storage.deleted"]);
128
+ // storage.uploaded carries the affected key AND the full object metadata.
129
+ const uploaded = events.published[0].payload;
130
+ assert.equal(uploaded.key, "photo.png");
131
+ assert.ok(uploaded.metadata, "uploaded event must carry metadata");
132
+ assert.equal(uploaded.metadata.key, "photo.png");
133
+ assert.equal(uploaded.metadata.contentType, "image/png");
134
+ // storage.deleted carries the affected key.
135
+ const deleted = events.published[1].payload;
136
+ assert.equal(deleted.key, "photo.png");
137
+ });
138
+ //# sourceMappingURL=bridge-degradation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-degradation.test.js","sourceRoot":"","sources":["../../src/tests/bridge-degradation.test.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,eAAe;AACf,EAAE;AACF,0EAA0E;AAC1E,0DAA0D;AAC1D,6EAA6E;AAC7E,6EAA6E;AAC7E,2EAA2E;AAC3E,+EAA+E;AAC/E,2DAA2D;AAC3D,EAAE;AACF,WAAW;AACX,8EAA8E;AAC9E,mBAAmB;AACnB,2EAA2E;AAC3E,sDAAsD;AACtD,iFAAiF;AACjF,gFAAgF;AAChF,0EAA0E;AAC1E,aAAa;AACb,EAAE;AACF,kEAAkE;AAClE,sCAAsC;AACtC,EAAE;AACF,uCAAuC;AAEvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ5C,oEAAoE;AACpE,SAAS,eAAe;IACtB,OAAO;QACL,MAAM,EAAE;YACN,OAAO;gBACL,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACrC,CAAC;SACF;QACD,KAAK,EAAE;YACL,QAAQ;gBACN,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;YAChC,CAAC;SACF;QACD,QAAQ,EAAE;YACR,SAAS;gBACP,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;YACnC,CAAC;SACF;KACF,CAAC;AACJ,CAAC;AAED,gFAAgF;AAChF,SAAS,eAAe;IACtB,MAAM,SAAS,GAAoB,EAAE,CAAC;IACtC,OAAO;QACL,SAAS;QACT,OAAO,CAAC,KAAa,EAAE,OAAgB;YACrC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAA8B,EAAE,CAAC,CAAC;QACrE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,IAAI,CAAC,qFAAqF,EAAE,KAAK,IAAI,EAAE;IACrG,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEtD,qBAAqB;IACrB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC9B,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IAE/C,oBAAoB;IACpB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5F,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IAE9C,oBAAoB;IACpB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kGAAkG,EAAE,KAAK,IAAI,EAAE;IAClH,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;IAElF,gFAAgF;IAChF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC;IACxE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE5B,gCAAgC;IAChC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAE9B,yDAAyD;IACzD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE/B,0CAA0C;IAC1C,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8GAA8G,EAAE,KAAK,IAAI,EAAE;IAC9H,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;IAElF,8EAA8E;IAC9E,kCAAkC;IAClC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5F,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IAE9C,yEAAyE;IACzE,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;IAC5G,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,aAAa,CAAC;QAC5B,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE;YACP,MAAM;YACN,KAAK,EAAE;gBACL,QAAQ;oBACN,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;gBAChC,CAAC;aACF;YACD,QAAQ,EAAE;gBACR,SAAS;oBACP,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;gBACnC,CAAC;aACF;SACF;KACF,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IACtE,MAAM,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAElC,MAAM,CAAC,SAAS,CACd,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EACpC,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CACxC,CAAC;IAEF,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACxC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,oCAAoC,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAEzD,4CAA4C;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC5C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AACzC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.d.ts","sourceRoot":"","sources":["../../src/tests/cli.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,127 @@
1
+ // cli.test.js — unit tests for the @streetjs/storage CLI generators and the
2
+ // storage:verify command (Requirements 21.2, 21.4).
3
+ //
4
+ // Covers three concerns:
5
+ // (1) Generator name validation — isValidGeneratorName / generateStorage
6
+ // reject invalid names and accept valid PascalCase identifiers.
7
+ // (2) Compile-clean scaffold output — the generated `contents` imports only
8
+ // public @streetjs/storage symbols (createStorage + StorageConfig) and
9
+ // wires them into a typed factory.
10
+ // (3) storage:verify pass/fail reporting — StorageCommands.storageVerify
11
+ // reports a pass for the built-in memory provider (process.exitCode is
12
+ // not set to 1) and a failure for an unknown/misconfigured provider
13
+ // (process.exitCode === 1).
14
+ //
15
+ // Uses the Node.js built-in test runner (node:test); executed via
16
+ // `node --test dist/tests/*.test.js`.
17
+ import test from "node:test";
18
+ import assert from "node:assert/strict";
19
+ import { generateStorage, isValidGeneratorName, isValidProvider, DEFAULT_STORAGE_DIR, } from "../cli/generators.js";
20
+ import { StorageCommands } from "../cli/commands.js";
21
+ // ── Helpers ───────────────────────────────────────────────────────────────────
22
+ /** Build a ParsedArgs object matching the shape streetjs' parseArgv produces. */
23
+ function parsedArgs(options = {}) {
24
+ const { command = null, positional = [], flags = {} } = options;
25
+ return { command, positional, flags };
26
+ }
27
+ /**
28
+ * Run `fn` while capturing everything written to console.log/console.error and
29
+ * with process.exitCode reset, restoring both afterwards. Returns the captured
30
+ * output plus the exitCode observed after `fn` completes.
31
+ */
32
+ async function captureRun(fn) {
33
+ const originalLog = console.log;
34
+ const originalError = console.error;
35
+ const originalExitCode = process.exitCode;
36
+ const logs = [];
37
+ const errors = [];
38
+ console.log = (...args) => logs.push(args.join(" "));
39
+ console.error = (...args) => errors.push(args.join(" "));
40
+ process.exitCode = undefined;
41
+ try {
42
+ await fn();
43
+ return { logs, errors, exitCode: process.exitCode };
44
+ }
45
+ finally {
46
+ console.log = originalLog;
47
+ console.error = originalError;
48
+ process.exitCode = originalExitCode;
49
+ }
50
+ }
51
+ // ── (1) Generator name validation ──────────────────────────────────────────────
52
+ test("isValidGeneratorName rejects invalid names and accepts PascalCase", () => {
53
+ // Invalid: empty, non-identifier, leading digit, hyphen/space/dot.
54
+ assert.equal(isValidGeneratorName(""), false);
55
+ assert.equal(isValidGeneratorName("1Uploads"), false);
56
+ assert.equal(isValidGeneratorName("my-storage"), false);
57
+ assert.equal(isValidGeneratorName("my storage"), false);
58
+ assert.equal(isValidGeneratorName("Up.loads"), false);
59
+ assert.equal(isValidGeneratorName("$Uploads"), false);
60
+ // Valid: identifier-safe tokens including PascalCase.
61
+ assert.equal(isValidGeneratorName("Uploads"), true);
62
+ assert.equal(isValidGeneratorName("UserAvatars"), true);
63
+ assert.equal(isValidGeneratorName("A1"), true);
64
+ assert.equal(isValidGeneratorName("uploads"), true);
65
+ });
66
+ test("generateStorage throws for invalid names before producing output", () => {
67
+ assert.throws(() => generateStorage(""), /Invalid generator name/);
68
+ assert.throws(() => generateStorage("bad-name"), /Invalid generator name/);
69
+ assert.throws(() => generateStorage("9lives"), /Invalid generator name/);
70
+ });
71
+ test("generateStorage throws for a non-built-in provider", () => {
72
+ assert.throws(() => generateStorage("Uploads", DEFAULT_STORAGE_DIR, "s3"), /Invalid storage provider/);
73
+ assert.equal(isValidProvider("memory"), true);
74
+ assert.equal(isValidProvider("local"), true);
75
+ assert.equal(isValidProvider("s3"), false);
76
+ });
77
+ // ── (2) Compile-clean scaffold output ──────────────────────────────────────────
78
+ test("generateStorage emits a scaffold importing only public @streetjs/storage symbols", () => {
79
+ const result = generateStorage("Uploads");
80
+ // Path is derived from the PascalCase class name under the default dir.
81
+ assert.ok(result.path.endsWith("UploadsStorage.ts"), `unexpected path: ${result.path}`);
82
+ const contents = result.contents;
83
+ // Imports only the public package entry point (no deep/internal imports).
84
+ assert.match(contents, /import \{ createStorage \} from "@streetjs\/storage";/);
85
+ assert.match(contents, /import type \{ Storage, StorageConfig \} from "@streetjs\/storage";/);
86
+ assert.ok(!/from "\.\//.test(contents) && !/from "\.\.\//.test(contents), "scaffold must not import from relative/internal paths");
87
+ // Wires a typed StorageConfig and a factory that calls createStorage.
88
+ assert.match(contents, /: StorageConfig = \{/);
89
+ assert.match(contents, /provider: "memory"/);
90
+ assert.match(contents, /export function createUploadsStorage\(\): Storage \{/);
91
+ assert.match(contents, /return createStorage\(/);
92
+ });
93
+ test("generateStorage local provider scaffold supplies a root and stays on the public surface", () => {
94
+ const result = generateStorage("Assets", DEFAULT_STORAGE_DIR, "local");
95
+ const contents = result.contents;
96
+ assert.match(contents, /provider: "local"/);
97
+ assert.match(contents, /root: "\.\/var\/assets"/);
98
+ assert.match(contents, /import \{ createStorage \} from "@streetjs\/storage";/);
99
+ });
100
+ // ── (3) storage:verify pass/fail reporting ──────────────────────────────────────
101
+ test("storageVerify reports a pass for the built-in memory provider", async () => {
102
+ const commands = new StorageCommands();
103
+ const args = parsedArgs({ command: "storage:verify", flags: { provider: "memory" } });
104
+ const { logs, exitCode } = await captureRun(() => commands.storageVerify(args));
105
+ // A passing run must NOT set a failure exit code.
106
+ assert.notEqual(exitCode, 1);
107
+ const output = logs.join("\n");
108
+ assert.match(output, /Contract conformance for driver "memory"/);
109
+ assert.match(output, /— PASS\./);
110
+ // No FAIL check lines expected.
111
+ assert.ok(!/\[FAIL\]/.test(output), "memory provider should have no failing checks");
112
+ });
113
+ test("storageVerify reports failure for an unknown provider (exitCode 1)", async () => {
114
+ const commands = new StorageCommands();
115
+ const args = parsedArgs({ command: "storage:verify", flags: { provider: "does-not-exist" } });
116
+ const { errors, exitCode } = await captureRun(() => commands.storageVerify(args));
117
+ assert.equal(exitCode, 1);
118
+ assert.match(errors.join("\n"), /Unknown storage provider "does-not-exist"/);
119
+ });
120
+ test("storageVerify reports failure for a misconfigured local provider (missing root)", async () => {
121
+ const commands = new StorageCommands();
122
+ const args = parsedArgs({ command: "storage:verify", flags: { provider: "local" } });
123
+ const { errors, exitCode } = await captureRun(() => commands.storageVerify(args));
124
+ assert.equal(exitCode, 1);
125
+ assert.match(errors.join("\n"), /"local" storage provider requires a "root" directory/);
126
+ });
127
+ //# sourceMappingURL=cli.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../src/tests/cli.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * @streetjs/storage — the shared, parameterized contract-conformance suite.
3
+ *
4
+ * Requirement 2 states that every provider implements one `StorageDriver`
5
+ * contract with identical observable behavior: object existence, content bytes,
6
+ * and returned metadata must be equivalent across drivers (Requirement 2.1,
7
+ * 2.3), and a missing key must be reported the same way everywhere
8
+ * (Requirement 2.4). This module encodes the observable core of that contract
9
+ * as a **reusable, driver-agnostic conformance suite** so the exact same checks
10
+ * can be run against any {@link StorageDriver} — the zero-dependency Memory and
11
+ * Local drivers, the in-process testing doubles, and every cloud driver.
12
+ *
13
+ * The suite is designed to be consumed in two ways from one definition:
14
+ *
15
+ * - **Programmatically** (returns pass/fail results). {@link runStorageDriverContract}
16
+ * runs every check against a freshly constructed driver and returns a
17
+ * {@link ContractReport} describing which checks passed. This is what the
18
+ * `storage:verify` CLI command (task 24.2) uses to report whether the
19
+ * configured driver satisfies the contract, and what Property 19 (task 27.3)
20
+ * uses to assert that every driver conforms.
21
+ * - **As node:test tests**. {@link registerStorageDriverContractTests} turns each
22
+ * check into a `node:test` case using a caller-supplied `test` function, so a
23
+ * thin `*.test.js` can run the suite against Memory + Local without this
24
+ * support module importing `node:test` itself (keeping it importable from the
25
+ * CLI, which has no test runner in scope).
26
+ *
27
+ * Each check receives its **own freshly constructed driver** (from the supplied
28
+ * factory) so checks are fully isolated and order-independent. Assertions use
29
+ * `node:assert/strict`; a check throws on failure and returns normally on
30
+ * success. The checked behaviors are:
31
+ *
32
+ * 1. **existence** — `put` then `exists(key)` is `true`; `exists(other)` is `false`.
33
+ * 2. **byte round-trip** — `put(key, bytes)` then `get(key)` yields
34
+ * `{ found: true }` with content bytes exactly equal to the input.
35
+ * 3. **not-found (get)** — `get(missing)` yields `{ found: false }`.
36
+ * 4. **not-found (stat)** — `stat(missing)` yields `null`.
37
+ * 5. **metadata shape** — `put` returns the complete typed
38
+ * {@link StorageObjectMetadata} field set with correctly typed values.
39
+ *
40
+ * This module is a support module under `src/tests/` (not itself a `*.test.js`
41
+ * picked up by the default test glob); it is imported by tests and by the CLI.
42
+ *
43
+ * _Requirements: 2.1, 2.3, 2.4_
44
+ */
45
+ import type { StorageDriver } from "../driver.js";
46
+ /**
47
+ * A single named conformance check. {@link run} performs the check against the
48
+ * supplied driver and throws (via `node:assert`) when the driver violates the
49
+ * contract; it returns normally when the check passes.
50
+ */
51
+ export interface ContractCheck {
52
+ /** Stable, human-readable check name (e.g. "byte round-trip"). */
53
+ readonly name: string;
54
+ /** The acceptance-criteria reference this check exercises. */
55
+ readonly requirement: string;
56
+ /** Run the check against `driver`; throws on violation. */
57
+ run(driver: StorageDriver): Promise<void>;
58
+ }
59
+ /** The outcome of running a single {@link ContractCheck}. */
60
+ export interface ContractCheckResult {
61
+ readonly name: string;
62
+ readonly requirement: string;
63
+ readonly passed: boolean;
64
+ /** The failure message when {@link passed} is `false`. */
65
+ readonly error?: string;
66
+ }
67
+ /** The aggregate outcome of running the whole suite against one driver. */
68
+ export interface ContractReport {
69
+ /** The `name` of the driver under test (e.g. "memory", "local", "s3"). */
70
+ readonly driver: string;
71
+ /** `true` when every check passed. */
72
+ readonly passed: boolean;
73
+ /** Per-check results, in suite order. */
74
+ readonly results: readonly ContractCheckResult[];
75
+ }
76
+ /**
77
+ * Produces a fresh {@link StorageDriver} to test. A new instance is requested
78
+ * for each check so the checks are isolated from one another; the factory may
79
+ * be async (e.g. to allocate a temp directory for the Local driver).
80
+ */
81
+ export type StorageDriverFactory = () => StorageDriver | Promise<StorageDriver>;
82
+ /**
83
+ * A minimal `node:test`-style runner: a function taking a test name and an async
84
+ * body. Callers pass `test` from `node:test`; typing it structurally keeps this
85
+ * module free of a hard `node:test` import so it stays importable from the CLI.
86
+ */
87
+ export type TestRunner = (name: string, fn: () => void | Promise<void>) => unknown;
88
+ /**
89
+ * The ordered set of observable-behavior checks that make up the driver
90
+ * contract-conformance suite. Exported so consumers can inspect, subset, or
91
+ * extend the list; most callers use {@link runStorageDriverContract} or
92
+ * {@link registerStorageDriverContractTests} instead.
93
+ */
94
+ export declare const storageDriverContractChecks: readonly ContractCheck[];
95
+ /** Options for {@link runStorageDriverContract}. */
96
+ export interface RunContractOptions {
97
+ /** Override the checks to run. Defaults to {@link storageDriverContractChecks}. */
98
+ readonly checks?: readonly ContractCheck[];
99
+ }
100
+ /**
101
+ * Run the contract-conformance suite against a driver and return a pass/fail
102
+ * {@link ContractReport}. Each check is executed against a freshly constructed
103
+ * driver from `makeDriver` so the checks never interfere with one another.
104
+ *
105
+ * This never throws for a contract violation — a failing check is captured as a
106
+ * `passed: false` entry with its error message — so a consumer such as the
107
+ * `storage:verify` CLI (task 24.2) can render every result. Property 19
108
+ * (task 27.3) uses the returned {@link ContractReport.passed} to assert
109
+ * conformance across drivers.
110
+ *
111
+ * @param makeDriver Factory producing a fresh driver for each check.
112
+ * @param options Optional override of the checks to run.
113
+ */
114
+ export declare function runStorageDriverContract(makeDriver: StorageDriverFactory, options?: RunContractOptions): Promise<ContractReport>;
115
+ /**
116
+ * Register each contract check as an individual `node:test` case using the
117
+ * supplied `test` runner. A thin `*.test.js` passes `test` from `node:test` and
118
+ * a driver factory; each check runs against a fresh driver and fails the test if
119
+ * the driver violates the contract.
120
+ *
121
+ * Taking the runner as a parameter keeps this module free of a hard `node:test`
122
+ * import, so it remains importable from non-test contexts (e.g. the CLI's
123
+ * `storage:verify`).
124
+ *
125
+ * @param label Prefix for each generated test name (e.g. the driver label).
126
+ * @param makeDriver Factory producing a fresh driver for each check.
127
+ * @param runner The `test` function from `node:test` (or a compatible runner).
128
+ * @param checks Optional override of the checks to run.
129
+ */
130
+ export declare function registerStorageDriverContractTests(label: string, makeDriver: StorageDriverFactory, runner: TestRunner, checks?: readonly ContractCheck[]): void;
131
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/tests/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMlD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2DAA2D;IAC3D,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAClD;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC;AAmEnF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,aAAa,EAuE/D,CAAC;AAIF,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,oBAAoB,EAChC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,cAAc,CAAC,CA0BzB;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,SAAS,aAAa,EAAgC,GAC7D,IAAI,CAON"}