@effect-kit/storage 0.0.0-stage → 0.1.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 (615) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/LICENSE +204 -0
  3. package/README.md +369 -2
  4. package/dist/_virtual/_rolldown/runtime.js +17 -0
  5. package/dist/azure/account-admin.d.ts +116 -0
  6. package/dist/azure/account-admin.js +90 -0
  7. package/dist/azure/account-admin.js.map +1 -0
  8. package/dist/azure/admin.d.ts +68 -0
  9. package/dist/azure/admin.js +85 -0
  10. package/dist/azure/admin.js.map +1 -0
  11. package/dist/azure/archive.d.ts +95 -0
  12. package/dist/azure/archive.js +52 -0
  13. package/dist/azure/archive.js.map +1 -0
  14. package/dist/azure/events.d.ts +40 -0
  15. package/dist/azure/events.js +62 -0
  16. package/dist/azure/events.js.map +1 -0
  17. package/dist/azure/governance.d.ts +139 -0
  18. package/dist/azure/governance.js +59 -0
  19. package/dist/azure/governance.js.map +1 -0
  20. package/dist/azure/identity.d.ts +4 -0
  21. package/dist/azure/identity.js +8 -0
  22. package/dist/azure/identity.js.map +1 -0
  23. package/dist/azure/lifecycle.d.ts +21 -0
  24. package/dist/azure/lifecycle.js +193 -0
  25. package/dist/azure/lifecycle.js.map +1 -0
  26. package/dist/azure/signing.d.ts +17 -0
  27. package/dist/azure/signing.js +71 -0
  28. package/dist/azure/signing.js.map +1 -0
  29. package/dist/azure/uploads.d.ts +11 -0
  30. package/dist/azure/uploads.js +83 -0
  31. package/dist/azure/uploads.js.map +1 -0
  32. package/dist/azure.d.ts +427 -0
  33. package/dist/azure.js +77 -0
  34. package/dist/azure.js.map +1 -0
  35. package/dist/b2/admin.d.ts +149 -0
  36. package/dist/b2/admin.js +157 -0
  37. package/dist/b2/admin.js.map +1 -0
  38. package/dist/b2.d.ts +15 -0
  39. package/dist/b2.js +15 -0
  40. package/dist/b2.js.map +1 -0
  41. package/dist/browser.d.ts +7 -0
  42. package/dist/browser.js +11 -0
  43. package/dist/browser.js.map +1 -0
  44. package/dist/bun.d.ts +14 -0
  45. package/dist/bun.js +17 -0
  46. package/dist/bun.js.map +1 -0
  47. package/dist/cache.d.ts +18 -0
  48. package/dist/cache.js +116 -0
  49. package/dist/cache.js.map +1 -0
  50. package/dist/client/atoms/controller.d.ts +10 -0
  51. package/dist/client/atoms/controller.js +267 -0
  52. package/dist/client/atoms/controller.js.map +1 -0
  53. package/dist/client/atoms/state.d.ts +17 -0
  54. package/dist/client/atoms/state.js +11 -0
  55. package/dist/client/atoms/state.js.map +1 -0
  56. package/dist/client/atoms.d.ts +59 -0
  57. package/dist/client/atoms.js +39 -0
  58. package/dist/client/atoms.js.map +1 -0
  59. package/dist/client/fingerprint.js +28 -0
  60. package/dist/client/fingerprint.js.map +1 -0
  61. package/dist/client/store.d.ts +31 -0
  62. package/dist/client/store.js +56 -0
  63. package/dist/client/store.js.map +1 -0
  64. package/dist/client/transport.d.ts +11 -0
  65. package/dist/client/transport.js +78 -0
  66. package/dist/client/transport.js.map +1 -0
  67. package/dist/client.d.ts +259 -0
  68. package/dist/client.js +350 -0
  69. package/dist/client.js.map +1 -0
  70. package/dist/composition/layer.js +22 -0
  71. package/dist/composition/layer.js.map +1 -0
  72. package/dist/composition/representation/staging.js +46 -0
  73. package/dist/composition/representation/staging.js.map +1 -0
  74. package/dist/composition/representation/storage.js +188 -0
  75. package/dist/composition/representation/storage.js.map +1 -0
  76. package/dist/composition.d.ts +20 -0
  77. package/dist/composition.js +124 -0
  78. package/dist/composition.js.map +1 -0
  79. package/dist/compression.d.ts +16 -0
  80. package/dist/compression.js +38 -0
  81. package/dist/compression.js.map +1 -0
  82. package/dist/content.d.ts +590 -0
  83. package/dist/content.js +168 -0
  84. package/dist/content.js.map +1 -0
  85. package/dist/core/capabilities.d.ts +53 -0
  86. package/dist/core/capabilities.js +9 -0
  87. package/dist/core/capabilities.js.map +1 -0
  88. package/dist/core/contracts/multipart.d.ts +56 -0
  89. package/dist/core/contracts/resumable.d.ts +70 -0
  90. package/dist/core/errors.d.ts +55 -0
  91. package/dist/core/errors.js +55 -0
  92. package/dist/core/errors.js.map +1 -0
  93. package/dist/core/object.d.ts +97 -0
  94. package/dist/core/object.js +55 -0
  95. package/dist/core/object.js.map +1 -0
  96. package/dist/core/ranges.d.ts +17 -0
  97. package/dist/core/ranges.js +27 -0
  98. package/dist/core/ranges.js.map +1 -0
  99. package/dist/core/requests.d.ts +185 -0
  100. package/dist/core/requests.js +42 -0
  101. package/dist/core/requests.js.map +1 -0
  102. package/dist/core/storage.d.ts +249 -0
  103. package/dist/core/storage.js +173 -0
  104. package/dist/core/storage.js.map +1 -0
  105. package/dist/deno.d.ts +14 -0
  106. package/dist/deno.js +17 -0
  107. package/dist/deno.js.map +1 -0
  108. package/dist/encryption/age.d.ts +14 -0
  109. package/dist/encryption/age.js +46 -0
  110. package/dist/encryption/age.js.map +1 -0
  111. package/dist/encryption.d.ts +16 -0
  112. package/dist/encryption.js +16 -0
  113. package/dist/encryption.js.map +1 -0
  114. package/dist/events.d.ts +57 -0
  115. package/dist/events.js +106 -0
  116. package/dist/events.js.map +1 -0
  117. package/dist/filesystem.d.ts +23 -0
  118. package/dist/filesystem.js +75 -0
  119. package/dist/filesystem.js.map +1 -0
  120. package/dist/gcs/admin.d.ts +470 -0
  121. package/dist/gcs/admin.js +206 -0
  122. package/dist/gcs/admin.js.map +1 -0
  123. package/dist/gcs/events.d.ts +41 -0
  124. package/dist/gcs/events.js +45 -0
  125. package/dist/gcs/events.js.map +1 -0
  126. package/dist/gcs/governance.d.ts +158 -0
  127. package/dist/gcs/governance.js +100 -0
  128. package/dist/gcs/governance.js.map +1 -0
  129. package/dist/gcs/lifecycle.d.ts +161 -0
  130. package/dist/gcs/lifecycle.js +174 -0
  131. package/dist/gcs/lifecycle.js.map +1 -0
  132. package/dist/gcs/post.d.ts +31 -0
  133. package/dist/gcs/post.js +70 -0
  134. package/dist/gcs/post.js.map +1 -0
  135. package/dist/gcs/signing.d.ts +10 -0
  136. package/dist/gcs/signing.js +61 -0
  137. package/dist/gcs/signing.js.map +1 -0
  138. package/dist/gcs/uploads.d.ts +10 -0
  139. package/dist/gcs/uploads.js +76 -0
  140. package/dist/gcs/uploads.js.map +1 -0
  141. package/dist/gcs.d.ts +888 -0
  142. package/dist/gcs.js +91 -0
  143. package/dist/gcs.js.map +1 -0
  144. package/dist/hetzner/admin.d.ts +112 -0
  145. package/dist/hetzner/admin.js +19 -0
  146. package/dist/hetzner/admin.js.map +1 -0
  147. package/dist/hetzner.d.ts +15 -0
  148. package/dist/hetzner.js +15 -0
  149. package/dist/hetzner.js.map +1 -0
  150. package/dist/http/api.d.ts +236 -0
  151. package/dist/http/api.js +54 -0
  152. package/dist/http/api.js.map +1 -0
  153. package/dist/http/download.js +99 -0
  154. package/dist/http/download.js.map +1 -0
  155. package/dist/http/schema.d.ts +3 -0
  156. package/dist/http/schema.js +4 -0
  157. package/dist/http.d.ts +35 -0
  158. package/dist/http.js +178 -0
  159. package/dist/http.js.map +1 -0
  160. package/dist/index.d.ts +10 -0
  161. package/dist/index.js +9 -0
  162. package/dist/internal/http/control-plane.js +71 -0
  163. package/dist/internal/http/control-plane.js.map +1 -0
  164. package/dist/internal/listing-cursor.js +44 -0
  165. package/dist/internal/listing-cursor.js.map +1 -0
  166. package/dist/internal/node/provider-errors.js +16 -0
  167. package/dist/internal/node/provider-errors.js.map +1 -0
  168. package/dist/internal/node/upload-body.js +111 -0
  169. package/dist/internal/node/upload-body.js.map +1 -0
  170. package/dist/internal/provider-response.js +14 -0
  171. package/dist/internal/provider-response.js.map +1 -0
  172. package/dist/internal/public-urls.js +30 -0
  173. package/dist/internal/public-urls.js.map +1 -0
  174. package/dist/internal/read-condition.js +11 -0
  175. package/dist/internal/read-condition.js.map +1 -0
  176. package/dist/internal/request-validation.js +24 -0
  177. package/dist/internal/request-validation.js.map +1 -0
  178. package/dist/internal/signing-request.js +22 -0
  179. package/dist/internal/signing-request.js.map +1 -0
  180. package/dist/internal/web-upload-body.js +71 -0
  181. package/dist/internal/web-upload-body.js.map +1 -0
  182. package/dist/lifecycle/configuration-state.js +26 -0
  183. package/dist/lifecycle/configuration-state.js.map +1 -0
  184. package/dist/lifecycle/metadata.js +28 -0
  185. package/dist/lifecycle/metadata.js.map +1 -0
  186. package/dist/lifecycle.d.ts +269 -0
  187. package/dist/lifecycle.js +72 -0
  188. package/dist/lifecycle.js.map +1 -0
  189. package/dist/migrations.d.ts +537 -0
  190. package/dist/migrations.js +296 -0
  191. package/dist/migrations.js.map +1 -0
  192. package/dist/minio/admin.d.ts +112 -0
  193. package/dist/minio/admin.js +19 -0
  194. package/dist/minio/admin.js.map +1 -0
  195. package/dist/minio.d.ts +15 -0
  196. package/dist/minio.js +15 -0
  197. package/dist/minio.js.map +1 -0
  198. package/dist/mirror.d.ts +830 -0
  199. package/dist/mirror.js +290 -0
  200. package/dist/mirror.js.map +1 -0
  201. package/dist/node.d.ts +14 -0
  202. package/dist/node.js +17 -0
  203. package/dist/node.js.map +1 -0
  204. package/dist/providers/azure/blocks.js +94 -0
  205. package/dist/providers/azure/blocks.js.map +1 -0
  206. package/dist/providers/azure/config.d.ts +41 -0
  207. package/dist/providers/azure/config.js +62 -0
  208. package/dist/providers/azure/config.js.map +1 -0
  209. package/dist/providers/azure/mapping.js +83 -0
  210. package/dist/providers/azure/mapping.js.map +1 -0
  211. package/dist/providers/azure/native.js +88 -0
  212. package/dist/providers/azure/native.js.map +1 -0
  213. package/dist/providers/azure/primitives.js +203 -0
  214. package/dist/providers/azure/primitives.js.map +1 -0
  215. package/dist/providers/azure/properties.d.ts +180 -0
  216. package/dist/providers/azure/properties.js +55 -0
  217. package/dist/providers/azure/properties.js.map +1 -0
  218. package/dist/providers/azure/transport.js +14 -0
  219. package/dist/providers/azure/transport.js.map +1 -0
  220. package/dist/providers/azure/validation.js +11 -0
  221. package/dist/providers/azure/validation.js.map +1 -0
  222. package/dist/providers/filesystem/envelope.js +56 -0
  223. package/dist/providers/filesystem/envelope.js.map +1 -0
  224. package/dist/providers/filesystem/identity.js +68 -0
  225. package/dist/providers/filesystem/identity.js.map +1 -0
  226. package/dist/providers/filesystem/layout.d.ts +15 -0
  227. package/dist/providers/filesystem/layout.js +112 -0
  228. package/dist/providers/filesystem/layout.js.map +1 -0
  229. package/dist/providers/filesystem/list.js +82 -0
  230. package/dist/providers/filesystem/list.js.map +1 -0
  231. package/dist/providers/filesystem/operations.js +134 -0
  232. package/dist/providers/filesystem/operations.js.map +1 -0
  233. package/dist/providers/gcs/config.d.ts +34 -0
  234. package/dist/providers/gcs/config.js +60 -0
  235. package/dist/providers/gcs/config.js.map +1 -0
  236. package/dist/providers/gcs/iam.js +45 -0
  237. package/dist/providers/gcs/iam.js.map +1 -0
  238. package/dist/providers/gcs/mapping.js +118 -0
  239. package/dist/providers/gcs/mapping.js.map +1 -0
  240. package/dist/providers/gcs/native.d.ts +11 -0
  241. package/dist/providers/gcs/native.js +122 -0
  242. package/dist/providers/gcs/native.js.map +1 -0
  243. package/dist/providers/gcs/primitives.js +194 -0
  244. package/dist/providers/gcs/primitives.js.map +1 -0
  245. package/dist/providers/gcs/resumable.js +145 -0
  246. package/dist/providers/gcs/resumable.js.map +1 -0
  247. package/dist/providers/gcs/tier.d.ts +176 -0
  248. package/dist/providers/gcs/tier.js +34 -0
  249. package/dist/providers/gcs/tier.js.map +1 -0
  250. package/dist/providers/gcs/transport.js +123 -0
  251. package/dist/providers/gcs/transport.js.map +1 -0
  252. package/dist/providers/gcs/upload.js +28 -0
  253. package/dist/providers/gcs/upload.js.map +1 -0
  254. package/dist/providers/gcs/validation.js +10 -0
  255. package/dist/providers/gcs/validation.js.map +1 -0
  256. package/dist/providers/r2-workers/binding.d.ts +102 -0
  257. package/dist/providers/r2-workers/body.js +82 -0
  258. package/dist/providers/r2-workers/body.js.map +1 -0
  259. package/dist/providers/r2-workers/list.js +62 -0
  260. package/dist/providers/r2-workers/list.js.map +1 -0
  261. package/dist/providers/r2-workers/mapping.js +140 -0
  262. package/dist/providers/r2-workers/mapping.js.map +1 -0
  263. package/dist/providers/r2-workers/multipart.js +121 -0
  264. package/dist/providers/r2-workers/multipart.js.map +1 -0
  265. package/dist/providers/r2-workers/primitives.js +80 -0
  266. package/dist/providers/r2-workers/primitives.js.map +1 -0
  267. package/dist/providers/s3/admin-configuration.d.ts +19 -0
  268. package/dist/providers/s3/admin-configuration.js +171 -0
  269. package/dist/providers/s3/admin-configuration.js.map +1 -0
  270. package/dist/providers/s3/bulk-delete.d.ts +43 -0
  271. package/dist/providers/s3/bulk-delete.js +58 -0
  272. package/dist/providers/s3/bulk-delete.js.map +1 -0
  273. package/dist/providers/s3/config.d.ts +43 -0
  274. package/dist/providers/s3/config.js +89 -0
  275. package/dist/providers/s3/config.js.map +1 -0
  276. package/dist/providers/s3/copy.d.ts +115 -0
  277. package/dist/providers/s3/copy.js +122 -0
  278. package/dist/providers/s3/copy.js.map +1 -0
  279. package/dist/providers/s3/lifecycle-validation.js +33 -0
  280. package/dist/providers/s3/lifecycle-validation.js.map +1 -0
  281. package/dist/providers/s3/listing.js +56 -0
  282. package/dist/providers/s3/listing.js.map +1 -0
  283. package/dist/providers/s3/metadata.d.ts +10 -0
  284. package/dist/providers/s3/metadata.js +90 -0
  285. package/dist/providers/s3/metadata.js.map +1 -0
  286. package/dist/providers/s3/multipart.d.ts +41 -0
  287. package/dist/providers/s3/multipart.js +299 -0
  288. package/dist/providers/s3/multipart.js.map +1 -0
  289. package/dist/providers/s3/native-models.d.ts +82 -0
  290. package/dist/providers/s3/native-models.js +91 -0
  291. package/dist/providers/s3/native-models.js.map +1 -0
  292. package/dist/providers/s3/object-mapping.js +114 -0
  293. package/dist/providers/s3/object-mapping.js.map +1 -0
  294. package/dist/providers/s3/primitives.d.ts +8 -0
  295. package/dist/providers/s3/primitives.js +235 -0
  296. package/dist/providers/s3/primitives.js.map +1 -0
  297. package/dist/providers/s3/profile.d.ts +25 -0
  298. package/dist/providers/s3/profile.js +46 -0
  299. package/dist/providers/s3/profile.js.map +1 -0
  300. package/dist/providers/s3/request-extension.js +29 -0
  301. package/dist/providers/s3/request-extension.js.map +1 -0
  302. package/dist/providers/s3/service.js +55 -0
  303. package/dist/providers/s3/service.js.map +1 -0
  304. package/dist/providers/s3/signing-credentials.js +32 -0
  305. package/dist/providers/s3/signing-credentials.js.map +1 -0
  306. package/dist/providers/s3/tags.d.ts +10 -0
  307. package/dist/providers/s3/tags.js +65 -0
  308. package/dist/providers/s3/tags.js.map +1 -0
  309. package/dist/providers/s3/tier.d.ts +171 -0
  310. package/dist/providers/s3/tier.js +100 -0
  311. package/dist/providers/s3/tier.js.map +1 -0
  312. package/dist/providers/s3/transfer-driver.js +72 -0
  313. package/dist/providers/s3/transfer-driver.js.map +1 -0
  314. package/dist/providers/s3/transport.js +94 -0
  315. package/dist/providers/s3/transport.js.map +1 -0
  316. package/dist/providers/s3/upload-body.js +10 -0
  317. package/dist/providers/s3/upload-body.js.map +1 -0
  318. package/dist/providers/s3/validation.js +31 -0
  319. package/dist/providers/s3/validation.js.map +1 -0
  320. package/dist/providers/s3/versions.d.ts +10 -0
  321. package/dist/providers/s3/versions.js +143 -0
  322. package/dist/providers/s3/versions.js.map +1 -0
  323. package/dist/providers/s3-compatible/config.d.ts +36 -0
  324. package/dist/providers/s3-compatible/config.js +174 -0
  325. package/dist/providers/s3-compatible/config.js.map +1 -0
  326. package/dist/providers/s3-compatible/service.js +48 -0
  327. package/dist/providers/s3-compatible/service.js.map +1 -0
  328. package/dist/providers/supabase/config.d.ts +20 -0
  329. package/dist/providers/supabase/config.js +41 -0
  330. package/dist/providers/supabase/config.js.map +1 -0
  331. package/dist/providers/supabase/mapping.js +60 -0
  332. package/dist/providers/supabase/mapping.js.map +1 -0
  333. package/dist/providers/supabase/primitives.js +205 -0
  334. package/dist/providers/supabase/primitives.js.map +1 -0
  335. package/dist/providers/supabase/transport.js +64 -0
  336. package/dist/providers/supabase/transport.js.map +1 -0
  337. package/dist/providers/supabase/tus.js +163 -0
  338. package/dist/providers/supabase/tus.js.map +1 -0
  339. package/dist/providers/tigris/configuration.js +118 -0
  340. package/dist/providers/tigris/configuration.js.map +1 -0
  341. package/dist/providers/tigris/snapshots.js +87 -0
  342. package/dist/providers/tigris/snapshots.js.map +1 -0
  343. package/dist/providers/tigris/transport.js +18 -0
  344. package/dist/providers/tigris/transport.js.map +1 -0
  345. package/dist/providers/vercel/config.d.ts +16 -0
  346. package/dist/providers/vercel/config.js +48 -0
  347. package/dist/providers/vercel/config.js.map +1 -0
  348. package/dist/providers/vercel/mapping.js +79 -0
  349. package/dist/providers/vercel/mapping.js.map +1 -0
  350. package/dist/providers/vercel/multipart.js +113 -0
  351. package/dist/providers/vercel/multipart.js.map +1 -0
  352. package/dist/providers/vercel/primitives.js +168 -0
  353. package/dist/providers/vercel/primitives.js.map +1 -0
  354. package/dist/providers/vercel/transport.js +32 -0
  355. package/dist/providers/vercel/transport.js.map +1 -0
  356. package/dist/providers/wasabi/compliance.d.ts +52 -0
  357. package/dist/providers/wasabi/compliance.js +89 -0
  358. package/dist/providers/wasabi/compliance.js.map +1 -0
  359. package/dist/providers/wasabi/xml.js +55 -0
  360. package/dist/providers/wasabi/xml.js.map +1 -0
  361. package/dist/r2/admin.d.ts +126 -0
  362. package/dist/r2/admin.js +138 -0
  363. package/dist/r2/admin.js.map +1 -0
  364. package/dist/r2/events.d.ts +41 -0
  365. package/dist/r2/events.js +37 -0
  366. package/dist/r2/events.js.map +1 -0
  367. package/dist/r2-workers.d.ts +24 -0
  368. package/dist/r2-workers.js +115 -0
  369. package/dist/r2-workers.js.map +1 -0
  370. package/dist/r2.d.ts +15 -0
  371. package/dist/r2.js +15 -0
  372. package/dist/r2.js.map +1 -0
  373. package/dist/react.d.ts +73 -0
  374. package/dist/react.js +49 -0
  375. package/dist/react.js.map +1 -0
  376. package/dist/representation.d.ts +24 -0
  377. package/dist/representation.js +7 -0
  378. package/dist/representation.js.map +1 -0
  379. package/dist/runtime/bun-filesystem.js +136 -0
  380. package/dist/runtime/bun-filesystem.js.map +1 -0
  381. package/dist/runtime/file-target.d.ts +10 -0
  382. package/dist/runtime/file-target.js +66 -0
  383. package/dist/runtime/file-target.js.map +1 -0
  384. package/dist/runtime/filesystem.d.ts +6 -0
  385. package/dist/runtime/filesystem.js +68 -0
  386. package/dist/runtime/filesystem.js.map +1 -0
  387. package/dist/runtime/node-hash.d.ts +4 -0
  388. package/dist/runtime/node-hash.js +31 -0
  389. package/dist/runtime/node-hash.js.map +1 -0
  390. package/dist/runtime/node-protection.d.ts +4 -0
  391. package/dist/runtime/node-protection.js +46 -0
  392. package/dist/runtime/node-protection.js.map +1 -0
  393. package/dist/runtime/portable-hash.d.ts +3 -0
  394. package/dist/runtime/portable-hash.js +31 -0
  395. package/dist/runtime/portable-hash.js.map +1 -0
  396. package/dist/runtime/session-store.d.ts +12 -0
  397. package/dist/runtime/session-store.js +19 -0
  398. package/dist/runtime/session-store.js.map +1 -0
  399. package/dist/runtime/web-protection.d.ts +7 -0
  400. package/dist/runtime/web-protection.js +54 -0
  401. package/dist/runtime/web-protection.js.map +1 -0
  402. package/dist/s3/admin.d.ts +183 -0
  403. package/dist/s3/admin.js +197 -0
  404. package/dist/s3/admin.js.map +1 -0
  405. package/dist/s3/archive.d.ts +25 -0
  406. package/dist/s3/archive.js +113 -0
  407. package/dist/s3/archive.js.map +1 -0
  408. package/dist/s3/events.d.ts +42 -0
  409. package/dist/s3/events.js +69 -0
  410. package/dist/s3/events.js.map +1 -0
  411. package/dist/s3/governance.d.ts +319 -0
  412. package/dist/s3/governance.js +108 -0
  413. package/dist/s3/governance.js.map +1 -0
  414. package/dist/s3/lifecycle.d.ts +4 -0
  415. package/dist/s3/lifecycle.js +5 -0
  416. package/dist/s3/post.d.ts +31 -0
  417. package/dist/s3/post.js +93 -0
  418. package/dist/s3/post.js.map +1 -0
  419. package/dist/s3/signing.d.ts +105 -0
  420. package/dist/s3/signing.js +198 -0
  421. package/dist/s3/signing.js.map +1 -0
  422. package/dist/s3/uploads.d.ts +11 -0
  423. package/dist/s3/uploads.js +173 -0
  424. package/dist/s3/uploads.js.map +1 -0
  425. package/dist/s3.d.ts +37 -0
  426. package/dist/s3.js +114 -0
  427. package/dist/s3.js.map +1 -0
  428. package/dist/scaleway/admin.d.ts +112 -0
  429. package/dist/scaleway/admin.js +19 -0
  430. package/dist/scaleway/admin.js.map +1 -0
  431. package/dist/scaleway.d.ts +15 -0
  432. package/dist/scaleway.js +15 -0
  433. package/dist/scaleway.js.map +1 -0
  434. package/dist/session-events.d.ts +22 -0
  435. package/dist/session-events.js +22 -0
  436. package/dist/session-events.js.map +1 -0
  437. package/dist/sessions/checkpoint.d.ts +423 -0
  438. package/dist/sessions/checkpoint.js +102 -0
  439. package/dist/sessions/checkpoint.js.map +1 -0
  440. package/dist/sessions/download.d.ts +17 -0
  441. package/dist/sessions/download.js +111 -0
  442. package/dist/sessions/download.js.map +1 -0
  443. package/dist/sessions/native-upload.js +168 -0
  444. package/dist/sessions/native-upload.js.map +1 -0
  445. package/dist/sessions/store.d.ts +40 -0
  446. package/dist/sessions/store.js +77 -0
  447. package/dist/sessions/store.js.map +1 -0
  448. package/dist/sessions/upload.d.ts +10 -0
  449. package/dist/sessions/upload.js +329 -0
  450. package/dist/sessions/upload.js.map +1 -0
  451. package/dist/sessions.d.ts +98 -0
  452. package/dist/sessions.js +268 -0
  453. package/dist/sessions.js.map +1 -0
  454. package/dist/spaces/admin.d.ts +112 -0
  455. package/dist/spaces/admin.js +19 -0
  456. package/dist/spaces/admin.js.map +1 -0
  457. package/dist/spaces.d.ts +15 -0
  458. package/dist/spaces.js +15 -0
  459. package/dist/spaces.js.map +1 -0
  460. package/dist/supabase/admin.d.ts +77 -0
  461. package/dist/supabase/admin.js +74 -0
  462. package/dist/supabase/admin.js.map +1 -0
  463. package/dist/supabase/s3.d.ts +311 -0
  464. package/dist/supabase/s3.js +153 -0
  465. package/dist/supabase/s3.js.map +1 -0
  466. package/dist/supabase/signing.d.ts +23 -0
  467. package/dist/supabase/signing.js +93 -0
  468. package/dist/supabase/signing.js.map +1 -0
  469. package/dist/supabase/tus-uploads.d.ts +13 -0
  470. package/dist/supabase/tus-uploads.js +109 -0
  471. package/dist/supabase/tus-uploads.js.map +1 -0
  472. package/dist/supabase/uploads.d.ts +5 -0
  473. package/dist/supabase/uploads.js +32 -0
  474. package/dist/supabase/uploads.js.map +1 -0
  475. package/dist/supabase.d.ts +100 -0
  476. package/dist/supabase.js +50 -0
  477. package/dist/supabase.js.map +1 -0
  478. package/dist/testing/body-failure.js +18 -0
  479. package/dist/testing/body-failure.js.map +1 -0
  480. package/dist/testing/conformance/assertions.d.ts +10 -0
  481. package/dist/testing/conformance/assertions.js +21 -0
  482. package/dist/testing/conformance/assertions.js.map +1 -0
  483. package/dist/testing/conformance/core-cases.js +107 -0
  484. package/dist/testing/conformance/core-cases.js.map +1 -0
  485. package/dist/testing/conformance/list-cases.js +72 -0
  486. package/dist/testing/conformance/list-cases.js.map +1 -0
  487. package/dist/testing/conformance/read-cases.js +105 -0
  488. package/dist/testing/conformance/read-cases.js.map +1 -0
  489. package/dist/testing/conformance.d.ts +23 -0
  490. package/dist/testing/conformance.js +37 -0
  491. package/dist/testing/conformance.js.map +1 -0
  492. package/dist/testing/faults.d.ts +258 -0
  493. package/dist/testing/faults.js +111 -0
  494. package/dist/testing/faults.js.map +1 -0
  495. package/dist/testing/memory-list.js +79 -0
  496. package/dist/testing/memory-list.js.map +1 -0
  497. package/dist/testing/memory-state.d.ts +18 -0
  498. package/dist/testing/memory-state.js +57 -0
  499. package/dist/testing/memory-state.js.map +1 -0
  500. package/dist/testing/memory-upload.js +123 -0
  501. package/dist/testing/memory-upload.js.map +1 -0
  502. package/dist/testing/memory.d.ts +23 -0
  503. package/dist/testing/memory.js +121 -0
  504. package/dist/testing/memory.js.map +1 -0
  505. package/dist/testing.d.ts +6 -0
  506. package/dist/testing.js +6 -0
  507. package/dist/tigris/events.d.ts +42 -0
  508. package/dist/tigris/events.js +42 -0
  509. package/dist/tigris/events.js.map +1 -0
  510. package/dist/tigris/native.d.ts +438 -0
  511. package/dist/tigris/native.js +166 -0
  512. package/dist/tigris/native.js.map +1 -0
  513. package/dist/tigris.d.ts +15 -0
  514. package/dist/tigris.js +15 -0
  515. package/dist/tigris.js.map +1 -0
  516. package/dist/transfers/budget.js +50 -0
  517. package/dist/transfers/budget.js.map +1 -0
  518. package/dist/transfers/copy.js +250 -0
  519. package/dist/transfers/copy.js.map +1 -0
  520. package/dist/transfers/dependencies.d.ts +10 -0
  521. package/dist/transfers/dependencies.js +11 -0
  522. package/dist/transfers/dependencies.js.map +1 -0
  523. package/dist/transfers/download.js +132 -0
  524. package/dist/transfers/download.js.map +1 -0
  525. package/dist/transfers/managed-runtime.d.ts +34 -0
  526. package/dist/transfers/managed-runtime.js +30 -0
  527. package/dist/transfers/managed-runtime.js.map +1 -0
  528. package/dist/transfers/models.d.ts +160 -0
  529. package/dist/transfers/native-upload.js +195 -0
  530. package/dist/transfers/native-upload.js.map +1 -0
  531. package/dist/transfers/part-receipts.js +32 -0
  532. package/dist/transfers/part-receipts.js.map +1 -0
  533. package/dist/transfers/planner.d.ts +19 -0
  534. package/dist/transfers/planner.js +153 -0
  535. package/dist/transfers/planner.js.map +1 -0
  536. package/dist/transfers/reader.js +81 -0
  537. package/dist/transfers/reader.js.map +1 -0
  538. package/dist/transfers/runtime.d.ts +19 -0
  539. package/dist/transfers/runtime.js +132 -0
  540. package/dist/transfers/runtime.js.map +1 -0
  541. package/dist/transfers/sources.d.ts +22 -0
  542. package/dist/transfers/sources.js +83 -0
  543. package/dist/transfers/sources.js.map +1 -0
  544. package/dist/transfers/upload.js +235 -0
  545. package/dist/transfers/upload.js.map +1 -0
  546. package/dist/transfers.d.ts +31 -0
  547. package/dist/transfers.js +82 -0
  548. package/dist/transfers.js.map +1 -0
  549. package/dist/uploads/driver.d.ts +22 -0
  550. package/dist/uploads/driver.js +18 -0
  551. package/dist/uploads/driver.js.map +1 -0
  552. package/dist/uploads/policy.d.ts +39 -0
  553. package/dist/uploads/schema.d.ts +278 -0
  554. package/dist/uploads/schema.js +167 -0
  555. package/dist/uploads/schema.js.map +1 -0
  556. package/dist/uploads/signed-driver.d.ts +8 -0
  557. package/dist/uploads/signed-driver.js +36 -0
  558. package/dist/uploads/signed-driver.js.map +1 -0
  559. package/dist/uploads/store.d.ts +26 -0
  560. package/dist/uploads/store.js +51 -0
  561. package/dist/uploads/store.js.map +1 -0
  562. package/dist/uploads/verification.js +86 -0
  563. package/dist/uploads/verification.js.map +1 -0
  564. package/dist/uploads.d.ts +518 -0
  565. package/dist/uploads.js +330 -0
  566. package/dist/uploads.js.map +1 -0
  567. package/dist/vercel/authorized-uploads.d.ts +7 -0
  568. package/dist/vercel/authorized-uploads.js +15 -0
  569. package/dist/vercel/authorized-uploads.js.map +1 -0
  570. package/dist/vercel/client.d.ts +16 -0
  571. package/dist/vercel/client.js +28 -0
  572. package/dist/vercel/client.js.map +1 -0
  573. package/dist/vercel/signing.d.ts +19 -0
  574. package/dist/vercel/signing.js +120 -0
  575. package/dist/vercel/signing.js.map +1 -0
  576. package/dist/vercel/uploads.d.ts +36 -0
  577. package/dist/vercel/uploads.js +161 -0
  578. package/dist/vercel/uploads.js.map +1 -0
  579. package/dist/vercel.d.ts +86 -0
  580. package/dist/vercel.js +46 -0
  581. package/dist/vercel.js.map +1 -0
  582. package/dist/wasabi/admin.d.ts +112 -0
  583. package/dist/wasabi/admin.js +19 -0
  584. package/dist/wasabi/admin.js.map +1 -0
  585. package/dist/wasabi/native.d.ts +200 -0
  586. package/dist/wasabi/native.js +132 -0
  587. package/dist/wasabi/native.js.map +1 -0
  588. package/dist/wasabi.d.ts +15 -0
  589. package/dist/wasabi.js +15 -0
  590. package/dist/wasabi.js.map +1 -0
  591. package/dist/workflows/content/collection.js +122 -0
  592. package/dist/workflows/content/collection.js.map +1 -0
  593. package/dist/workflows/content/references.js +113 -0
  594. package/dist/workflows/content/references.js.map +1 -0
  595. package/dist/workflows/content/schema.d.ts +58 -0
  596. package/dist/workflows/content/schema.js +64 -0
  597. package/dist/workflows/content/schema.js.map +1 -0
  598. package/dist/workflows/endpoint.js +16 -0
  599. package/dist/workflows/endpoint.js.map +1 -0
  600. package/dist/workflows/migrations/schema.d.ts +149 -0
  601. package/dist/workflows/migrations/schema.js +58 -0
  602. package/dist/workflows/migrations/schema.js.map +1 -0
  603. package/dist/workflows/mirror/operations.js +175 -0
  604. package/dist/workflows/mirror/operations.js.map +1 -0
  605. package/dist/workflows/mirror/schema.d.ts +68 -0
  606. package/dist/workflows/mirror/schema.js +57 -0
  607. package/dist/workflows/mirror/schema.js.map +1 -0
  608. package/dist/workflows/mirror/view.js +103 -0
  609. package/dist/workflows/mirror/view.js.map +1 -0
  610. package/dist/workflows/objects.js +54 -0
  611. package/dist/workflows/objects.js.map +1 -0
  612. package/dist/workflows/store.d.ts +13 -0
  613. package/dist/workflows/store.js +58 -0
  614. package/dist/workflows/store.js.map +1 -0
  615. package/package.json +513 -3
