@fragno-dev/upload 0.1.1

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 (355) hide show
  1. package/LICENSE.md +16 -0
  2. package/README.md +43 -0
  3. package/bin/run.js +5 -0
  4. package/dist/browser/client/clients.js +49 -0
  5. package/dist/browser/client/clients.js.map +1 -0
  6. package/dist/browser/client/helpers.d.ts +51 -0
  7. package/dist/browser/client/helpers.d.ts.map +1 -0
  8. package/dist/browser/client/helpers.js +242 -0
  9. package/dist/browser/client/helpers.js.map +1 -0
  10. package/dist/browser/client/node_modules/.pnpm/@nanostores_query@0.3.4_nanostores@1.1.0/node_modules/@nanostores/query/dist/nanoquery.js +354 -0
  11. package/dist/browser/client/node_modules/.pnpm/@nanostores_query@0.3.4_nanostores@1.1.0/node_modules/@nanostores/query/dist/nanoquery.js.map +1 -0
  12. package/dist/browser/client/node_modules/.pnpm/@nanostores_solid@1.1.1_nanostores@1.1.0_solid-js@1.9.10/node_modules/@nanostores/solid/dist/index.js +14 -0
  13. package/dist/browser/client/node_modules/.pnpm/@nanostores_solid@1.1.1_nanostores@1.1.0_solid-js@1.9.10/node_modules/@nanostores/solid/dist/index.js.map +1 -0
  14. package/dist/browser/client/node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js +17 -0
  15. package/dist/browser/client/node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js.map +1 -0
  16. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/atom/index.js +62 -0
  17. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/atom/index.js.map +1 -0
  18. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/clean-stores/index.js +6 -0
  19. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/clean-stores/index.js.map +1 -0
  20. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/computed/index.js +50 -0
  21. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/computed/index.js.map +1 -0
  22. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/lifecycle/index.js +99 -0
  23. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/lifecycle/index.js.map +1 -0
  24. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/listen-keys/index.js +11 -0
  25. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/listen-keys/index.js.map +1 -0
  26. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/map/index.js +25 -0
  27. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/map/index.js.map +1 -0
  28. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/task/index.js +24 -0
  29. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/task/index.js.map +1 -0
  30. package/dist/browser/client/packages/fragment-upload/src/definition.js +49 -0
  31. package/dist/browser/client/packages/fragment-upload/src/definition.js.map +1 -0
  32. package/dist/browser/client/packages/fragment-upload/src/keys.d.ts +7 -0
  33. package/dist/browser/client/packages/fragment-upload/src/keys.d.ts.map +1 -0
  34. package/dist/browser/client/packages/fragment-upload/src/keys.js +28 -0
  35. package/dist/browser/client/packages/fragment-upload/src/keys.js.map +1 -0
  36. package/dist/browser/client/packages/fragment-upload/src/routes/files.js +98 -0
  37. package/dist/browser/client/packages/fragment-upload/src/routes/files.js.map +1 -0
  38. package/dist/browser/client/packages/fragment-upload/src/routes/index.js +9 -0
  39. package/dist/browser/client/packages/fragment-upload/src/routes/index.js.map +1 -0
  40. package/dist/browser/client/packages/fragment-upload/src/routes/shared.js +41 -0
  41. package/dist/browser/client/packages/fragment-upload/src/routes/shared.js.map +1 -0
  42. package/dist/browser/client/packages/fragment-upload/src/routes/uploads.js +186 -0
  43. package/dist/browser/client/packages/fragment-upload/src/routes/uploads.js.map +1 -0
  44. package/dist/browser/client/packages/fragment-upload/src/schema.js +8 -0
  45. package/dist/browser/client/packages/fragment-upload/src/schema.js.map +1 -0
  46. package/dist/browser/client/packages/fragment-upload/src/storage/types.d.ts +9 -0
  47. package/dist/browser/client/packages/fragment-upload/src/storage/types.d.ts.map +1 -0
  48. package/dist/browser/client/packages/fragment-upload/src/types.d.ts +31 -0
  49. package/dist/browser/client/packages/fragment-upload/src/types.d.ts.map +1 -0
  50. package/dist/browser/client/packages/fragno/dist/api/error.js +48 -0
  51. package/dist/browser/client/packages/fragno/dist/api/error.js.map +1 -0
  52. package/dist/browser/client/packages/fragno/dist/api/internal/path.js +76 -0
  53. package/dist/browser/client/packages/fragno/dist/api/internal/path.js.map +1 -0
  54. package/dist/browser/client/packages/fragno/dist/api/internal/response-stream.js +81 -0
  55. package/dist/browser/client/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
  56. package/dist/browser/client/packages/fragno/dist/api/internal/route.js +10 -0
  57. package/dist/browser/client/packages/fragno/dist/api/internal/route.js.map +1 -0
  58. package/dist/browser/client/packages/fragno/dist/api/request-input-context.js +185 -0
  59. package/dist/browser/client/packages/fragno/dist/api/request-input-context.js.map +1 -0
  60. package/dist/browser/client/packages/fragno/dist/api/request-output-context.js +119 -0
  61. package/dist/browser/client/packages/fragno/dist/api/request-output-context.js.map +1 -0
  62. package/dist/browser/client/packages/fragno/dist/api/route.js +17 -0
  63. package/dist/browser/client/packages/fragno/dist/api/route.js.map +1 -0
  64. package/dist/browser/client/packages/fragno/dist/client/client-error.js +92 -0
  65. package/dist/browser/client/packages/fragno/dist/client/client-error.js.map +1 -0
  66. package/dist/browser/client/packages/fragno/dist/client/client.js +495 -0
  67. package/dist/browser/client/packages/fragno/dist/client/client.js.map +1 -0
  68. package/dist/browser/client/packages/fragno/dist/client/client.svelte.js +120 -0
  69. package/dist/browser/client/packages/fragno/dist/client/client.svelte.js.map +1 -0
  70. package/dist/browser/client/packages/fragno/dist/client/internal/fetcher-merge.js +36 -0
  71. package/dist/browser/client/packages/fragno/dist/client/internal/fetcher-merge.js.map +1 -0
  72. package/dist/browser/client/packages/fragno/dist/client/internal/ndjson-streaming.js +139 -0
  73. package/dist/browser/client/packages/fragno/dist/client/internal/ndjson-streaming.js.map +1 -0
  74. package/dist/browser/client/packages/fragno/dist/client/react.js +70 -0
  75. package/dist/browser/client/packages/fragno/dist/client/react.js.map +1 -0
  76. package/dist/browser/client/packages/fragno/dist/client/solid.js +108 -0
  77. package/dist/browser/client/packages/fragno/dist/client/solid.js.map +1 -0
  78. package/dist/browser/client/packages/fragno/dist/client/vanilla.js +96 -0
  79. package/dist/browser/client/packages/fragno/dist/client/vanilla.js.map +1 -0
  80. package/dist/browser/client/packages/fragno/dist/client/vue.js +120 -0
  81. package/dist/browser/client/packages/fragno/dist/client/vue.js.map +1 -0
  82. package/dist/browser/client/packages/fragno/dist/util/async.js +40 -0
  83. package/dist/browser/client/packages/fragno/dist/util/async.js.map +1 -0
  84. package/dist/browser/client/packages/fragno/dist/util/content-type.js +49 -0
  85. package/dist/browser/client/packages/fragno/dist/util/content-type.js.map +1 -0
  86. package/dist/browser/client/packages/fragno/dist/util/nanostores.js +31 -0
  87. package/dist/browser/client/packages/fragno/dist/util/nanostores.js.map +1 -0
  88. package/dist/browser/client/packages/fragno/dist/util/ssr.js +18 -0
  89. package/dist/browser/client/packages/fragno/dist/util/ssr.js.map +1 -0
  90. package/dist/browser/client/react.d.ts +295 -0
  91. package/dist/browser/client/react.d.ts.map +1 -0
  92. package/dist/browser/client/react.js +11 -0
  93. package/dist/browser/client/react.js.map +1 -0
  94. package/dist/browser/client/solid.d.ts +303 -0
  95. package/dist/browser/client/solid.d.ts.map +1 -0
  96. package/dist/browser/client/solid.js +11 -0
  97. package/dist/browser/client/solid.js.map +1 -0
  98. package/dist/browser/client/svelte.d.ts +295 -0
  99. package/dist/browser/client/svelte.d.ts.map +1 -0
  100. package/dist/browser/client/svelte.js +11 -0
  101. package/dist/browser/client/svelte.js.map +1 -0
  102. package/dist/browser/client/vanilla.d.ts +296 -0
  103. package/dist/browser/client/vanilla.d.ts.map +1 -0
  104. package/dist/browser/client/vanilla.js +11 -0
  105. package/dist/browser/client/vanilla.js.map +1 -0
  106. package/dist/browser/client/vue.d.ts +295 -0
  107. package/dist/browser/client/vue.d.ts.map +1 -0
  108. package/dist/browser/client/vue.js +11 -0
  109. package/dist/browser/client/vue.js.map +1 -0
  110. package/dist/browser/index-BdjKPO4J.d.ts +177 -0
  111. package/dist/browser/index-BdjKPO4J.d.ts.map +1 -0
  112. package/dist/browser/index.js +3 -0
  113. package/dist/browser/src-vdNJUbjT.js +1982 -0
  114. package/dist/browser/src-vdNJUbjT.js.map +1 -0
  115. package/dist/cli/commands/files/delete.d.ts +40 -0
  116. package/dist/cli/commands/files/delete.d.ts.map +1 -0
  117. package/dist/cli/commands/files/delete.js +31 -0
  118. package/dist/cli/commands/files/delete.js.map +1 -0
  119. package/dist/cli/commands/files/download-url.d.ts +40 -0
  120. package/dist/cli/commands/files/download-url.d.ts.map +1 -0
  121. package/dist/cli/commands/files/download-url.js +31 -0
  122. package/dist/cli/commands/files/download-url.js.map +1 -0
  123. package/dist/cli/commands/files/download.d.ts +49 -0
  124. package/dist/cli/commands/files/download.d.ts.map +1 -0
  125. package/dist/cli/commands/files/download.js +65 -0
  126. package/dist/cli/commands/files/download.js.map +1 -0
  127. package/dist/cli/commands/files/get.d.ts +40 -0
  128. package/dist/cli/commands/files/get.d.ts.map +1 -0
  129. package/dist/cli/commands/files/get.js +31 -0
  130. package/dist/cli/commands/files/get.js.map +1 -0
  131. package/dist/cli/commands/files/list.d.ts +56 -0
  132. package/dist/cli/commands/files/list.d.ts.map +1 -0
  133. package/dist/cli/commands/files/list.js +53 -0
  134. package/dist/cli/commands/files/list.js.map +1 -0
  135. package/dist/cli/commands/files/update.d.ts +56 -0
  136. package/dist/cli/commands/files/update.d.ts.map +1 -0
  137. package/dist/cli/commands/files/update.js +53 -0
  138. package/dist/cli/commands/files/update.js.map +1 -0
  139. package/dist/cli/commands/files/upload.d.ts +73 -0
  140. package/dist/cli/commands/files/upload.d.ts.map +1 -0
  141. package/dist/cli/commands/files/upload.js +87 -0
  142. package/dist/cli/commands/files/upload.js.map +1 -0
  143. package/dist/cli/commands/uploads/abort.d.ts +37 -0
  144. package/dist/cli/commands/uploads/abort.d.ts.map +1 -0
  145. package/dist/cli/commands/uploads/abort.js +26 -0
  146. package/dist/cli/commands/uploads/abort.js.map +1 -0
  147. package/dist/cli/commands/uploads/complete.d.ts +41 -0
  148. package/dist/cli/commands/uploads/complete.d.ts.map +1 -0
  149. package/dist/cli/commands/uploads/complete.js +45 -0
  150. package/dist/cli/commands/uploads/complete.js.map +1 -0
  151. package/dist/cli/commands/uploads/content.d.ts +46 -0
  152. package/dist/cli/commands/uploads/content.d.ts.map +1 -0
  153. package/dist/cli/commands/uploads/content.js +43 -0
  154. package/dist/cli/commands/uploads/content.js.map +1 -0
  155. package/dist/cli/commands/uploads/create.d.ts +72 -0
  156. package/dist/cli/commands/uploads/create.d.ts.map +1 -0
  157. package/dist/cli/commands/uploads/create.js +84 -0
  158. package/dist/cli/commands/uploads/create.js.map +1 -0
  159. package/dist/cli/commands/uploads/get.d.ts +37 -0
  160. package/dist/cli/commands/uploads/get.d.ts.map +1 -0
  161. package/dist/cli/commands/uploads/get.js +26 -0
  162. package/dist/cli/commands/uploads/get.js.map +1 -0
  163. package/dist/cli/commands/uploads/parts-complete.d.ts +41 -0
  164. package/dist/cli/commands/uploads/parts-complete.d.ts.map +1 -0
  165. package/dist/cli/commands/uploads/parts-complete.js +44 -0
  166. package/dist/cli/commands/uploads/parts-complete.js.map +1 -0
  167. package/dist/cli/commands/uploads/parts-list.d.ts +37 -0
  168. package/dist/cli/commands/uploads/parts-list.d.ts.map +1 -0
  169. package/dist/cli/commands/uploads/parts-list.js +26 -0
  170. package/dist/cli/commands/uploads/parts-list.js.map +1 -0
  171. package/dist/cli/commands/uploads/parts-urls.d.ts +46 -0
  172. package/dist/cli/commands/uploads/parts-urls.d.ts.map +1 -0
  173. package/dist/cli/commands/uploads/parts-urls.js +57 -0
  174. package/dist/cli/commands/uploads/parts-urls.js.map +1 -0
  175. package/dist/cli/commands/uploads/progress.d.ts +45 -0
  176. package/dist/cli/commands/uploads/progress.d.ts.map +1 -0
  177. package/dist/cli/commands/uploads/progress.js +40 -0
  178. package/dist/cli/commands/uploads/progress.js.map +1 -0
  179. package/dist/cli/commands/uploads/transfer.d.ts +73 -0
  180. package/dist/cli/commands/uploads/transfer.d.ts.map +1 -0
  181. package/dist/cli/commands/uploads/transfer.js +170 -0
  182. package/dist/cli/commands/uploads/transfer.js.map +1 -0
  183. package/dist/cli/index.d.ts +27 -0
  184. package/dist/cli/index.d.ts.map +1 -0
  185. package/dist/cli/index.js +198 -0
  186. package/dist/cli/index.js.map +1 -0
  187. package/dist/cli/keys.js +32 -0
  188. package/dist/cli/keys.js.map +1 -0
  189. package/dist/cli/utils/client.js +174 -0
  190. package/dist/cli/utils/client.js.map +1 -0
  191. package/dist/cli/utils/options.js +135 -0
  192. package/dist/cli/utils/options.js.map +1 -0
  193. package/dist/node/cli/commands/files/delete.d.ts +40 -0
  194. package/dist/node/cli/commands/files/delete.d.ts.map +1 -0
  195. package/dist/node/cli/commands/files/delete.js +31 -0
  196. package/dist/node/cli/commands/files/delete.js.map +1 -0
  197. package/dist/node/cli/commands/files/download-url.d.ts +40 -0
  198. package/dist/node/cli/commands/files/download-url.d.ts.map +1 -0
  199. package/dist/node/cli/commands/files/download-url.js +31 -0
  200. package/dist/node/cli/commands/files/download-url.js.map +1 -0
  201. package/dist/node/cli/commands/files/download.d.ts +49 -0
  202. package/dist/node/cli/commands/files/download.d.ts.map +1 -0
  203. package/dist/node/cli/commands/files/download.js +65 -0
  204. package/dist/node/cli/commands/files/download.js.map +1 -0
  205. package/dist/node/cli/commands/files/get.d.ts +40 -0
  206. package/dist/node/cli/commands/files/get.d.ts.map +1 -0
  207. package/dist/node/cli/commands/files/get.js +31 -0
  208. package/dist/node/cli/commands/files/get.js.map +1 -0
  209. package/dist/node/cli/commands/files/list.d.ts +56 -0
  210. package/dist/node/cli/commands/files/list.d.ts.map +1 -0
  211. package/dist/node/cli/commands/files/list.js +53 -0
  212. package/dist/node/cli/commands/files/list.js.map +1 -0
  213. package/dist/node/cli/commands/files/update.d.ts +56 -0
  214. package/dist/node/cli/commands/files/update.d.ts.map +1 -0
  215. package/dist/node/cli/commands/files/update.js +53 -0
  216. package/dist/node/cli/commands/files/update.js.map +1 -0
  217. package/dist/node/cli/commands/files/upload.d.ts +73 -0
  218. package/dist/node/cli/commands/files/upload.d.ts.map +1 -0
  219. package/dist/node/cli/commands/files/upload.js +87 -0
  220. package/dist/node/cli/commands/files/upload.js.map +1 -0
  221. package/dist/node/cli/commands/uploads/abort.d.ts +37 -0
  222. package/dist/node/cli/commands/uploads/abort.d.ts.map +1 -0
  223. package/dist/node/cli/commands/uploads/abort.js +26 -0
  224. package/dist/node/cli/commands/uploads/abort.js.map +1 -0
  225. package/dist/node/cli/commands/uploads/complete.d.ts +41 -0
  226. package/dist/node/cli/commands/uploads/complete.d.ts.map +1 -0
  227. package/dist/node/cli/commands/uploads/complete.js +45 -0
  228. package/dist/node/cli/commands/uploads/complete.js.map +1 -0
  229. package/dist/node/cli/commands/uploads/content.d.ts +46 -0
  230. package/dist/node/cli/commands/uploads/content.d.ts.map +1 -0
  231. package/dist/node/cli/commands/uploads/content.js +43 -0
  232. package/dist/node/cli/commands/uploads/content.js.map +1 -0
  233. package/dist/node/cli/commands/uploads/create.d.ts +72 -0
  234. package/dist/node/cli/commands/uploads/create.d.ts.map +1 -0
  235. package/dist/node/cli/commands/uploads/create.js +84 -0
  236. package/dist/node/cli/commands/uploads/create.js.map +1 -0
  237. package/dist/node/cli/commands/uploads/get.d.ts +37 -0
  238. package/dist/node/cli/commands/uploads/get.d.ts.map +1 -0
  239. package/dist/node/cli/commands/uploads/get.js +26 -0
  240. package/dist/node/cli/commands/uploads/get.js.map +1 -0
  241. package/dist/node/cli/commands/uploads/parts-complete.d.ts +41 -0
  242. package/dist/node/cli/commands/uploads/parts-complete.d.ts.map +1 -0
  243. package/dist/node/cli/commands/uploads/parts-complete.js +44 -0
  244. package/dist/node/cli/commands/uploads/parts-complete.js.map +1 -0
  245. package/dist/node/cli/commands/uploads/parts-list.d.ts +37 -0
  246. package/dist/node/cli/commands/uploads/parts-list.d.ts.map +1 -0
  247. package/dist/node/cli/commands/uploads/parts-list.js +26 -0
  248. package/dist/node/cli/commands/uploads/parts-list.js.map +1 -0
  249. package/dist/node/cli/commands/uploads/parts-urls.d.ts +46 -0
  250. package/dist/node/cli/commands/uploads/parts-urls.d.ts.map +1 -0
  251. package/dist/node/cli/commands/uploads/parts-urls.js +57 -0
  252. package/dist/node/cli/commands/uploads/parts-urls.js.map +1 -0
  253. package/dist/node/cli/commands/uploads/progress.d.ts +45 -0
  254. package/dist/node/cli/commands/uploads/progress.d.ts.map +1 -0
  255. package/dist/node/cli/commands/uploads/progress.js +40 -0
  256. package/dist/node/cli/commands/uploads/progress.js.map +1 -0
  257. package/dist/node/cli/commands/uploads/transfer.d.ts +73 -0
  258. package/dist/node/cli/commands/uploads/transfer.d.ts.map +1 -0
  259. package/dist/node/cli/commands/uploads/transfer.js +170 -0
  260. package/dist/node/cli/commands/uploads/transfer.js.map +1 -0
  261. package/dist/node/cli/index.d.ts +27 -0
  262. package/dist/node/cli/index.d.ts.map +1 -0
  263. package/dist/node/cli/index.js +198 -0
  264. package/dist/node/cli/index.js.map +1 -0
  265. package/dist/node/cli/utils/client.js +174 -0
  266. package/dist/node/cli/utils/client.js.map +1 -0
  267. package/dist/node/cli/utils/options.js +135 -0
  268. package/dist/node/cli/utils/options.js.map +1 -0
  269. package/dist/node/client/clients.d.ts +295 -0
  270. package/dist/node/client/clients.d.ts.map +1 -0
  271. package/dist/node/client/clients.js +49 -0
  272. package/dist/node/client/clients.js.map +1 -0
  273. package/dist/node/client/helpers.d.ts +51 -0
  274. package/dist/node/client/helpers.d.ts.map +1 -0
  275. package/dist/node/client/helpers.js +242 -0
  276. package/dist/node/client/helpers.js.map +1 -0
  277. package/dist/node/client/react.d.ts +295 -0
  278. package/dist/node/client/react.d.ts.map +1 -0
  279. package/dist/node/client/react.js +11 -0
  280. package/dist/node/client/react.js.map +1 -0
  281. package/dist/node/client/solid.d.ts +303 -0
  282. package/dist/node/client/solid.d.ts.map +1 -0
  283. package/dist/node/client/solid.js +11 -0
  284. package/dist/node/client/solid.js.map +1 -0
  285. package/dist/node/client/svelte.d.ts +295 -0
  286. package/dist/node/client/svelte.d.ts.map +1 -0
  287. package/dist/node/client/svelte.js +11 -0
  288. package/dist/node/client/svelte.js.map +1 -0
  289. package/dist/node/client/vanilla.d.ts +296 -0
  290. package/dist/node/client/vanilla.d.ts.map +1 -0
  291. package/dist/node/client/vanilla.js +11 -0
  292. package/dist/node/client/vanilla.js.map +1 -0
  293. package/dist/node/client/vue.d.ts +295 -0
  294. package/dist/node/client/vue.d.ts.map +1 -0
  295. package/dist/node/client/vue.js +11 -0
  296. package/dist/node/client/vue.js.map +1 -0
  297. package/dist/node/config.d.ts +41 -0
  298. package/dist/node/config.d.ts.map +1 -0
  299. package/dist/node/config.js +26 -0
  300. package/dist/node/config.js.map +1 -0
  301. package/dist/node/definition.d.ts +829 -0
  302. package/dist/node/definition.d.ts.map +1 -0
  303. package/dist/node/definition.js +59 -0
  304. package/dist/node/definition.js.map +1 -0
  305. package/dist/node/index.d.ts +1246 -0
  306. package/dist/node/index.d.ts.map +1 -0
  307. package/dist/node/index.js +19 -0
  308. package/dist/node/index.js.map +1 -0
  309. package/dist/node/keys.d.ts +12 -0
  310. package/dist/node/keys.d.ts.map +1 -0
  311. package/dist/node/keys.js +63 -0
  312. package/dist/node/keys.js.map +1 -0
  313. package/dist/node/routes/files.js +450 -0
  314. package/dist/node/routes/files.js.map +1 -0
  315. package/dist/node/routes/index.d.ts +2023 -0
  316. package/dist/node/routes/index.d.ts.map +1 -0
  317. package/dist/node/routes/index.js +9 -0
  318. package/dist/node/routes/index.js.map +1 -0
  319. package/dist/node/routes/shared.js +66 -0
  320. package/dist/node/routes/shared.js.map +1 -0
  321. package/dist/node/routes/uploads.js +454 -0
  322. package/dist/node/routes/uploads.js.map +1 -0
  323. package/dist/node/schema.d.ts +14 -0
  324. package/dist/node/schema.d.ts.map +1 -0
  325. package/dist/node/schema.js +30 -0
  326. package/dist/node/schema.js.map +1 -0
  327. package/dist/node/services/files.d.ts +20 -0
  328. package/dist/node/services/files.d.ts.map +1 -0
  329. package/dist/node/services/files.js +93 -0
  330. package/dist/node/services/files.js.map +1 -0
  331. package/dist/node/services/helpers.js +36 -0
  332. package/dist/node/services/helpers.js.map +1 -0
  333. package/dist/node/services/index.js +4 -0
  334. package/dist/node/services/uploads.d.ts +50 -0
  335. package/dist/node/services/uploads.d.ts.map +1 -0
  336. package/dist/node/services/uploads.js +358 -0
  337. package/dist/node/services/uploads.js.map +1 -0
  338. package/dist/node/storage/fs.d.ts +16 -0
  339. package/dist/node/storage/fs.d.ts.map +1 -0
  340. package/dist/node/storage/fs.js +94 -0
  341. package/dist/node/storage/fs.js.map +1 -0
  342. package/dist/node/storage/r2.d.ts +103 -0
  343. package/dist/node/storage/r2.d.ts.map +1 -0
  344. package/dist/node/storage/r2.js +23 -0
  345. package/dist/node/storage/r2.js.map +1 -0
  346. package/dist/node/storage/s3.d.ts +44 -0
  347. package/dist/node/storage/s3.d.ts.map +1 -0
  348. package/dist/node/storage/s3.js +398 -0
  349. package/dist/node/storage/s3.js.map +1 -0
  350. package/dist/node/storage/types.d.ts +118 -0
  351. package/dist/node/storage/types.d.ts.map +1 -0
  352. package/dist/node/types.d.ts +32 -0
  353. package/dist/node/types.d.ts.map +1 -0
  354. package/dist/tsconfig.tsbuildinfo +1 -0
  355. package/package.json +105 -0
