@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.
- package/LICENSE.md +16 -0
- package/README.md +43 -0
- package/bin/run.js +5 -0
- package/dist/browser/client/clients.js +49 -0
- package/dist/browser/client/clients.js.map +1 -0
- package/dist/browser/client/helpers.d.ts +51 -0
- package/dist/browser/client/helpers.d.ts.map +1 -0
- package/dist/browser/client/helpers.js +242 -0
- package/dist/browser/client/helpers.js.map +1 -0
- 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
- 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
- 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
- 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
- package/dist/browser/client/node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js +17 -0
- package/dist/browser/client/node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js.map +1 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/atom/index.js +62 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/atom/index.js.map +1 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/clean-stores/index.js +6 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/clean-stores/index.js.map +1 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/computed/index.js +50 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/computed/index.js.map +1 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/lifecycle/index.js +99 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/lifecycle/index.js.map +1 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/listen-keys/index.js +11 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/listen-keys/index.js.map +1 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/map/index.js +25 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/map/index.js.map +1 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/task/index.js +24 -0
- package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/task/index.js.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/definition.js +49 -0
- package/dist/browser/client/packages/fragment-upload/src/definition.js.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/keys.d.ts +7 -0
- package/dist/browser/client/packages/fragment-upload/src/keys.d.ts.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/keys.js +28 -0
- package/dist/browser/client/packages/fragment-upload/src/keys.js.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/routes/files.js +98 -0
- package/dist/browser/client/packages/fragment-upload/src/routes/files.js.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/routes/index.js +9 -0
- package/dist/browser/client/packages/fragment-upload/src/routes/index.js.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/routes/shared.js +41 -0
- package/dist/browser/client/packages/fragment-upload/src/routes/shared.js.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/routes/uploads.js +186 -0
- package/dist/browser/client/packages/fragment-upload/src/routes/uploads.js.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/schema.js +8 -0
- package/dist/browser/client/packages/fragment-upload/src/schema.js.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/storage/types.d.ts +9 -0
- package/dist/browser/client/packages/fragment-upload/src/storage/types.d.ts.map +1 -0
- package/dist/browser/client/packages/fragment-upload/src/types.d.ts +31 -0
- package/dist/browser/client/packages/fragment-upload/src/types.d.ts.map +1 -0
- package/dist/browser/client/packages/fragno/dist/api/error.js +48 -0
- package/dist/browser/client/packages/fragno/dist/api/error.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/api/internal/path.js +76 -0
- package/dist/browser/client/packages/fragno/dist/api/internal/path.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/api/internal/response-stream.js +81 -0
- package/dist/browser/client/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/api/internal/route.js +10 -0
- package/dist/browser/client/packages/fragno/dist/api/internal/route.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/api/request-input-context.js +185 -0
- package/dist/browser/client/packages/fragno/dist/api/request-input-context.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/api/request-output-context.js +119 -0
- package/dist/browser/client/packages/fragno/dist/api/request-output-context.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/api/route.js +17 -0
- package/dist/browser/client/packages/fragno/dist/api/route.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/client-error.js +92 -0
- package/dist/browser/client/packages/fragno/dist/client/client-error.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/client.js +495 -0
- package/dist/browser/client/packages/fragno/dist/client/client.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/client.svelte.js +120 -0
- package/dist/browser/client/packages/fragno/dist/client/client.svelte.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/internal/fetcher-merge.js +36 -0
- package/dist/browser/client/packages/fragno/dist/client/internal/fetcher-merge.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/internal/ndjson-streaming.js +139 -0
- package/dist/browser/client/packages/fragno/dist/client/internal/ndjson-streaming.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/react.js +70 -0
- package/dist/browser/client/packages/fragno/dist/client/react.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/solid.js +108 -0
- package/dist/browser/client/packages/fragno/dist/client/solid.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/vanilla.js +96 -0
- package/dist/browser/client/packages/fragno/dist/client/vanilla.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/client/vue.js +120 -0
- package/dist/browser/client/packages/fragno/dist/client/vue.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/util/async.js +40 -0
- package/dist/browser/client/packages/fragno/dist/util/async.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/util/content-type.js +49 -0
- package/dist/browser/client/packages/fragno/dist/util/content-type.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/util/nanostores.js +31 -0
- package/dist/browser/client/packages/fragno/dist/util/nanostores.js.map +1 -0
- package/dist/browser/client/packages/fragno/dist/util/ssr.js +18 -0
- package/dist/browser/client/packages/fragno/dist/util/ssr.js.map +1 -0
- package/dist/browser/client/react.d.ts +295 -0
- package/dist/browser/client/react.d.ts.map +1 -0
- package/dist/browser/client/react.js +11 -0
- package/dist/browser/client/react.js.map +1 -0
- package/dist/browser/client/solid.d.ts +303 -0
- package/dist/browser/client/solid.d.ts.map +1 -0
- package/dist/browser/client/solid.js +11 -0
- package/dist/browser/client/solid.js.map +1 -0
- package/dist/browser/client/svelte.d.ts +295 -0
- package/dist/browser/client/svelte.d.ts.map +1 -0
- package/dist/browser/client/svelte.js +11 -0
- package/dist/browser/client/svelte.js.map +1 -0
- package/dist/browser/client/vanilla.d.ts +296 -0
- package/dist/browser/client/vanilla.d.ts.map +1 -0
- package/dist/browser/client/vanilla.js +11 -0
- package/dist/browser/client/vanilla.js.map +1 -0
- package/dist/browser/client/vue.d.ts +295 -0
- package/dist/browser/client/vue.d.ts.map +1 -0
- package/dist/browser/client/vue.js +11 -0
- package/dist/browser/client/vue.js.map +1 -0
- package/dist/browser/index-BdjKPO4J.d.ts +177 -0
- package/dist/browser/index-BdjKPO4J.d.ts.map +1 -0
- package/dist/browser/index.js +3 -0
- package/dist/browser/src-vdNJUbjT.js +1982 -0
- package/dist/browser/src-vdNJUbjT.js.map +1 -0
- package/dist/cli/commands/files/delete.d.ts +40 -0
- package/dist/cli/commands/files/delete.d.ts.map +1 -0
- package/dist/cli/commands/files/delete.js +31 -0
- package/dist/cli/commands/files/delete.js.map +1 -0
- package/dist/cli/commands/files/download-url.d.ts +40 -0
- package/dist/cli/commands/files/download-url.d.ts.map +1 -0
- package/dist/cli/commands/files/download-url.js +31 -0
- package/dist/cli/commands/files/download-url.js.map +1 -0
- package/dist/cli/commands/files/download.d.ts +49 -0
- package/dist/cli/commands/files/download.d.ts.map +1 -0
- package/dist/cli/commands/files/download.js +65 -0
- package/dist/cli/commands/files/download.js.map +1 -0
- package/dist/cli/commands/files/get.d.ts +40 -0
- package/dist/cli/commands/files/get.d.ts.map +1 -0
- package/dist/cli/commands/files/get.js +31 -0
- package/dist/cli/commands/files/get.js.map +1 -0
- package/dist/cli/commands/files/list.d.ts +56 -0
- package/dist/cli/commands/files/list.d.ts.map +1 -0
- package/dist/cli/commands/files/list.js +53 -0
- package/dist/cli/commands/files/list.js.map +1 -0
- package/dist/cli/commands/files/update.d.ts +56 -0
- package/dist/cli/commands/files/update.d.ts.map +1 -0
- package/dist/cli/commands/files/update.js +53 -0
- package/dist/cli/commands/files/update.js.map +1 -0
- package/dist/cli/commands/files/upload.d.ts +73 -0
- package/dist/cli/commands/files/upload.d.ts.map +1 -0
- package/dist/cli/commands/files/upload.js +87 -0
- package/dist/cli/commands/files/upload.js.map +1 -0
- package/dist/cli/commands/uploads/abort.d.ts +37 -0
- package/dist/cli/commands/uploads/abort.d.ts.map +1 -0
- package/dist/cli/commands/uploads/abort.js +26 -0
- package/dist/cli/commands/uploads/abort.js.map +1 -0
- package/dist/cli/commands/uploads/complete.d.ts +41 -0
- package/dist/cli/commands/uploads/complete.d.ts.map +1 -0
- package/dist/cli/commands/uploads/complete.js +45 -0
- package/dist/cli/commands/uploads/complete.js.map +1 -0
- package/dist/cli/commands/uploads/content.d.ts +46 -0
- package/dist/cli/commands/uploads/content.d.ts.map +1 -0
- package/dist/cli/commands/uploads/content.js +43 -0
- package/dist/cli/commands/uploads/content.js.map +1 -0
- package/dist/cli/commands/uploads/create.d.ts +72 -0
- package/dist/cli/commands/uploads/create.d.ts.map +1 -0
- package/dist/cli/commands/uploads/create.js +84 -0
- package/dist/cli/commands/uploads/create.js.map +1 -0
- package/dist/cli/commands/uploads/get.d.ts +37 -0
- package/dist/cli/commands/uploads/get.d.ts.map +1 -0
- package/dist/cli/commands/uploads/get.js +26 -0
- package/dist/cli/commands/uploads/get.js.map +1 -0
- package/dist/cli/commands/uploads/parts-complete.d.ts +41 -0
- package/dist/cli/commands/uploads/parts-complete.d.ts.map +1 -0
- package/dist/cli/commands/uploads/parts-complete.js +44 -0
- package/dist/cli/commands/uploads/parts-complete.js.map +1 -0
- package/dist/cli/commands/uploads/parts-list.d.ts +37 -0
- package/dist/cli/commands/uploads/parts-list.d.ts.map +1 -0
- package/dist/cli/commands/uploads/parts-list.js +26 -0
- package/dist/cli/commands/uploads/parts-list.js.map +1 -0
- package/dist/cli/commands/uploads/parts-urls.d.ts +46 -0
- package/dist/cli/commands/uploads/parts-urls.d.ts.map +1 -0
- package/dist/cli/commands/uploads/parts-urls.js +57 -0
- package/dist/cli/commands/uploads/parts-urls.js.map +1 -0
- package/dist/cli/commands/uploads/progress.d.ts +45 -0
- package/dist/cli/commands/uploads/progress.d.ts.map +1 -0
- package/dist/cli/commands/uploads/progress.js +40 -0
- package/dist/cli/commands/uploads/progress.js.map +1 -0
- package/dist/cli/commands/uploads/transfer.d.ts +73 -0
- package/dist/cli/commands/uploads/transfer.d.ts.map +1 -0
- package/dist/cli/commands/uploads/transfer.js +170 -0
- package/dist/cli/commands/uploads/transfer.js.map +1 -0
- package/dist/cli/index.d.ts +27 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +198 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/keys.js +32 -0
- package/dist/cli/keys.js.map +1 -0
- package/dist/cli/utils/client.js +174 -0
- package/dist/cli/utils/client.js.map +1 -0
- package/dist/cli/utils/options.js +135 -0
- package/dist/cli/utils/options.js.map +1 -0
- package/dist/node/cli/commands/files/delete.d.ts +40 -0
- package/dist/node/cli/commands/files/delete.d.ts.map +1 -0
- package/dist/node/cli/commands/files/delete.js +31 -0
- package/dist/node/cli/commands/files/delete.js.map +1 -0
- package/dist/node/cli/commands/files/download-url.d.ts +40 -0
- package/dist/node/cli/commands/files/download-url.d.ts.map +1 -0
- package/dist/node/cli/commands/files/download-url.js +31 -0
- package/dist/node/cli/commands/files/download-url.js.map +1 -0
- package/dist/node/cli/commands/files/download.d.ts +49 -0
- package/dist/node/cli/commands/files/download.d.ts.map +1 -0
- package/dist/node/cli/commands/files/download.js +65 -0
- package/dist/node/cli/commands/files/download.js.map +1 -0
- package/dist/node/cli/commands/files/get.d.ts +40 -0
- package/dist/node/cli/commands/files/get.d.ts.map +1 -0
- package/dist/node/cli/commands/files/get.js +31 -0
- package/dist/node/cli/commands/files/get.js.map +1 -0
- package/dist/node/cli/commands/files/list.d.ts +56 -0
- package/dist/node/cli/commands/files/list.d.ts.map +1 -0
- package/dist/node/cli/commands/files/list.js +53 -0
- package/dist/node/cli/commands/files/list.js.map +1 -0
- package/dist/node/cli/commands/files/update.d.ts +56 -0
- package/dist/node/cli/commands/files/update.d.ts.map +1 -0
- package/dist/node/cli/commands/files/update.js +53 -0
- package/dist/node/cli/commands/files/update.js.map +1 -0
- package/dist/node/cli/commands/files/upload.d.ts +73 -0
- package/dist/node/cli/commands/files/upload.d.ts.map +1 -0
- package/dist/node/cli/commands/files/upload.js +87 -0
- package/dist/node/cli/commands/files/upload.js.map +1 -0
- package/dist/node/cli/commands/uploads/abort.d.ts +37 -0
- package/dist/node/cli/commands/uploads/abort.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/abort.js +26 -0
- package/dist/node/cli/commands/uploads/abort.js.map +1 -0
- package/dist/node/cli/commands/uploads/complete.d.ts +41 -0
- package/dist/node/cli/commands/uploads/complete.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/complete.js +45 -0
- package/dist/node/cli/commands/uploads/complete.js.map +1 -0
- package/dist/node/cli/commands/uploads/content.d.ts +46 -0
- package/dist/node/cli/commands/uploads/content.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/content.js +43 -0
- package/dist/node/cli/commands/uploads/content.js.map +1 -0
- package/dist/node/cli/commands/uploads/create.d.ts +72 -0
- package/dist/node/cli/commands/uploads/create.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/create.js +84 -0
- package/dist/node/cli/commands/uploads/create.js.map +1 -0
- package/dist/node/cli/commands/uploads/get.d.ts +37 -0
- package/dist/node/cli/commands/uploads/get.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/get.js +26 -0
- package/dist/node/cli/commands/uploads/get.js.map +1 -0
- package/dist/node/cli/commands/uploads/parts-complete.d.ts +41 -0
- package/dist/node/cli/commands/uploads/parts-complete.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/parts-complete.js +44 -0
- package/dist/node/cli/commands/uploads/parts-complete.js.map +1 -0
- package/dist/node/cli/commands/uploads/parts-list.d.ts +37 -0
- package/dist/node/cli/commands/uploads/parts-list.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/parts-list.js +26 -0
- package/dist/node/cli/commands/uploads/parts-list.js.map +1 -0
- package/dist/node/cli/commands/uploads/parts-urls.d.ts +46 -0
- package/dist/node/cli/commands/uploads/parts-urls.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/parts-urls.js +57 -0
- package/dist/node/cli/commands/uploads/parts-urls.js.map +1 -0
- package/dist/node/cli/commands/uploads/progress.d.ts +45 -0
- package/dist/node/cli/commands/uploads/progress.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/progress.js +40 -0
- package/dist/node/cli/commands/uploads/progress.js.map +1 -0
- package/dist/node/cli/commands/uploads/transfer.d.ts +73 -0
- package/dist/node/cli/commands/uploads/transfer.d.ts.map +1 -0
- package/dist/node/cli/commands/uploads/transfer.js +170 -0
- package/dist/node/cli/commands/uploads/transfer.js.map +1 -0
- package/dist/node/cli/index.d.ts +27 -0
- package/dist/node/cli/index.d.ts.map +1 -0
- package/dist/node/cli/index.js +198 -0
- package/dist/node/cli/index.js.map +1 -0
- package/dist/node/cli/utils/client.js +174 -0
- package/dist/node/cli/utils/client.js.map +1 -0
- package/dist/node/cli/utils/options.js +135 -0
- package/dist/node/cli/utils/options.js.map +1 -0
- package/dist/node/client/clients.d.ts +295 -0
- package/dist/node/client/clients.d.ts.map +1 -0
- package/dist/node/client/clients.js +49 -0
- package/dist/node/client/clients.js.map +1 -0
- package/dist/node/client/helpers.d.ts +51 -0
- package/dist/node/client/helpers.d.ts.map +1 -0
- package/dist/node/client/helpers.js +242 -0
- package/dist/node/client/helpers.js.map +1 -0
- package/dist/node/client/react.d.ts +295 -0
- package/dist/node/client/react.d.ts.map +1 -0
- package/dist/node/client/react.js +11 -0
- package/dist/node/client/react.js.map +1 -0
- package/dist/node/client/solid.d.ts +303 -0
- package/dist/node/client/solid.d.ts.map +1 -0
- package/dist/node/client/solid.js +11 -0
- package/dist/node/client/solid.js.map +1 -0
- package/dist/node/client/svelte.d.ts +295 -0
- package/dist/node/client/svelte.d.ts.map +1 -0
- package/dist/node/client/svelte.js +11 -0
- package/dist/node/client/svelte.js.map +1 -0
- package/dist/node/client/vanilla.d.ts +296 -0
- package/dist/node/client/vanilla.d.ts.map +1 -0
- package/dist/node/client/vanilla.js +11 -0
- package/dist/node/client/vanilla.js.map +1 -0
- package/dist/node/client/vue.d.ts +295 -0
- package/dist/node/client/vue.d.ts.map +1 -0
- package/dist/node/client/vue.js +11 -0
- package/dist/node/client/vue.js.map +1 -0
- package/dist/node/config.d.ts +41 -0
- package/dist/node/config.d.ts.map +1 -0
- package/dist/node/config.js +26 -0
- package/dist/node/config.js.map +1 -0
- package/dist/node/definition.d.ts +829 -0
- package/dist/node/definition.d.ts.map +1 -0
- package/dist/node/definition.js +59 -0
- package/dist/node/definition.js.map +1 -0
- package/dist/node/index.d.ts +1246 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +19 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/keys.d.ts +12 -0
- package/dist/node/keys.d.ts.map +1 -0
- package/dist/node/keys.js +63 -0
- package/dist/node/keys.js.map +1 -0
- package/dist/node/routes/files.js +450 -0
- package/dist/node/routes/files.js.map +1 -0
- package/dist/node/routes/index.d.ts +2023 -0
- package/dist/node/routes/index.d.ts.map +1 -0
- package/dist/node/routes/index.js +9 -0
- package/dist/node/routes/index.js.map +1 -0
- package/dist/node/routes/shared.js +66 -0
- package/dist/node/routes/shared.js.map +1 -0
- package/dist/node/routes/uploads.js +454 -0
- package/dist/node/routes/uploads.js.map +1 -0
- package/dist/node/schema.d.ts +14 -0
- package/dist/node/schema.d.ts.map +1 -0
- package/dist/node/schema.js +30 -0
- package/dist/node/schema.js.map +1 -0
- package/dist/node/services/files.d.ts +20 -0
- package/dist/node/services/files.d.ts.map +1 -0
- package/dist/node/services/files.js +93 -0
- package/dist/node/services/files.js.map +1 -0
- package/dist/node/services/helpers.js +36 -0
- package/dist/node/services/helpers.js.map +1 -0
- package/dist/node/services/index.js +4 -0
- package/dist/node/services/uploads.d.ts +50 -0
- package/dist/node/services/uploads.d.ts.map +1 -0
- package/dist/node/services/uploads.js +358 -0
- package/dist/node/services/uploads.js.map +1 -0
- package/dist/node/storage/fs.d.ts +16 -0
- package/dist/node/storage/fs.d.ts.map +1 -0
- package/dist/node/storage/fs.js +94 -0
- package/dist/node/storage/fs.js.map +1 -0
- package/dist/node/storage/r2.d.ts +103 -0
- package/dist/node/storage/r2.d.ts.map +1 -0
- package/dist/node/storage/r2.js +23 -0
- package/dist/node/storage/r2.js.map +1 -0
- package/dist/node/storage/s3.d.ts +44 -0
- package/dist/node/storage/s3.d.ts.map +1 -0
- package/dist/node/storage/s3.js +398 -0
- package/dist/node/storage/s3.js.map +1 -0
- package/dist/node/storage/types.d.ts +118 -0
- package/dist/node/storage/types.d.ts.map +1 -0
- package/dist/node/types.d.ts +32 -0
- package/dist/node/types.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- 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 @@
|
|
|
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 @@
|
|
|
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"}
|