@@ -0,0 +1,55 @@
1
+ import { storageError } from "../../core/errors.js";
2
+ import { decodeRequest } from "../../internal/request-validation.js";
3
+ import { encryption, lease } from "./config.js";
4
+ import { metadata, nativeHeaders, target } from "./mapping.js";
5
+ import { request } from "./transport.js";
6
+ import { AzureStorage } from "../../azure.js";
7
+ import { MetadataReplace } from "../../lifecycle.js";
8
+ import { replaceHeaders } from "../../lifecycle/metadata.js";
9
+ import { Context, Effect, Layer } from "effect";
10
+
11
+ // src/providers/azure/properties.ts
12
+ const make = (storage) => ({
13
+ /** Azure writes system headers separately from custom metadata. Each operation has its own CAS. */
14
+ setHeaders: Effect.fnUntraced(function* (input) {
15
+ const value = yield* decodeRequest(MetadataReplace, input, "setHeaders", "azure", true);
16
+ if (value.ref.version || value.condition?._tag !== "IfMatch" || value.headers.customMetadata) return yield* storageError("setHeaders", "azure", {
17
+ _tag: "InvalidInput",
18
+ field: "current-if-match-system-headers"
19
+ }, "not-started");
20
+ const address = yield* target(storage, { ref: value.ref }, "setHeaders");
21
+ const conditions = {
22
+ ifMatch: value.condition.etag,
23
+ ...lease(storage.config)
24
+ };
25
+ const before = yield* request(storage, "setHeaders.head", false, (signal) => address.client.getProperties({
26
+ abortSignal: signal,
27
+ conditions,
28
+ ...encryption(storage.config)
29
+ }));
30
+ const previous = metadata(storage, value.ref.key, before);
31
+ const headers = replaceHeaders(previous, value.headers);
32
+ const output = yield* request(storage, "setHeaders", true, (signal) => address.client.setHTTPHeaders(nativeHeaders(headers), {
33
+ abortSignal: signal,
34
+ conditions
35
+ }));
36
+ if (!output.etag) return yield* storageError("setHeaders", "azure", {
37
+ _tag: "ProviderFailure",
38
+ code: "MissingHeadersReceipt"
39
+ }, "unknown");
40
+ return {
41
+ ...metadata(storage, value.ref.key, {
42
+ ...before,
43
+ versionId: void 0,
44
+ ...output
45
+ }),
46
+ ...value.headers
47
+ };
48
+ }) });
49
+ var AzureProperties = class AzureProperties extends Context.Service()("@effect-kit/storage/azure/AzureProperties") {
50
+ static make = make;
51
+ static layer = Layer.effect(AzureProperties, Effect.map(AzureStorage, make));
52
+ };
53
+
54
+ export { AzureProperties };
55
+ //# sourceMappingURL=properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"properties.js","names":[],"sources":["../../../src/providers/azure/properties.ts"],"sourcesContent":["import { Context, Effect, Layer } from \"effect\";\n\nimport { storageError } from \"../../core/errors.js\";\nimport { decodeRequest } from \"../../internal/request-validation.js\";\nimport { MetadataReplace } from \"../../lifecycle/index.js\";\nimport { replaceHeaders } from \"../../lifecycle/metadata.js\";\nimport { encryption, lease } from \"./config.js\";\nimport { AzureStorage } from \"./index.js\";\nimport type { AzureStorageService } from \"./index.js\";\nimport { metadata, nativeHeaders, target } from \"./mapping.js\";\nimport { request } from \"./transport.js\";\n\nconst make = (storage: AzureStorageService) => ({\n /** Azure writes system headers separately from custom metadata. Each operation has its own CAS. */\n setHeaders: Effect.fnUntraced(function* (input: typeof MetadataReplace.Type) {\n const value = yield* decodeRequest(MetadataReplace, input, \"setHeaders\", \"azure\", true);\n if (value.ref.version || value.condition?._tag !== \"IfMatch\" || value.headers.customMetadata)\n return yield* storageError(\n \"setHeaders\",\n \"azure\",\n { _tag: \"InvalidInput\", field: \"current-if-match-system-headers\" },\n \"not-started\",\n );\n const address = yield* target(storage, { ref: value.ref }, \"setHeaders\");\n const conditions = { ifMatch: value.condition.etag, ...lease(storage.config) };\n const before = yield* request(storage, \"setHeaders.head\", false, (signal) =>\n address.client.getProperties({\n abortSignal: signal,\n conditions,\n ...encryption(storage.config),\n }),\n );\n const previous = metadata(storage, value.ref.key, before);\n const headers = replaceHeaders(previous, value.headers);\n const output = yield* request(storage, \"setHeaders\", true, (signal) =>\n address.client.setHTTPHeaders(nativeHeaders(headers), { abortSignal: signal, conditions }),\n );\n if (!output.etag)\n return yield* storageError(\n \"setHeaders\",\n \"azure\",\n { _tag: \"ProviderFailure\", code: \"MissingHeadersReceipt\" },\n \"unknown\",\n );\n return {\n ...metadata(storage, value.ref.key, { ...before, versionId: undefined, ...output }),\n ...value.headers,\n };\n }),\n});\nexport class AzureProperties extends Context.Service<AzureProperties, ReturnType<typeof make>>()(\n \"@effect-kit/storage/azure/AzureProperties\",\n) {\n static readonly make = make;\n static readonly layer = Layer.effect(AzureProperties, Effect.map(AzureStorage, make));\n}\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,QAAQ,aAAkC;;AAE9C,YAAY,OAAO,WAAW,WAAW,OAAoC;CAC3E,MAAM,QAAQ,OAAO,cAAc,iBAAiB,OAAO,cAAc,SAAS,IAAI;CACtF,IAAI,MAAM,IAAI,WAAW,MAAM,WAAW,SAAS,aAAa,MAAM,QAAQ,gBAC5E,OAAO,OAAO,aACZ,cACA,SACA;EAAE,MAAM;EAAgB,OAAO;CAAkC,GACjE,aACF;CACF,MAAM,UAAU,OAAO,OAAO,SAAS,EAAE,KAAK,MAAM,IAAI,GAAG,YAAY;CACvE,MAAM,aAAa;EAAE,SAAS,MAAM,UAAU;EAAM,GAAG,MAAM,QAAQ,MAAM;CAAE;CAC7E,MAAM,SAAS,OAAO,QAAQ,SAAS,mBAAmB,QAAQ,WAChE,QAAQ,OAAO,cAAc;EAC3B,aAAa;EACb;EACA,GAAG,WAAW,QAAQ,MAAM;CAC9B,CAAC,CACH;CACA,MAAM,WAAW,SAAS,SAAS,MAAM,IAAI,KAAK,MAAM;CACxD,MAAM,UAAU,eAAe,UAAU,MAAM,OAAO;CACtD,MAAM,SAAS,OAAO,QAAQ,SAAS,cAAc,OAAO,WAC1D,QAAQ,OAAO,eAAe,cAAc,OAAO,GAAG;EAAE,aAAa;EAAQ;CAAW,CAAC,CAC3F;CACA,IAAI,CAAC,OAAO,MACV,OAAO,OAAO,aACZ,cACA,SACA;EAAE,MAAM;EAAmB,MAAM;CAAwB,GACzD,SACF;CACF,OAAO;EACL,GAAG,SAAS,SAAS,MAAM,IAAI,KAAK;GAAE,GAAG;GAAQ,WAAW;GAAW,GAAG;EAAO,CAAC;EAClF,GAAG,MAAM;CACX;AACF,CAAC,EACH;AACA,IAAa,kBAAb,MAAa,wBAAwB,QAAQ,QAAkD,CAAC,CAC9F,2CACF,CAAC,CAAC;CACA,OAAgB,OAAO;CACvB,OAAgB,QAAQ,MAAM,OAAO,iBAAiB,OAAO,IAAI,cAAc,IAAI,CAAC;AACtF"}
@@ -0,0 +1,14 @@
1
+ import { providerError } from "../../internal/node/provider-errors.js";
2
+ import { Effect } from "effect";
3
+
4
+ // src/providers/azure/transport.ts
5
+ const request = (connection, operation, mutation, call) => Effect.tryPromise({
6
+ try: call,
7
+ catch: (error) => providerError("azure", operation, mutation, error)
8
+ }).pipe(Effect.timeoutOrElse({
9
+ duration: connection.config.requestTimeoutMillis,
10
+ orElse: () => Effect.fail(providerError("azure", operation, mutation, void 0))
11
+ }));
12
+
13
+ export { request };
14
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","names":[],"sources":["../../../src/providers/azure/transport.ts"],"sourcesContent":["import { Effect } from \"effect\";\n\nimport { providerError } from \"../../internal/node/provider-errors.js\";\nimport type { AzureConnection } from \"./config.js\";\n\nexport const request = <A>(\n connection: AzureConnection,\n operation: string,\n mutation: boolean,\n call: (signal: AbortSignal) => Promise<A>,\n) =>\n Effect.tryPromise({\n try: call,\n catch: (error) => providerError(\"azure\", operation, mutation, error),\n }).pipe(\n Effect.timeoutOrElse({\n duration: connection.config.requestTimeoutMillis,\n orElse: () => Effect.fail(providerError(\"azure\", operation, mutation, undefined)),\n }),\n );\n"],"mappings":";;;;AAKA,MAAa,WACX,YACA,WACA,UACA,SAEA,OAAO,WAAW;CAChB,KAAK;CACL,QAAQ,UAAU,cAAc,SAAS,WAAW,UAAU,KAAK;AACrE,CAAC,CAAC,CAAC,KACD,OAAO,cAAc;CACnB,UAAU,WAAW,OAAO;CAC5B,cAAc,OAAO,KAAK,cAAc,SAAS,WAAW,UAAU,MAAS,CAAC;AAClF,CAAC,CACH"}
@@ -0,0 +1,11 @@
1
+ import { ObjectKey } from "../../core/object.js";
2
+ import { decodeRequest } from "../../internal/request-validation.js";
3
+ import { Schema } from "effect";
4
+
5
+ // src/providers/azure/validation.ts
6
+ /** The SDK normalizes dot segments, so accepting them would address a different blob. */
7
+ const AzureKey = ObjectKey.check(Schema.makeFilter((key) => Array.from(key).length <= 1024 && !key.split("/").some((segment) => segment === "." || segment === ".."), { expected: "an Azure blob name within 1024 characters without dot segments" }));
8
+ const validateKey = (key, operation, mutation = false) => decodeRequest(AzureKey, key, operation, "azure", mutation);
9
+
10
+ export { AzureKey, validateKey };
11
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","names":[],"sources":["../../../src/providers/azure/validation.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nimport { ObjectKey } from \"../../core/object.js\";\nimport { decodeRequest } from \"../../internal/request-validation.js\";\n\n/** The SDK normalizes dot segments, so accepting them would address a different blob. */\nexport const AzureKey = ObjectKey.check(\n Schema.makeFilter(\n (key) =>\n Array.from(key).length <= 1024 &&\n !key.split(\"/\").some((segment) => segment === \".\" || segment === \"..\"),\n { expected: \"an Azure blob name within 1024 characters without dot segments\" },\n ),\n);\nexport const validateKey = (key: string, operation: string, mutation = false) =>\n decodeRequest(AzureKey, key, operation, \"azure\", mutation);\n"],"mappings":";;;;;;AAMA,MAAa,WAAW,UAAU,MAChC,OAAO,YACJ,QACC,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,QAC1B,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,MAAM,YAAY,YAAY,OAAO,YAAY,IAAI,GACvE,EAAE,UAAU,iEAAiE,CAC/E,CACF;AACA,MAAa,eAAe,KAAa,WAAmB,WAAW,UACrE,cAAc,UAAU,KAAK,WAAW,SAAS,QAAQ"}
@@ -0,0 +1,56 @@
1
+ import { ObjectMetadata } from "../../core/object.js";
2
+ import { fileError, fileSize } from "./layout.js";
3
+ import { Effect, Option, Schema } from "effect";
4
+
5
+ // src/providers/filesystem/envelope.ts
6
+ const headerBytes = 65536;
7
+ const magic = new TextEncoder().encode("EFSTOR01");
8
+ const Envelope = Schema.fromJsonString(Schema.Struct({
9
+ version: Schema.Literal(1),
10
+ metadata: ObjectMetadata
11
+ }));
12
+ const readExactly = Effect.fnUntraced(function* (file, length, position) {
13
+ const bytes = new Uint8Array(length);
14
+ let offset = 0;
15
+ while (offset < length) {
16
+ const count = yield* file.read(bytes.subarray(offset), { position: BigInt(position + offset) });
17
+ if (count === 0) return yield* fileError("get", "TruncatedEnvelope");
18
+ offset += count;
19
+ }
20
+ return bytes;
21
+ });
22
+ const encodeEnvelope = Effect.fnUntraced(function* (metadata) {
23
+ const encoded = yield* Schema.encodeEffect(Envelope)({
24
+ version: 1,
25
+ metadata
26
+ }).pipe(Effect.mapError(() => fileError("put", "InvalidMetadata", "not-started")));
27
+ const bytes = new TextEncoder().encode(encoded);
28
+ if (bytes.length > 65524) return yield* fileError("put", "MetadataTooLarge", "not-started");
29
+ const header = new Uint8Array(headerBytes);
30
+ header.set(magic);
31
+ new DataView(header.buffer).setUint32(8, bytes.length);
32
+ header.set(bytes, 12);
33
+ return header;
34
+ });
35
+ const readEnvelope = Effect.fnUntraced(function* (context, file, key) {
36
+ const prefix = yield* readExactly(file, 12, 0);
37
+ if (!magic.every((byte, index) => prefix[index] === byte)) return yield* fileError("get", "InvalidEnvelope");
38
+ const length = new DataView(prefix.buffer).getUint32(8);
39
+ if (length < 1 || length > 65524) return yield* fileError("get", "InvalidEnvelope");
40
+ const encoded = yield* readExactly(file, length, 12);
41
+ const text = yield* Effect.try({
42
+ try: () => new TextDecoder("utf-8", { fatal: true }).decode(encoded),
43
+ catch: () => fileError("get", "InvalidEnvelope")
44
+ });
45
+ const { metadata } = yield* Schema.decodeUnknownEffect(Envelope)(text).pipe(Effect.mapError(() => fileError("get", "InvalidEnvelope")));
46
+ if (metadata.ref.storeId !== context.storeId || metadata.ref.version || key !== void 0 && metadata.ref.key !== key || metadata.size === void 0 || !metadata.etag || metadata.checksums?.length !== 1 || metadata.checksums[0]?.algorithm !== "sha256" || metadata.checksums[0]?.scope !== "full-object" || fileSize(yield* file.stat) !== BigInt(65536) + BigInt(metadata.size)) return yield* fileError("get", "InvalidEnvelope");
47
+ return metadata;
48
+ });
49
+ const readChunk = Effect.fnUntraced(function* (file, position, length) {
50
+ const bytes = yield* file.readAlloc(length, { position: BigInt(position) });
51
+ if (Option.isNone(bytes)) return yield* fileError("get", "TruncatedBody");
52
+ return bytes.value;
53
+ });
54
+
55
+ export { encodeEnvelope, headerBytes, readChunk, readEnvelope, readExactly };
56
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.js","names":[],"sources":["../../../src/providers/filesystem/envelope.ts"],"sourcesContent":["import { Effect, Option, Schema } from \"effect\";\nimport type { FileSystem } from \"effect\";\n\nimport { ObjectMetadata } from \"../../core/object.js\";\nimport { fileError, fileSize } from \"./layout.js\";\nimport type { FilesystemContext } from \"./layout.js\";\n\n// One immutable file publishes bytes and metadata together, without sidecar races.\nexport const headerBytes = 65536;\nconst magic = new TextEncoder().encode(\"EFSTOR01\");\nconst Envelope = Schema.fromJsonString(\n Schema.Struct({ version: Schema.Literal(1), metadata: ObjectMetadata }),\n);\n\nexport const readExactly = Effect.fnUntraced(function* (\n file: FileSystem.File,\n length: number,\n position: number,\n) {\n const bytes = new Uint8Array(length);\n let offset = 0;\n while (offset < length) {\n const count = yield* file.read(bytes.subarray(offset), { position: BigInt(position + offset) });\n if (count === 0) return yield* fileError(\"get\", \"TruncatedEnvelope\");\n offset += count;\n }\n return bytes;\n});\n\nexport const encodeEnvelope = Effect.fnUntraced(function* (metadata: ObjectMetadata) {\n const encoded = yield* Schema.encodeEffect(Envelope)({ version: 1, metadata }).pipe(\n Effect.mapError(() => fileError(\"put\", \"InvalidMetadata\", \"not-started\")),\n );\n const bytes = new TextEncoder().encode(encoded);\n if (bytes.length > headerBytes - 12)\n return yield* fileError(\"put\", \"MetadataTooLarge\", \"not-started\");\n const header = new Uint8Array(headerBytes);\n header.set(magic);\n new DataView(header.buffer).setUint32(8, bytes.length);\n header.set(bytes, 12);\n return header;\n});\n\nexport const readEnvelope = Effect.fnUntraced(function* (\n context: FilesystemContext,\n file: FileSystem.File,\n key?: string,\n) {\n const prefix = yield* readExactly(file, 12, 0);\n if (!magic.every((byte, index) => prefix[index] === byte))\n return yield* fileError(\"get\", \"InvalidEnvelope\");\n const length = new DataView(prefix.buffer).getUint32(8);\n if (length < 1 || length > headerBytes - 12) return yield* fileError(\"get\", \"InvalidEnvelope\");\n const encoded = yield* readExactly(file, length, 12);\n const text = yield* Effect.try({\n try: () => new TextDecoder(\"utf-8\", { fatal: true }).decode(encoded),\n catch: () => fileError(\"get\", \"InvalidEnvelope\"),\n });\n const { metadata } = yield* Schema.decodeUnknownEffect(Envelope)(text).pipe(\n Effect.mapError(() => fileError(\"get\", \"InvalidEnvelope\")),\n );\n if (\n metadata.ref.storeId !== context.storeId ||\n metadata.ref.version ||\n (key !== undefined && metadata.ref.key !== key) ||\n metadata.size === undefined ||\n !metadata.etag ||\n metadata.checksums?.length !== 1 ||\n metadata.checksums[0]?.algorithm !== \"sha256\" ||\n metadata.checksums[0]?.scope !== \"full-object\" ||\n fileSize(yield* file.stat) !== BigInt(headerBytes) + BigInt(metadata.size)\n )\n return yield* fileError(\"get\", \"InvalidEnvelope\");\n return metadata;\n});\n\nexport const readChunk = Effect.fnUntraced(function* (\n file: FileSystem.File,\n position: number,\n length: number,\n) {\n const bytes = yield* file.readAlloc(length, { position: BigInt(position) });\n if (Option.isNone(bytes)) return yield* fileError(\"get\", \"TruncatedBody\");\n return bytes.value;\n});\n"],"mappings":";;;;;AAQA,MAAa,cAAc;AAC3B,MAAM,QAAQ,IAAI,YAAY,CAAC,CAAC,OAAO,UAAU;AACjD,MAAM,WAAW,OAAO,eACtB,OAAO,OAAO;CAAE,SAAS,OAAO,QAAQ,CAAC;CAAG,UAAU;AAAe,CAAC,CACxE;AAEA,MAAa,cAAc,OAAO,WAAW,WAC3C,MACA,QACA,UACA;CACA,MAAM,QAAQ,IAAI,WAAW,MAAM;CACnC,IAAI,SAAS;CACb,OAAO,SAAS,QAAQ;EACtB,MAAM,QAAQ,OAAO,KAAK,KAAK,MAAM,SAAS,MAAM,GAAG,EAAE,UAAU,OAAO,WAAW,MAAM,EAAE,CAAC;EAC9F,IAAI,UAAU,GAAG,OAAO,OAAO,UAAU,OAAO,mBAAmB;EACnE,UAAU;CACZ;CACA,OAAO;AACT,CAAC;AAED,MAAa,iBAAiB,OAAO,WAAW,WAAW,UAA0B;CACnF,MAAM,UAAU,OAAO,OAAO,aAAa,QAAQ,CAAC,CAAC;EAAE,SAAS;EAAG;CAAS,CAAC,CAAC,CAAC,KAC7E,OAAO,eAAe,UAAU,OAAO,mBAAmB,aAAa,CAAC,CAC1E;CACA,MAAM,QAAQ,IAAI,YAAY,CAAC,CAAC,OAAO,OAAO;CAC9C,IAAI,MAAM,SAAS,OACjB,OAAO,OAAO,UAAU,OAAO,oBAAoB,aAAa;CAClE,MAAM,SAAS,IAAI,WAAW,WAAW;CACzC,OAAO,IAAI,KAAK;CAChB,IAAI,SAAS,OAAO,MAAM,CAAC,CAAC,UAAU,GAAG,MAAM,MAAM;CACrD,OAAO,IAAI,OAAO,EAAE;CACpB,OAAO;AACT,CAAC;AAED,MAAa,eAAe,OAAO,WAAW,WAC5C,SACA,MACA,KACA;CACA,MAAM,SAAS,OAAO,YAAY,MAAM,IAAI,CAAC;CAC7C,IAAI,CAAC,MAAM,OAAO,MAAM,UAAU,OAAO,WAAW,IAAI,GACtD,OAAO,OAAO,UAAU,OAAO,iBAAiB;CAClD,MAAM,SAAS,IAAI,SAAS,OAAO,MAAM,CAAC,CAAC,UAAU,CAAC;CACtD,IAAI,SAAS,KAAK,SAAS,OAAkB,OAAO,OAAO,UAAU,OAAO,iBAAiB;CAC7F,MAAM,UAAU,OAAO,YAAY,MAAM,QAAQ,EAAE;CACnD,MAAM,OAAO,OAAO,OAAO,IAAI;EAC7B,WAAW,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO;EACnE,aAAa,UAAU,OAAO,iBAAiB;CACjD,CAAC;CACD,MAAM,EAAE,aAAa,OAAO,OAAO,oBAAoB,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,KACrE,OAAO,eAAe,UAAU,OAAO,iBAAiB,CAAC,CAC3D;CACA,IACE,SAAS,IAAI,YAAY,QAAQ,WACjC,SAAS,IAAI,WACZ,QAAQ,UAAa,SAAS,IAAI,QAAQ,OAC3C,SAAS,SAAS,UAClB,CAAC,SAAS,QACV,SAAS,WAAW,WAAW,KAC/B,SAAS,UAAU,EAAE,EAAE,cAAc,YACrC,SAAS,UAAU,EAAE,EAAE,UAAU,iBACjC,SAAS,OAAO,KAAK,IAAI,MAAM,YAAkB,IAAI,OAAO,SAAS,IAAI,GAEzE,OAAO,OAAO,UAAU,OAAO,iBAAiB;CAClD,OAAO;AACT,CAAC;AAED,MAAa,YAAY,OAAO,WAAW,WACzC,MACA,UACA,QACA;CACA,MAAM,QAAQ,OAAO,KAAK,UAAU,QAAQ,EAAE,UAAU,OAAO,QAAQ,EAAE,CAAC;CAC1E,IAAI,OAAO,OAAO,KAAK,GAAG,OAAO,OAAO,UAAU,OAAO,eAAe;CACxE,OAAO,MAAM;AACf,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { storageError } from "../../core/errors.js";
2
+ import { syncDirectory } from "../../runtime/filesystem.js";
3
+ import { ByteSize, Effect, Schema } from "effect";
4
+
5
+ // src/providers/filesystem/identity.ts
6
+ const Identity = Schema.fromJsonString(Schema.Struct({
7
+ version: Schema.Literal(1),
8
+ storeId: Schema.NonEmptyString,
9
+ id: Schema.NonEmptyString
10
+ }));
11
+ /** A root is bound to one format/store identity; reopening with another identity fails closed. */
12
+ const invalid = () => storageError("make", "filesystem", {
13
+ _tag: "InvalidConfiguration",
14
+ field: "root.identity"
15
+ });
16
+ const initializeIdentity = Effect.fnUntraced(function* (fs, path, root, storeId, random) {
17
+ const filename = path.join(root, "format.json");
18
+ if (!(yield* fs.exists(filename))) {
19
+ if ((yield* fs.readDirectory(root)).some((name) => name !== "objects" && name !== "staging" && name !== "format.json") || (yield* fs.readDirectory(path.join(root, "objects"))).length) {
20
+ if (!(yield* fs.exists(filename))) return yield* invalid();
21
+ }
22
+ const temporary = path.join(root, "staging", `upload-${yield* random.uuidV4()}.pending`);
23
+ const encoded = Schema.encodeSync(Identity)({
24
+ version: 1,
25
+ storeId,
26
+ id: yield* random.uuidV4()
27
+ });
28
+ yield* Effect.acquireUseRelease(Effect.succeed(temporary), () => Effect.gen(function* () {
29
+ yield* Effect.scoped(Effect.gen(function* () {
30
+ const file = yield* fs.open(temporary, {
31
+ flag: "wx",
32
+ mode: 384,
33
+ noFollow: true
34
+ });
35
+ yield* file.writeAll(new TextEncoder().encode(encoded));
36
+ yield* file.sync;
37
+ }));
38
+ yield* fs.link(temporary, filename).pipe(Effect.catchReason("PlatformError", "AlreadyExists", () => Effect.void));
39
+ yield* syncDirectory(fs, root);
40
+ }), () => fs.remove(temporary, { force: true }).pipe(Effect.orDie)).pipe(Effect.uninterruptible);
41
+ }
42
+ const identity = yield* Effect.scoped(Effect.gen(function* () {
43
+ if ((yield* fs.lstat(filename)).type !== "File") return yield* invalid();
44
+ const file = yield* fs.open(filename, {
45
+ flag: "r",
46
+ noFollow: true
47
+ });
48
+ const length = Number(ByteSize.toBigInt((yield* file.stat).size));
49
+ if (length < 1 || length > 16384) return yield* invalid();
50
+ const bytes = new Uint8Array(length);
51
+ let offset = 0;
52
+ while (offset < length) {
53
+ const count = yield* file.read(bytes.subarray(offset));
54
+ if (count === 0) return yield* invalid();
55
+ offset += count;
56
+ }
57
+ const text = yield* Effect.try({
58
+ try: () => new TextDecoder("utf-8", { fatal: true }).decode(bytes),
59
+ catch: invalid
60
+ });
61
+ return yield* Schema.decodeUnknownEffect(Identity)(text).pipe(Effect.mapError(invalid));
62
+ }));
63
+ if (identity.storeId !== storeId) return yield* invalid();
64
+ return identity.id;
65
+ });
66
+
67
+ export { initializeIdentity };
68
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","names":[],"sources":["../../../src/providers/filesystem/identity.ts"],"sourcesContent":["import { ByteSize, Effect, Schema } from \"effect\";\nimport type { FileSystem, Path } from \"effect\";\nimport type { SecureRandom } from \"effect/crypto\";\n\nimport { storageError } from \"../../core/errors.js\";\nimport { syncDirectory } from \"../../runtime/filesystem.js\";\n\nconst Identity = Schema.fromJsonString(\n Schema.Struct({\n version: Schema.Literal(1),\n storeId: Schema.NonEmptyString,\n id: Schema.NonEmptyString,\n }),\n);\n\n/** A root is bound to one format/store identity; reopening with another identity fails closed. */\nconst invalid = () =>\n storageError(\"make\", \"filesystem\", { _tag: \"InvalidConfiguration\", field: \"root.identity\" });\n\nexport const initializeIdentity = Effect.fnUntraced(function* (\n fs: FileSystem.FileSystem,\n path: Path.Path,\n root: string,\n storeId: string,\n random: SecureRandom.SecureRandom[\"Service\"],\n) {\n const filename = path.join(root, \"format.json\");\n if (!(yield* fs.exists(filename))) {\n const names = yield* fs.readDirectory(root);\n if (\n names.some((name) => name !== \"objects\" && name !== \"staging\" && name !== \"format.json\") ||\n (yield* fs.readDirectory(path.join(root, \"objects\"))).length\n ) {\n if (!(yield* fs.exists(filename))) return yield* invalid();\n }\n const temporary = path.join(root, \"staging\", `upload-${yield* random.uuidV4()}.pending`);\n const encoded = Schema.encodeSync(Identity)({\n version: 1,\n storeId,\n id: yield* random.uuidV4(),\n });\n yield* Effect.acquireUseRelease(\n Effect.succeed(temporary),\n () =>\n Effect.gen(function* () {\n yield* Effect.scoped(\n Effect.gen(function* () {\n const file = yield* fs.open(temporary, { flag: \"wx\", mode: 0o600, noFollow: true });\n yield* file.writeAll(new TextEncoder().encode(encoded));\n yield* file.sync;\n }),\n );\n yield* fs\n .link(temporary, filename)\n .pipe(Effect.catchReason(\"PlatformError\", \"AlreadyExists\", () => Effect.void));\n yield* syncDirectory(fs, root);\n }),\n () => fs.remove(temporary, { force: true }).pipe(Effect.orDie),\n ).pipe(Effect.uninterruptible);\n }\n const identity = yield* Effect.scoped(\n Effect.gen(function* () {\n if ((yield* fs.lstat(filename)).type !== \"File\") return yield* invalid();\n const file = yield* fs.open(filename, { flag: \"r\", noFollow: true });\n const length = Number(ByteSize.toBigInt((yield* file.stat).size));\n if (length < 1 || length > 16384) return yield* invalid();\n const bytes = new Uint8Array(length);\n let offset = 0;\n while (offset < length) {\n const count = yield* file.read(bytes.subarray(offset));\n if (count === 0) return yield* invalid();\n offset += count;\n }\n const text = yield* Effect.try({\n try: () => new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes),\n catch: invalid,\n });\n return yield* Schema.decodeUnknownEffect(Identity)(text).pipe(Effect.mapError(invalid));\n }),\n );\n if (identity.storeId !== storeId) return yield* invalid();\n return identity.id;\n});\n"],"mappings":";;;;;AAOA,MAAM,WAAW,OAAO,eACtB,OAAO,OAAO;CACZ,SAAS,OAAO,QAAQ,CAAC;CACzB,SAAS,OAAO;CAChB,IAAI,OAAO;AACb,CAAC,CACH;;AAGA,MAAM,gBACJ,aAAa,QAAQ,cAAc;CAAE,MAAM;CAAwB,OAAO;AAAgB,CAAC;AAE7F,MAAa,qBAAqB,OAAO,WAAW,WAClD,IACA,MACA,MACA,SACA,QACA;CACA,MAAM,WAAW,KAAK,KAAK,MAAM,aAAa;CAC9C,IAAI,EAAE,OAAO,GAAG,OAAO,QAAQ,IAAI;EAEjC,KACE,OAFmB,GAAG,cAAc,IAAI,EAEnC,CAAC,MAAM,SAAS,SAAS,aAAa,SAAS,aAAa,SAAS,aAAa,MACtF,OAAO,GAAG,cAAc,KAAK,KAAK,MAAM,SAAS,CAAC,EAAC,CAAE,QAEtD;OAAI,EAAE,OAAO,GAAG,OAAO,QAAQ,IAAI,OAAO,OAAO,QAAQ;EAAC;EAE5D,MAAM,YAAY,KAAK,KAAK,MAAM,WAAW,UAAU,OAAO,OAAO,OAAO,EAAE,SAAS;EACvF,MAAM,UAAU,OAAO,WAAW,QAAQ,CAAC,CAAC;GAC1C,SAAS;GACT;GACA,IAAI,OAAO,OAAO,OAAO;EAC3B,CAAC;EACD,OAAO,OAAO,kBACZ,OAAO,QAAQ,SAAS,SAEtB,OAAO,IAAI,aAAa;GACtB,OAAO,OAAO,OACZ,OAAO,IAAI,aAAa;IACtB,MAAM,OAAO,OAAO,GAAG,KAAK,WAAW;KAAE,MAAM;KAAM,MAAM;KAAO,UAAU;IAAK,CAAC;IAClF,OAAO,KAAK,SAAS,IAAI,YAAY,CAAC,CAAC,OAAO,OAAO,CAAC;IACtD,OAAO,KAAK;GACd,CAAC,CACH;GACA,OAAO,GACJ,KAAK,WAAW,QAAQ,CAAC,CACzB,KAAK,OAAO,YAAY,iBAAiB,uBAAuB,OAAO,IAAI,CAAC;GAC/E,OAAO,cAAc,IAAI,IAAI;EAC/B,CAAC,SACG,GAAG,OAAO,WAAW,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,KAAK,CAC/D,CAAC,CAAC,KAAK,OAAO,eAAe;CAC/B;CACA,MAAM,WAAW,OAAO,OAAO,OAC7B,OAAO,IAAI,aAAa;EACtB,KAAK,OAAO,GAAG,MAAM,QAAQ,EAAC,CAAE,SAAS,QAAQ,OAAO,OAAO,QAAQ;EACvE,MAAM,OAAO,OAAO,GAAG,KAAK,UAAU;GAAE,MAAM;GAAK,UAAU;EAAK,CAAC;EACnE,MAAM,SAAS,OAAO,SAAS,UAAU,OAAO,KAAK,KAAI,CAAE,IAAI,CAAC;EAChE,IAAI,SAAS,KAAK,SAAS,OAAO,OAAO,OAAO,QAAQ;EACxD,MAAM,QAAQ,IAAI,WAAW,MAAM;EACnC,IAAI,SAAS;EACb,OAAO,SAAS,QAAQ;GACtB,MAAM,QAAQ,OAAO,KAAK,KAAK,MAAM,SAAS,MAAM,CAAC;GACrD,IAAI,UAAU,GAAG,OAAO,OAAO,QAAQ;GACvC,UAAU;EACZ;EACA,MAAM,OAAO,OAAO,OAAO,IAAI;GAC7B,WAAW,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK;GACjE,OAAO;EACT,CAAC;EACD,OAAO,OAAO,OAAO,oBAAoB,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,OAAO,SAAS,OAAO,CAAC;CACxF,CAAC,CACH;CACA,IAAI,SAAS,YAAY,SAAS,OAAO,OAAO,QAAQ;CACxD,OAAO,SAAS;AAClB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import "../../core/errors.js";
2
+ import "../../index.js";
3
+ import "../../transfers/models.js";
4
+ import "../../transfers/dependencies.js";
5
+ import { Effect, FileSystem, Path, Schema } from "effect";
6
+ import { Digest, SecureRandom } from "effect/crypto";
7
+ import { PlatformError } from "effect/PlatformError";
8
+ export declare const FilesystemOptions: Schema.Struct<{
9
+ readonly root: Schema.NonEmptyString;
10
+ readonly storeId: Schema.NonEmptyString;
11
+ readonly maxObjectBytes: Schema.optional<Schema.Natural>;
12
+ readonly maxListEntries: Schema.optional<Schema.Int>;
13
+ }>;
14
+ export type FilesystemOptions = typeof FilesystemOptions.Type;
15
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1,112 @@
1
+ import { storageError } from "../../core/errors.js";
2
+ import { TransferHash } from "../../transfers/dependencies.js";
3
+ import { syncDirectory } from "../../runtime/filesystem.js";
4
+ import { initializeIdentity } from "./identity.js";
5
+ import { ByteSize, Effect, FileSystem, Path, Schema } from "effect";
6
+ import { Digest, SecureRandom } from "effect/crypto";
7
+
8
+ // src/providers/filesystem/layout.ts
9
+ const FilesystemOptions = Schema.Struct({
10
+ root: Schema.NonEmptyString,
11
+ storeId: Schema.NonEmptyString,
12
+ maxObjectBytes: Schema.optional(Schema.Natural.check(Schema.isLessThanOrEqualTo(Number.MAX_SAFE_INTEGER - 65536))),
13
+ maxListEntries: Schema.optional(Schema.Int.check(Schema.isBetween({
14
+ minimum: 1,
15
+ maximum: 1e6
16
+ })))
17
+ });
18
+ const fileError = (operation, code, outcome = "not-applicable") => storageError(operation, "filesystem", {
19
+ _tag: "ProviderFailure",
20
+ code
21
+ }, outcome);
22
+ const mapIO = (operation, outcome = "not-applicable") => (error) => {
23
+ const reason = error.reason._tag;
24
+ return storageError(operation, "filesystem", reason === "NotFound" ? { _tag: "NotFound" } : reason === "PermissionDenied" ? { _tag: "AccessDenied" } : {
25
+ _tag: "ProviderFailure",
26
+ code: reason
27
+ }, outcome);
28
+ };
29
+ const makeLayout = Effect.fnUntraced(function* (options) {
30
+ const input = yield* Schema.decodeUnknownEffect(FilesystemOptions, { onExcessProperty: "error" })(options).pipe(Effect.mapError(() => storageError("make", "filesystem", {
31
+ _tag: "InvalidConfiguration",
32
+ field: "options"
33
+ })));
34
+ const fs = yield* FileSystem.FileSystem;
35
+ const path = yield* Path.Path;
36
+ const identities = yield* Digest.Digest;
37
+ const random = yield* SecureRandom.SecureRandom;
38
+ const hash = yield* TransferHash;
39
+ if (hash.algorithm !== "sha256") return yield* storageError("make", "filesystem", {
40
+ _tag: "InvalidConfiguration",
41
+ field: "TransferHash.algorithm"
42
+ });
43
+ const assertDirectory = Effect.fnUntraced(function* (directory) {
44
+ if ((yield* fs.lstat(directory)).type !== "Directory") return yield* fileError("filesystem.directory", "UnsafeDirectory");
45
+ });
46
+ const suppliedRoot = path.resolve(input.root);
47
+ if (yield* fs.exists(suppliedRoot)) yield* assertDirectory(suppliedRoot);
48
+ const missing = [];
49
+ let ancestor = suppliedRoot;
50
+ while (!(yield* fs.exists(ancestor))) {
51
+ missing.push(ancestor);
52
+ if (path.dirname(ancestor) === ancestor) break;
53
+ ancestor = path.dirname(ancestor);
54
+ }
55
+ yield* fs.makeDirectory(suppliedRoot, {
56
+ recursive: true,
57
+ mode: 448
58
+ }).pipe(Effect.mapError(mapIO("make")));
59
+ for (const created of missing) yield* syncDirectory(fs, created).pipe(Effect.mapError(mapIO("make")));
60
+ if (missing.length) yield* syncDirectory(fs, ancestor).pipe(Effect.mapError(mapIO("make")));
61
+ const root = yield* fs.realPath(suppliedRoot).pipe(Effect.mapError(mapIO("make")));
62
+ const objects = path.join(root, "objects");
63
+ const staging = path.join(root, "staging");
64
+ for (const directory of [objects, staging]) {
65
+ yield* fs.makeDirectory(directory, { mode: 448 }).pipe(Effect.catchReason("PlatformError", "AlreadyExists", () => Effect.void), Effect.mapError(mapIO("make")));
66
+ yield* assertDirectory(directory).pipe(Effect.mapError((error) => error._tag === "PlatformError" ? mapIO("make")(error) : error));
67
+ }
68
+ yield* syncDirectory(fs, root).pipe(Effect.mapError(mapIO("make")));
69
+ const rootId = yield* initializeIdentity(fs, path, root, input.storeId, random);
70
+ const checkDirectories = Effect.all([
71
+ assertDirectory(root),
72
+ assertDirectory(objects),
73
+ assertDirectory(staging)
74
+ ], { discard: true }).pipe(Effect.mapError((error) => error._tag === "PlatformError" ? mapIO("filesystem.directory")(error) : error));
75
+ const objectFilename = (key) => identities.digestHex(Digest.sha256, new TextEncoder().encode(key)).pipe(Effect.map((digest) => path.join(objects, `${digest}.object`)));
76
+ const regularFile = Effect.fnUntraced(function* (filename) {
77
+ const info = yield* fs.lstat(filename);
78
+ if (info.type !== "File") return yield* fileError("filesystem.open", "UnsafeObject");
79
+ return info;
80
+ });
81
+ const open = Effect.fnUntraced(function* (filename) {
82
+ yield* checkDirectories;
83
+ yield* regularFile(filename);
84
+ const file = yield* fs.open(filename, {
85
+ flag: "r",
86
+ noFollow: true
87
+ });
88
+ if ((yield* file.stat).type !== "File") return yield* fileError("filesystem.open", "UnsafeObject");
89
+ return file;
90
+ });
91
+ return {
92
+ fs,
93
+ path,
94
+ root,
95
+ rootId,
96
+ objects,
97
+ staging,
98
+ storeId: input.storeId,
99
+ random,
100
+ hash,
101
+ filename: objectFilename,
102
+ open,
103
+ regularFile,
104
+ checkDirectories,
105
+ maxObjectBytes: input.maxObjectBytes ?? 1073741824,
106
+ maxListEntries: input.maxListEntries ?? 1e4
107
+ };
108
+ });
109
+ const fileSize = (info) => ByteSize.toBigInt(info.size);
110
+
111
+ export { FilesystemOptions, fileError, fileSize, makeLayout, mapIO };
112
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","names":[],"sources":["../../../src/providers/filesystem/layout.ts"],"sourcesContent":["import { ByteSize, Effect, FileSystem, Path, Schema } from \"effect\";\nimport { Digest, SecureRandom } from \"effect/crypto\";\nimport type { PlatformError } from \"effect/PlatformError\";\n\nimport { storageError } from \"../../core/errors.js\";\nimport type { MutationOutcome } from \"../../core/errors.js\";\nimport { syncDirectory } from \"../../runtime/filesystem.js\";\nimport { TransferHash } from \"../../transfers/dependencies.js\";\nimport { initializeIdentity } from \"./identity.js\";\n\nexport const FilesystemOptions = Schema.Struct({\n root: Schema.NonEmptyString,\n storeId: Schema.NonEmptyString,\n maxObjectBytes: Schema.optional(\n Schema.Natural.check(Schema.isLessThanOrEqualTo(Number.MAX_SAFE_INTEGER - 65536)),\n ),\n maxListEntries: Schema.optional(\n Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 1000000 })),\n ),\n});\nexport type FilesystemOptions = typeof FilesystemOptions.Type;\n\nexport const fileError = (\n operation: string,\n code: string,\n outcome: MutationOutcome = \"not-applicable\",\n) => storageError(operation, \"filesystem\", { _tag: \"ProviderFailure\", code }, outcome);\n\nexport const mapIO =\n (operation: string, outcome: MutationOutcome = \"not-applicable\") =>\n (error: PlatformError) => {\n const reason = error.reason._tag;\n return storageError(\n operation,\n \"filesystem\",\n reason === \"NotFound\"\n ? { _tag: \"NotFound\" }\n : reason === \"PermissionDenied\"\n ? { _tag: \"AccessDenied\" }\n : { _tag: \"ProviderFailure\", code: reason },\n outcome,\n );\n };\n\nexport const makeLayout = Effect.fnUntraced(function* (options: FilesystemOptions) {\n const input = yield* Schema.decodeUnknownEffect(FilesystemOptions, { onExcessProperty: \"error\" })(\n options,\n ).pipe(\n Effect.mapError(() =>\n storageError(\"make\", \"filesystem\", { _tag: \"InvalidConfiguration\", field: \"options\" }),\n ),\n );\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const identities = yield* Digest.Digest;\n const random = yield* SecureRandom.SecureRandom;\n const hash = yield* TransferHash;\n if (hash.algorithm !== \"sha256\")\n return yield* storageError(\"make\", \"filesystem\", {\n _tag: \"InvalidConfiguration\",\n field: \"TransferHash.algorithm\",\n });\n\n const assertDirectory = Effect.fnUntraced(function* (directory: string) {\n const info = yield* fs.lstat(directory);\n if (info.type !== \"Directory\")\n return yield* fileError(\"filesystem.directory\", \"UnsafeDirectory\");\n });\n const suppliedRoot = path.resolve(input.root);\n if (yield* fs.exists(suppliedRoot)) yield* assertDirectory(suppliedRoot);\n const missing: string[] = [];\n let ancestor = suppliedRoot;\n while (!(yield* fs.exists(ancestor))) {\n missing.push(ancestor);\n if (path.dirname(ancestor) === ancestor) break;\n ancestor = path.dirname(ancestor);\n }\n yield* fs\n .makeDirectory(suppliedRoot, { recursive: true, mode: 0o700 })\n .pipe(Effect.mapError(mapIO(\"make\")));\n for (const created of missing)\n yield* syncDirectory(fs, created).pipe(Effect.mapError(mapIO(\"make\")));\n if (missing.length) yield* syncDirectory(fs, ancestor).pipe(Effect.mapError(mapIO(\"make\")));\n const root = yield* fs.realPath(suppliedRoot).pipe(Effect.mapError(mapIO(\"make\")));\n const objects = path.join(root, \"objects\");\n const staging = path.join(root, \"staging\");\n for (const directory of [objects, staging]) {\n yield* fs.makeDirectory(directory, { mode: 0o700 }).pipe(\n Effect.catchReason(\"PlatformError\", \"AlreadyExists\", () => Effect.void),\n Effect.mapError(mapIO(\"make\")),\n );\n yield* assertDirectory(directory).pipe(\n Effect.mapError((error) => (error._tag === \"PlatformError\" ? mapIO(\"make\")(error) : error)),\n );\n }\n yield* syncDirectory(fs, root).pipe(Effect.mapError(mapIO(\"make\")));\n\n const rootId = yield* initializeIdentity(fs, path, root, input.storeId, random);\n\n const checkDirectories = Effect.all(\n [assertDirectory(root), assertDirectory(objects), assertDirectory(staging)],\n { discard: true },\n ).pipe(\n Effect.mapError((error) =>\n error._tag === \"PlatformError\" ? mapIO(\"filesystem.directory\")(error) : error,\n ),\n );\n const objectFilename = (key: string) =>\n identities\n .digestHex(Digest.sha256, new TextEncoder().encode(key))\n .pipe(Effect.map((digest) => path.join(objects, `${digest}.object`)));\n const regularFile = Effect.fnUntraced(function* (filename: string) {\n const info = yield* fs.lstat(filename);\n if (info.type !== \"File\") return yield* fileError(\"filesystem.open\", \"UnsafeObject\");\n return info;\n });\n const open = Effect.fnUntraced(function* (filename: string) {\n yield* checkDirectories;\n yield* regularFile(filename);\n const file = yield* fs.open(filename, { flag: \"r\", noFollow: true });\n if ((yield* file.stat).type !== \"File\")\n return yield* fileError(\"filesystem.open\", \"UnsafeObject\");\n return file;\n });\n\n return {\n fs,\n path,\n root,\n rootId,\n objects,\n staging,\n storeId: input.storeId,\n random,\n hash,\n filename: objectFilename,\n open,\n regularFile,\n checkDirectories,\n maxObjectBytes: input.maxObjectBytes ?? 1024 * 1024 * 1024,\n maxListEntries: input.maxListEntries ?? 10000,\n };\n});\nexport type FilesystemContext = Effect.Success<ReturnType<typeof makeLayout>>;\nexport const fileSize = (info: FileSystem.File.Info) => ByteSize.toBigInt(info.size);\n"],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { storageError } from "../../core/errors.js";
2
+ import { mapIO } from "./layout.js";
3
+ import { readEnvelope } from "./envelope.js";
4
+ import { Effect, Schema } from "effect";
5
+ import { Base64Url } from "effect/encoding";
6
+
7
+ // src/providers/filesystem/list.ts
8
+ const Cursor = Schema.fromJsonString(Schema.Struct({
9
+ version: Schema.Literal(1),
10
+ root: Schema.String,
11
+ storeId: Schema.String,
12
+ prefix: Schema.String,
13
+ delimiter: Schema.NullOr(Schema.String),
14
+ limit: Schema.Natural,
15
+ after: Schema.String
16
+ }));
17
+ const invalid = () => storageError("listPage", "filesystem", {
18
+ _tag: "InvalidInput",
19
+ field: "cursor"
20
+ });
21
+ const list = Effect.fnUntraced(function* (context, request = {}) {
22
+ const { prefix = "", delimiter, limit = 100 } = request;
23
+ let after;
24
+ if (request.cursor) {
25
+ if (request.cursor.length > 32768) return yield* invalid();
26
+ const text = yield* Effect.fromResult(Base64Url.decodeString(request.cursor)).pipe(Effect.mapError(invalid));
27
+ const cursor = yield* Schema.decodeUnknownEffect(Cursor)(text).pipe(Effect.mapError(invalid));
28
+ if (cursor.root !== context.rootId || cursor.storeId !== context.storeId || cursor.prefix !== prefix || cursor.delimiter !== (delimiter ?? null) || cursor.limit !== limit) return yield* invalid();
29
+ after = cursor.after;
30
+ }
31
+ yield* context.checkDirectories;
32
+ const names = yield* context.fs.readDirectory(context.objects).pipe(Effect.mapError(mapIO("listPage")));
33
+ if (names.length > context.maxListEntries) return yield* storageError("listPage", "filesystem", {
34
+ _tag: "LimitExceeded",
35
+ limit: context.maxListEntries
36
+ });
37
+ const entries = /* @__PURE__ */ new Map();
38
+ for (const name of names) {
39
+ if (!/^[a-f0-9]{64}\.object$/u.test(name)) continue;
40
+ const filename = context.path.join(context.objects, name);
41
+ const metadata = yield* Effect.scoped(Effect.gen(function* () {
42
+ const file = yield* context.open(filename);
43
+ const saved = yield* readEnvelope(context, file);
44
+ if ((yield* context.filename(saved.ref.key)) !== filename) return yield* invalid();
45
+ return saved;
46
+ })).pipe(Effect.mapError((error) => error._tag === "PlatformError" ? mapIO("listPage")(error) : error), Effect.catchReason("StorageError", "NotFound", () => Effect.undefined));
47
+ if (!metadata || !metadata.ref.key.startsWith(prefix)) continue;
48
+ const key = metadata.ref.key;
49
+ const index = delimiter ? key.indexOf(delimiter, prefix.length) : -1;
50
+ if (delimiter && index >= 0) {
51
+ const common = key.slice(0, index + delimiter.length);
52
+ entries.set(common, {
53
+ _tag: "CommonPrefix",
54
+ prefix: common
55
+ });
56
+ } else entries.set(key, {
57
+ _tag: "Object",
58
+ metadata
59
+ });
60
+ }
61
+ const sorted = [...entries.keys()].toSorted().filter((key) => after === void 0 || key > after);
62
+ const keys = sorted.slice(0, limit);
63
+ const last = keys.at(-1);
64
+ return {
65
+ entries: keys.flatMap((key) => {
66
+ const entry = entries.get(key);
67
+ return entry ? [entry] : [];
68
+ }),
69
+ ...last !== void 0 && sorted.length > limit ? { cursor: Base64Url.encode(Schema.encodeSync(Cursor)({
70
+ version: 1,
71
+ root: context.rootId,
72
+ storeId: context.storeId,
73
+ prefix,
74
+ delimiter: delimiter ?? null,
75
+ limit,
76
+ after: last
77
+ })) } : {}
78
+ };
79
+ });
80
+
81
+ export { list };
82
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","names":[],"sources":["../../../src/providers/filesystem/list.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\nimport { Base64Url } from \"effect/encoding\";\n\nimport type { StorageError } from \"../../core/errors.js\";\nimport { storageError } from \"../../core/errors.js\";\nimport type { ListEntry, ListPage, ListRequest } from \"../../core/requests.js\";\nimport { readEnvelope } from \"./envelope.js\";\nimport { mapIO } from \"./layout.js\";\nimport type { FilesystemContext } from \"./layout.js\";\n\nconst Cursor = Schema.fromJsonString(\n Schema.Struct({\n version: Schema.Literal(1),\n root: Schema.String,\n storeId: Schema.String,\n prefix: Schema.String,\n delimiter: Schema.NullOr(Schema.String),\n limit: Schema.Natural,\n after: Schema.String,\n }),\n);\n\nconst invalid = () =>\n storageError(\"listPage\", \"filesystem\", { _tag: \"InvalidInput\", field: \"cursor\" });\n\nexport const list = Effect.fnUntraced(function* (\n context: FilesystemContext,\n request: ListRequest = {},\n): Effect.fn.Return<ListPage, StorageError> {\n const { prefix = \"\", delimiter, limit = 100 } = request;\n let after: string | undefined;\n if (request.cursor) {\n if (request.cursor.length > 32768) return yield* invalid();\n const text = yield* Effect.fromResult(Base64Url.decodeString(request.cursor)).pipe(\n Effect.mapError(invalid),\n );\n const cursor = yield* Schema.decodeUnknownEffect(Cursor)(text).pipe(Effect.mapError(invalid));\n if (\n cursor.root !== context.rootId ||\n cursor.storeId !== context.storeId ||\n cursor.prefix !== prefix ||\n cursor.delimiter !== (delimiter ?? null) ||\n cursor.limit !== limit\n )\n return yield* invalid();\n after = cursor.after;\n }\n yield* context.checkDirectories;\n // readDirectory allocates an array. This profile deliberately documents O(directory) scans.\n const names = yield* context.fs\n .readDirectory(context.objects)\n .pipe(Effect.mapError(mapIO(\"listPage\")));\n if (names.length > context.maxListEntries)\n return yield* storageError(\"listPage\", \"filesystem\", {\n _tag: \"LimitExceeded\",\n limit: context.maxListEntries,\n });\n const entries = new Map<string, ListEntry>();\n for (const name of names) {\n if (!/^[a-f0-9]{64}\\.object$/u.test(name)) continue;\n const filename = context.path.join(context.objects, name);\n const metadata = yield* Effect.scoped(\n Effect.gen(function* () {\n const file = yield* context.open(filename);\n const saved = yield* readEnvelope(context, file);\n if ((yield* context.filename(saved.ref.key)) !== filename) return yield* invalid();\n return saved;\n }),\n ).pipe(\n Effect.mapError((error) =>\n error._tag === \"PlatformError\" ? mapIO(\"listPage\")(error) : error,\n ),\n Effect.catchReason(\"StorageError\", \"NotFound\", () => Effect.undefined),\n );\n if (!metadata || !metadata.ref.key.startsWith(prefix)) continue;\n const key = metadata.ref.key;\n const index = delimiter ? key.indexOf(delimiter, prefix.length) : -1;\n if (delimiter && index >= 0) {\n const common = key.slice(0, index + delimiter.length);\n entries.set(common, { _tag: \"CommonPrefix\", prefix: common });\n } else entries.set(key, { _tag: \"Object\", metadata });\n }\n const sorted = [...entries.keys()].toSorted().filter((key) => after === undefined || key > after);\n const keys = sorted.slice(0, limit);\n const last = keys.at(-1);\n return {\n entries: keys.flatMap((key) => {\n const entry = entries.get(key);\n return entry ? [entry] : [];\n }),\n ...(last !== undefined && sorted.length > limit\n ? {\n cursor: Base64Url.encode(\n Schema.encodeSync(Cursor)({\n version: 1,\n root: context.rootId,\n storeId: context.storeId,\n prefix,\n delimiter: delimiter ?? null,\n limit,\n after: last,\n }),\n ),\n }\n : {}),\n };\n});\n"],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ import { storageError } from "../../core/errors.js";
2
+ import { resolveRange } from "../../core/ranges.js";
3
+ import { syncDirectory } from "../../runtime/filesystem.js";
4
+ import { mapIO } from "./layout.js";
5
+ import { encodeEnvelope, headerBytes, readChunk, readEnvelope } from "./envelope.js";
6
+ import { Cause, DateTime, Effect, Predicate, Stream } from "effect";
7
+
8
+ // src/providers/filesystem/operations.ts
9
+ const head = Effect.fnUntraced(function* (context, request) {
10
+ const key = "ref" in request ? request.ref.key : request.key;
11
+ return yield* Effect.scoped(Effect.gen(function* () {
12
+ const file = yield* context.open(yield* context.filename(key));
13
+ return yield* readEnvelope(context, file, key);
14
+ })).pipe(Effect.mapError((error) => error._tag === "PlatformError" ? mapIO("head")(error) : error));
15
+ });
16
+ const get = Effect.fnUntraced(function* (context, request) {
17
+ const key = "ref" in request ? request.ref.key : request.key;
18
+ const file = yield* context.open(yield* context.filename(key)).pipe(Effect.mapError((error) => error._tag === "PlatformError" ? mapIO("get")(error) : error));
19
+ const metadata = yield* readEnvelope(context, file, key).pipe(Effect.mapError((error) => error._tag === "PlatformError" ? mapIO("get")(error) : error));
20
+ if (request.condition?._tag === "IfMatch" && request.condition.etag !== "*" && request.condition.etag !== metadata.etag) return yield* storageError("get", "filesystem", { _tag: "PreconditionFailed" });
21
+ if (request.condition?._tag === "IfNoneMatch" && (request.condition.etag === "*" || request.condition.etag === metadata.etag)) return {
22
+ _tag: "NotModified",
23
+ metadata
24
+ };
25
+ const size = metadata.size ?? 0;
26
+ const range = request.range ? yield* Effect.fromResult(resolveRange(request.range, size, "filesystem")) : void 0;
27
+ const start = range?.start ?? 0;
28
+ const length = range ? range.end - range.start + 1 : size;
29
+ let offset = 0;
30
+ return {
31
+ _tag: "Object",
32
+ metadata,
33
+ body: Stream.fromPull(Effect.succeed(Effect.gen(function* () {
34
+ if (offset >= length) return yield* Cause.done();
35
+ const bytes = yield* readChunk(file, headerBytes + start + offset, Math.min(65536, length - offset)).pipe(Effect.mapError((error) => error._tag === "PlatformError" ? mapIO("get")(error) : error));
36
+ offset += bytes.length;
37
+ return [bytes];
38
+ }))),
39
+ contentLength: length,
40
+ range
41
+ };
42
+ });
43
+ const put = Effect.fnUntraced(function* (context, request) {
44
+ const { fs, path } = context;
45
+ const headers = {
46
+ contentType: request.contentType,
47
+ contentEncoding: request.contentEncoding,
48
+ contentLanguage: request.contentLanguage,
49
+ contentDisposition: request.contentDisposition,
50
+ cacheControl: request.cacheControl,
51
+ customMetadata: request.customMetadata ? { ...request.customMetadata } : void 0
52
+ };
53
+ const limit = Math.min(context.maxObjectBytes, request.maxBytes ?? context.maxObjectBytes);
54
+ if (new TextEncoder().encode(request.key).length > 4096) return yield* storageError("put", "filesystem", {
55
+ _tag: "InvalidInput",
56
+ field: "key"
57
+ }, "not-started");
58
+ if (new TextEncoder().encode(JSON.stringify(headers)).length > 32768) return yield* storageError("put", "filesystem", {
59
+ _tag: "InvalidInput",
60
+ field: "metadata"
61
+ }, "not-started");
62
+ if (request.contentLength !== void 0 && request.contentLength > limit) return yield* storageError("put", "filesystem", {
63
+ _tag: "LimitExceeded",
64
+ limit
65
+ }, "not-started");
66
+ yield* context.checkDirectories;
67
+ const destination = yield* context.filename(request.key);
68
+ const temporary = path.join(context.staging, `upload-${yield* context.random.uuidV4()}.pending`);
69
+ let outcome = "not-started";
70
+ const map = (error) => mapIO("put", outcome)(error);
71
+ return yield* Effect.acquireUseRelease(Effect.succeed(temporary), () => Effect.gen(function* () {
72
+ const metadata = yield* Effect.scoped(Effect.gen(function* () {
73
+ const file = yield* fs.open(temporary, {
74
+ flag: "wx+",
75
+ mode: 384,
76
+ noFollow: true
77
+ }).pipe(Effect.mapError(map));
78
+ yield* file.seek(BigInt(headerBytes), "start").pipe(Effect.mapError(map));
79
+ const hash = context.hash.create();
80
+ let length = 0;
81
+ const source = Predicate.isUint8Array(request.body) ? Stream.succeed(request.body) : request.body;
82
+ yield* Stream.runForEach(source, (chunk) => Effect.gen(function* () {
83
+ if (!Predicate.isUint8Array(chunk)) return yield* storageError("put", "filesystem", {
84
+ _tag: "InvalidInput",
85
+ field: "body"
86
+ }, "not-started");
87
+ if (chunk.length > limit - length) return yield* storageError("put", "filesystem", {
88
+ _tag: "LimitExceeded",
89
+ limit
90
+ }, "not-started");
91
+ for (let offset = 0; offset < chunk.length; offset += 65536) {
92
+ const bytes = chunk.subarray(offset, offset + 65536);
93
+ hash.update(bytes);
94
+ yield* file.writeAll(bytes).pipe(Effect.uninterruptible, Effect.mapError(map));
95
+ }
96
+ length += chunk.length;
97
+ }));
98
+ if (request.contentLength !== void 0 && request.contentLength !== length) return yield* storageError("put", "filesystem", {
99
+ _tag: "LengthMismatch",
100
+ expected: request.contentLength,
101
+ actual: length
102
+ }, "not-started");
103
+ const saved = {
104
+ ...headers,
105
+ ref: {
106
+ storeId: context.storeId,
107
+ key: request.key
108
+ },
109
+ size: length,
110
+ etag: `"${yield* context.random.uuidV4()}"`,
111
+ lastModified: yield* DateTime.now,
112
+ checksums: [hash.finish()]
113
+ };
114
+ const header = yield* encodeEnvelope(saved);
115
+ yield* file.seek(0n, "start").pipe(Effect.mapError(map));
116
+ yield* file.writeAll(header).pipe(Effect.uninterruptible, Effect.mapError(map));
117
+ yield* file.sync.pipe(Effect.uninterruptible, Effect.mapError(map));
118
+ return saved;
119
+ }));
120
+ yield* Effect.gen(function* () {
121
+ yield* context.checkDirectories;
122
+ yield* context.regularFile(destination).pipe(Effect.asVoid, Effect.catchReason("PlatformError", "NotFound", () => Effect.void), Effect.mapError((error) => error._tag === "PlatformError" ? map(error) : error));
123
+ outcome = "unknown";
124
+ if (request.condition?._tag === "CreateOnly") yield* fs.link(temporary, destination).pipe(Effect.catchReason("PlatformError", "AlreadyExists", () => storageError("put", "filesystem", { _tag: "PreconditionFailed" }, "rejected")), Effect.mapError((error) => error._tag === "PlatformError" ? map(error) : error));
125
+ else yield* fs.rename(temporary, destination).pipe(Effect.mapError(map));
126
+ yield* syncDirectory(fs, context.objects).pipe(Effect.mapError(map));
127
+ outcome = "succeeded";
128
+ }).pipe(Effect.uninterruptible);
129
+ return metadata;
130
+ }), () => fs.remove(temporary, { force: true }).pipe(Effect.andThen(syncDirectory(fs, context.staging)), Effect.mapError(map), Effect.orDie));
131
+ });
132
+
133
+ export { get, head, put };
134
+ //# sourceMappingURL=operations.js.map