@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,148 @@
1
+ /**
2
+ * @streetjs/storage — the Directory API over a flat key space (task 17.1).
3
+ *
4
+ * Object stores have a flat key space with no real directories. This module
5
+ * implements a directory-style API entirely over that flat key space using
6
+ * `/`-delimited prefixes, so the same code runs unchanged on every
7
+ * {@link StorageDriver} — including prefix-only cloud providers (Requirement
8
+ * 15.5). The facade exposes the constructed instance as `storage.directory`.
9
+ *
10
+ * The four operations map onto driver primitives (`list`/`put`/`delete`) as
11
+ * follows:
12
+ *
13
+ * - `mkdir(path)` records an empty marker key `path/`, making the path
14
+ * available as a directory prefix (Requirement 15.1). A root/empty path needs
15
+ * no marker and is a no-op.
16
+ * - `listDirectory(path)` calls `driver.list(path/)` and collapses the results
17
+ * to the **immediate** children by splitting each key on the next `/` after
18
+ * the prefix: keys with no further `/` are file entries, keys with a further
19
+ * `/` contribute a single synthesized sub-directory entry (Requirement 15.2).
20
+ * - `removeDirectory(path)` deletes every key under the prefix; when the prefix
21
+ * contains no objects it is a success no-op that removes nothing
22
+ * (Requirements 15.3, 15.6).
23
+ * - `walk(path)` returns every object key strictly beneath the prefix
24
+ * (Requirement 15.4).
25
+ *
26
+ * The public {@link DirectoryApi} type is owned by `facade.ts` (and re-exported
27
+ * from `index.ts`); it is imported here type-only so there is no runtime import
28
+ * cycle between the two modules.
29
+ *
30
+ * _Requirements: 15.1, 15.2, 15.3, 15.4, 15.5, 15.6_
31
+ */
32
+ /** The directory delimiter used to derive prefixes from paths. */
33
+ const DELIMITER = "/";
34
+ /**
35
+ * A {@link DirectoryApi} implementation over any {@link StorageDriver}'s flat
36
+ * key space. It holds only the driver and derives every directory operation
37
+ * from `/`-delimited prefixes, so it behaves identically across providers.
38
+ */
39
+ export class StorageDirectoryApi {
40
+ driver;
41
+ constructor(driver) {
42
+ this.driver = driver;
43
+ }
44
+ /**
45
+ * Normalize a directory `path` to a prefix ending in the delimiter. The root
46
+ * (`""` or `"/"`) normalizes to the empty prefix (which matches every key),
47
+ * and any leading delimiter is dropped so `"/photos"` and `"photos"` refer to
48
+ * the same directory. A path that already ends with the delimiter is left
49
+ * unchanged.
50
+ */
51
+ toPrefix(path) {
52
+ let p = path;
53
+ while (p.startsWith(DELIMITER)) {
54
+ p = p.slice(DELIMITER.length);
55
+ }
56
+ if (p === "") {
57
+ return "";
58
+ }
59
+ return p.endsWith(DELIMITER) ? p : p + DELIMITER;
60
+ }
61
+ /**
62
+ * List the keys stored under `prefix`, defensively re-filtering by the prefix
63
+ * so drivers that interpret `list` loosely never leak keys from outside the
64
+ * directory into a directory operation.
65
+ */
66
+ async keysUnder(prefix) {
67
+ const items = await this.driver.list(prefix);
68
+ if (prefix === "") {
69
+ return items;
70
+ }
71
+ return items.filter((item) => item.key.startsWith(prefix));
72
+ }
73
+ /**
74
+ * Make `path` available as a directory prefix by recording an empty marker
75
+ * key `path/` (Requirement 15.1). The root/empty path requires no marker and
76
+ * is a no-op.
77
+ */
78
+ async mkdir(path) {
79
+ const prefix = this.toPrefix(path);
80
+ if (prefix === "") {
81
+ return;
82
+ }
83
+ await this.driver.put(prefix, new Uint8Array(0), {});
84
+ }
85
+ /**
86
+ * Return the immediate child entries under `path` (Requirement 15.2). Each
87
+ * key under the prefix is split on the next delimiter: a key with no further
88
+ * delimiter is returned as its file entry; keys sharing a further path
89
+ * segment collapse into a single synthesized sub-directory entry (key
90
+ * `path/child/`, `size` 0). The directory's own marker (a key equal to the
91
+ * prefix) is not reported as a child.
92
+ */
93
+ async listDirectory(path) {
94
+ const prefix = this.toPrefix(path);
95
+ const items = await this.keysUnder(prefix);
96
+ const files = [];
97
+ const directories = new Map();
98
+ for (const item of items) {
99
+ const remainder = item.key.slice(prefix.length);
100
+ if (remainder === "") {
101
+ // The directory's own marker key — not one of its children.
102
+ continue;
103
+ }
104
+ const slash = remainder.indexOf(DELIMITER);
105
+ if (slash === -1) {
106
+ // Immediate file child.
107
+ files.push(item);
108
+ continue;
109
+ }
110
+ // Immediate sub-directory child: collapse everything sharing this segment
111
+ // into a single directory entry, tracking the most recent update time.
112
+ const dirKey = prefix + remainder.slice(0, slash) + DELIMITER;
113
+ const existing = directories.get(dirKey);
114
+ if (existing === undefined || item.updatedAt > existing.updatedAt) {
115
+ directories.set(dirKey, { key: dirKey, size: 0, updatedAt: item.updatedAt });
116
+ }
117
+ }
118
+ return [...directories.values(), ...files];
119
+ }
120
+ /**
121
+ * Remove every object stored under `path` (Requirement 15.3). When the prefix
122
+ * contains no objects — because the directory does not exist or is already
123
+ * empty — nothing is removed and a success result of `{ removed: false }` is
124
+ * returned without throwing (Requirement 15.6). When at least one object is
125
+ * removed the result is `{ removed: true }`.
126
+ */
127
+ async removeDirectory(path) {
128
+ const prefix = this.toPrefix(path);
129
+ const items = await this.keysUnder(prefix);
130
+ if (items.length === 0) {
131
+ return { removed: false };
132
+ }
133
+ for (const item of items) {
134
+ await this.driver.delete(item.key);
135
+ }
136
+ return { removed: true };
137
+ }
138
+ /**
139
+ * Return every object key strictly beneath `path` (Requirement 15.4),
140
+ * excluding the directory's own marker key (a key equal to the prefix).
141
+ */
142
+ async walk(path) {
143
+ const prefix = this.toPrefix(path);
144
+ const items = await this.keysUnder(prefix);
145
+ return items.map((item) => item.key).filter((key) => key !== prefix);
146
+ }
147
+ }
148
+ //# sourceMappingURL=directory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory.js","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @streetjs/storage — the single driver contract.
3
+ *
4
+ * `StorageDriver` is the one interface every provider implements. The storage
5
+ * facade never assumes a provider; it only calls the methods defined here.
6
+ * Mandatory methods are the primitive object operations (`put`/`get`/`exists`/
7
+ * `delete`/`stat`/`list`) plus streaming (`putStream`/`getStream`). Advanced
8
+ * capabilities (`multipart`/`resumable`/`versioning`/`signedUrl`/`lifecycle`)
9
+ * are **optional**; when a driver does not implement one natively, the facade's
10
+ * cross-cutting layer supplies a provider-agnostic simulation built on the
11
+ * mandatory primitives, keeping observable behavior identical across providers.
12
+ *
13
+ * Requirements: 2.1, 2.3, 2.4, 4.6, 5.5
14
+ */
15
+ import type { Readable } from "node:stream";
16
+ import type { StorageObjectMetadata, WriteMetadata, StorageListItem, ListOptions, VersionInfo, SignedOperation, SignedUrlOptions, SignedUrlVerification, LifecycleRule, LifecycleOutcome, DriverProbe } from "./types.js";
17
+ /** Node's `Readable` stream, used for streaming uploads/downloads. */
18
+ export type NodeReadable = Readable;
19
+ /** Result of a lookup that may be absent, distinguishing "not found" from errors. */
20
+ export type MaybeObject = {
21
+ readonly found: true;
22
+ readonly bytes: Uint8Array;
23
+ readonly metadata: StorageObjectMetadata;
24
+ } | {
25
+ readonly found: false;
26
+ };
27
+ /** A single stored part for multipart assembly. */
28
+ export interface StoredPart {
29
+ readonly partNumber: number;
30
+ readonly etag: string;
31
+ readonly size: number;
32
+ }
33
+ /**
34
+ * The single contract every provider implements. Mandatory methods are the
35
+ * primitive object operations; capability methods are optional and, when
36
+ * absent, are simulated by the facade over the primitives.
37
+ */
38
+ export interface StorageDriver {
39
+ /** Stable driver name (e.g. "memory", "local", "s3"). */
40
+ readonly name: string;
41
+ put(key: string, bytes: Uint8Array, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
42
+ get(key: string): Promise<MaybeObject>;
43
+ exists(key: string): Promise<boolean>;
44
+ delete(key: string): Promise<void>;
45
+ stat(key: string): Promise<StorageObjectMetadata | null>;
46
+ list(prefix: string, options?: ListOptions): Promise<StorageListItem[]>;
47
+ putStream(key: string, stream: NodeReadable, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
48
+ getStream(key: string): Promise<NodeReadable>;
49
+ multipart?: MultipartCapability;
50
+ resumable?: ResumableCapability;
51
+ versioning?: VersioningCapability;
52
+ signedUrl?: SignedUrlCapability;
53
+ lifecycle?: LifecycleCapability;
54
+ /** Best-effort connectivity/quota probe for health checks. */
55
+ probe?(): Promise<DriverProbe>;
56
+ }
57
+ export interface MultipartCapability {
58
+ create(key: string, metadata: WriteMetadata): Promise<string>;
59
+ uploadPart(uploadId: string, partNumber: number, bytes: Uint8Array): Promise<StoredPart>;
60
+ complete(uploadId: string, parts: readonly StoredPart[]): Promise<StorageObjectMetadata>;
61
+ abort(uploadId: string): Promise<void>;
62
+ }
63
+ export interface ResumableCapability {
64
+ start(key: string, metadata: WriteMetadata): Promise<string>;
65
+ append(sessionId: string, bytes: Uint8Array, offset: number): Promise<number>;
66
+ offset(sessionId: string): Promise<number>;
67
+ finish(sessionId: string): Promise<StorageObjectMetadata>;
68
+ cancel(sessionId: string): Promise<void>;
69
+ }
70
+ export interface VersioningCapability {
71
+ snapshot(key: string): Promise<string | null>;
72
+ list(key: string): Promise<VersionInfo[]>;
73
+ restore(key: string, versionId: string): Promise<StorageObjectMetadata>;
74
+ deleteVersion(key: string, versionId: string): Promise<void>;
75
+ }
76
+ export interface SignedUrlCapability {
77
+ sign(key: string, op: SignedOperation, options: SignedUrlOptions): Promise<string>;
78
+ verify(url: string, now: number): SignedUrlVerification;
79
+ }
80
+ export interface LifecycleCapability {
81
+ apply(rule: LifecycleRule, now: number): Promise<LifecycleOutcome[]>;
82
+ }
83
+ //# sourceMappingURL=driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}
package/dist/driver.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @streetjs/storage — the single driver contract.
3
+ *
4
+ * `StorageDriver` is the one interface every provider implements. The storage
5
+ * facade never assumes a provider; it only calls the methods defined here.
6
+ * Mandatory methods are the primitive object operations (`put`/`get`/`exists`/
7
+ * `delete`/`stat`/`list`) plus streaming (`putStream`/`getStream`). Advanced
8
+ * capabilities (`multipart`/`resumable`/`versioning`/`signedUrl`/`lifecycle`)
9
+ * are **optional**; when a driver does not implement one natively, the facade's
10
+ * cross-cutting layer supplies a provider-agnostic simulation built on the
11
+ * mandatory primitives, keeping observable behavior identical across providers.
12
+ *
13
+ * Requirements: 2.1, 2.3, 2.4, 4.6, 5.5
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * @streetjs/storage — Azure Blob Storage driver submodule (`@streetjs/storage/azure`).
3
+ *
4
+ * Azure Blob Storage does **not** speak the S3 wire shape, so — unlike
5
+ * `s3.ts`/`r2.ts`/`minio.ts`/`backblaze.ts`, which specialize the shared
6
+ * {@link createS3StyleDriver} base — this driver maps the {@link StorageDriver}
7
+ * contract **directly** onto a structural Azure Blob client
8
+ * ({@link AzureBlobClientLike}). It computes object identity fields
9
+ * (`size`/`checksum`/`etag`) and timestamps locally and assembles every
10
+ * {@link StorageObjectMetadata} through the shared metadata layer
11
+ * ({@link buildObjectMetadata}) so the field set is identical to Memory/Local
12
+ * and every other provider (Requirement 2.1, 10.1).
13
+ *
14
+ * ## SDK isolation (Requirements 3.1, 3.3)
15
+ *
16
+ * This module imports **no provider SDK** at the top level — only Node built-ins,
17
+ * `streetjs` (for the injected {@link Clock}), and this package's own type
18
+ * surface. There are two ways to obtain a driver:
19
+ *
20
+ * 1. **Inject a structural client.** {@link createAzureBlobDriver} accepts an
21
+ * already-built {@link AzureBlobClientLike} (real SDK adapter or a test
22
+ * double) and maps the contract onto it. The `@azure/storage-blob` SDK stays
23
+ * an optional peer concern of the consumer and is never touched by this
24
+ * package.
25
+ *
26
+ * 2. **Let the driver build its own client.** {@link connectAzureBlobDriver}
27
+ * resolves the optional `@azure/storage-blob` peer SDK with a **lazy dynamic
28
+ * `import()`** performed *inside the function* (never at module top level),
29
+ * constructs a container-scoped client, adapts it to
30
+ * {@link AzureBlobClientLike}, and hands it to {@link createAzureBlobDriver}.
31
+ * If the SDK is absent, it throws {@link StorageConfigError} rather than a raw
32
+ * module-resolution error.
33
+ *
34
+ * Because the driver lives behind the `./azure` subpath export
35
+ * (`dist/drivers/azure.js`) and is *not* re-exported from the package index, a
36
+ * consumer only loads this code — and any SDK it lazily resolves — when they
37
+ * import `@streetjs/storage/azure`. `package.json` lists `@azure/storage-blob`
38
+ * as an optional peer dependency, never a runtime dependency, keeping `streetjs`
39
+ * the only runtime dependency.
40
+ *
41
+ * ## Capability delegation (Requirement 2.3)
42
+ *
43
+ * Only the **mandatory primitives** (`put`/`get`/`exists`/`delete`/`stat`/
44
+ * `list`/`putStream`/`getStream`) are implemented. The advanced capabilities
45
+ * (`multipart`/`resumable`/`versioning`/`signedUrl`/`lifecycle`) are left
46
+ * `undefined` so the facade's cross-cutting layer supplies a provider-agnostic
47
+ * simulation over the primitives, keeping observable behavior identical across
48
+ * providers.
49
+ *
50
+ * _Requirements: 2.1, 2.3, 3.3_
51
+ */
52
+ import { type Clock } from "streetjs";
53
+ import type { MaybeObject, NodeReadable, StorageDriver } from "../driver.js";
54
+ import type { ListOptions, StorageListItem, StorageObjectMetadata, WriteMetadata } from "../types.js";
55
+ /** Input to {@link AzureBlobClientLike.upload}. */
56
+ export interface AzureUploadInput {
57
+ /** The blob name (object key) within the container. */
58
+ readonly blobName: string;
59
+ /** The bytes to store. */
60
+ readonly body: Uint8Array;
61
+ /** Blob content type, mapped to `blobHTTPHeaders.blobContentType`. */
62
+ readonly contentType?: string;
63
+ /** Blob metadata (string→string); used to round-trip the typed field set. */
64
+ readonly metadata?: Record<string, string>;
65
+ }
66
+ /** Result of {@link AzureBlobClientLike.upload}. */
67
+ export interface AzureUploadResult {
68
+ /** The blob's entity tag, when the service returns one. */
69
+ readonly etag?: string;
70
+ }
71
+ /** Blob attributes shared by download and property reads. */
72
+ export interface AzureBlobProperties {
73
+ /** Blob content type (`blobContentType`). */
74
+ readonly contentType?: string;
75
+ /** The blob's entity tag. */
76
+ readonly etag?: string;
77
+ /** Byte length of the blob content (`contentLength`). */
78
+ readonly contentLength?: number;
79
+ /** Last-modified time as epoch ms. */
80
+ readonly lastModified?: number;
81
+ /** Blob metadata (string→string). */
82
+ readonly metadata?: Record<string, string>;
83
+ }
84
+ /** Result of {@link AzureBlobClientLike.download} — attributes plus the body. */
85
+ export interface AzureBlobDownloadResult extends AzureBlobProperties {
86
+ /** The blob's content bytes. */
87
+ readonly body: Uint8Array;
88
+ }
89
+ /** A single entry returned by {@link AzureBlobClientLike.listBlobs}. */
90
+ export interface AzureBlobListItem {
91
+ /** The blob name (object key). */
92
+ readonly name: string;
93
+ /** Byte length of the blob content. */
94
+ readonly contentLength: number;
95
+ /** Last-modified time as epoch ms. */
96
+ readonly lastModified: number;
97
+ }
98
+ /** Options passed to {@link AzureBlobClientLike.listBlobs}. */
99
+ export interface AzureListInput {
100
+ /** Only blobs whose name begins with this prefix are returned. */
101
+ readonly prefix: string;
102
+ /** Maximum number of blobs to return. */
103
+ readonly limit?: number;
104
+ }
105
+ /**
106
+ * The **minimal, container-scoped structural interface** the Azure Blob driver
107
+ * depends on.
108
+ *
109
+ * It describes just the blob operations the driver needs — never any concrete
110
+ * `@azure/storage-blob` type — so the actual SDK stays an optional peer concern
111
+ * of the consumer (Requirement 3.1). Every call is scoped to a single container
112
+ * (the adapter built by {@link connectAzureBlobDriver} closes over the container
113
+ * name), so the driver only ever passes blob names.
114
+ */
115
+ export interface AzureBlobClientLike {
116
+ /** Upload `body` to `blobName` with optional content type and metadata. */
117
+ upload(input: AzureUploadInput): Promise<AzureUploadResult>;
118
+ /** Download the blob at `blobName`, or `null` when it does not exist. */
119
+ download(input: {
120
+ readonly blobName: string;
121
+ }): Promise<AzureBlobDownloadResult | null>;
122
+ /** Read blob attributes without the body, or `null` when absent. */
123
+ getProperties(input: {
124
+ readonly blobName: string;
125
+ }): Promise<AzureBlobProperties | null>;
126
+ /** Delete the blob at `blobName` (a no-op when it is already absent). */
127
+ deleteBlob(input: {
128
+ readonly blobName: string;
129
+ }): Promise<void>;
130
+ /** Report whether a blob exists at `blobName`. */
131
+ exists(input: {
132
+ readonly blobName: string;
133
+ }): Promise<boolean>;
134
+ /** List blobs whose name begins with `prefix`. */
135
+ listBlobs(input: AzureListInput): Promise<readonly AzureBlobListItem[]>;
136
+ }
137
+ /** Options for {@link createAzureBlobDriver} / {@link AzureBlobDriver}. */
138
+ export interface AzureBlobDriverOptions {
139
+ /** Injected clock for deterministic timestamps in tests. Default `systemClock`. */
140
+ readonly clock?: Clock;
141
+ }
142
+ /**
143
+ * Maps the {@link StorageDriver} contract directly onto an injected
144
+ * {@link AzureBlobClientLike}.
145
+ *
146
+ * Unlike the S3-compatible providers, Azure Blob does not share the S3 wire
147
+ * shape, so this driver does not build on {@link createS3StyleDriver}. It
148
+ * computes size/checksum/etag and timestamps locally, encodes the typed metadata
149
+ * into the blob metadata map so it round-trips on read, and reports a missing
150
+ * key consistently ({@link MaybeObject} `{ found: false }` for `get`, `null` for
151
+ * `stat`, {@link NotFoundError} for `getStream`).
152
+ */
153
+ export declare class AzureBlobDriver implements StorageDriver {
154
+ /** Stable driver name. */
155
+ readonly name = "azure";
156
+ private readonly client;
157
+ private readonly clock;
158
+ constructor(client: AzureBlobClientLike, options?: AzureBlobDriverOptions);
159
+ /**
160
+ * Store `bytes` under `key`, computing size and sha-256 checksum locally and
161
+ * taking timestamps from the injected clock. When overwriting, the original
162
+ * `createdAt` is preserved (a preceding attribute read). The typed metadata is
163
+ * encoded into the blob metadata map so it round-trips on read
164
+ * (Requirements 4.1, 10.1, 10.2).
165
+ */
166
+ put(key: string, bytes: Uint8Array, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
167
+ /**
168
+ * Read the object at `key`, returning a discriminated {@link MaybeObject} so
169
+ * absence is reported rather than thrown (Requirements 4.2, 2.4). Metadata is
170
+ * rebuilt from the blob attributes and encoded metadata via the shared layer.
171
+ */
172
+ get(key: string): Promise<MaybeObject>;
173
+ /** Report whether an object is stored under `key` (Requirement 4.3). */
174
+ exists(key: string): Promise<boolean>;
175
+ /** Delete the object at `key`; deleting a missing key is a no-op (Requirement 4.4). */
176
+ delete(key: string): Promise<void>;
177
+ /**
178
+ * Return the metadata for `key` without its content, or `null` when absent
179
+ * (Requirement 4.10).
180
+ */
181
+ stat(key: string): Promise<StorageObjectMetadata | null>;
182
+ /** List objects whose key begins with `prefix` (Requirement 4.9). */
183
+ list(prefix: string, options?: ListOptions): Promise<StorageListItem[]>;
184
+ /**
185
+ * Consume a Node {@link Readable} and persist the assembled bytes under `key`
186
+ * with the same computed metadata as {@link put} (Requirement 5.1). Chunks are
187
+ * drained through a `pipeline` (correct backpressure and error propagation),
188
+ * then handed to {@link put}.
189
+ */
190
+ putStream(key: string, stream: NodeReadable, metadata: WriteMetadata): Promise<StorageObjectMetadata>;
191
+ /**
192
+ * Return a Node {@link Readable} of the stored bytes at `key` (Requirement
193
+ * 5.2). Throws {@link NotFoundError} for a missing key (Requirement 5.5).
194
+ */
195
+ getStream(key: string): Promise<NodeReadable>;
196
+ /**
197
+ * Rebuild the typed {@link StorageObjectMetadata} field set from blob
198
+ * attributes and the encoded metadata map, applying the shared layer's
199
+ * canonical defaults. Provider-supplied values back-fill identity/timestamp
200
+ * fields when the encoded ones are absent (e.g. a blob written outside this
201
+ * driver), keeping the shape consistent across providers.
202
+ */
203
+ private decodeMeta;
204
+ }
205
+ /**
206
+ * Create an Azure-Blob-backed {@link StorageDriver} over an **injected**
207
+ * structural {@link AzureBlobClientLike}.
208
+ *
209
+ * This is the primary, SDK-free entry point: the caller supplies a client that
210
+ * already speaks the {@link AzureBlobClientLike} shape (built from
211
+ * `@azure/storage-blob`, or a test double), and this function maps the contract
212
+ * onto it. No provider SDK is imported.
213
+ *
214
+ * @throws {StorageConfigError} when no client is injected — use
215
+ * {@link connectAzureBlobDriver} to build a client from connection options.
216
+ */
217
+ export declare function createAzureBlobDriver(client: AzureBlobClientLike, options?: AzureBlobDriverOptions): StorageDriver;
218
+ /** Connection options for building an Azure Blob client via {@link connectAzureBlobDriver}. */
219
+ export interface AzureBlobConnectionOptions {
220
+ /** The blob container the driver operates within (required). */
221
+ readonly container: string;
222
+ /** An Azure Storage connection string (e.g. from the portal). */
223
+ readonly connectionString: string;
224
+ }
225
+ /**
226
+ * Build an Azure-Blob-backed {@link StorageDriver}, constructing the underlying
227
+ * client from `connection` options using the optional `@azure/storage-blob` peer
228
+ * SDK.
229
+ *
230
+ * The SDK is resolved with a **lazy dynamic `import()`** performed inside this
231
+ * function, so the peer dependency is only touched when a caller actually asks
232
+ * the driver to build its own client. The resolved SDK client is adapted to the
233
+ * structural {@link AzureBlobClientLike} and handed to {@link createAzureBlobDriver}.
234
+ *
235
+ * @throws {StorageConfigError} when the `@azure/storage-blob` SDK is not
236
+ * installed, or when the client cannot be constructed from the supplied options.
237
+ */
238
+ export declare function connectAzureBlobDriver(connection: AzureBlobConnectionOptions, options?: AzureBlobDriverOptions): Promise<StorageDriver>;
239
+ //# sourceMappingURL=azure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"azure.d.ts","sourceRoot":"","sources":["../../src/drivers/azure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAMH,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,UAAU,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7E,OAAO,KAAK,EAEV,WAAW,EACX,eAAe,EACf,qBAAqB,EACrB,aAAa,EACd,MAAM,aAAa,CAAC;AAOrB,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED,oDAAoD;AACpD,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC,6CAA6C;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,sCAAsC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED,iFAAiF;AACjF,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAClE,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC3B;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC5D,yEAAyE;IACzE,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IACxF,oEAAoE;IACpE,aAAa,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IACzF,yEAAyE;IACzE,UAAU,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,kDAAkD;IAClD,MAAM,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,kDAAkD;IAClD,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAAC;CACzE;AAwBD,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAID;;;;;;;;;;GAUG;AACH,qBAAa,eAAgB,YAAW,aAAa;IACnD,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,WAAqB;IAElC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;gBAElB,MAAM,EAAE,mBAAmB,EAAE,OAAO,GAAE,sBAA2B;IAO7E;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,qBAAqB,CAAC;IAyBjC;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAgB5C,wEAAwE;IAClE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3C,uFAAuF;IACjF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC;;;OAGG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAQ9D,qEAAqE;IAC/D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAc7E;;;;;OAKG;IACG,SAAS,CACb,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,qBAAqB,CAAC;IAcjC;;;OAGG;IACG,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAUnD;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;CAyBnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,GAAE,sBAA2B,GACnC,aAAa,CAWf;AAID,+FAA+F;AAC/F,MAAM,WAAW,0BAA0B;IACzC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,0BAA0B,EACtC,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,aAAa,CAAC,CAcxB"}