@@ -0,0 +1,186 @@
1
+ import { uploadFragmentDefinition } from "../definition.js";
2
+ import { checksumSchema, fileKeyPartsSchema, fileMetadataSchema } from "./shared.js";
3
+ import { defineRoutes } from "@fragno-dev/core";
4
+ import { z } from "zod";
5
+
6
+ //#region src/routes/uploads.ts
7
+ const uploadStrategySchema = z.enum([
8
+ "direct-single",
9
+ "direct-multipart",
10
+ "proxy"
11
+ ]);
12
+ const safeIntSchema = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
13
+ const createUploadInputSchema = z.object({
14
+ keyParts: fileKeyPartsSchema.optional(),
15
+ fileKey: z.string().optional(),
16
+ filename: z.string().min(1),
17
+ sizeBytes: safeIntSchema,
18
+ contentType: z.string().min(1),
19
+ checksum: checksumSchema.optional(),
20
+ tags: z.array(z.string()).optional(),
21
+ visibility: z.enum([
22
+ "private",
23
+ "public",
24
+ "unlisted"
25
+ ]).optional(),
26
+ uploaderId: z.string().optional(),
27
+ metadata: z.record(z.string(), z.unknown()).optional()
28
+ });
29
+ const progressSchema = z.object({
30
+ bytesUploaded: safeIntSchema.optional(),
31
+ partsUploaded: z.number().int().min(0).optional()
32
+ });
33
+ const partNumbersSchema = z.object({ partNumbers: z.array(z.number().int().min(1)).min(1) });
34
+ const completePartsSchema = z.object({ parts: z.array(z.object({
35
+ partNumber: z.number().int().min(1),
36
+ etag: z.string().min(1),
37
+ sizeBytes: safeIntSchema
38
+ })).min(1) });
39
+ const completeUploadSchema = z.object({ parts: z.array(z.object({
40
+ partNumber: z.number().int().min(1),
41
+ etag: z.string().min(1)
42
+ })).optional() });
43
+ const uploadStatusSchema = z.object({
44
+ uploadId: z.string(),
45
+ fileKey: z.string(),
46
+ status: z.enum([
47
+ "created",
48
+ "in_progress",
49
+ "completed",
50
+ "aborted",
51
+ "failed",
52
+ "expired"
53
+ ]),
54
+ strategy: uploadStrategySchema,
55
+ expectedSizeBytes: z.number(),
56
+ bytesUploaded: z.number(),
57
+ partsUploaded: z.number(),
58
+ partSizeBytes: z.number().nullable(),
59
+ expiresAt: z.date(),
60
+ createdAt: z.date(),
61
+ updatedAt: z.date(),
62
+ completedAt: z.date().nullable(),
63
+ errorCode: z.string().nullable(),
64
+ errorMessage: z.string().nullable()
65
+ });
66
+ const errorCodes = [
67
+ "UPLOAD_NOT_FOUND",
68
+ "UPLOAD_ALREADY_ACTIVE",
69
+ "UPLOAD_METADATA_MISMATCH",
70
+ "FILE_ALREADY_EXISTS",
71
+ "UPLOAD_EXPIRED",
72
+ "UPLOAD_INVALID_STATE",
73
+ "INVALID_FILE_KEY",
74
+ "INVALID_CHECKSUM",
75
+ "INVALID_REQUEST",
76
+ "STORAGE_ERROR"
77
+ ];
78
+ const uploadRoutesFactory = defineRoutes(uploadFragmentDefinition).create(({ services, defineRoute, config }) => {
79
+ return [
80
+ defineRoute({
81
+ method: "POST",
82
+ path: "/uploads",
83
+ inputSchema: createUploadInputSchema,
84
+ outputSchema: z.object({
85
+ uploadId: z.string(),
86
+ fileKey: z.string(),
87
+ status: z.enum(["created", "in_progress"]),
88
+ strategy: uploadStrategySchema,
89
+ expiresAt: z.date(),
90
+ upload: z.object({
91
+ mode: z.enum(["single", "multipart"]),
92
+ transport: z.enum(["direct", "proxy"]),
93
+ uploadUrl: z.string().optional(),
94
+ uploadHeaders: z.record(z.string(), z.string()).optional(),
95
+ partSizeBytes: z.number().optional(),
96
+ maxParts: z.number().optional(),
97
+ partsEndpoint: z.string().optional(),
98
+ completeEndpoint: z.string(),
99
+ contentEndpoint: z.string().optional()
100
+ })
101
+ }),
102
+ errorCodes,
103
+ handler: () => {}
104
+ }),
105
+ defineRoute({
106
+ method: "GET",
107
+ path: "/uploads/:uploadId",
108
+ outputSchema: uploadStatusSchema,
109
+ errorCodes,
110
+ handler: () => {}
111
+ }),
112
+ defineRoute({
113
+ method: "POST",
114
+ path: "/uploads/:uploadId/progress",
115
+ inputSchema: progressSchema,
116
+ outputSchema: z.object({
117
+ bytesUploaded: z.number(),
118
+ partsUploaded: z.number()
119
+ }),
120
+ errorCodes,
121
+ handler: () => {}
122
+ }),
123
+ defineRoute({
124
+ method: "POST",
125
+ path: "/uploads/:uploadId/parts",
126
+ inputSchema: partNumbersSchema,
127
+ outputSchema: z.object({ parts: z.array(z.object({
128
+ partNumber: z.number(),
129
+ url: z.string(),
130
+ headers: z.record(z.string(), z.string()).optional()
131
+ })) }),
132
+ errorCodes,
133
+ handler: () => {}
134
+ }),
135
+ defineRoute({
136
+ method: "GET",
137
+ path: "/uploads/:uploadId/parts",
138
+ outputSchema: z.object({ parts: z.array(z.object({
139
+ partNumber: z.number(),
140
+ etag: z.string(),
141
+ sizeBytes: z.number(),
142
+ createdAt: z.date()
143
+ })) }),
144
+ errorCodes,
145
+ handler: () => {}
146
+ }),
147
+ defineRoute({
148
+ method: "POST",
149
+ path: "/uploads/:uploadId/parts/complete",
150
+ inputSchema: completePartsSchema,
151
+ outputSchema: z.object({
152
+ bytesUploaded: z.number(),
153
+ partsUploaded: z.number()
154
+ }),
155
+ errorCodes,
156
+ handler: () => {}
157
+ }),
158
+ defineRoute({
159
+ method: "POST",
160
+ path: "/uploads/:uploadId/complete",
161
+ inputSchema: completeUploadSchema,
162
+ outputSchema: fileMetadataSchema,
163
+ errorCodes,
164
+ handler: () => {}
165
+ }),
166
+ defineRoute({
167
+ method: "POST",
168
+ path: "/uploads/:uploadId/abort",
169
+ outputSchema: z.object({ ok: z.literal(true) }),
170
+ errorCodes,
171
+ handler: () => {}
172
+ }),
173
+ defineRoute({
174
+ method: "PUT",
175
+ path: "/uploads/:uploadId/content",
176
+ contentType: "application/octet-stream",
177
+ outputSchema: fileMetadataSchema,
178
+ errorCodes,
179
+ handler: () => {}
180
+ })
181
+ ];
182
+ });
183
+
184
+ //#endregion
185
+ export { uploadRoutesFactory };
186
+ //# sourceMappingURL=uploads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploads.js","names":["defineRoutes","FragnoRouteConfig","z","uploadFragmentDefinition","checksumSchema","fileKeyPartsSchema","fileMetadataSchema","uploadStrategySchema","enum","safeIntSchema","number","int","min","max","Number","MAX_SAFE_INTEGER","createUploadInputSchema","object","keyParts","optional","fileKey","string","filename","sizeBytes","contentType","checksum","tags","array","visibility","uploaderId","metadata","record","unknown","progressSchema","bytesUploaded","partsUploaded","partNumbersSchema","partNumbers","completePartsSchema","parts","partNumber","etag","completeUploadSchema","uploadStatusSchema","uploadId","status","strategy","expectedSizeBytes","partSizeBytes","nullable","expiresAt","date","createdAt","updatedAt","completedAt","errorCode","errorMessage","errorCodes","const","UploadErrorCode","ErrorFn","Parameters","Code","uploadRoutesFactory","create","services","defineRoute","config","method","path","inputSchema","outputSchema","upload","mode","transport","uploadUrl","uploadHeaders","maxParts","partsEndpoint","completeEndpoint","contentEndpoint","handler","url","headers","ok","literal"],"sources":["../../../../../../../src/routes/uploads.ts"],"sourcesContent":["import { defineRoutes } from \"@fragno-dev/core\";\nimport type { FragnoRouteConfig } from \"@fragno-dev/core\";\nimport { z } from \"zod\";\nimport { resolveUploadFragmentConfig } from \"../config\";\nimport { uploadFragmentDefinition } from \"../definition\";\nimport { resolveFileKeyInput } from \"../services/helpers\";\nimport { checksumSchema, fileKeyPartsSchema, fileMetadataSchema, toFileMetadata } from \"./shared\";\nimport type { UploadStatus, UploadStrategy } from \"../types\";\nimport type { UploadChecksum } from \"../storage/types\";\n\nconst uploadStrategySchema = z.enum([\"direct-single\", \"direct-multipart\", \"proxy\"]);\nconst safeIntSchema = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);\n\nconst createUploadInputSchema = z.object({\n keyParts: fileKeyPartsSchema.optional(),\n fileKey: z.string().optional(),\n filename: z.string().min(1),\n sizeBytes: safeIntSchema,\n contentType: z.string().min(1),\n checksum: checksumSchema.optional(),\n tags: z.array(z.string()).optional(),\n visibility: z.enum([\"private\", \"public\", \"unlisted\"]).optional(),\n uploaderId: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nconst progressSchema = z.object({\n bytesUploaded: safeIntSchema.optional(),\n partsUploaded: z.number().int().min(0).optional(),\n});\n\nconst partNumbersSchema = z.object({\n partNumbers: z.array(z.number().int().min(1)).min(1),\n});\n\nconst completePartsSchema = z.object({\n parts: z\n .array(\n z.object({\n partNumber: z.number().int().min(1),\n etag: z.string().min(1),\n sizeBytes: safeIntSchema,\n }),\n )\n .min(1),\n});\n\nconst completeUploadSchema = z.object({\n parts: z\n .array(\n z.object({\n partNumber: z.number().int().min(1),\n etag: z.string().min(1),\n }),\n )\n .optional(),\n});\n\nconst uploadStatusSchema = z.object({\n uploadId: z.string(),\n fileKey: z.string(),\n status: z.enum([\"created\", \"in_progress\", \"completed\", \"aborted\", \"failed\", \"expired\"]),\n strategy: uploadStrategySchema,\n expectedSizeBytes: z.number(),\n bytesUploaded: z.number(),\n partsUploaded: z.number(),\n partSizeBytes: z.number().nullable(),\n expiresAt: z.date(),\n createdAt: z.date(),\n updatedAt: z.date(),\n completedAt: z.date().nullable(),\n errorCode: z.string().nullable(),\n errorMessage: z.string().nullable(),\n});\n\nconst errorCodes = [\n \"UPLOAD_NOT_FOUND\",\n \"UPLOAD_ALREADY_ACTIVE\",\n \"UPLOAD_METADATA_MISMATCH\",\n \"FILE_ALREADY_EXISTS\",\n \"UPLOAD_EXPIRED\",\n \"UPLOAD_INVALID_STATE\",\n \"INVALID_FILE_KEY\",\n \"INVALID_CHECKSUM\",\n \"INVALID_REQUEST\",\n \"STORAGE_ERROR\",\n] as const;\n\ntype UploadErrorCode = (typeof errorCodes)[number];\n\ntype ErrorFn<Code extends string> = Parameters<\n FragnoRouteConfig<\"GET\", \"/__error\", undefined, undefined, Code>[\"handler\"]\n>[1][\"error\"];\n\nconst handleServiceError = <Code extends UploadErrorCode>(\n err: unknown,\n error: ErrorFn<Code>,\n): Response => {\n if (!(err instanceof Error)) {\n throw err;\n }\n\n switch (err.message) {\n case \"UPLOAD_NOT_FOUND\":\n return error({ message: \"Upload not found\", code: \"UPLOAD_NOT_FOUND\" as Code }, 404);\n case \"FILE_ALREADY_EXISTS\":\n return error({ message: \"File already exists\", code: \"FILE_ALREADY_EXISTS\" as Code }, 409);\n case \"UPLOAD_ALREADY_ACTIVE\":\n return error(\n { message: \"Upload already active\", code: \"UPLOAD_ALREADY_ACTIVE\" as Code },\n 409,\n );\n case \"UPLOAD_METADATA_MISMATCH\":\n return error(\n { message: \"Upload metadata mismatch\", code: \"UPLOAD_METADATA_MISMATCH\" as Code },\n 409,\n );\n case \"UPLOAD_EXPIRED\":\n return error({ message: \"Upload expired\", code: \"UPLOAD_EXPIRED\" as Code }, 410);\n case \"UPLOAD_INVALID_STATE\":\n return error({ message: \"Upload invalid state\", code: \"UPLOAD_INVALID_STATE\" as Code }, 409);\n case \"INVALID_FILE_KEY\":\n return error({ message: \"Invalid file key\", code: \"INVALID_FILE_KEY\" as Code }, 400);\n case \"INVALID_CHECKSUM\":\n return error({ message: \"Invalid checksum\", code: \"INVALID_CHECKSUM\" as Code }, 400);\n case \"INVALID_REQUEST\":\n return error({ message: \"Invalid request\", code: \"INVALID_REQUEST\" as Code }, 400);\n case \"STORAGE_ERROR\":\n return error({ message: \"Storage error\", code: \"STORAGE_ERROR\" as Code }, 502);\n default:\n throw err;\n }\n};\n\nexport const uploadRoutesFactory = defineRoutes(uploadFragmentDefinition).create(\n ({ services, defineRoute, config }) => {\n const getResolvedConfig = () => resolveUploadFragmentConfig(config);\n\n return [\n defineRoute({\n method: \"POST\",\n path: \"/uploads\",\n inputSchema: createUploadInputSchema,\n outputSchema: z.object({\n uploadId: z.string(),\n fileKey: z.string(),\n status: z.enum([\"created\", \"in_progress\"]),\n strategy: uploadStrategySchema,\n expiresAt: z.date(),\n upload: z.object({\n mode: z.enum([\"single\", \"multipart\"]),\n transport: z.enum([\"direct\", \"proxy\"]),\n uploadUrl: z.string().optional(),\n uploadHeaders: z.record(z.string(), z.string()).optional(),\n partSizeBytes: z.number().optional(),\n maxParts: z.number().optional(),\n partsEndpoint: z.string().optional(),\n completeEndpoint: z.string(),\n contentEndpoint: z.string().optional(),\n }),\n }),\n errorCodes,\n handler: async function ({ input }, { json, error }) {\n const payload = await input.valid();\n const resolvedConfig = getResolvedConfig();\n\n let resolvedKey;\n try {\n resolvedKey = resolveFileKeyInput({\n keyParts: payload.keyParts,\n fileKey: payload.fileKey,\n });\n } catch (err) {\n return handleServiceError(err, error);\n }\n\n try {\n const existing = await this.handlerTx()\n .withServiceCalls(() => [\n services.checkUploadAvailability(payload, { allowIdempotentReuse: true }),\n ])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n if (existing) {\n return json(existing);\n }\n } catch (err) {\n return handleServiceError(err, error);\n }\n\n let storageInit;\n try {\n storageInit = await resolvedConfig.storage.initUpload({\n fileKey: resolvedKey.fileKey,\n fileKeyParts: resolvedKey.fileKeyParts,\n sizeBytes: BigInt(payload.sizeBytes),\n contentType: payload.contentType,\n checksum: payload.checksum ?? null,\n metadata: payload.metadata ?? null,\n });\n } catch (err) {\n if (err instanceof Error && err.message === \"INVALID_CHECKSUM\") {\n return error({ message: \"Invalid checksum\", code: \"INVALID_CHECKSUM\" }, 400);\n }\n return error({ message: \"Storage error\", code: \"STORAGE_ERROR\" }, 502);\n }\n\n try {\n const result = await this.handlerTx()\n .withServiceCalls(() => [\n services.createUploadRecord({\n ...payload,\n storageInit,\n allowIdempotentReuse: true,\n }),\n ])\n .transform(({ serviceResult: [created] }) => created)\n .execute();\n\n if (\n result.reused &&\n storageInit.strategy === \"direct-multipart\" &&\n resolvedConfig.storage.abortMultipartUpload &&\n storageInit.storageUploadId\n ) {\n try {\n await resolvedConfig.storage.abortMultipartUpload({\n storageKey: storageInit.storageKey,\n storageUploadId: storageInit.storageUploadId,\n });\n } catch {\n // Ignore abort failures for races.\n }\n }\n\n return json(result.result);\n } catch (err) {\n if (\n storageInit.strategy === \"direct-multipart\" &&\n resolvedConfig.storage.abortMultipartUpload &&\n storageInit.storageUploadId\n ) {\n try {\n await resolvedConfig.storage.abortMultipartUpload({\n storageKey: storageInit.storageKey,\n storageUploadId: storageInit.storageUploadId,\n });\n } catch {\n // Ignore abort failures for races.\n }\n }\n return handleServiceError(err, error);\n }\n },\n }),\n\n defineRoute({\n method: \"GET\",\n path: \"/uploads/:uploadId\",\n outputSchema: uploadStatusSchema,\n errorCodes,\n handler: async function ({ pathParams }, { json, error }) {\n try {\n const upload = await this.handlerTx()\n .withServiceCalls(() => [services.getUploadStatus(pathParams.uploadId)])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n return json({\n uploadId: upload.id.toString(),\n fileKey: upload.fileKey,\n status: upload.status as UploadStatus,\n strategy: upload.strategy as UploadStrategy,\n expectedSizeBytes: Number(upload.expectedSizeBytes),\n bytesUploaded: Number(upload.bytesUploaded),\n partsUploaded: upload.partsUploaded,\n partSizeBytes: upload.partSizeBytes,\n expiresAt: upload.expiresAt,\n createdAt: upload.createdAt,\n updatedAt: upload.updatedAt,\n completedAt: upload.completedAt,\n errorCode: upload.errorCode,\n errorMessage: upload.errorMessage,\n });\n } catch (err) {\n return handleServiceError(err, error);\n }\n },\n }),\n\n defineRoute({\n method: \"POST\",\n path: \"/uploads/:uploadId/progress\",\n inputSchema: progressSchema,\n outputSchema: z.object({\n bytesUploaded: z.number(),\n partsUploaded: z.number(),\n }),\n errorCodes,\n handler: async function ({ pathParams, input }, { json, error }) {\n const payload = await input.valid();\n try {\n const result = await this.handlerTx()\n .withServiceCalls(() => [services.recordUploadProgress(pathParams.uploadId, payload)])\n .transform(({ serviceResult: [updated] }) => updated)\n .execute();\n\n return json({\n bytesUploaded: Number(result.bytesUploaded),\n partsUploaded: result.partsUploaded,\n });\n } catch (err) {\n return handleServiceError(err, error);\n }\n },\n }),\n\n defineRoute({\n method: \"POST\",\n path: \"/uploads/:uploadId/parts\",\n inputSchema: partNumbersSchema,\n outputSchema: z.object({\n parts: z.array(\n z.object({\n partNumber: z.number(),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ),\n }),\n errorCodes,\n handler: async function ({ pathParams, input }, { json, error }) {\n const payload = await input.valid();\n const resolvedConfig = getResolvedConfig();\n try {\n const upload = await this.handlerTx()\n .withServiceCalls(() => [services.getUploadStorageInfo(pathParams.uploadId)])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n if (upload.strategy !== \"direct-multipart\") {\n return error({ message: \"Upload invalid state\", code: \"UPLOAD_INVALID_STATE\" }, 409);\n }\n\n if (!resolvedConfig.storage.getPartUploadUrls) {\n return error({ message: \"Storage error\", code: \"STORAGE_ERROR\" }, 502);\n }\n\n const parts = await resolvedConfig.storage.getPartUploadUrls({\n storageKey: upload.storageKey,\n storageUploadId: upload.storageUploadId ?? \"\",\n partNumbers: payload.partNumbers,\n partSizeBytes: upload.partSizeBytes ?? 0,\n });\n\n return json({ parts });\n } catch (err) {\n return handleServiceError(err, error);\n }\n },\n }),\n\n defineRoute({\n method: \"GET\",\n path: \"/uploads/:uploadId/parts\",\n outputSchema: z.object({\n parts: z.array(\n z.object({\n partNumber: z.number(),\n etag: z.string(),\n sizeBytes: z.number(),\n createdAt: z.date(),\n }),\n ),\n }),\n errorCodes,\n handler: async function ({ pathParams }, { json, error }) {\n try {\n const parts = await this.handlerTx()\n .withServiceCalls(() => [services.getUploadParts(pathParams.uploadId)])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n const typedParts = parts as {\n partNumber: number;\n etag: string;\n sizeBytes: bigint;\n createdAt: Date;\n }[];\n\n return json({\n parts: typedParts.map((part) => ({\n partNumber: part.partNumber,\n etag: part.etag,\n sizeBytes: Number(part.sizeBytes),\n createdAt: part.createdAt,\n })),\n });\n } catch (err) {\n return handleServiceError(err, error);\n }\n },\n }),\n\n defineRoute({\n method: \"POST\",\n path: \"/uploads/:uploadId/parts/complete\",\n inputSchema: completePartsSchema,\n outputSchema: z.object({\n bytesUploaded: z.number(),\n partsUploaded: z.number(),\n }),\n errorCodes,\n handler: async function ({ pathParams, input }, { json, error }) {\n const payload = await input.valid();\n try {\n const result = await this.handlerTx()\n .withServiceCalls(() => [services.recordUploadParts(pathParams.uploadId, payload)])\n .transform(({ serviceResult: [updated] }) => updated)\n .execute();\n\n return json({\n bytesUploaded: Number(result.bytesUploaded),\n partsUploaded: result.partsUploaded,\n });\n } catch (err) {\n return handleServiceError(err, error);\n }\n },\n }),\n\n defineRoute({\n method: \"POST\",\n path: \"/uploads/:uploadId/complete\",\n inputSchema: completeUploadSchema,\n outputSchema: fileMetadataSchema,\n errorCodes,\n handler: async function ({ pathParams, input }, { json, error }) {\n const payload = await input.valid();\n const resolvedConfig = getResolvedConfig();\n try {\n const upload = await this.handlerTx()\n .withServiceCalls(() => [services.getUploadStorageInfo(pathParams.uploadId)])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n const existingFile = await this.handlerTx()\n .withServiceCalls(() => [services.findFileByKey(upload.fileKey)])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n if (existingFile) {\n return error({ message: \"File already exists\", code: \"FILE_ALREADY_EXISTS\" }, 409);\n }\n\n let finalizeResult: { sizeBytes?: bigint } | undefined;\n\n if (upload.strategy === \"direct-multipart\") {\n if (!resolvedConfig.storage.completeMultipartUpload) {\n return error({ message: \"Storage error\", code: \"STORAGE_ERROR\" }, 502);\n }\n\n if (!payload.parts || payload.parts.length === 0) {\n return error(\n { message: \"Upload invalid state\", code: \"UPLOAD_INVALID_STATE\" },\n 409,\n );\n }\n\n await resolvedConfig.storage.completeMultipartUpload({\n storageKey: upload.storageKey,\n storageUploadId: upload.storageUploadId ?? \"\",\n parts: payload.parts,\n });\n } else if (resolvedConfig.storage.finalizeUpload) {\n finalizeResult = await resolvedConfig.storage.finalizeUpload({\n storageKey: upload.storageKey,\n expectedSizeBytes: upload.expectedSizeBytes,\n checksum: upload.checksum as UploadChecksum | null,\n });\n }\n\n const completed = await this.handlerTx()\n .withServiceCalls(() => [\n services.markUploadComplete(\n upload.id.toString(),\n upload.fileKey,\n finalizeResult?.sizeBytes ? { sizeBytes: finalizeResult.sizeBytes } : undefined,\n ),\n ])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n return json(toFileMetadata(completed.file));\n } catch (err) {\n return handleServiceError(err, error);\n }\n },\n }),\n\n defineRoute({\n method: \"POST\",\n path: \"/uploads/:uploadId/abort\",\n outputSchema: z.object({ ok: z.literal(true) }),\n errorCodes,\n handler: async function ({ pathParams }, { json, error }) {\n const resolvedConfig = getResolvedConfig();\n try {\n const upload = await this.handlerTx()\n .withServiceCalls(() => [services.getUploadStorageInfo(pathParams.uploadId)])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n if (\n upload.strategy === \"direct-multipart\" &&\n resolvedConfig.storage.abortMultipartUpload\n ) {\n await resolvedConfig.storage.abortMultipartUpload({\n storageKey: upload.storageKey,\n storageUploadId: upload.storageUploadId ?? \"\",\n });\n }\n\n await this.handlerTx()\n .withServiceCalls(() => [services.markUploadAborted(upload.id.toString())])\n .execute();\n\n return json({ ok: true });\n } catch (err) {\n return handleServiceError(err, error);\n }\n },\n }),\n\n defineRoute({\n method: \"PUT\",\n path: \"/uploads/:uploadId/content\",\n contentType: \"application/octet-stream\",\n outputSchema: fileMetadataSchema,\n errorCodes,\n handler: async function (context, { json, error }) {\n const { pathParams } = context;\n const resolvedConfig = getResolvedConfig();\n try {\n const upload = await this.handlerTx()\n .withServiceCalls(() => [services.getUploadStorageInfo(pathParams.uploadId)])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n if (upload.strategy !== \"proxy\") {\n return error({ message: \"Upload invalid state\", code: \"UPLOAD_INVALID_STATE\" }, 409);\n }\n\n const existingFile = await this.handlerTx()\n .withServiceCalls(() => [services.findFileByKey(upload.fileKey)])\n .transform(({ serviceResult: [result] }) => result)\n .execute();\n\n if (existingFile) {\n return error({ message: \"File already exists\", code: \"FILE_ALREADY_EXISTS\" }, 409);\n }\n\n if (!resolvedConfig.storage.writeStream) {\n return error({ message: \"Storage error\", code: \"STORAGE_ERROR\" }, 502);\n }\n\n let result: Awaited<ReturnType<NonNullable<typeof resolvedConfig.storage.writeStream>>>;\n try {\n result = await resolvedConfig.storage.writeStream({\n storageKey: upload.storageKey,\n body: context.bodyStream(),\n contentType: upload.contentType,\n sizeBytes: upload.expectedSizeBytes,\n });\n } catch {\n await this.handlerTx()\n .withServiceCalls(() => [\n services.markUploadFailed(\n upload.id.toString(),\n \"STORAGE_ERROR\",\n \"Storage upload failed\",\n ),\n ])\n .execute();\n return error({ message: \"Storage error\", code: \"STORAGE_ERROR\" }, 502);\n }\n\n const completed = await this.handlerTx()\n .withServiceCalls(() => [\n services.markUploadComplete(\n upload.id.toString(),\n upload.fileKey,\n result?.sizeBytes ? { sizeBytes: result.sizeBytes } : undefined,\n ),\n ])\n .transform(({ serviceResult: [done] }) => done)\n .execute();\n\n return json(toFileMetadata(completed.file));\n } catch (err) {\n return handleServiceError(err, error);\n }\n },\n }),\n ];\n },\n);\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { schema } from "@fragno-dev/db/schema";
2
+
3
+ //#region src/schema.ts
4
+ const uploadSchema = schema("upload", (s) => s);
5
+
6
+ //#endregion
7
+ export { uploadSchema };
8
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","names":["schema","uploadSchema","s"],"sources":["../../../../../../src/schema.ts"],"sourcesContent":["import { column, idColumn, referenceColumn, schema } from \"@fragno-dev/db/schema\";\n\nexport const uploadSchema = schema(\"upload\", (s) => {\n return s\n .addTable(\"file\", (t) => {\n return t\n .addColumn(\"id\", idColumn())\n .addColumn(\"fileKey\", column(\"string\"))\n .addColumn(\"uploaderId\", column(\"string\").nullable())\n .addColumn(\"filename\", column(\"string\"))\n .addColumn(\"sizeBytes\", column(\"bigint\"))\n .addColumn(\"contentType\", column(\"string\"))\n .addColumn(\"checksum\", column(\"json\").nullable())\n .addColumn(\"visibility\", column(\"string\"))\n .addColumn(\"tags\", column(\"json\").nullable())\n .addColumn(\"metadata\", column(\"json\").nullable())\n .addColumn(\"status\", column(\"string\"))\n .addColumn(\"storageProvider\", column(\"string\"))\n .addColumn(\"storageKey\", column(\"string\"))\n .addColumn(\n \"createdAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .addColumn(\n \"updatedAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .addColumn(\"completedAt\", column(\"timestamp\").nullable())\n .addColumn(\"deletedAt\", column(\"timestamp\").nullable())\n .addColumn(\"errorCode\", column(\"string\").nullable())\n .addColumn(\"errorMessage\", column(\"string\").nullable())\n .createIndex(\"idx_file_key\", [\"fileKey\"], { unique: true })\n .createIndex(\"idx_file_key_status\", [\"fileKey\", \"status\"])\n .createIndex(\"idx_file_key_uploaderId\", [\"fileKey\", \"uploaderId\"])\n .createIndex(\"idx_file_key_status_uploaderId\", [\"fileKey\", \"status\", \"uploaderId\"])\n .createIndex(\"idx_file_uploaderId\", [\"uploaderId\"])\n .createIndex(\"idx_file_createdAt\", [\"createdAt\"])\n .createIndex(\"idx_file_status_createdAt\", [\"status\", \"createdAt\"]);\n })\n .addTable(\"upload\", (t) => {\n return t\n .addColumn(\"id\", idColumn())\n .addColumn(\"fileKey\", column(\"string\"))\n .addColumn(\"uploaderId\", column(\"string\").nullable())\n .addColumn(\"filename\", column(\"string\"))\n .addColumn(\"expectedSizeBytes\", column(\"bigint\"))\n .addColumn(\"contentType\", column(\"string\"))\n .addColumn(\"checksum\", column(\"json\").nullable())\n .addColumn(\"visibility\", column(\"string\"))\n .addColumn(\"tags\", column(\"json\").nullable())\n .addColumn(\"metadata\", column(\"json\").nullable())\n .addColumn(\"status\", column(\"string\"))\n .addColumn(\"strategy\", column(\"string\"))\n .addColumn(\"storageProvider\", column(\"string\"))\n .addColumn(\"storageKey\", column(\"string\"))\n .addColumn(\"storageUploadId\", column(\"string\").nullable())\n .addColumn(\"uploadUrl\", column(\"string\").nullable())\n .addColumn(\"uploadHeaders\", column(\"json\").nullable())\n .addColumn(\"bytesUploaded\", column(\"bigint\").defaultTo(0n))\n .addColumn(\"partsUploaded\", column(\"integer\").defaultTo(0))\n .addColumn(\"partSizeBytes\", column(\"integer\").nullable())\n .addColumn(\"expiresAt\", column(\"timestamp\"))\n .addColumn(\n \"createdAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .addColumn(\n \"updatedAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .addColumn(\"completedAt\", column(\"timestamp\").nullable())\n .addColumn(\"errorCode\", column(\"string\").nullable())\n .addColumn(\"errorMessage\", column(\"string\").nullable())\n .createIndex(\"idx_upload_file_key\", [\"fileKey\"])\n .createIndex(\"idx_upload_status\", [\"status\"])\n .createIndex(\"idx_upload_expiresAt\", [\"expiresAt\"]);\n })\n .addTable(\"upload_part\", (t) => {\n return t\n .addColumn(\"id\", idColumn())\n .addColumn(\"uploadId\", referenceColumn())\n .addColumn(\"partNumber\", column(\"integer\"))\n .addColumn(\"etag\", column(\"string\"))\n .addColumn(\"sizeBytes\", column(\"bigint\"))\n .addColumn(\n \"createdAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .createIndex(\"idx_upload_part_upload\", [\"uploadId\"])\n .createIndex(\"idx_upload_part_number\", [\"uploadId\", \"partNumber\"], {\n unique: true,\n });\n })\n .addReference(\"upload\", {\n type: \"one\",\n from: { table: \"upload_part\", column: \"uploadId\" },\n to: { table: \"upload\", column: \"id\" },\n });\n});\n"],"mappings":";;;AAEA,MAAaC,eAAeD,OAAO,WAAQE,MAAAA,EAgGzC"}
@@ -0,0 +1,9 @@
1
+ //#region src/storage/types.d.ts
2
+
3
+ type UploadChecksum = {
4
+ algo: "sha256" | "md5";
5
+ value: string;
6
+ };
7
+ //#endregion
8
+ export { UploadChecksum };
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../../../../../src/storage/types.ts"],"sourcesContent":[],"mappings":";;KAYY,cAAA"}
@@ -0,0 +1,31 @@
1
+ //#region src/types.d.ts
2
+ type FileVisibility = "private" | "public" | "unlisted";
3
+ type FileStatus = "ready" | "deleted";
4
+ type UploadStrategy = "direct-single" | "direct-multipart" | "proxy";
5
+ type FileMetadata = {
6
+ fileKey: string;
7
+ fileKeyParts: (string | number)[];
8
+ uploaderId: string | null;
9
+ filename: string;
10
+ sizeBytes: number;
11
+ contentType: string;
12
+ checksum: {
13
+ algo: "sha256" | "md5";
14
+ value: string;
15
+ } | null;
16
+ visibility: FileVisibility;
17
+ tags: string[] | null;
18
+ metadata: Record<string, unknown> | null;
19
+ status: FileStatus;
20
+ storageProvider: string;
21
+ createdAt: string;
22
+ updatedAt: string;
23
+ completedAt: string | null;
24
+ deletedAt: string | null;
25
+ errorCode: string | null;
26
+ errorMessage: string | null;
27
+ };
28
+ //# sourceMappingURL=types.d.ts.map
29
+ //#endregion
30
+ export { FileMetadata, FileVisibility, UploadStrategy };
31
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../../../../src/types.ts"],"sourcesContent":[],"mappings":";KAAY,cAAA;AAAA,KAEA,UAAA,GAFc,OAAA,GAAA,SAAA;AAYd,KAAA,cAAA,GAAc,eAAA,GAAA,kBAAA,GAAA,OAAA;AAEd,KAAA,YAAA,GAAY;EAAA,OAAA,EAAA,MAAA;cAQV,EAAA,CAAA,MAAA,GAAA,MAAA,CAAA,EAAA;YAEF,EAAA,MAAA,GAAA,IAAA;UACF,EAAA,MAAA;EAAU,SAAA,EAAA,MAAA;;;;;;cAHN;;YAEF;UACF"}
@@ -0,0 +1,48 @@
1
+ //#region ../fragno/dist/api/error.js
2
+ var FragnoApiError = class extends Error {
3
+ #status;
4
+ #code;
5
+ constructor({ message, code }, status) {
6
+ super(message);
7
+ this.name = "FragnoApiError";
8
+ this.#status = status;
9
+ this.#code = code;
10
+ }
11
+ get status() {
12
+ return this.#status;
13
+ }
14
+ get code() {
15
+ return this.#code;
16
+ }
17
+ toResponse() {
18
+ return Response.json({
19
+ message: this.message,
20
+ code: this.code
21
+ }, { status: this.status });
22
+ }
23
+ };
24
+ var FragnoApiValidationError = class extends FragnoApiError {
25
+ #issues;
26
+ constructor(message, issues) {
27
+ super({
28
+ message,
29
+ code: "FRAGNO_VALIDATION_ERROR"
30
+ }, 400);
31
+ this.name = "FragnoApiValidationError";
32
+ this.#issues = issues;
33
+ }
34
+ get issues() {
35
+ return this.#issues;
36
+ }
37
+ toResponse() {
38
+ return Response.json({
39
+ message: this.message,
40
+ issues: this.#issues,
41
+ code: this.code
42
+ }, { status: this.status });
43
+ }
44
+ };
45
+
46
+ //#endregion
47
+ export { FragnoApiValidationError };
48
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","names":["FragnoApiError","Error","status","code","constructor","message","name","toResponse","Response","json","FragnoApiValidationError","issues"],"sources":["../../../../../../../../fragno/dist/api/error.js"],"sourcesContent":["//#region src/api/error.ts\nvar FragnoApiError = class extends Error {\n\t#status;\n\t#code;\n\tconstructor({ message, code }, status) {\n\t\tsuper(message);\n\t\tthis.name = \"FragnoApiError\";\n\t\tthis.#status = status;\n\t\tthis.#code = code;\n\t}\n\tget status() {\n\t\treturn this.#status;\n\t}\n\tget code() {\n\t\treturn this.#code;\n\t}\n\ttoResponse() {\n\t\treturn Response.json({\n\t\t\tmessage: this.message,\n\t\t\tcode: this.code\n\t\t}, { status: this.status });\n\t}\n};\nvar FragnoApiValidationError = class extends FragnoApiError {\n\t#issues;\n\tconstructor(message, issues) {\n\t\tsuper({\n\t\t\tmessage,\n\t\t\tcode: \"FRAGNO_VALIDATION_ERROR\"\n\t\t}, 400);\n\t\tthis.name = \"FragnoApiValidationError\";\n\t\tthis.#issues = issues;\n\t}\n\tget issues() {\n\t\treturn this.#issues;\n\t}\n\ttoResponse() {\n\t\treturn Response.json({\n\t\t\tmessage: this.message,\n\t\t\tissues: this.#issues,\n\t\t\tcode: this.code\n\t\t}, { status: this.status });\n\t}\n};\n\n//#endregion\nexport { FragnoApiError, FragnoApiValidationError };\n//# sourceMappingURL=error.js.map"],"mappings":";AACA,IAAIA,iBAAiB,cAAcC,MAAM;CACxC;CACA;CACAG,YAAY,EAAEC,SAASF,QAAQD,QAAQ;AACtC,QAAMG,QAAQ;AACd,OAAKC,OAAO;AACZ,QAAK,SAAUJ;AACf,QAAK,OAAQC;;CAEd,IAAID,SAAS;AACZ,SAAO,MAAK;;CAEb,IAAIC,OAAO;AACV,SAAO,MAAK;;CAEbI,aAAa;AACZ,SAAOC,SAASC,KAAK;GACpBJ,SAAS,KAAKA;GACdF,MAAM,KAAKA;GACX,EAAE,EAAED,QAAQ,KAAKA,QAAQ,CAAC;;;AAG7B,IAAIQ,2BAA2B,cAAcV,eAAe;CAC3D;CACAI,YAAYC,SAASM,QAAQ;AAC5B,QAAM;GACLN;GACAF,MAAM;GACN,EAAE,IAAI;AACP,OAAKG,OAAO;AACZ,QAAK,SAAUK;;CAEhB,IAAIA,SAAS;AACZ,SAAO,MAAK;;CAEbJ,aAAa;AACZ,SAAOC,SAASC,KAAK;GACpBJ,SAAS,KAAKA;GACdM,QAAQ,MAAK;GACbR,MAAM,KAAKA;GACX,EAAE,EAAED,QAAQ,KAAKA,QAAQ,CAAC"}
@@ -0,0 +1,76 @@
1
+ //#region ../fragno/dist/api/internal/path.js
2
+ /**
3
+ * Extract parameter names from a path pattern at runtime.
4
+ * Examples:
5
+ * - "/users/:id" => ["id"]
6
+ * - "/files/**" => ["**"]
7
+ * - "/files/**:rest" => ["rest"]
8
+ */
9
+ function extractPathParams(pathPattern) {
10
+ const segments = pathPattern.split("/").filter((s) => s.length > 0);
11
+ const names = [];
12
+ for (const segment of segments) {
13
+ if (segment.startsWith(":")) {
14
+ names.push(segment.slice(1));
15
+ continue;
16
+ }
17
+ if (segment === "**") {
18
+ names.push("**");
19
+ continue;
20
+ }
21
+ if (segment.startsWith("**:")) {
22
+ names.push(segment.slice(3));
23
+ continue;
24
+ }
25
+ }
26
+ return names;
27
+ }
28
+ /**
29
+ * Build a concrete path by replacing placeholders in a path pattern with values.
30
+ *
31
+ * Supports the same placeholder syntax as the matcher:
32
+ * - Named parameter ":name" is URL-encoded as a single segment
33
+ * - Anonymous wildcard "**" inserts the remainder as-is (slashes preserved)
34
+ * - Named wildcard "**:name" inserts the remainder from the named key
35
+ *
36
+ * Examples:
37
+ * - buildPath("/users/:id", { id: "123" }) => "/users/123"
38
+ * - buildPath("/files/**", { "**": "a/b" }) => "/files/a/b"
39
+ * - buildPath("/files/**:rest", { rest: "a/b" }) => "/files/a/b"
40
+ */
41
+ function buildPath(pathPattern, params) {
42
+ const patternSegments = pathPattern.split("/");
43
+ const builtSegments = [];
44
+ for (const segment of patternSegments) {
45
+ if (segment.length === 0) {
46
+ builtSegments.push("");
47
+ continue;
48
+ }
49
+ if (segment.startsWith(":")) {
50
+ const name = segment.slice(1);
51
+ const value = params[name];
52
+ if (value === void 0) throw new Error(`Missing value for path parameter :${name}`);
53
+ builtSegments.push(encodeURIComponent(value));
54
+ continue;
55
+ }
56
+ if (segment === "**") {
57
+ const value = params["**"];
58
+ if (value === void 0) throw new Error("Missing value for path wildcard **");
59
+ builtSegments.push(value);
60
+ continue;
61
+ }
62
+ if (segment.startsWith("**:")) {
63
+ const name = segment.slice(3);
64
+ const value = params[name];
65
+ if (value === void 0) throw new Error(`Missing value for path wildcard **:${name}`);
66
+ builtSegments.push(value);
67
+ continue;
68
+ }
69
+ builtSegments.push(segment);
70
+ }
71
+ return builtSegments.join("/");
72
+ }
73
+
74
+ //#endregion
75
+ export { buildPath, extractPathParams };
76
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","names":["extractPathParams","pathPattern","segments","split","filter","s","length","names","segment","startsWith","push","slice","buildPath","params","patternSegments","builtSegments","name","value","Error","encodeURIComponent","join"],"sources":["../../../../../../../../../fragno/dist/api/internal/path.js"],"sourcesContent":["//#region src/api/internal/path.ts\n/**\n* Extract parameter names from a path pattern at runtime.\n* Examples:\n* - \"/users/:id\" => [\"id\"]\n* - \"/files/**\" => [\"**\"]\n* - \"/files/**:rest\" => [\"rest\"]\n*/\nfunction extractPathParams(pathPattern) {\n\tconst segments = pathPattern.split(\"/\").filter((s) => s.length > 0);\n\tconst names = [];\n\tfor (const segment of segments) {\n\t\tif (segment.startsWith(\":\")) {\n\t\t\tnames.push(segment.slice(1));\n\t\t\tcontinue;\n\t\t}\n\t\tif (segment === \"**\") {\n\t\t\tnames.push(\"**\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (segment.startsWith(\"**:\")) {\n\t\t\tnames.push(segment.slice(3));\n\t\t\tcontinue;\n\t\t}\n\t}\n\treturn names;\n}\n/**\n* Build a concrete path by replacing placeholders in a path pattern with values.\n*\n* Supports the same placeholder syntax as the matcher:\n* - Named parameter \":name\" is URL-encoded as a single segment\n* - Anonymous wildcard \"**\" inserts the remainder as-is (slashes preserved)\n* - Named wildcard \"**:name\" inserts the remainder from the named key\n*\n* Examples:\n* - buildPath(\"/users/:id\", { id: \"123\" }) => \"/users/123\"\n* - buildPath(\"/files/**\", { \"**\": \"a/b\" }) => \"/files/a/b\"\n* - buildPath(\"/files/**:rest\", { rest: \"a/b\" }) => \"/files/a/b\"\n*/\nfunction buildPath(pathPattern, params) {\n\tconst patternSegments = pathPattern.split(\"/\");\n\tconst builtSegments = [];\n\tfor (const segment of patternSegments) {\n\t\tif (segment.length === 0) {\n\t\t\tbuiltSegments.push(\"\");\n\t\t\tcontinue;\n\t\t}\n\t\tif (segment.startsWith(\":\")) {\n\t\t\tconst name = segment.slice(1);\n\t\t\tconst value = params[name];\n\t\t\tif (value === void 0) throw new Error(`Missing value for path parameter :${name}`);\n\t\t\tbuiltSegments.push(encodeURIComponent(value));\n\t\t\tcontinue;\n\t\t}\n\t\tif (segment === \"**\") {\n\t\t\tconst value = params[\"**\"];\n\t\t\tif (value === void 0) throw new Error(\"Missing value for path wildcard **\");\n\t\t\tbuiltSegments.push(value);\n\t\t\tcontinue;\n\t\t}\n\t\tif (segment.startsWith(\"**:\")) {\n\t\t\tconst name = segment.slice(3);\n\t\t\tconst value = params[name];\n\t\t\tif (value === void 0) throw new Error(`Missing value for path wildcard **:${name}`);\n\t\t\tbuiltSegments.push(value);\n\t\t\tcontinue;\n\t\t}\n\t\tbuiltSegments.push(segment);\n\t}\n\treturn builtSegments.join(\"/\");\n}\n\n//#endregion\nexport { buildPath, extractPathParams };\n//# sourceMappingURL=path.js.map"],"mappings":";;;;;;;;AAQA,SAASA,kBAAkBC,aAAa;CACvC,MAAMC,WAAWD,YAAYE,MAAM,IAAI,CAACC,QAAQC,MAAMA,EAAEC,SAAS,EAAE;CACnE,MAAMC,QAAQ,EAAE;AAChB,MAAK,MAAMC,WAAWN,UAAU;AAC/B,MAAIM,QAAQC,WAAW,IAAI,EAAE;AAC5BF,SAAMG,KAAKF,QAAQG,MAAM,EAAE,CAAC;AAC5B;;AAED,MAAIH,YAAY,MAAM;AACrBD,SAAMG,KAAK,KAAK;AAChB;;AAED,MAAIF,QAAQC,WAAW,MAAM,EAAE;AAC9BF,SAAMG,KAAKF,QAAQG,MAAM,EAAE,CAAC;AAC5B;;;AAGF,QAAOJ;;;;;;;;;;;;;;;AAeR,SAASK,UAAUX,aAAaY,QAAQ;CACvC,MAAMC,kBAAkBb,YAAYE,MAAM,IAAI;CAC9C,MAAMY,gBAAgB,EAAE;AACxB,MAAK,MAAMP,WAAWM,iBAAiB;AACtC,MAAIN,QAAQF,WAAW,GAAG;AACzBS,iBAAcL,KAAK,GAAG;AACtB;;AAED,MAAIF,QAAQC,WAAW,IAAI,EAAE;GAC5B,MAAMO,OAAOR,QAAQG,MAAM,EAAE;GAC7B,MAAMM,QAAQJ,OAAOG;AACrB,OAAIC,UAAU,KAAK,EAAG,OAAM,IAAIC,MAAM,qCAAqCF,OAAO;AAClFD,iBAAcL,KAAKS,mBAAmBF,MAAM,CAAC;AAC7C;;AAED,MAAIT,YAAY,MAAM;GACrB,MAAMS,QAAQJ,OAAO;AACrB,OAAII,UAAU,KAAK,EAAG,OAAM,IAAIC,MAAM,qCAAqC;AAC3EH,iBAAcL,KAAKO,MAAM;AACzB;;AAED,MAAIT,QAAQC,WAAW,MAAM,EAAE;GAC9B,MAAMO,OAAOR,QAAQG,MAAM,EAAE;GAC7B,MAAMM,QAAQJ,OAAOG;AACrB,OAAIC,UAAU,KAAK,EAAG,OAAM,IAAIC,MAAM,sCAAsCF,OAAO;AACnFD,iBAAcL,KAAKO,MAAM;AACzB;;AAEDF,gBAAcL,KAAKF,QAAQ;;AAE5B,QAAOO,cAAcK,KAAK,IAAI"}
@@ -0,0 +1,81 @@
1
+ //#region ../fragno/dist/api/internal/response-stream.js
2
+ var ResponseStream = class {
3
+ #writer;
4
+ #encoder;
5
+ #abortSubscribers = [];
6
+ #responseReadable;
7
+ #aborted = false;
8
+ #closed = false;
9
+ /**
10
+ * Whether the stream has been aborted.
11
+ */
12
+ get aborted() {
13
+ return this.#aborted;
14
+ }
15
+ /**
16
+ * Whether the stream has been closed normally.
17
+ */
18
+ get closed() {
19
+ return this.#closed;
20
+ }
21
+ /**
22
+ * The readable stream that the response is piped to.
23
+ */
24
+ get responseReadable() {
25
+ return this.#responseReadable;
26
+ }
27
+ constructor(writable, readable) {
28
+ this.#writer = writable.getWriter();
29
+ this.#encoder = new TextEncoder();
30
+ const reader = readable.getReader();
31
+ this.#abortSubscribers.push(async () => {
32
+ await reader.cancel();
33
+ });
34
+ this.#responseReadable = new ReadableStream({
35
+ async pull(controller) {
36
+ const { done, value } = await reader.read();
37
+ if (done) controller.close();
38
+ else controller.enqueue(value);
39
+ },
40
+ cancel: () => {
41
+ this.abort();
42
+ }
43
+ });
44
+ }
45
+ async writeRaw(input) {
46
+ try {
47
+ if (typeof input === "string") input = this.#encoder.encode(input);
48
+ await this.#writer.write(input);
49
+ } catch {}
50
+ }
51
+ write(input) {
52
+ return this.writeRaw(JSON.stringify(input) + "\n");
53
+ }
54
+ sleep(ms) {
55
+ return new Promise((res) => setTimeout(res, ms));
56
+ }
57
+ async close() {
58
+ try {
59
+ await this.#writer.close();
60
+ } catch {} finally {
61
+ this.#closed = true;
62
+ }
63
+ }
64
+ onAbort(listener) {
65
+ this.#abortSubscribers.push(listener);
66
+ }
67
+ /**
68
+ * Abort the stream.
69
+ * You can call this method when stream is aborted by external event.
70
+ */
71
+ abort() {
72
+ if (!this.aborted) {
73
+ this.#aborted = true;
74
+ this.#abortSubscribers.forEach((subscriber) => subscriber());
75
+ }
76
+ }
77
+ };
78
+
79
+ //#endregion
80
+ export { ResponseStream };
81
+ //# sourceMappingURL=response-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-stream.js","names":["ResponseStream","writer","encoder","abortSubscribers","responseReadable","aborted","closed","constructor","writable","readable","getWriter","TextEncoder","reader","getReader","push","cancel","ReadableStream","pull","controller","done","value","read","close","enqueue","abort","writeRaw","input","encode","write","JSON","stringify","sleep","ms","Promise","res","setTimeout","onAbort","listener","forEach","subscriber"],"sources":["../../../../../../../../../fragno/dist/api/internal/response-stream.js"],"sourcesContent":["//#region src/api/internal/response-stream.ts\nvar ResponseStream = class {\n\t#writer;\n\t#encoder;\n\t#abortSubscribers = [];\n\t#responseReadable;\n\t#aborted = false;\n\t#closed = false;\n\t/**\n\t* Whether the stream has been aborted.\n\t*/\n\tget aborted() {\n\t\treturn this.#aborted;\n\t}\n\t/**\n\t* Whether the stream has been closed normally.\n\t*/\n\tget closed() {\n\t\treturn this.#closed;\n\t}\n\t/**\n\t* The readable stream that the response is piped to.\n\t*/\n\tget responseReadable() {\n\t\treturn this.#responseReadable;\n\t}\n\tconstructor(writable, readable) {\n\t\tthis.#writer = writable.getWriter();\n\t\tthis.#encoder = new TextEncoder();\n\t\tconst reader = readable.getReader();\n\t\tthis.#abortSubscribers.push(async () => {\n\t\t\tawait reader.cancel();\n\t\t});\n\t\tthis.#responseReadable = new ReadableStream({\n\t\t\tasync pull(controller) {\n\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\tif (done) controller.close();\n\t\t\t\telse controller.enqueue(value);\n\t\t\t},\n\t\t\tcancel: () => {\n\t\t\t\tthis.abort();\n\t\t\t}\n\t\t});\n\t}\n\tasync writeRaw(input) {\n\t\ttry {\n\t\t\tif (typeof input === \"string\") input = this.#encoder.encode(input);\n\t\t\tawait this.#writer.write(input);\n\t\t} catch {}\n\t}\n\twrite(input) {\n\t\treturn this.writeRaw(JSON.stringify(input) + \"\\n\");\n\t}\n\tsleep(ms) {\n\t\treturn new Promise((res) => setTimeout(res, ms));\n\t}\n\tasync close() {\n\t\ttry {\n\t\t\tawait this.#writer.close();\n\t\t} catch {} finally {\n\t\t\tthis.#closed = true;\n\t\t}\n\t}\n\tonAbort(listener) {\n\t\tthis.#abortSubscribers.push(listener);\n\t}\n\t/**\n\t* Abort the stream.\n\t* You can call this method when stream is aborted by external event.\n\t*/\n\tabort() {\n\t\tif (!this.aborted) {\n\t\t\tthis.#aborted = true;\n\t\t\tthis.#abortSubscribers.forEach((subscriber) => subscriber());\n\t\t}\n\t}\n};\n\n//#endregion\nexport { ResponseStream };\n//# sourceMappingURL=response-stream.js.map"],"mappings":";AACA,IAAIA,iBAAiB,MAAM;CAC1B;CACA;CACA,oBAAoB,EAAE;CACtB;CACA,WAAW;CACX,UAAU;;;;CAIV,IAAIK,UAAU;AACb,SAAO,MAAK;;;;;CAKb,IAAIC,SAAS;AACZ,SAAO,MAAK;;;;;CAKb,IAAIF,mBAAmB;AACtB,SAAO,MAAK;;CAEbG,YAAYC,UAAUC,UAAU;AAC/B,QAAK,SAAUD,SAASE,WAAW;AACnC,QAAK,UAAW,IAAIC,aAAa;EACjC,MAAMC,SAASH,SAASI,WAAW;AACnC,QAAK,iBAAkBC,KAAK,YAAY;AACvC,SAAMF,OAAOG,QAAQ;IACpB;AACF,QAAK,mBAAoB,IAAIC,eAAe;GAC3C,MAAMC,KAAKC,YAAY;IACtB,MAAM,EAAEC,MAAMC,UAAU,MAAMR,OAAOS,MAAM;AAC3C,QAAIF,KAAMD,YAAWI,OAAO;QACvBJ,YAAWK,QAAQH,MAAM;;GAE/BL,cAAc;AACb,SAAKS,OAAO;;GAEb,CAAC;;CAEH,MAAMC,SAASC,OAAO;AACrB,MAAI;AACH,OAAI,OAAOA,UAAU,SAAUA,SAAQ,MAAK,QAASC,OAAOD,MAAM;AAClE,SAAM,MAAK,OAAQE,MAAMF,MAAM;UACxB;;CAETE,MAAMF,OAAO;AACZ,SAAO,KAAKD,SAASI,KAAKC,UAAUJ,MAAM,GAAG,KAAK;;CAEnDK,MAAMC,IAAI;AACT,SAAO,IAAIC,SAASC,QAAQC,WAAWD,KAAKF,GAAG,CAAC;;CAEjD,MAAMV,QAAQ;AACb,MAAI;AACH,SAAM,MAAK,OAAQA,OAAO;UACnB,WAAW;AAClB,SAAK,SAAU;;;CAGjBc,QAAQC,UAAU;AACjB,QAAK,iBAAkBvB,KAAKuB,SAAS;;;;;;CAMtCb,QAAQ;AACP,MAAI,CAAC,KAAKnB,SAAS;AAClB,SAAK,UAAW;AAChB,SAAK,iBAAkBiC,SAASC,eAAeA,YAAY,CAAC"}
@@ -0,0 +1,10 @@
1
+ //#region ../fragno/dist/api/internal/route.js
2
+ function getMountRoute(opts) {
3
+ const mountRoute = opts.mountRoute ?? `/api/${opts.name}`;
4
+ if (mountRoute.endsWith("/")) return mountRoute.slice(0, -1);
5
+ return mountRoute;
6
+ }
7
+
8
+ //#endregion
9
+ export { getMountRoute };
10
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.js","names":["getMountRoute","opts","mountRoute","name","endsWith","slice"],"sources":["../../../../../../../../../fragno/dist/api/internal/route.js"],"sourcesContent":["//#region src/api/internal/route.ts\nfunction getMountRoute(opts) {\n\tconst mountRoute = opts.mountRoute ?? `/api/${opts.name}`;\n\tif (mountRoute.endsWith(\"/\")) return mountRoute.slice(0, -1);\n\treturn mountRoute;\n}\n\n//#endregion\nexport { getMountRoute };\n//# sourceMappingURL=route.js.map"],"mappings":";AACA,SAASA,cAAcC,MAAM;CAC5B,MAAMC,aAAaD,KAAKC,cAAc,QAAQD,KAAKE;AACnD,KAAID,WAAWE,SAAS,IAAI,CAAE,QAAOF,WAAWG,MAAM,GAAG,GAAG;AAC5D,QAAOH"}