@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,270 @@
1
+ // Unit tests for the provider-agnostic access controller of @streetjs/storage.
2
+ //
3
+ // Covers the AccessController decision rules directly (permissive default,
4
+ // public-read allowance, bridge-governed deny/permit for every access level)
5
+ // and the facade wiring: with a configured `config.auth` bridge, a denied
6
+ // operation throws an AuthorizationError and performs no persistence/read;
7
+ // with NO bridge configured the facade stays fully permissive (Requirements
8
+ // 11.1, 11.2, 11.3, 11.4).
9
+ //
10
+ // Uses the Node.js built-in test runner (node:test), executed via
11
+ // `node --test dist/tests/*.test.js`.
12
+ //
13
+ // Requirements: 11.1, 11.2, 11.3, 11.4
14
+ import test from "node:test";
15
+ import assert from "node:assert/strict";
16
+ import { AccessController } from "../access.js";
17
+ import { createStorage } from "../facade.js";
18
+ import { AuthorizationError } from "../errors.js";
19
+ // A tiny structural AuthLike bridge whose `can` is driven by an injected fn.
20
+ function makeAuth(decision) {
21
+ const calls = [];
22
+ return {
23
+ calls,
24
+ can(context) {
25
+ calls.push(context);
26
+ return typeof decision === "function" ? decision(context) : decision;
27
+ },
28
+ };
29
+ }
30
+ // ── Controller-level tests ────────────────────────────────────────────────────
31
+ test("controller with no auth bridge is permissive and not enforced", async () => {
32
+ const access = new AccessController();
33
+ assert.equal(access.enforced, false);
34
+ // Even a normally-restricted level is permitted when nothing is configured.
35
+ await access.authorize({ key: "k", operation: "write", accessLevel: "private" });
36
+ await access.authorize({ key: "k", operation: "read", accessLevel: "role-based" });
37
+ });
38
+ test("controller reports enforced when an auth bridge is configured", () => {
39
+ const access = new AccessController({ auth: makeAuth(true) });
40
+ assert.equal(access.enforced, true);
41
+ });
42
+ test("controller supports every access level and denies when the bridge says false", async () => {
43
+ const levels = ["public", "private", "signed", "authenticated", "role-based", "tenant-aware"];
44
+ for (const accessLevel of levels) {
45
+ const access = new AccessController({ auth: makeAuth(false) });
46
+ // A write is denied for every level when the bridge returns false (11.1/11.3).
47
+ await assert.rejects(() => access.authorize({ key: "k", operation: "write", accessLevel }), (err) => err instanceof AuthorizationError && err.accessLevel === accessLevel);
48
+ }
49
+ });
50
+ test("controller permits when the bridge returns true", async () => {
51
+ const auth = makeAuth(true);
52
+ const access = new AccessController({ auth });
53
+ await access.authorize({
54
+ key: "docs/a.txt",
55
+ operation: "read",
56
+ accessLevel: "authenticated",
57
+ owner: "alice",
58
+ tenant: "acme",
59
+ });
60
+ // The full context is forwarded to the bridge (11.2).
61
+ assert.deepEqual(auth.calls[0], {
62
+ key: "docs/a.txt",
63
+ operation: "read",
64
+ accessLevel: "authenticated",
65
+ owner: "alice",
66
+ tenant: "acme",
67
+ });
68
+ });
69
+ test("public reads are permitted without authentication (bridge returns false)", async () => {
70
+ // Even when the bridge denies by default, a public READ is still allowed
71
+ // unless the bridge is treating public as the blocking factor. Here the
72
+ // bridge only blocks writes; public reads pass (Requirement 11.4).
73
+ const access = new AccessController({
74
+ auth: makeAuth((ctx) => ctx.operation !== "write"),
75
+ });
76
+ await access.authorize({ key: "p", operation: "read", accessLevel: "public" });
77
+ });
78
+ test("public reads can still be blocked by a configured factor", async () => {
79
+ // A bridge that explicitly returns false blocks even a public read
80
+ // ("unless another configured factor blocks", Requirement 11.4).
81
+ const access = new AccessController({ auth: makeAuth(false) });
82
+ await assert.rejects(() => access.authorize({ key: "p", operation: "read", accessLevel: "public" }), (err) => err instanceof AuthorizationError);
83
+ });
84
+ test("controller awaits an async bridge decision", async () => {
85
+ const access = new AccessController({ auth: makeAuth(async () => false) });
86
+ await assert.rejects(() => access.authorize({ key: "k", operation: "read", accessLevel: "private" }), (err) => err instanceof AuthorizationError);
87
+ });
88
+ // ── Facade wiring tests ─────────────────────────────────────────────────────
89
+ test("facade stays permissive when no auth bridge is configured", async () => {
90
+ const storage = createStorage({ provider: "memory" });
91
+ const meta = await storage.put("a.txt", "hello", { accessLevel: "private" });
92
+ assert.equal(meta.key, "a.txt");
93
+ const got = await storage.get("a.txt");
94
+ assert.equal(got.found, true);
95
+ await storage.delete("a.txt");
96
+ assert.equal(await storage.exists("a.txt"), false);
97
+ });
98
+ test("facade put denial throws AuthorizationError and persists nothing", async () => {
99
+ const storage = createStorage({
100
+ provider: "memory",
101
+ auth: makeAuth((ctx) => ctx.operation !== "write"),
102
+ });
103
+ await assert.rejects(() => storage.put("secret.txt", "top secret", { accessLevel: "private" }), (err) => err instanceof AuthorizationError && err.operation === "write");
104
+ // Nothing was written.
105
+ assert.equal(await storage.exists("secret.txt"), false);
106
+ });
107
+ test("facade get denial throws AuthorizationError and returns no bytes", async () => {
108
+ // The bridge permits the initial write but denies reads.
109
+ let allowRead = true;
110
+ const storage = createStorage({
111
+ provider: "memory",
112
+ auth: makeAuth((ctx) => (ctx.operation === "read" ? allowRead : true)),
113
+ });
114
+ await storage.put("doc.txt", "content", { accessLevel: "authenticated" });
115
+ allowRead = false;
116
+ await assert.rejects(() => storage.get("doc.txt"), (err) => err instanceof AuthorizationError && err.operation === "read");
117
+ });
118
+ test("facade get of a public object is permitted without authentication", async () => {
119
+ // The bridge permits the seeding write and any public read, but denies every
120
+ // non-public read. A public object must remain readable (Requirement 11.4).
121
+ const storage = createStorage({
122
+ provider: "memory",
123
+ auth: makeAuth((ctx) => ctx.operation === "write" || ctx.accessLevel === "public"),
124
+ });
125
+ await storage.put("pub.txt", "hello", { accessLevel: "public" });
126
+ const got = await storage.get("pub.txt");
127
+ assert.equal(got.found, true);
128
+ assert.equal(new TextDecoder().decode(got.bytes), "hello");
129
+ });
130
+ test("facade delete denial throws AuthorizationError and keeps the object", async () => {
131
+ let allowDelete = true;
132
+ const storage = createStorage({
133
+ provider: "memory",
134
+ auth: makeAuth((ctx) => (ctx.operation === "delete" ? allowDelete : true)),
135
+ });
136
+ await storage.put("keep.txt", "content", { accessLevel: "private" });
137
+ allowDelete = false;
138
+ await assert.rejects(() => storage.delete("keep.txt"), (err) => err instanceof AuthorizationError && err.operation === "delete");
139
+ assert.equal(await storage.exists("keep.txt"), true);
140
+ });
141
+ // ── Task 16.2: exhaustive per-level allow/deny + auth-bridge integration ─────
142
+ //
143
+ // The cases above prove the permissive default, the public-read allowance, and
144
+ // a single deny path per level (write). The block below rounds out the access
145
+ // decision matrix required by this task: an explicit ALLOW *and* an explicit
146
+ // DENY for EACH access level, across read/write/delete, plus context-driven
147
+ // role-based and tenant-aware decisions and an async bridge that permits.
148
+ //
149
+ // Requirements: 11.1, 11.3, 11.4
150
+ const ALL_LEVELS = [
151
+ "public",
152
+ "private",
153
+ "signed",
154
+ "authenticated",
155
+ "role-based",
156
+ "tenant-aware",
157
+ ];
158
+ const ALL_OPERATIONS = ["read", "write", "delete"];
159
+ test("controller permits every access level across every operation when the bridge allows", async () => {
160
+ for (const accessLevel of ALL_LEVELS) {
161
+ for (const operation of ALL_OPERATIONS) {
162
+ const auth = makeAuth(true);
163
+ const access = new AccessController({ auth });
164
+ // Should resolve without throwing for allow (11.1).
165
+ await access.authorize({ key: `k/${accessLevel}`, operation, accessLevel });
166
+ // The bridge was consulted with the exact context (11.2 wiring).
167
+ assert.deepEqual(auth.calls.at(-1), {
168
+ key: `k/${accessLevel}`,
169
+ operation,
170
+ accessLevel,
171
+ owner: undefined,
172
+ tenant: undefined,
173
+ });
174
+ }
175
+ }
176
+ });
177
+ test("controller denies every access level across write/delete when the bridge blocks", async () => {
178
+ // Read is validated separately below because `public` reads have a distinct
179
+ // rule; here we cover the uniformly-denied write and delete operations for
180
+ // EACH level (11.3).
181
+ for (const accessLevel of ALL_LEVELS) {
182
+ for (const operation of ["write", "delete"]) {
183
+ const access = new AccessController({ auth: makeAuth(false) });
184
+ await assert.rejects(() => access.authorize({ key: "k", operation, accessLevel }), (err) => err instanceof AuthorizationError &&
185
+ err.accessLevel === accessLevel &&
186
+ err.operation === operation);
187
+ }
188
+ }
189
+ });
190
+ test("controller denies non-public reads for every restricted level when the bridge blocks", async () => {
191
+ // A `read` is denied for every NON-public level when the bridge returns false
192
+ // (public reads are covered by the dedicated 11.4 cases above).
193
+ for (const accessLevel of ALL_LEVELS.filter((l) => l !== "public")) {
194
+ const access = new AccessController({ auth: makeAuth(false) });
195
+ await assert.rejects(() => access.authorize({ key: "k", operation: "read", accessLevel }), (err) => err instanceof AuthorizationError && err.accessLevel === accessLevel);
196
+ }
197
+ });
198
+ test("signed access level allows and denies strictly per the bridge decision", async () => {
199
+ const allow = new AccessController({ auth: makeAuth(true) });
200
+ await allow.authorize({ key: "s", operation: "read", accessLevel: "signed" });
201
+ const deny = new AccessController({ auth: makeAuth(false) });
202
+ await assert.rejects(() => deny.authorize({ key: "s", operation: "read", accessLevel: "signed" }), (err) => err instanceof AuthorizationError && err.accessLevel === "signed");
203
+ });
204
+ test("authenticated access level allows and denies strictly per the bridge decision", async () => {
205
+ const allow = new AccessController({ auth: makeAuth(true) });
206
+ await allow.authorize({ key: "a", operation: "write", accessLevel: "authenticated" });
207
+ const deny = new AccessController({ auth: makeAuth(false) });
208
+ await assert.rejects(() => deny.authorize({ key: "a", operation: "write", accessLevel: "authenticated" }), (err) => err instanceof AuthorizationError && err.accessLevel === "authenticated");
209
+ });
210
+ test("role-based decisions key on the bridge's view of the context", async () => {
211
+ // A structural bridge modelling roles: only the owner "admin" may write a
212
+ // role-based object; everyone else is denied. This exercises the bridge
213
+ // integration for role-based access (11.1/11.2/11.3).
214
+ const roleBridge = makeAuth((ctx) => ctx.owner === "admin");
215
+ const access = new AccessController({ auth: roleBridge });
216
+ await access.authorize({
217
+ key: "r",
218
+ operation: "write",
219
+ accessLevel: "role-based",
220
+ owner: "admin",
221
+ });
222
+ await assert.rejects(() => access.authorize({
223
+ key: "r",
224
+ operation: "write",
225
+ accessLevel: "role-based",
226
+ owner: "guest",
227
+ }), (err) => err instanceof AuthorizationError && err.accessLevel === "role-based");
228
+ });
229
+ test("tenant-aware decisions isolate access to the matching tenant", async () => {
230
+ // A structural bridge modelling tenant isolation: access is granted only when
231
+ // the context tenant matches the bridge's expected tenant (11.1/11.2/11.3).
232
+ const expectedTenant = "acme";
233
+ const tenantBridge = makeAuth((ctx) => ctx.tenant === expectedTenant);
234
+ const access = new AccessController({ auth: tenantBridge });
235
+ await access.authorize({
236
+ key: "t",
237
+ operation: "read",
238
+ accessLevel: "tenant-aware",
239
+ tenant: "acme",
240
+ });
241
+ await assert.rejects(() => access.authorize({
242
+ key: "t",
243
+ operation: "read",
244
+ accessLevel: "tenant-aware",
245
+ tenant: "other-corp",
246
+ }), (err) => err instanceof AuthorizationError && err.accessLevel === "tenant-aware");
247
+ });
248
+ test("controller permits when an async bridge resolves true", async () => {
249
+ // Complements the existing async-deny case: an async bridge that resolves
250
+ // true must be awaited and permit the operation.
251
+ const access = new AccessController({ auth: makeAuth(async () => true) });
252
+ await access.authorize({ key: "k", operation: "write", accessLevel: "private" });
253
+ });
254
+ test("private access level allows and denies strictly per the bridge decision", async () => {
255
+ const allow = new AccessController({ auth: makeAuth(true) });
256
+ await allow.authorize({ key: "pv", operation: "delete", accessLevel: "private" });
257
+ const deny = new AccessController({ auth: makeAuth(false) });
258
+ await assert.rejects(() => deny.authorize({ key: "pv", operation: "delete", accessLevel: "private" }), (err) => err instanceof AuthorizationError && err.accessLevel === "private");
259
+ });
260
+ test("facade put of a role-based object is denied for a non-owner and persists nothing", async () => {
261
+ // End-to-end auth-bridge integration through the facade for a role-based
262
+ // level: a non-admin writer is denied and no object is persisted (11.3).
263
+ const storage = createStorage({
264
+ provider: "memory",
265
+ auth: makeAuth((ctx) => ctx.owner === "admin"),
266
+ });
267
+ await assert.rejects(() => storage.put("role.txt", "data", { accessLevel: "role-based", owner: "guest" }), (err) => err instanceof AuthorizationError && err.operation === "write");
268
+ assert.equal(await storage.exists("role.txt"), false);
269
+ });
270
+ //# sourceMappingURL=access.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.test.js","sourceRoot":"","sources":["../../src/tests/access.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=azure-driver.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-driver.test.d.ts","sourceRoot":"","sources":["../../src/tests/azure-driver.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,183 @@
1
+ // Unit tests for the Azure Blob driver submodule (task 29.3). Azure Blob does
2
+ // not speak the S3 wire shape, so this driver maps the StorageDriver contract
3
+ // directly onto a structural AzureBlobClientLike (not the S3-style base). These
4
+ // tests exercise the injected-client path with an in-memory AzureBlobClientLike
5
+ // double (no `@azure/storage-blob` SDK, no external service), the
6
+ // StorageConfigError guard when no client is injected, the lazy-SDK connect
7
+ // path when the SDK is absent, and the shared driver contract-conformance suite.
8
+ //
9
+ // Requirements: 2.1, 2.3, 3.3
10
+ import test from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { createAzureBlobDriver, connectAzureBlobDriver } from "../drivers/azure.js";
13
+ import { StorageConfigError } from "../errors.js";
14
+ import { registerStorageDriverContractTests } from "./contract.js";
15
+ const FIXED_NOW = 1_700_000_000_000;
16
+ const fixedClock = () => FIXED_NOW;
17
+ function bytes(str) {
18
+ return new TextEncoder().encode(str);
19
+ }
20
+ /** A minimal in-memory AzureBlobClientLike double. */
21
+ function makeFakeClient() {
22
+ const blobs = new Map(); // blobName -> { body, contentType, metadata }
23
+ return {
24
+ async upload({ blobName, body, contentType, metadata }) {
25
+ blobs.set(blobName, {
26
+ body: body.slice(),
27
+ contentType,
28
+ metadata: metadata ? { ...metadata } : undefined,
29
+ });
30
+ return { etag: `"${blobName}-etag"` };
31
+ },
32
+ async download({ blobName }) {
33
+ const blob = blobs.get(blobName);
34
+ if (blob === undefined)
35
+ return null;
36
+ return {
37
+ body: blob.body.slice(),
38
+ contentType: blob.contentType,
39
+ etag: `"${blobName}-etag"`,
40
+ contentLength: blob.body.byteLength,
41
+ lastModified: FIXED_NOW,
42
+ metadata: blob.metadata,
43
+ };
44
+ },
45
+ async getProperties({ blobName }) {
46
+ const blob = blobs.get(blobName);
47
+ if (blob === undefined)
48
+ return null;
49
+ return {
50
+ contentType: blob.contentType,
51
+ etag: `"${blobName}-etag"`,
52
+ contentLength: blob.body.byteLength,
53
+ lastModified: FIXED_NOW,
54
+ metadata: blob.metadata,
55
+ };
56
+ },
57
+ async deleteBlob({ blobName }) {
58
+ blobs.delete(blobName);
59
+ },
60
+ async exists({ blobName }) {
61
+ return blobs.has(blobName);
62
+ },
63
+ async listBlobs({ prefix }) {
64
+ return [...blobs.entries()]
65
+ .filter(([name]) => name.startsWith(prefix))
66
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
67
+ .map(([name, blob]) => ({
68
+ name,
69
+ contentLength: blob.body.byteLength,
70
+ lastModified: FIXED_NOW,
71
+ }));
72
+ },
73
+ };
74
+ }
75
+ function makeDriver() {
76
+ return createAzureBlobDriver(makeFakeClient(), { clock: fixedClock });
77
+ }
78
+ // ── name ──────────────────────────────────────────────────────────────────────
79
+ test("driver name is azure", () => {
80
+ assert.equal(makeDriver().name, "azure");
81
+ });
82
+ // ── injected-client primitives round-trip ─────────────────────────────────────
83
+ test("put/get round-trips bytes and typed metadata over the injected client", async () => {
84
+ const driver = makeDriver();
85
+ const content = bytes("azure blob payload");
86
+ await driver.put("container/key.txt", content, {
87
+ contentType: "text/plain",
88
+ owner: "user-7",
89
+ tenant: "tenant-q",
90
+ accessLevel: "public",
91
+ custom: { label: "report" },
92
+ });
93
+ const result = await driver.get("container/key.txt");
94
+ assert.equal(result.found, true);
95
+ assert.deepEqual(result.bytes, content);
96
+ assert.equal(result.metadata.contentType, "text/plain");
97
+ assert.equal(result.metadata.owner, "user-7");
98
+ assert.equal(result.metadata.tenant, "tenant-q");
99
+ assert.equal(result.metadata.accessLevel, "public");
100
+ assert.deepEqual(result.metadata.custom, { label: "report" });
101
+ assert.equal(result.metadata.size, content.byteLength);
102
+ });
103
+ test("exists/delete/stat/list behave consistently", async () => {
104
+ const driver = makeDriver();
105
+ await driver.put("d/a.txt", bytes("a"), {});
106
+ await driver.put("d/b.txt", bytes("bb"), {});
107
+ assert.equal(await driver.exists("d/a.txt"), true);
108
+ assert.equal(await driver.exists("d/missing.txt"), false);
109
+ const stat = await driver.stat("d/b.txt");
110
+ assert.ok(stat);
111
+ assert.equal(stat.size, 2);
112
+ assert.equal(await driver.stat("d/missing.txt"), null);
113
+ const items = await driver.list("d/");
114
+ assert.deepEqual(items.map((i) => i.key), ["d/a.txt", "d/b.txt"]);
115
+ await driver.delete("d/a.txt");
116
+ assert.equal(await driver.exists("d/a.txt"), false);
117
+ });
118
+ test("list honors the limit option", async () => {
119
+ const driver = makeDriver();
120
+ await driver.put("p/1.txt", bytes("1"), {});
121
+ await driver.put("p/2.txt", bytes("2"), {});
122
+ await driver.put("p/3.txt", bytes("3"), {});
123
+ const items = await driver.list("p/", { limit: 2 });
124
+ assert.deepEqual(items.map((i) => i.key), ["p/1.txt", "p/2.txt"]);
125
+ });
126
+ test("get on a missing key reports found:false", async () => {
127
+ const driver = makeDriver();
128
+ const result = await driver.get("nope");
129
+ assert.equal(result.found, false);
130
+ });
131
+ test("overwrite preserves createdAt and advances updatedAt semantics", async () => {
132
+ const driver = makeDriver();
133
+ const first = await driver.put("k.txt", bytes("one"), {});
134
+ const second = await driver.put("k.txt", bytes("two-longer"), {});
135
+ assert.equal(second.createdAt, first.createdAt);
136
+ assert.equal(second.size, bytes("two-longer").byteLength);
137
+ });
138
+ // ── streaming ───────────────────────────────────────────────────────────────
139
+ test("putStream/getStream round-trips content", async () => {
140
+ const { Readable } = await import("node:stream");
141
+ const driver = makeDriver();
142
+ const content = bytes("streamed azure content");
143
+ await driver.putStream("s/obj.bin", Readable.from([Buffer.from(content)]), {});
144
+ const stream = await driver.getStream("s/obj.bin");
145
+ const chunks = [];
146
+ for await (const chunk of stream)
147
+ chunks.push(chunk);
148
+ assert.deepEqual(new Uint8Array(Buffer.concat(chunks)), content);
149
+ });
150
+ test("getStream throws on a missing key", async () => {
151
+ const driver = makeDriver();
152
+ await assert.rejects(() => driver.getStream("absent"));
153
+ });
154
+ // ── advanced capabilities left undefined for facade simulation ────────────────
155
+ test("advanced capabilities are left undefined for facade simulation", () => {
156
+ const driver = makeDriver();
157
+ assert.equal(driver.multipart, undefined);
158
+ assert.equal(driver.resumable, undefined);
159
+ assert.equal(driver.versioning, undefined);
160
+ assert.equal(driver.signedUrl, undefined);
161
+ assert.equal(driver.lifecycle, undefined);
162
+ });
163
+ // ── configuration guards ──────────────────────────────────────────────────────
164
+ test("createAzureBlobDriver throws StorageConfigError when no client is injected", () => {
165
+ assert.throws(() => createAzureBlobDriver(undefined), (err) => {
166
+ assert.ok(err instanceof StorageConfigError);
167
+ assert.equal(err.provider, "azure");
168
+ return true;
169
+ });
170
+ });
171
+ test("connectAzureBlobDriver throws StorageConfigError when the Azure SDK is absent", async () => {
172
+ await assert.rejects(() => connectAzureBlobDriver({
173
+ container: "c",
174
+ connectionString: "UseDevelopmentStorage=true",
175
+ }), (err) => {
176
+ assert.ok(err instanceof StorageConfigError);
177
+ assert.equal(err.provider, "azure");
178
+ return true;
179
+ });
180
+ });
181
+ // ── shared contract-conformance suite ─────────────────────────────────────────
182
+ registerStorageDriverContractTests("azure", () => createAzureBlobDriver(makeFakeClient(), { clock: fixedClock }), test);
183
+ //# sourceMappingURL=azure-driver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure-driver.test.js","sourceRoot":"","sources":["../../src/tests/azure-driver.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backblaze-driver.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backblaze-driver.test.d.ts","sourceRoot":"","sources":["../../src/tests/backblaze-driver.test.ts"],"names":[],"mappings":""}