insforge 1.2.10 → 1.4.8

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 (506) hide show
  1. package/.claude-plugin/marketplace.json +20 -20
  2. package/.dockerignore +60 -60
  3. package/.env.example +83 -77
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -36
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -26
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -7
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +65 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -63
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +46 -44
  15. package/CLAUDE_PLUGIN.md +104 -104
  16. package/CODE_OF_CONDUCT.md +128 -128
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -30
  19. package/GITHUB_OAUTH_SETUP.md +49 -49
  20. package/GOOGLE_OAUTH_SETUP.md +148 -148
  21. package/LICENSE +201 -201
  22. package/README.md +182 -182
  23. package/assets/Dark.svg +23 -23
  24. package/auth/package.json +30 -28
  25. package/auth/src/lib/broadcastService.ts +4 -4
  26. package/auth/src/lib/insforge.ts +8 -0
  27. package/auth/src/main.tsx +2 -4
  28. package/auth/src/pages/SignInPage.tsx +5 -2
  29. package/auth/src/pages/SignUpPage.tsx +5 -2
  30. package/auth/src/pages/VerifyEmailPage.tsx +18 -0
  31. package/auth/tsconfig.json +33 -32
  32. package/auth/tsconfig.node.json +11 -11
  33. package/backend/package.json +82 -75
  34. package/backend/src/api/middlewares/rate-limiters.ts +127 -127
  35. package/backend/src/api/routes/ai/index.routes.ts +475 -468
  36. package/backend/src/api/routes/auth/index.routes.ts +720 -570
  37. package/backend/src/api/routes/auth/oauth.routes.ts +478 -448
  38. package/backend/src/api/routes/database/advance.routes.ts +37 -16
  39. package/backend/src/api/routes/database/index.routes.ts +80 -1
  40. package/backend/src/api/routes/database/records.routes.ts +48 -184
  41. package/backend/src/api/routes/database/rpc.routes.ts +69 -0
  42. package/backend/src/api/routes/database/tables.routes.ts +0 -14
  43. package/backend/src/api/routes/deployments/index.routes.ts +192 -0
  44. package/backend/src/api/routes/docs/index.routes.ts +76 -76
  45. package/backend/src/api/routes/email/index.routes.ts +35 -0
  46. package/backend/src/api/routes/functions/index.routes.ts +21 -15
  47. package/backend/src/api/routes/metadata/index.routes.ts +38 -0
  48. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  49. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  50. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  51. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  52. package/backend/src/api/routes/storage/index.routes.ts +18 -12
  53. package/backend/src/api/routes/usage/index.routes.ts +6 -4
  54. package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
  55. package/backend/src/infra/database/database.manager.ts +14 -11
  56. package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
  57. package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
  58. package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
  59. package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
  60. package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
  61. package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
  62. package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
  63. package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
  64. package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
  65. package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
  66. package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
  67. package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
  68. package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
  69. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
  70. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
  71. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
  72. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
  73. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  74. package/backend/src/infra/database/migrations/018_schema-rework.sql +441 -0
  75. package/backend/src/infra/database/migrations/019_create-deployments-table.sql +36 -0
  76. package/backend/src/infra/database/migrations/020_add-audio-modality.sql +11 -0
  77. package/backend/src/infra/database/migrations/bootstrap/bootstrap-migrations.js +103 -0
  78. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  79. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  80. package/backend/src/infra/security/token.manager.ts +216 -125
  81. package/backend/src/infra/socket/socket.manager.ts +198 -64
  82. package/backend/src/providers/ai/openrouter.provider.ts +24 -12
  83. package/backend/src/providers/database/base.provider.ts +39 -0
  84. package/backend/src/providers/database/cloud.provider.ts +159 -0
  85. package/backend/src/providers/deployments/vercel.provider.ts +516 -0
  86. package/backend/src/providers/email/base.provider.ts +4 -7
  87. package/backend/src/providers/email/cloud.provider.ts +84 -0
  88. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  89. package/backend/src/providers/oauth/index.ts +1 -0
  90. package/backend/src/server.ts +329 -284
  91. package/backend/src/services/ai/ai-config.service.ts +6 -6
  92. package/backend/src/services/ai/ai-model.service.ts +60 -60
  93. package/backend/src/services/ai/ai-usage.service.ts +7 -7
  94. package/backend/src/services/ai/chat-completion.service.ts +415 -220
  95. package/backend/src/services/ai/helpers.ts +64 -64
  96. package/backend/src/services/ai/image-generation.service.ts +3 -3
  97. package/backend/src/services/ai/index.ts +13 -13
  98. package/backend/src/services/auth/auth-config.service.ts +4 -4
  99. package/backend/src/services/auth/auth-otp.service.ts +6 -6
  100. package/backend/src/services/auth/auth.service.ts +148 -74
  101. package/backend/src/services/auth/index.ts +4 -4
  102. package/backend/src/services/auth/oauth-config.service.ts +12 -12
  103. package/backend/src/services/database/database-advance.service.ts +19 -55
  104. package/backend/src/services/database/database-table.service.ts +38 -94
  105. package/backend/src/services/database/database.service.ts +127 -0
  106. package/backend/src/services/database/postgrest-proxy.service.ts +165 -0
  107. package/backend/src/services/deployments/deployment.service.ts +693 -0
  108. package/backend/src/services/email/email.service.ts +5 -7
  109. package/backend/src/services/functions/function.service.ts +61 -41
  110. package/backend/src/services/logs/audit.service.ts +10 -10
  111. package/backend/src/services/realtime/index.ts +3 -0
  112. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  113. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  114. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  115. package/backend/src/services/secrets/secret.service.ts +101 -27
  116. package/backend/src/services/storage/storage.service.ts +30 -30
  117. package/backend/src/services/usage/usage.service.ts +6 -6
  118. package/backend/src/types/ai.ts +8 -0
  119. package/backend/src/types/auth.ts +16 -1
  120. package/backend/src/types/database.ts +2 -0
  121. package/backend/src/types/deployments.ts +33 -0
  122. package/backend/src/types/realtime.ts +18 -0
  123. package/backend/src/types/socket.ts +7 -31
  124. package/backend/src/types/storage.ts +1 -1
  125. package/backend/src/types/webhooks.ts +45 -0
  126. package/backend/src/utils/cookies.ts +34 -0
  127. package/backend/src/utils/environment.ts +0 -14
  128. package/backend/src/utils/s3-config-loader.ts +64 -0
  129. package/backend/src/utils/seed.ts +79 -43
  130. package/backend/src/utils/sql-parser.ts +216 -0
  131. package/backend/src/utils/utils.ts +114 -114
  132. package/backend/src/utils/validations.ts +10 -10
  133. package/backend/tests/README.md +133 -133
  134. package/backend/tests/cleanup-all-test-data.sh +230 -230
  135. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  136. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  137. package/backend/tests/local/test-ai-config.sh +129 -129
  138. package/backend/tests/local/test-ai-usage.sh +80 -80
  139. package/backend/tests/local/test-auth-router.sh +143 -143
  140. package/backend/tests/local/test-database-router.sh +222 -222
  141. package/backend/tests/local/test-e2e.sh +240 -240
  142. package/backend/tests/local/test-fk-errors.sh +96 -96
  143. package/backend/tests/local/test-functions.sh +123 -123
  144. package/backend/tests/local/test-id-field.sh +200 -200
  145. package/backend/tests/local/test-logs.sh +132 -132
  146. package/backend/tests/local/test-public-bucket.sh +264 -264
  147. package/backend/tests/local/test-rpc.sh +141 -0
  148. package/backend/tests/local/test-secrets.sh +249 -249
  149. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  150. package/backend/tests/local/test-traditional-rest.sh +208 -208
  151. package/backend/tests/manual/README.md +50 -50
  152. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  153. package/backend/tests/manual/seed-large-table.sql +100 -100
  154. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  155. package/backend/tests/manual/test-ai-model-plugins.sh +258 -0
  156. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  157. package/backend/tests/manual/test-database-advance.sh +296 -296
  158. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  159. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  160. package/backend/tests/manual/test-rawsql-modes.sh +244 -244
  161. package/backend/tests/manual/test-universal-storage.sh +263 -263
  162. package/backend/tests/manual/test-users.sql +17 -17
  163. package/backend/tests/run-all-tests.sh +139 -139
  164. package/backend/tests/setup.ts +0 -0
  165. package/backend/tests/test-config.sh +338 -338
  166. package/backend/tests/unit/analyze-query.test.ts +697 -0
  167. package/backend/tests/unit/database-advance.test.ts +326 -0
  168. package/backend/tests/unit/helpers.test.ts +2 -2
  169. package/backend/tsconfig.json +22 -22
  170. package/claude-plugin/.claude-plugin/plugin.json +24 -24
  171. package/claude-plugin/README.md +133 -133
  172. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +273 -270
  173. package/docker-compose.prod.yml +204 -200
  174. package/docker-compose.yml +232 -228
  175. package/docker-init/db/db-init.sql +97 -97
  176. package/docker-init/db/jwt.sql +5 -5
  177. package/docker-init/db/postgresql.conf +16 -16
  178. package/docker-init/logs/vector.yml +236 -236
  179. package/docs/README.md +44 -44
  180. package/docs/agent-docs/deployment.md +79 -0
  181. package/docs/agent-docs/real-time.md +269 -0
  182. package/docs/changelog.mdx +212 -67
  183. package/docs/core-concepts/ai/architecture.mdx +350 -372
  184. package/docs/core-concepts/ai/sdk.mdx +238 -213
  185. package/docs/core-concepts/authentication/architecture.mdx +276 -278
  186. package/docs/core-concepts/authentication/sdk.mdx +710 -414
  187. package/docs/core-concepts/authentication/ui-components/customization.mdx +733 -529
  188. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +247 -221
  189. package/docs/core-concepts/authentication/ui-components/react-router.mdx +183 -184
  190. package/docs/core-concepts/authentication/ui-components/react.mdx +136 -129
  191. package/docs/core-concepts/database/architecture.mdx +292 -255
  192. package/docs/core-concepts/database/pgvector.mdx +138 -0
  193. package/docs/core-concepts/database/sdk.mdx +382 -382
  194. package/docs/core-concepts/deployments/architecture.mdx +152 -0
  195. package/docs/core-concepts/email/architecture.mdx +103 -0
  196. package/docs/core-concepts/email/sdk.mdx +53 -0
  197. package/docs/core-concepts/functions/architecture.mdx +105 -105
  198. package/docs/core-concepts/functions/sdk.mdx +183 -184
  199. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  200. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  201. package/docs/core-concepts/storage/architecture.mdx +243 -243
  202. package/docs/core-concepts/storage/sdk.mdx +253 -253
  203. package/docs/deployment/README.md +94 -94
  204. package/docs/deployment/deploy-to-aws-ec2.md +564 -564
  205. package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
  206. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
  207. package/docs/deployment/deploy-to-render.md +441 -441
  208. package/docs/deprecated/insforge-auth-api.md +214 -214
  209. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  210. package/docs/deprecated/insforge-db-api.md +358 -358
  211. package/docs/deprecated/insforge-db-sdk.md +139 -139
  212. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  213. package/docs/deprecated/insforge-debug.md +64 -64
  214. package/docs/deprecated/insforge-instructions.md +123 -123
  215. package/docs/deprecated/insforge-project.md +117 -117
  216. package/docs/deprecated/insforge-storage-api.md +278 -278
  217. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  218. package/docs/docs.json +240 -210
  219. package/docs/examples/framework-guides/nextjs.mdx +131 -131
  220. package/docs/examples/framework-guides/nuxt.mdx +165 -165
  221. package/docs/examples/framework-guides/react.mdx +165 -165
  222. package/docs/examples/framework-guides/svelte.mdx +153 -153
  223. package/docs/examples/framework-guides/vue.mdx +159 -159
  224. package/docs/examples/overview.mdx +67 -67
  225. package/docs/favicon.png +0 -0
  226. package/docs/favicon.svg +4 -19
  227. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  228. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  229. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  230. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  231. package/docs/images/changelog/dec-2025/apple-oauth.mp4 +0 -0
  232. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  233. package/docs/images/changelog/dec-2025/moreModels.png +0 -0
  234. package/docs/images/changelog/dec-2025/multi-region.webp +0 -0
  235. package/docs/images/changelog/dec-2025/postgres-connection.webp +0 -0
  236. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  237. package/docs/images/changelog/dec-2025/realtime2.png +0 -0
  238. package/docs/images/icons/ai.svg +4 -4
  239. package/docs/images/logos/nextjs.svg +4 -4
  240. package/docs/images/logos/nuxt.svg +4 -4
  241. package/docs/images/logos/react.svg +5 -5
  242. package/docs/images/logos/svelte.svg +4 -4
  243. package/docs/images/logos/vue.svg +5 -5
  244. package/docs/images/mcp-setup/CC-MCP-1.mp4 +0 -0
  245. package/docs/images/mcp-setup/CC-MCP-2.mp4 +0 -0
  246. package/docs/images/mcp-setup/Cursor-MCP-1.mp4 +0 -0
  247. package/docs/images/mcp-setup/Cursor-MCP-2.mp4 +0 -0
  248. package/docs/images/mcp-setup/Cursor-MCP-3.mp4 +0 -0
  249. package/docs/images/mcp-setup/claude-code-connect.png +0 -0
  250. package/docs/images/mcp-setup/cline-1.png +0 -0
  251. package/docs/images/mcp-setup/cline-2.png +0 -0
  252. package/docs/images/mcp-setup/cline-3.png +0 -0
  253. package/docs/images/mcp-setup/connect-project.png +0 -0
  254. package/docs/images/mcp-setup/copilot-1.png +0 -0
  255. package/docs/images/mcp-setup/copilot-2.png +0 -0
  256. package/docs/images/mcp-setup/copilot-3.png +0 -0
  257. package/docs/images/mcp-setup/mcp-json-1.png +0 -0
  258. package/docs/images/mcp-setup/mcp-json-2.png +0 -0
  259. package/docs/images/mcp-setup/qoder-1.png +0 -0
  260. package/docs/images/mcp-setup/qoder-2.png +0 -0
  261. package/docs/images/mcp-setup/roocode-1.png +0 -0
  262. package/docs/images/mcp-setup/roocode-2.png +0 -0
  263. package/docs/images/mcp-setup/trae-1.png +0 -0
  264. package/docs/images/mcp-setup/trae-2.png +0 -0
  265. package/docs/images/mcp-setup/trae-3.png +0 -0
  266. package/docs/images/mcp-setup/trae-4.png +0 -0
  267. package/docs/images/mcp-setup/trae-5.png +0 -0
  268. package/docs/images/mcp-setup/windsurf-1.png +0 -0
  269. package/docs/images/mcp-setup/windsurf-2.png +0 -0
  270. package/docs/insforge-instructions-sdk.md +93 -88
  271. package/docs/introduction.mdx +46 -45
  272. package/docs/logo/dark.svg +22 -22
  273. package/docs/logo/light.svg +20 -20
  274. package/docs/mcp-setup.mdx +332 -0
  275. package/docs/oauth-server.mdx +563 -0
  276. package/docs/partnership.mdx +720 -646
  277. package/docs/quickstart.mdx +82 -82
  278. package/docs/showcase.mdx +52 -52
  279. package/docs/snippets/sdk-installation.mdx +21 -21
  280. package/docs/snippets/service-icons.mdx +27 -27
  281. package/docs/vscode-extension.mdx +74 -0
  282. package/eslint.config.js +1 -0
  283. package/examples/oauth/frontend-oauth-example.html +250 -250
  284. package/examples/response-examples.md +443 -443
  285. package/frontend/components.json +17 -17
  286. package/frontend/package.json +69 -69
  287. package/frontend/src/App.tsx +8 -3
  288. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  289. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  290. package/frontend/src/assets/icons/checked.svg +3 -3
  291. package/frontend/src/assets/icons/connected.svg +3 -3
  292. package/frontend/src/assets/icons/error.svg +3 -3
  293. package/frontend/src/assets/icons/loader.svg +9 -9
  294. package/frontend/src/assets/icons/pencil.svg +4 -4
  295. package/frontend/src/assets/icons/refresh.svg +4 -4
  296. package/frontend/src/assets/icons/step_active.svg +3 -3
  297. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  298. package/frontend/src/assets/icons/warning.svg +3 -3
  299. package/frontend/src/assets/logos/antigravity.svg +1 -0
  300. package/frontend/src/assets/logos/apple.svg +3 -3
  301. package/frontend/src/assets/logos/claude_code.svg +3 -3
  302. package/frontend/src/assets/logos/cline.svg +6 -6
  303. package/frontend/src/assets/logos/copilot.svg +10 -0
  304. package/frontend/src/assets/logos/cursor.svg +20 -20
  305. package/frontend/src/assets/logos/deepseek.svg +139 -0
  306. package/frontend/src/assets/logos/discord.svg +8 -8
  307. package/frontend/src/assets/logos/facebook.svg +3 -3
  308. package/frontend/src/assets/logos/gemini.svg +19 -19
  309. package/frontend/src/assets/logos/github.svg +5 -5
  310. package/frontend/src/assets/logos/google.svg +13 -13
  311. package/frontend/src/assets/logos/grok.svg +10 -10
  312. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  313. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  314. package/frontend/src/assets/logos/instagram.svg +1 -1
  315. package/frontend/src/assets/logos/kiro.svg +9 -0
  316. package/frontend/src/assets/logos/linkedin.svg +3 -3
  317. package/frontend/src/assets/logos/openai.svg +10 -10
  318. package/frontend/src/assets/logos/qoder.svg +4 -0
  319. package/frontend/src/assets/logos/qwen.svg +15 -0
  320. package/frontend/src/assets/logos/roo_code.svg +9 -9
  321. package/frontend/src/assets/logos/spotify.svg +16 -16
  322. package/frontend/src/assets/logos/tiktok.svg +5 -5
  323. package/frontend/src/assets/logos/trae.svg +3 -3
  324. package/frontend/src/assets/logos/windsurf.svg +10 -10
  325. package/frontend/src/assets/logos/x.svg +3 -3
  326. package/frontend/src/components/CodeBlock.tsx +2 -2
  327. package/frontend/src/components/ConnectCTA.tsx +3 -2
  328. package/frontend/src/components/datagrid/DataGrid.tsx +90 -62
  329. package/frontend/src/components/datagrid/datagridTypes.tsx +2 -1
  330. package/frontend/src/components/datagrid/index.ts +1 -1
  331. package/frontend/src/components/index.ts +0 -1
  332. package/frontend/src/components/layout/AppHeader.tsx +13 -37
  333. package/frontend/src/components/layout/AppSidebar.tsx +85 -100
  334. package/frontend/src/components/layout/Layout.tsx +34 -32
  335. package/frontend/src/components/layout/PrimaryMenu.tsx +12 -4
  336. package/frontend/src/components/radix/Select.tsx +151 -151
  337. package/frontend/src/features/ai/components/AIConfigCard.tsx +200 -200
  338. package/frontend/src/features/ai/components/AIEmptyState.tsx +23 -23
  339. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +102 -101
  340. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -135
  341. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -51
  342. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -118
  343. package/frontend/src/features/ai/components/index.ts +6 -6
  344. package/frontend/src/features/ai/helpers.ts +147 -141
  345. package/frontend/src/features/ai/{page → pages}/AIPage.tsx +166 -166
  346. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
  347. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
  348. package/frontend/src/features/auth/components/UsersDataGrid.tsx +61 -31
  349. package/frontend/src/features/auth/components/index.ts +5 -5
  350. package/frontend/src/features/auth/helpers.tsx +8 -0
  351. package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +275 -275
  352. package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
  353. package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +1 -1
  354. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +0 -2
  355. package/frontend/src/features/database/components/ForeignKeyCell.tsx +38 -11
  356. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +18 -8
  357. package/frontend/src/features/database/components/LinkRecordModal.tsx +61 -13
  358. package/frontend/src/features/database/components/RecordFormField.tsx +1 -1
  359. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  360. package/frontend/src/features/database/components/TableForm.tsx +0 -4
  361. package/frontend/src/features/database/components/TableSidebar.tsx +0 -3
  362. package/frontend/src/features/database/components/TablesEmptyState.tsx +1 -1
  363. package/frontend/src/features/database/components/TemplatePreview.tsx +1 -2
  364. package/frontend/src/features/database/constants.ts +16 -28
  365. package/frontend/src/features/database/hooks/useCSVImport.ts +3 -2
  366. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  367. package/frontend/src/features/database/hooks/useRawSQL.ts +3 -2
  368. package/frontend/src/features/database/hooks/useTables.ts +30 -28
  369. package/frontend/src/features/database/index.ts +1 -0
  370. package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -42
  371. package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +34 -51
  372. package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +42 -58
  373. package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +2 -2
  374. package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
  375. package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +34 -51
  376. package/frontend/src/features/database/services/advance.service.ts +1 -41
  377. package/frontend/src/features/database/services/database.service.ts +55 -0
  378. package/frontend/src/features/database/services/record.service.ts +4 -20
  379. package/frontend/src/features/database/services/table.service.ts +1 -10
  380. package/frontend/src/features/database/templates/ai-chatbot.ts +6 -6
  381. package/frontend/src/features/database/templates/ecommerce-platform.ts +2 -2
  382. package/frontend/src/features/database/templates/instagram-clone.ts +10 -10
  383. package/frontend/src/features/database/templates/notion-clone.ts +8 -8
  384. package/frontend/src/features/database/templates/reddit-clone.ts +10 -10
  385. package/frontend/src/features/deployments/components/DeploymentRow.tsx +93 -0
  386. package/frontend/src/features/deployments/components/DeploymentsEmptyState.tsx +15 -0
  387. package/frontend/src/features/deployments/hooks/useDeployments.ts +157 -0
  388. package/frontend/src/features/deployments/pages/DeploymentsPage.tsx +318 -0
  389. package/frontend/src/features/deployments/services/deployments.service.ts +63 -0
  390. package/frontend/src/features/functions/components/FunctionRow.tsx +72 -72
  391. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -56
  392. package/frontend/src/features/functions/components/SecretRow.tsx +3 -3
  393. package/frontend/src/features/functions/components/index.ts +5 -5
  394. package/frontend/src/features/functions/hooks/useFunctions.ts +5 -4
  395. package/frontend/src/features/functions/hooks/useSecrets.ts +6 -9
  396. package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
  397. package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +118 -116
  398. package/frontend/src/features/functions/services/function.service.ts +8 -25
  399. package/frontend/src/features/functions/services/secret.service.ts +23 -41
  400. package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +125 -118
  401. package/frontend/src/features/logs/components/LogDetailPanel.tsx +41 -0
  402. package/frontend/src/features/logs/components/LogsDataGrid.tsx +32 -1
  403. package/frontend/src/features/logs/components/index.ts +1 -0
  404. package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
  405. package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +36 -6
  406. package/frontend/src/features/onboard/components/ApiCredentialsSection.tsx +59 -0
  407. package/frontend/src/features/onboard/components/ConnectionStringSection.tsx +180 -0
  408. package/frontend/src/features/onboard/components/McpConnectionSection.tsx +159 -0
  409. package/frontend/src/features/onboard/components/OnboardingController.tsx +68 -0
  410. package/frontend/src/features/onboard/components/OnboardingModal.tsx +121 -267
  411. package/frontend/src/features/onboard/components/ShowPasswordButton.tsx +21 -0
  412. package/frontend/src/features/onboard/components/index.ts +9 -4
  413. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +1 -1
  414. package/frontend/src/features/onboard/components/mcp/QoderDeeplinkGenerator.tsx +36 -0
  415. package/frontend/src/features/onboard/components/mcp/helpers.tsx +123 -98
  416. package/frontend/src/features/onboard/components/mcp/index.ts +4 -3
  417. package/frontend/src/features/onboard/index.ts +17 -13
  418. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  419. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  420. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  421. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  422. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  423. package/frontend/src/features/realtime/index.ts +11 -0
  424. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  425. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  426. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  427. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  428. package/frontend/src/features/settings/pages/SettingsPage.tsx +349 -0
  429. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
  430. package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
  431. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +24 -11
  432. package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +11 -36
  433. package/frontend/src/index.css +249 -249
  434. package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
  435. package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
  436. package/frontend/src/lib/hooks/useMetadata.ts +45 -1
  437. package/frontend/src/lib/hooks/useModal.tsx +2 -0
  438. package/frontend/src/lib/routing/AppRoutes.tsx +103 -84
  439. package/frontend/src/lib/services/metadata.service.ts +20 -3
  440. package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
  441. package/frontend/src/lib/utils/menuItems.ts +223 -183
  442. package/frontend/src/lib/utils/utils.ts +196 -183
  443. package/frontend/tsconfig.json +25 -25
  444. package/frontend/tsconfig.node.json +9 -9
  445. package/functions/deno.json +24 -24
  446. package/functions/server.ts +6 -6
  447. package/functions/worker-template.js +1 -1
  448. package/i18n/README.ar.md +130 -130
  449. package/i18n/README.de.md +130 -130
  450. package/i18n/README.es.md +154 -154
  451. package/i18n/README.fr.md +134 -134
  452. package/i18n/README.hi.md +129 -129
  453. package/i18n/README.ja.md +174 -174
  454. package/i18n/README.ko.md +136 -136
  455. package/i18n/README.pt-BR.md +131 -131
  456. package/i18n/README.ru.md +129 -129
  457. package/i18n/README.zh-CN.md +133 -133
  458. package/openapi/ai.yaml +825 -715
  459. package/openapi/auth.yaml +1324 -1244
  460. package/openapi/email.yaml +158 -0
  461. package/openapi/functions.yaml +475 -475
  462. package/openapi/health.yaml +29 -29
  463. package/openapi/logs.yaml +221 -223
  464. package/openapi/metadata.yaml +175 -177
  465. package/openapi/realtime.yaml +699 -0
  466. package/openapi/records.yaml +381 -381
  467. package/openapi/secrets.yaml +370 -370
  468. package/openapi/storage.yaml +875 -875
  469. package/openapi/tables.yaml +462 -463
  470. package/package.json +97 -97
  471. package/shared-schemas/package.json +31 -31
  472. package/shared-schemas/src/ai-api.schema.ts +251 -143
  473. package/shared-schemas/src/ai.schema.ts +8 -4
  474. package/shared-schemas/src/auth-api.schema.ts +380 -339
  475. package/shared-schemas/src/auth.schema.ts +18 -11
  476. package/shared-schemas/src/cloud-events.schema.ts +26 -0
  477. package/shared-schemas/src/database-api.schema.ts +32 -1
  478. package/shared-schemas/src/database.schema.ts +39 -0
  479. package/shared-schemas/src/deployments-api.schema.ts +55 -0
  480. package/shared-schemas/src/deployments.schema.ts +30 -0
  481. package/shared-schemas/src/docs.schema.ts +32 -0
  482. package/shared-schemas/src/email-api.schema.ts +30 -0
  483. package/shared-schemas/src/functions-api.schema.ts +13 -4
  484. package/shared-schemas/src/functions.schema.ts +1 -1
  485. package/shared-schemas/src/index.ts +22 -14
  486. package/shared-schemas/src/metadata.schema.ts +39 -4
  487. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  488. package/shared-schemas/src/realtime.schema.ts +143 -0
  489. package/shared-schemas/src/secrets-api.schema.ts +44 -0
  490. package/shared-schemas/src/secrets.schema.ts +15 -0
  491. package/shared-schemas/tsconfig.json +21 -21
  492. package/tsconfig.json +7 -7
  493. package/zeabur/README.md +26 -13
  494. package/zeabur/template.yml +1001 -1032
  495. package/.cursor/rules/cursor-rules.mdc +0 -94
  496. package/backend/src/types/profile.ts +0 -55
  497. package/frontend/src/components/ProjectInfoModal.tsx +0 -128
  498. package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
  499. package/test-gemini.sh +0 -35
  500. package/test-usage-admin.sh +0 -57
  501. package/test-usage.sh +0 -50
  502. /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
  503. /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
  504. /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
  505. /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
  506. /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
@@ -1,876 +1,876 @@
1
- openapi: 3.0.3
2
- info:
3
- title: Insforge Storage API
4
- version: 2.0.0
5
- description: Bucket-based storage system similar to S3
6
-
7
- paths:
8
- /api/storage/buckets:
9
- get:
10
- summary: List All Buckets
11
- tags:
12
- - Admin
13
- security:
14
- - apiKey: []
15
- responses:
16
- '200':
17
- description: List of bucket names
18
- content:
19
- application/json:
20
- schema:
21
- type: object
22
- properties:
23
- buckets:
24
- type: array
25
- items:
26
- type: string
27
- example: ["avatars", "documents", "uploads"]
28
- example:
29
- buckets: ["avatars", "documents", "uploads", "public", "private"]
30
-
31
- post:
32
- summary: Create New Bucket
33
- tags:
34
- - Admin
35
- security:
36
- - apiKey: []
37
- requestBody:
38
- required: true
39
- content:
40
- application/json:
41
- schema:
42
- type: object
43
- required:
44
- - bucketName
45
- properties:
46
- bucketName:
47
- type: string
48
- pattern: '^[a-zA-Z0-9_-]+$'
49
- description: Bucket name (alphanumeric, underscore, and hyphen only)
50
- example: avatars
51
- isPublic:
52
- type: boolean
53
- description: Whether the bucket is publicly accessible
54
- default: true
55
- example: true
56
- responses:
57
- '201':
58
- description: Bucket created successfully
59
- content:
60
- application/json:
61
- schema:
62
- type: object
63
- properties:
64
- message:
65
- type: string
66
- example: "Bucket created successfully"
67
- bucketName:
68
- type: string
69
- example: avatars
70
- example:
71
- message: "Bucket created successfully"
72
- bucket: "avatars"
73
- '400':
74
- description: Invalid bucket name
75
- content:
76
- application/json:
77
- schema:
78
- $ref: '#/components/schemas/ErrorResponse'
79
- example:
80
- error: "INVALID_BUCKET_NAME"
81
- message: "Bucket name must contain only alphanumeric characters, underscores, and hyphens"
82
- statusCode: 400
83
- nextActions: "Use a valid bucket name format"
84
- '409':
85
- description: Bucket already exists
86
- content:
87
- application/json:
88
- schema:
89
- $ref: '#/components/schemas/ErrorResponse'
90
- example:
91
- error: "BUCKET_EXISTS"
92
- message: "Bucket 'avatars' already exists"
93
- statusCode: 409
94
- nextActions: "Choose a different bucket name"
95
-
96
- /api/storage/buckets/{bucketName}:
97
- patch:
98
- summary: Update Bucket
99
- tags:
100
- - Admin
101
- security:
102
- - apiKey: []
103
- parameters:
104
- - name: bucketName
105
- in: path
106
- required: true
107
- schema:
108
- type: string
109
- pattern: '^[a-zA-Z0-9_-]+$'
110
- example: avatars
111
- requestBody:
112
- required: true
113
- content:
114
- application/json:
115
- schema:
116
- type: object
117
- required:
118
- - is_public
119
- properties:
120
- isPublic:
121
- type: boolean
122
- description: Whether the bucket should be publicly accessible
123
- example: true
124
- responses:
125
- '200':
126
- description: Bucket visibility updated successfully
127
- content:
128
- application/json:
129
- schema:
130
- type: object
131
- properties:
132
- message:
133
- type: string
134
- example: "Bucket visibility updated"
135
- bucket:
136
- type: string
137
- example: avatars
138
- isPublic:
139
- type: boolean
140
- example: true
141
- example:
142
- message: "Bucket visibility updated"
143
- bucket: "avatars"
144
- isPublic: true
145
- '404':
146
- description: Bucket not found
147
- content:
148
- application/json:
149
- schema:
150
- $ref: '#/components/schemas/ErrorResponse'
151
- example:
152
- error: "BUCKET_NOT_FOUND"
153
- message: "Bucket 'nonexistent' does not exist"
154
- statusCode: 404
155
- nextActions: "Check bucket name and try again"
156
-
157
- /api/storage/buckets/{bucketName}/objects:
158
- get:
159
- summary: List Objects in Bucket
160
- tags:
161
- - Admin
162
- security:
163
- - apiKey: []
164
- parameters:
165
- - name: bucketName
166
- in: path
167
- required: true
168
- schema:
169
- type: string
170
- pattern: '^[a-zA-Z0-9_-]+$'
171
- example: avatars
172
- - name: prefix
173
- in: query
174
- required: false
175
- schema:
176
- type: string
177
- description: Filter objects by key prefix
178
- example: users/
179
- - name: limit
180
- in: query
181
- required: false
182
- schema:
183
- type: integer
184
- minimum: 1
185
- maximum: 1000
186
- default: 100
187
- - name: offset
188
- in: query
189
- required: false
190
- schema:
191
- type: integer
192
- minimum: 0
193
- default: 0
194
- responses:
195
- '200':
196
- description: List of objects in bucket
197
- content:
198
- application/json:
199
- schema:
200
- type: object
201
- properties:
202
- data:
203
- type: array
204
- items:
205
- $ref: '#/components/schemas/StoredFile'
206
- pagination:
207
- type: object
208
- properties:
209
- offset:
210
- type: integer
211
- example: 0
212
- limit:
213
- type: integer
214
- example: 100
215
- total:
216
- type: integer
217
- example: 2
218
- nextActions:
219
- type: string
220
- example: "You can use PUT /api/storage/buckets/:bucketName/objects/:objectKey to upload with a specific key, or POST /api/storage/buckets/:bucketName/objects to upload with auto-generated key, and GET /api/storage/buckets/:bucketName/objects/:objectKey to download an object."
221
- example:
222
- data:
223
- - bucket: "avatars"
224
- key: "users/user123.jpg"
225
- size: 102400
226
- mimeType: "image/jpeg"
227
- uploadedAt: "2024-01-15T10:30:00Z"
228
- url: "/api/storage/buckets/avatars/objects/users/user123.jpg"
229
- - bucket: "avatars"
230
- key: "users/user456.png"
231
- size: 204800
232
- mimeType: "image/png"
233
- uploadedAt: "2024-01-16T11:00:00Z"
234
- url: "/api/storage/buckets/avatars/objects/users/user456.png"
235
- pagination:
236
- offset: 0
237
- limit: 100
238
- total: 2
239
- nextActions: "You can use PUT /api/storage/buckets/:bucketName/objects/:objectKey to upload with a specific key, or POST /api/storage/buckets/:bucketName/objects to upload with auto-generated key, and GET /api/storage/buckets/:bucketName/objects/:objectKey to download an object."
240
-
241
- delete:
242
- summary: Delete Bucket
243
- tags:
244
- - Admin
245
- security:
246
- - apiKey: []
247
- parameters:
248
- - name: bucketName
249
- in: path
250
- required: true
251
- schema:
252
- type: string
253
- pattern: '^[a-zA-Z0-9_-]+$'
254
- example: avatars
255
- responses:
256
- '200':
257
- description: Bucket deleted successfully
258
- content:
259
- application/json:
260
- schema:
261
- type: object
262
- properties:
263
- message:
264
- type: string
265
- example:
266
- message: "Bucket deleted successfully"
267
- '404':
268
- description: Bucket not found
269
- content:
270
- application/json:
271
- schema:
272
- $ref: '#/components/schemas/ErrorResponse'
273
- example:
274
- error: "BUCKET_NOT_FOUND"
275
- message: "Bucket 'nonexistent' does not exist"
276
- statusCode: 404
277
- nextActions: "Check bucket name and try again"
278
-
279
- post:
280
- summary: Upload Object with Auto-Generated Key
281
- tags:
282
- - Client
283
- security:
284
- - apiKey: []
285
- parameters:
286
- - name: bucketName
287
- in: path
288
- required: true
289
- schema:
290
- type: string
291
- pattern: '^[a-zA-Z0-9_-]+$'
292
- example: avatars
293
- requestBody:
294
- required: true
295
- content:
296
- multipart/form-data:
297
- schema:
298
- type: object
299
- properties:
300
- file:
301
- type: string
302
- format: binary
303
- description: File to upload
304
- required:
305
- - file
306
- responses:
307
- '201':
308
- description: Object uploaded successfully with auto-generated key
309
- content:
310
- application/json:
311
- schema:
312
- $ref: '#/components/schemas/StoredFile'
313
- example:
314
- bucket: "avatars"
315
- key: "image-1737546841234-a3f2b1.jpg"
316
- size: 102400
317
- mimeType: "image/jpeg"
318
- uploadedAt: "2024-01-21T10:30:00Z"
319
- url: "/api/storage/buckets/avatars/objects/image-1737546841234-a3f2b1.jpg"
320
- '400':
321
- description: Invalid bucket name or file
322
- content:
323
- application/json:
324
- schema:
325
- $ref: '#/components/schemas/ErrorResponse'
326
- example:
327
- error: "INVALID_FILE"
328
- message: "No file provided in the request"
329
- statusCode: 400
330
- nextActions: "Include a file in the multipart form data"
331
- '404':
332
- description: Bucket not found
333
- content:
334
- application/json:
335
- schema:
336
- $ref: '#/components/schemas/ErrorResponse'
337
- example:
338
- error: "BUCKET_NOT_FOUND"
339
- message: "Bucket 'nonexistent' does not exist"
340
- statusCode: 404
341
- nextActions: "Create the bucket first"
342
-
343
- /api/storage/buckets/{bucketName}/upload-strategy:
344
- post:
345
- summary: Get Upload Strategy (Direct or Presigned URL)
346
- description: Returns upload strategy based on storage backend (S3 returns presigned URLs, local returns direct upload endpoints)
347
- tags:
348
- - Client
349
- security:
350
- - apiKey: []
351
- parameters:
352
- - name: bucketName
353
- in: path
354
- required: true
355
- schema:
356
- type: string
357
- pattern: '^[a-zA-Z0-9_-]+$'
358
- example: avatars
359
- requestBody:
360
- required: true
361
- content:
362
- application/json:
363
- schema:
364
- type: object
365
- required:
366
- - filename
367
- properties:
368
- filename:
369
- type: string
370
- description: Original filename for generating unique key
371
- example: profile-photo.jpg
372
- contentType:
373
- type: string
374
- description: MIME type of the file
375
- example: image/jpeg
376
- size:
377
- type: integer
378
- description: File size in bytes
379
- example: 102400
380
- responses:
381
- '200':
382
- description: Upload strategy details
383
- content:
384
- application/json:
385
- schema:
386
- $ref: '#/components/schemas/UploadStrategy'
387
- examples:
388
- s3:
389
- summary: S3 Backend Response
390
- value:
391
- method: presigned
392
- uploadUrl: https://s3-bucket.amazonaws.com/
393
- fields:
394
- bucket: my-s3-bucket
395
- key: app-key/avatars/profile-photo-1234567890-abc123.jpg
396
- X-Amz-Algorithm: AWS4-HMAC-SHA256
397
- X-Amz-Credential: AKIA.../20250905/us-east-2/s3/aws4_request
398
- X-Amz-Date: 20250905T000000Z
399
- Policy: eyJ...
400
- X-Amz-Signature: abc123...
401
- key: profile-photo-1234567890-abc123.jpg
402
- confirmRequired: true
403
- confirmUrl: /api/storage/buckets/avatars/objects/profile-photo-1234567890-abc123.jpg/confirm-upload
404
- expiresAt: "2025-09-05T01:00:00Z"
405
- local:
406
- summary: Local Storage Response
407
- value:
408
- method: direct
409
- uploadUrl: /api/storage/buckets/avatars/objects/profile-photo-1234567890-abc123.jpg
410
- key: profile-photo-1234567890-abc123.jpg
411
- confirmRequired: false
412
- '404':
413
- description: Bucket not found
414
- content:
415
- application/json:
416
- schema:
417
- $ref: '#/components/schemas/ErrorResponse'
418
-
419
- /api/storage/buckets/{bucketName}/objects/{objectKey}:
420
- put:
421
- summary: Upload Object
422
- tags:
423
- - Client
424
- security:
425
- - apiKey: []
426
- parameters:
427
- - name: bucketName
428
- in: path
429
- required: true
430
- schema:
431
- type: string
432
- pattern: '^[a-zA-Z0-9_-]+$'
433
- example: avatars
434
- - name: objectKey
435
- in: path
436
- required: true
437
- schema:
438
- type: string
439
- example: user123.jpg
440
- description: Object key (can include forward slashes for pseudo-folders)
441
- requestBody:
442
- required: true
443
- content:
444
- multipart/form-data:
445
- schema:
446
- type: object
447
- properties:
448
- file:
449
- type: string
450
- format: binary
451
- description: File to upload
452
- required:
453
- - file
454
- responses:
455
- '201':
456
- description: Object uploaded successfully
457
- content:
458
- application/json:
459
- schema:
460
- $ref: '#/components/schemas/StoredFile'
461
- example:
462
- bucket: "avatars"
463
- key: "user123.jpg"
464
- size: 102400
465
- mimeType: "image/jpeg"
466
- uploadedAt: "2024-01-21T10:30:00Z"
467
- url: "/api/storage/buckets/avatars/objects/user123.jpg"
468
- '400':
469
- description: Invalid bucket name, key, or file
470
- content:
471
- application/json:
472
- schema:
473
- $ref: '#/components/schemas/ErrorResponse'
474
- example:
475
- error: "INVALID_FILE"
476
- message: "No file provided in the request"
477
- statusCode: 400
478
- nextActions: "Include a file in the multipart form data"
479
- '404':
480
- description: Bucket not found
481
- content:
482
- application/json:
483
- schema:
484
- $ref: '#/components/schemas/ErrorResponse'
485
- example:
486
- error: "BUCKET_NOT_FOUND"
487
- message: "Bucket 'nonexistent' does not exist"
488
- statusCode: 404
489
- nextActions: "Create the bucket first"
490
-
491
- get:
492
- summary: Download Object
493
- tags:
494
- - Client
495
- security:
496
- - apiKey: []
497
- parameters:
498
- - name: bucketName
499
- in: path
500
- required: true
501
- schema:
502
- type: string
503
- pattern: '^[a-zA-Z0-9_-]+$'
504
- example: avatars
505
- - name: key
506
- in: path
507
- required: true
508
- schema:
509
- type: string
510
- example: user123.jpg
511
- responses:
512
- '200':
513
- description: File content
514
- content:
515
- '*/*':
516
- schema:
517
- type: string
518
- format: binary
519
- headers:
520
- Content-Type:
521
- schema:
522
- type: string
523
- description: MIME type of the file
524
- Content-Length:
525
- schema:
526
- type: integer
527
- description: Size of the file in bytes
528
- '404':
529
- description: Object not found
530
- content:
531
- application/json:
532
- schema:
533
- $ref: '#/components/schemas/ErrorResponse'
534
- example:
535
- error: "OBJECT_NOT_FOUND"
536
- message: "Object 'user123.jpg' not found in bucket 'avatars'"
537
- statusCode: 404
538
- nextActions: "Check the bucket and key combination"
539
-
540
- delete:
541
- summary: Delete Object
542
- tags:
543
- - Client
544
- security:
545
- - apiKey: []
546
- parameters:
547
- - name: bucketName
548
- in: path
549
- required: true
550
- schema:
551
- type: string
552
- pattern: '^[a-zA-Z0-9_-]+$'
553
- example: avatars
554
- - name: key
555
- in: path
556
- required: true
557
- schema:
558
- type: string
559
- example: user123.jpg
560
- responses:
561
- '200':
562
- description: Object deleted successfully
563
- content:
564
- application/json:
565
- schema:
566
- type: object
567
- properties:
568
- message:
569
- type: string
570
- example:
571
- message: "Object deleted successfully"
572
- '404':
573
- description: Object not found
574
- content:
575
- application/json:
576
- schema:
577
- $ref: '#/components/schemas/ErrorResponse'
578
- example:
579
- error: "OBJECT_NOT_FOUND"
580
- message: "Object 'user123.jpg' not found in bucket 'avatars'"
581
- statusCode: 404
582
- nextActions: "Check the bucket and key combination"
583
-
584
- /api/storage/buckets/{bucketName}/objects/{objectKey}/confirm-upload:
585
- post:
586
- summary: Confirm Presigned Upload
587
- description: Confirms that a file was successfully uploaded to S3 using presigned URL
588
- tags:
589
- - Client
590
- security:
591
- - apiKey: []
592
- parameters:
593
- - name: bucketName
594
- in: path
595
- required: true
596
- schema:
597
- type: string
598
- pattern: '^[a-zA-Z0-9_-]+$'
599
- example: avatars
600
- - name: objectKey
601
- in: path
602
- required: true
603
- schema:
604
- type: string
605
- example: profile-photo-1234567890-abc123.jpg
606
- requestBody:
607
- required: true
608
- content:
609
- application/json:
610
- schema:
611
- type: object
612
- required:
613
- - size
614
- properties:
615
- size:
616
- type: integer
617
- description: File size in bytes
618
- example: 102400
619
- contentType:
620
- type: string
621
- description: MIME type of the file
622
- example: image/jpeg
623
- etag:
624
- type: string
625
- description: S3 ETag of the uploaded object (optional)
626
- example: "9bb58f26192e4ba00f01e2e7b136bbd8"
627
- responses:
628
- '201':
629
- description: Upload confirmed successfully
630
- content:
631
- application/json:
632
- schema:
633
- $ref: '#/components/schemas/StoredFile'
634
- '404':
635
- description: Upload not found
636
- content:
637
- application/json:
638
- schema:
639
- $ref: '#/components/schemas/ErrorResponse'
640
- example:
641
- error: "UPLOAD_NOT_FOUND"
642
- message: "Upload not found for key 'profile-photo.jpg' in bucket 'avatars'"
643
- statusCode: 404
644
- '409':
645
- description: Already confirmed
646
- content:
647
- application/json:
648
- schema:
649
- $ref: '#/components/schemas/ErrorResponse'
650
- example:
651
- error: "ALREADY_CONFIRMED"
652
- message: "File 'profile-photo.jpg' already confirmed in bucket 'avatars'"
653
- statusCode: 409
654
-
655
- /api/storage/buckets/{bucketName}/objects/{objectKey}/download-strategy:
656
- post:
657
- summary: Get Download Strategy (Direct or Presigned URL)
658
- description: |
659
- Returns download strategy based on storage backend and bucket visibility.
660
- - S3 with public bucket: Direct URLs (no presigning, better performance)
661
- - S3 with private bucket: Presigned URLs with expiration
662
- - Local storage: Always direct endpoints
663
- tags:
664
- - Client
665
- security:
666
- - apiKey: []
667
- parameters:
668
- - name: bucketName
669
- in: path
670
- required: true
671
- schema:
672
- type: string
673
- pattern: '^[a-zA-Z0-9_-]+$'
674
- example: avatars
675
- - name: objectKey
676
- in: path
677
- required: true
678
- schema:
679
- type: string
680
- example: profile-photo.jpg
681
- requestBody:
682
- content:
683
- application/json:
684
- schema:
685
- type: object
686
- properties:
687
- expiresIn:
688
- type: integer
689
- description: URL expiration time in seconds (default 3600)
690
- example: 3600
691
- default: 3600
692
- responses:
693
- '200':
694
- description: Download strategy details
695
- content:
696
- application/json:
697
- schema:
698
- $ref: '#/components/schemas/DownloadStrategy'
699
- examples:
700
- s3-public:
701
- summary: S3 Public Bucket Response
702
- value:
703
- method: direct
704
- url: https://s3-bucket.s3.us-east-2.amazonaws.com/app-key/public-assets/logo.png
705
- s3-private:
706
- summary: S3 Private Bucket Response
707
- value:
708
- method: presigned
709
- url: https://s3-bucket.s3.us-east-2.amazonaws.com/app-key/avatars/profile.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
710
- expiresAt: "2025-09-05T01:00:00Z"
711
- local:
712
- summary: Local Storage Response
713
- value:
714
- method: direct
715
- url: /api/storage/buckets/avatars/objects/profile-photo.jpg
716
- '404':
717
- description: Object not found
718
- content:
719
- application/json:
720
- schema:
721
- $ref: '#/components/schemas/ErrorResponse'
722
-
723
- components:
724
- securitySchemes:
725
- apiKey:
726
- type: apiKey
727
- in: header
728
- name: x-api-key
729
-
730
- schemas:
731
- StoredFile:
732
- type: object
733
- properties:
734
- bucket:
735
- type: string
736
- example: avatars
737
- description: Name of the bucket containing the object
738
- key:
739
- type: string
740
- example: user123.jpg
741
- description: Unique key identifying the object within the bucket
742
- size:
743
- type: integer
744
- example: 102400
745
- description: Size of the file in bytes
746
- mimeType:
747
- type: string
748
- example: image/jpeg
749
- description: MIME type of the file
750
- uploadedAt:
751
- type: string
752
- format: date-time
753
- example: "2024-01-15T10:30:00Z"
754
- description: ISO timestamp when the file was uploaded
755
- url:
756
- type: string
757
- example: "/api/storage/buckets/avatars/objects/user123.jpg"
758
- description: URL to download the file
759
- required:
760
- - bucket
761
- - key
762
- - size
763
- - uploadedAt
764
- - url
765
-
766
- Pagination:
767
- type: object
768
- properties:
769
- limit:
770
- type: integer
771
- example: 100
772
- offset:
773
- type: integer
774
- example: 0
775
- total:
776
- type: integer
777
- example: 1
778
- required:
779
- - limit
780
- - offset
781
- - total
782
-
783
- UploadStrategy:
784
- type: object
785
- required:
786
- - method
787
- - uploadUrl
788
- - key
789
- - confirmRequired
790
- properties:
791
- method:
792
- type: string
793
- enum: [presigned, direct]
794
- description: Upload method - presigned for S3, direct for local storage
795
- example: presigned
796
- uploadUrl:
797
- type: string
798
- description: URL to upload the file to
799
- example: https://s3-bucket.amazonaws.com/
800
- fields:
801
- type: object
802
- description: Form fields for presigned POST (S3 only)
803
- additionalProperties: true
804
- example:
805
- bucket: my-s3-bucket
806
- key: app-key/avatars/profile.jpg
807
- X-Amz-Algorithm: AWS4-HMAC-SHA256
808
- key:
809
- type: string
810
- description: Generated unique key for the file
811
- example: profile-photo-1234567890-abc123.jpg
812
- confirmRequired:
813
- type: boolean
814
- description: Whether upload confirmation is required
815
- example: true
816
- confirmUrl:
817
- type: string
818
- description: URL to confirm the upload (if confirmRequired is true)
819
- example: /api/storage/buckets/avatars/objects/profile.jpg/confirm-upload
820
- expiresAt:
821
- type: string
822
- format: date-time
823
- description: Expiration time for presigned URL (S3 only)
824
- example: "2025-09-05T01:00:00Z"
825
-
826
- DownloadStrategy:
827
- type: object
828
- required:
829
- - method
830
- - url
831
- properties:
832
- method:
833
- type: string
834
- enum: [presigned, direct]
835
- description: |
836
- Download method:
837
- - `direct`: Direct URL access (S3 public buckets or local storage)
838
- - `presigned`: Secure URL with signature and expiration (S3 private buckets)
839
- example: direct
840
- url:
841
- type: string
842
- description: URL to download the file from
843
- example: https://s3-bucket.s3.us-east-2.amazonaws.com/app-key/public-assets/logo.png
844
- expiresAt:
845
- type: string
846
- format: date-time
847
- description: Expiration time for presigned URLs (only present when method is 'presigned')
848
- example: "2025-09-05T01:00:00Z"
849
- headers:
850
- type: object
851
- description: Optional headers to include in the download request
852
- additionalProperties: true
853
-
854
- ErrorResponse:
855
- type: object
856
- required:
857
- - error
858
- - message
859
- - statusCode
860
- properties:
861
- error:
862
- type: string
863
- description: Error code for programmatic handling
864
- example: "VALIDATION_ERROR"
865
- message:
866
- type: string
867
- description: Human-readable error message
868
- example: "Invalid request"
869
- statusCode:
870
- type: integer
871
- description: HTTP status code
872
- example: 400
873
- nextActions:
874
- type: string
875
- description: Suggested action to resolve the error
1
+ openapi: 3.0.3
2
+ info:
3
+ title: Insforge Storage API
4
+ version: 2.0.0
5
+ description: Bucket-based storage system similar to S3
6
+
7
+ paths:
8
+ /api/storage/buckets:
9
+ get:
10
+ summary: List All Buckets
11
+ tags:
12
+ - Admin
13
+ security:
14
+ - apiKey: []
15
+ responses:
16
+ '200':
17
+ description: List of bucket names
18
+ content:
19
+ application/json:
20
+ schema:
21
+ type: object
22
+ properties:
23
+ buckets:
24
+ type: array
25
+ items:
26
+ type: string
27
+ example: ["avatars", "documents", "uploads"]
28
+ example:
29
+ buckets: ["avatars", "documents", "uploads", "public", "private"]
30
+
31
+ post:
32
+ summary: Create New Bucket
33
+ tags:
34
+ - Admin
35
+ security:
36
+ - apiKey: []
37
+ requestBody:
38
+ required: true
39
+ content:
40
+ application/json:
41
+ schema:
42
+ type: object
43
+ required:
44
+ - bucketName
45
+ properties:
46
+ bucketName:
47
+ type: string
48
+ pattern: '^[a-zA-Z0-9_-]+$'
49
+ description: Bucket name (alphanumeric, underscore, and hyphen only)
50
+ example: avatars
51
+ isPublic:
52
+ type: boolean
53
+ description: Whether the bucket is publicly accessible
54
+ default: true
55
+ example: true
56
+ responses:
57
+ '201':
58
+ description: Bucket created successfully
59
+ content:
60
+ application/json:
61
+ schema:
62
+ type: object
63
+ properties:
64
+ message:
65
+ type: string
66
+ example: "Bucket created successfully"
67
+ bucketName:
68
+ type: string
69
+ example: avatars
70
+ example:
71
+ message: "Bucket created successfully"
72
+ bucket: "avatars"
73
+ '400':
74
+ description: Invalid bucket name
75
+ content:
76
+ application/json:
77
+ schema:
78
+ $ref: '#/components/schemas/ErrorResponse'
79
+ example:
80
+ error: "INVALID_BUCKET_NAME"
81
+ message: "Bucket name must contain only alphanumeric characters, underscores, and hyphens"
82
+ statusCode: 400
83
+ nextActions: "Use a valid bucket name format"
84
+ '409':
85
+ description: Bucket already exists
86
+ content:
87
+ application/json:
88
+ schema:
89
+ $ref: '#/components/schemas/ErrorResponse'
90
+ example:
91
+ error: "BUCKET_EXISTS"
92
+ message: "Bucket 'avatars' already exists"
93
+ statusCode: 409
94
+ nextActions: "Choose a different bucket name"
95
+
96
+ /api/storage/buckets/{bucketName}:
97
+ patch:
98
+ summary: Update Bucket
99
+ tags:
100
+ - Admin
101
+ security:
102
+ - apiKey: []
103
+ parameters:
104
+ - name: bucketName
105
+ in: path
106
+ required: true
107
+ schema:
108
+ type: string
109
+ pattern: '^[a-zA-Z0-9_-]+$'
110
+ example: avatars
111
+ requestBody:
112
+ required: true
113
+ content:
114
+ application/json:
115
+ schema:
116
+ type: object
117
+ required:
118
+ - is_public
119
+ properties:
120
+ isPublic:
121
+ type: boolean
122
+ description: Whether the bucket should be publicly accessible
123
+ example: true
124
+ responses:
125
+ '200':
126
+ description: Bucket visibility updated successfully
127
+ content:
128
+ application/json:
129
+ schema:
130
+ type: object
131
+ properties:
132
+ message:
133
+ type: string
134
+ example: "Bucket visibility updated"
135
+ bucket:
136
+ type: string
137
+ example: avatars
138
+ isPublic:
139
+ type: boolean
140
+ example: true
141
+ example:
142
+ message: "Bucket visibility updated"
143
+ bucket: "avatars"
144
+ isPublic: true
145
+ '404':
146
+ description: Bucket not found
147
+ content:
148
+ application/json:
149
+ schema:
150
+ $ref: '#/components/schemas/ErrorResponse'
151
+ example:
152
+ error: "BUCKET_NOT_FOUND"
153
+ message: "Bucket 'nonexistent' does not exist"
154
+ statusCode: 404
155
+ nextActions: "Check bucket name and try again"
156
+
157
+ /api/storage/buckets/{bucketName}/objects:
158
+ get:
159
+ summary: List Objects in Bucket
160
+ tags:
161
+ - Admin
162
+ security:
163
+ - apiKey: []
164
+ parameters:
165
+ - name: bucketName
166
+ in: path
167
+ required: true
168
+ schema:
169
+ type: string
170
+ pattern: '^[a-zA-Z0-9_-]+$'
171
+ example: avatars
172
+ - name: prefix
173
+ in: query
174
+ required: false
175
+ schema:
176
+ type: string
177
+ description: Filter objects by key prefix
178
+ example: users/
179
+ - name: limit
180
+ in: query
181
+ required: false
182
+ schema:
183
+ type: integer
184
+ minimum: 1
185
+ maximum: 1000
186
+ default: 100
187
+ - name: offset
188
+ in: query
189
+ required: false
190
+ schema:
191
+ type: integer
192
+ minimum: 0
193
+ default: 0
194
+ responses:
195
+ '200':
196
+ description: List of objects in bucket
197
+ content:
198
+ application/json:
199
+ schema:
200
+ type: object
201
+ properties:
202
+ data:
203
+ type: array
204
+ items:
205
+ $ref: '#/components/schemas/StoredFile'
206
+ pagination:
207
+ type: object
208
+ properties:
209
+ offset:
210
+ type: integer
211
+ example: 0
212
+ limit:
213
+ type: integer
214
+ example: 100
215
+ total:
216
+ type: integer
217
+ example: 2
218
+ nextActions:
219
+ type: string
220
+ example: "You can use PUT /api/storage/buckets/:bucketName/objects/:objectKey to upload with a specific key, or POST /api/storage/buckets/:bucketName/objects to upload with auto-generated key, and GET /api/storage/buckets/:bucketName/objects/:objectKey to download an object."
221
+ example:
222
+ data:
223
+ - bucket: "avatars"
224
+ key: "users/user123.jpg"
225
+ size: 102400
226
+ mimeType: "image/jpeg"
227
+ uploadedAt: "2024-01-15T10:30:00Z"
228
+ url: "/api/storage/buckets/avatars/objects/users/user123.jpg"
229
+ - bucket: "avatars"
230
+ key: "users/user456.png"
231
+ size: 204800
232
+ mimeType: "image/png"
233
+ uploadedAt: "2024-01-16T11:00:00Z"
234
+ url: "/api/storage/buckets/avatars/objects/users/user456.png"
235
+ pagination:
236
+ offset: 0
237
+ limit: 100
238
+ total: 2
239
+ nextActions: "You can use PUT /api/storage/buckets/:bucketName/objects/:objectKey to upload with a specific key, or POST /api/storage/buckets/:bucketName/objects to upload with auto-generated key, and GET /api/storage/buckets/:bucketName/objects/:objectKey to download an object."
240
+
241
+ delete:
242
+ summary: Delete Bucket
243
+ tags:
244
+ - Admin
245
+ security:
246
+ - apiKey: []
247
+ parameters:
248
+ - name: bucketName
249
+ in: path
250
+ required: true
251
+ schema:
252
+ type: string
253
+ pattern: '^[a-zA-Z0-9_-]+$'
254
+ example: avatars
255
+ responses:
256
+ '200':
257
+ description: Bucket deleted successfully
258
+ content:
259
+ application/json:
260
+ schema:
261
+ type: object
262
+ properties:
263
+ message:
264
+ type: string
265
+ example:
266
+ message: "Bucket deleted successfully"
267
+ '404':
268
+ description: Bucket not found
269
+ content:
270
+ application/json:
271
+ schema:
272
+ $ref: '#/components/schemas/ErrorResponse'
273
+ example:
274
+ error: "BUCKET_NOT_FOUND"
275
+ message: "Bucket 'nonexistent' does not exist"
276
+ statusCode: 404
277
+ nextActions: "Check bucket name and try again"
278
+
279
+ post:
280
+ summary: Upload Object with Auto-Generated Key
281
+ tags:
282
+ - Client
283
+ security:
284
+ - apiKey: []
285
+ parameters:
286
+ - name: bucketName
287
+ in: path
288
+ required: true
289
+ schema:
290
+ type: string
291
+ pattern: '^[a-zA-Z0-9_-]+$'
292
+ example: avatars
293
+ requestBody:
294
+ required: true
295
+ content:
296
+ multipart/form-data:
297
+ schema:
298
+ type: object
299
+ properties:
300
+ file:
301
+ type: string
302
+ format: binary
303
+ description: File to upload
304
+ required:
305
+ - file
306
+ responses:
307
+ '201':
308
+ description: Object uploaded successfully with auto-generated key
309
+ content:
310
+ application/json:
311
+ schema:
312
+ $ref: '#/components/schemas/StoredFile'
313
+ example:
314
+ bucket: "avatars"
315
+ key: "image-1737546841234-a3f2b1.jpg"
316
+ size: 102400
317
+ mimeType: "image/jpeg"
318
+ uploadedAt: "2024-01-21T10:30:00Z"
319
+ url: "/api/storage/buckets/avatars/objects/image-1737546841234-a3f2b1.jpg"
320
+ '400':
321
+ description: Invalid bucket name or file
322
+ content:
323
+ application/json:
324
+ schema:
325
+ $ref: '#/components/schemas/ErrorResponse'
326
+ example:
327
+ error: "INVALID_FILE"
328
+ message: "No file provided in the request"
329
+ statusCode: 400
330
+ nextActions: "Include a file in the multipart form data"
331
+ '404':
332
+ description: Bucket not found
333
+ content:
334
+ application/json:
335
+ schema:
336
+ $ref: '#/components/schemas/ErrorResponse'
337
+ example:
338
+ error: "BUCKET_NOT_FOUND"
339
+ message: "Bucket 'nonexistent' does not exist"
340
+ statusCode: 404
341
+ nextActions: "Create the bucket first"
342
+
343
+ /api/storage/buckets/{bucketName}/upload-strategy:
344
+ post:
345
+ summary: Get Upload Strategy (Direct or Presigned URL)
346
+ description: Returns upload strategy based on storage backend (S3 returns presigned URLs, local returns direct upload endpoints)
347
+ tags:
348
+ - Client
349
+ security:
350
+ - apiKey: []
351
+ parameters:
352
+ - name: bucketName
353
+ in: path
354
+ required: true
355
+ schema:
356
+ type: string
357
+ pattern: '^[a-zA-Z0-9_-]+$'
358
+ example: avatars
359
+ requestBody:
360
+ required: true
361
+ content:
362
+ application/json:
363
+ schema:
364
+ type: object
365
+ required:
366
+ - filename
367
+ properties:
368
+ filename:
369
+ type: string
370
+ description: Original filename for generating unique key
371
+ example: profile-photo.jpg
372
+ contentType:
373
+ type: string
374
+ description: MIME type of the file
375
+ example: image/jpeg
376
+ size:
377
+ type: integer
378
+ description: File size in bytes
379
+ example: 102400
380
+ responses:
381
+ '200':
382
+ description: Upload strategy details
383
+ content:
384
+ application/json:
385
+ schema:
386
+ $ref: '#/components/schemas/UploadStrategy'
387
+ examples:
388
+ s3:
389
+ summary: S3 Backend Response
390
+ value:
391
+ method: presigned
392
+ uploadUrl: https://s3-bucket.amazonaws.com/
393
+ fields:
394
+ bucket: my-s3-bucket
395
+ key: app-key/avatars/profile-photo-1234567890-abc123.jpg
396
+ X-Amz-Algorithm: AWS4-HMAC-SHA256
397
+ X-Amz-Credential: AKIA.../20250905/us-east-2/s3/aws4_request
398
+ X-Amz-Date: 20250905T000000Z
399
+ Policy: eyJ...
400
+ X-Amz-Signature: abc123...
401
+ key: profile-photo-1234567890-abc123.jpg
402
+ confirmRequired: true
403
+ confirmUrl: /api/storage/buckets/avatars/objects/profile-photo-1234567890-abc123.jpg/confirm-upload
404
+ expiresAt: "2025-09-05T01:00:00Z"
405
+ local:
406
+ summary: Local Storage Response
407
+ value:
408
+ method: direct
409
+ uploadUrl: /api/storage/buckets/avatars/objects/profile-photo-1234567890-abc123.jpg
410
+ key: profile-photo-1234567890-abc123.jpg
411
+ confirmRequired: false
412
+ '404':
413
+ description: Bucket not found
414
+ content:
415
+ application/json:
416
+ schema:
417
+ $ref: '#/components/schemas/ErrorResponse'
418
+
419
+ /api/storage/buckets/{bucketName}/objects/{objectKey}:
420
+ put:
421
+ summary: Upload Object
422
+ tags:
423
+ - Client
424
+ security:
425
+ - apiKey: []
426
+ parameters:
427
+ - name: bucketName
428
+ in: path
429
+ required: true
430
+ schema:
431
+ type: string
432
+ pattern: '^[a-zA-Z0-9_-]+$'
433
+ example: avatars
434
+ - name: objectKey
435
+ in: path
436
+ required: true
437
+ schema:
438
+ type: string
439
+ example: user123.jpg
440
+ description: Object key (can include forward slashes for pseudo-folders)
441
+ requestBody:
442
+ required: true
443
+ content:
444
+ multipart/form-data:
445
+ schema:
446
+ type: object
447
+ properties:
448
+ file:
449
+ type: string
450
+ format: binary
451
+ description: File to upload
452
+ required:
453
+ - file
454
+ responses:
455
+ '201':
456
+ description: Object uploaded successfully
457
+ content:
458
+ application/json:
459
+ schema:
460
+ $ref: '#/components/schemas/StoredFile'
461
+ example:
462
+ bucket: "avatars"
463
+ key: "user123.jpg"
464
+ size: 102400
465
+ mimeType: "image/jpeg"
466
+ uploadedAt: "2024-01-21T10:30:00Z"
467
+ url: "/api/storage/buckets/avatars/objects/user123.jpg"
468
+ '400':
469
+ description: Invalid bucket name, key, or file
470
+ content:
471
+ application/json:
472
+ schema:
473
+ $ref: '#/components/schemas/ErrorResponse'
474
+ example:
475
+ error: "INVALID_FILE"
476
+ message: "No file provided in the request"
477
+ statusCode: 400
478
+ nextActions: "Include a file in the multipart form data"
479
+ '404':
480
+ description: Bucket not found
481
+ content:
482
+ application/json:
483
+ schema:
484
+ $ref: '#/components/schemas/ErrorResponse'
485
+ example:
486
+ error: "BUCKET_NOT_FOUND"
487
+ message: "Bucket 'nonexistent' does not exist"
488
+ statusCode: 404
489
+ nextActions: "Create the bucket first"
490
+
491
+ get:
492
+ summary: Download Object
493
+ tags:
494
+ - Client
495
+ security:
496
+ - apiKey: []
497
+ parameters:
498
+ - name: bucketName
499
+ in: path
500
+ required: true
501
+ schema:
502
+ type: string
503
+ pattern: '^[a-zA-Z0-9_-]+$'
504
+ example: avatars
505
+ - name: key
506
+ in: path
507
+ required: true
508
+ schema:
509
+ type: string
510
+ example: user123.jpg
511
+ responses:
512
+ '200':
513
+ description: File content
514
+ content:
515
+ '*/*':
516
+ schema:
517
+ type: string
518
+ format: binary
519
+ headers:
520
+ Content-Type:
521
+ schema:
522
+ type: string
523
+ description: MIME type of the file
524
+ Content-Length:
525
+ schema:
526
+ type: integer
527
+ description: Size of the file in bytes
528
+ '404':
529
+ description: Object not found
530
+ content:
531
+ application/json:
532
+ schema:
533
+ $ref: '#/components/schemas/ErrorResponse'
534
+ example:
535
+ error: "OBJECT_NOT_FOUND"
536
+ message: "Object 'user123.jpg' not found in bucket 'avatars'"
537
+ statusCode: 404
538
+ nextActions: "Check the bucket and key combination"
539
+
540
+ delete:
541
+ summary: Delete Object
542
+ tags:
543
+ - Client
544
+ security:
545
+ - apiKey: []
546
+ parameters:
547
+ - name: bucketName
548
+ in: path
549
+ required: true
550
+ schema:
551
+ type: string
552
+ pattern: '^[a-zA-Z0-9_-]+$'
553
+ example: avatars
554
+ - name: key
555
+ in: path
556
+ required: true
557
+ schema:
558
+ type: string
559
+ example: user123.jpg
560
+ responses:
561
+ '200':
562
+ description: Object deleted successfully
563
+ content:
564
+ application/json:
565
+ schema:
566
+ type: object
567
+ properties:
568
+ message:
569
+ type: string
570
+ example:
571
+ message: "Object deleted successfully"
572
+ '404':
573
+ description: Object not found
574
+ content:
575
+ application/json:
576
+ schema:
577
+ $ref: '#/components/schemas/ErrorResponse'
578
+ example:
579
+ error: "OBJECT_NOT_FOUND"
580
+ message: "Object 'user123.jpg' not found in bucket 'avatars'"
581
+ statusCode: 404
582
+ nextActions: "Check the bucket and key combination"
583
+
584
+ /api/storage/buckets/{bucketName}/objects/{objectKey}/confirm-upload:
585
+ post:
586
+ summary: Confirm Presigned Upload
587
+ description: Confirms that a file was successfully uploaded to S3 using presigned URL
588
+ tags:
589
+ - Client
590
+ security:
591
+ - apiKey: []
592
+ parameters:
593
+ - name: bucketName
594
+ in: path
595
+ required: true
596
+ schema:
597
+ type: string
598
+ pattern: '^[a-zA-Z0-9_-]+$'
599
+ example: avatars
600
+ - name: objectKey
601
+ in: path
602
+ required: true
603
+ schema:
604
+ type: string
605
+ example: profile-photo-1234567890-abc123.jpg
606
+ requestBody:
607
+ required: true
608
+ content:
609
+ application/json:
610
+ schema:
611
+ type: object
612
+ required:
613
+ - size
614
+ properties:
615
+ size:
616
+ type: integer
617
+ description: File size in bytes
618
+ example: 102400
619
+ contentType:
620
+ type: string
621
+ description: MIME type of the file
622
+ example: image/jpeg
623
+ etag:
624
+ type: string
625
+ description: S3 ETag of the uploaded object (optional)
626
+ example: "9bb58f26192e4ba00f01e2e7b136bbd8"
627
+ responses:
628
+ '201':
629
+ description: Upload confirmed successfully
630
+ content:
631
+ application/json:
632
+ schema:
633
+ $ref: '#/components/schemas/StoredFile'
634
+ '404':
635
+ description: Upload not found
636
+ content:
637
+ application/json:
638
+ schema:
639
+ $ref: '#/components/schemas/ErrorResponse'
640
+ example:
641
+ error: "UPLOAD_NOT_FOUND"
642
+ message: "Upload not found for key 'profile-photo.jpg' in bucket 'avatars'"
643
+ statusCode: 404
644
+ '409':
645
+ description: Already confirmed
646
+ content:
647
+ application/json:
648
+ schema:
649
+ $ref: '#/components/schemas/ErrorResponse'
650
+ example:
651
+ error: "ALREADY_CONFIRMED"
652
+ message: "File 'profile-photo.jpg' already confirmed in bucket 'avatars'"
653
+ statusCode: 409
654
+
655
+ /api/storage/buckets/{bucketName}/objects/{objectKey}/download-strategy:
656
+ post:
657
+ summary: Get Download Strategy (Direct or Presigned URL)
658
+ description: |
659
+ Returns download strategy based on storage backend and bucket visibility.
660
+ - S3 with public bucket: Direct URLs (no presigning, better performance)
661
+ - S3 with private bucket: Presigned URLs with expiration
662
+ - Local storage: Always direct endpoints
663
+ tags:
664
+ - Client
665
+ security:
666
+ - apiKey: []
667
+ parameters:
668
+ - name: bucketName
669
+ in: path
670
+ required: true
671
+ schema:
672
+ type: string
673
+ pattern: '^[a-zA-Z0-9_-]+$'
674
+ example: avatars
675
+ - name: objectKey
676
+ in: path
677
+ required: true
678
+ schema:
679
+ type: string
680
+ example: profile-photo.jpg
681
+ requestBody:
682
+ content:
683
+ application/json:
684
+ schema:
685
+ type: object
686
+ properties:
687
+ expiresIn:
688
+ type: integer
689
+ description: URL expiration time in seconds (default 3600)
690
+ example: 3600
691
+ default: 3600
692
+ responses:
693
+ '200':
694
+ description: Download strategy details
695
+ content:
696
+ application/json:
697
+ schema:
698
+ $ref: '#/components/schemas/DownloadStrategy'
699
+ examples:
700
+ s3-public:
701
+ summary: S3 Public Bucket Response
702
+ value:
703
+ method: direct
704
+ url: https://s3-bucket.s3.us-east-2.amazonaws.com/app-key/public-assets/logo.png
705
+ s3-private:
706
+ summary: S3 Private Bucket Response
707
+ value:
708
+ method: presigned
709
+ url: https://s3-bucket.s3.us-east-2.amazonaws.com/app-key/avatars/profile.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
710
+ expiresAt: "2025-09-05T01:00:00Z"
711
+ local:
712
+ summary: Local Storage Response
713
+ value:
714
+ method: direct
715
+ url: /api/storage/buckets/avatars/objects/profile-photo.jpg
716
+ '404':
717
+ description: Object not found
718
+ content:
719
+ application/json:
720
+ schema:
721
+ $ref: '#/components/schemas/ErrorResponse'
722
+
723
+ components:
724
+ securitySchemes:
725
+ apiKey:
726
+ type: apiKey
727
+ in: header
728
+ name: x-api-key
729
+
730
+ schemas:
731
+ StoredFile:
732
+ type: object
733
+ properties:
734
+ bucket:
735
+ type: string
736
+ example: avatars
737
+ description: Name of the bucket containing the object
738
+ key:
739
+ type: string
740
+ example: user123.jpg
741
+ description: Unique key identifying the object within the bucket
742
+ size:
743
+ type: integer
744
+ example: 102400
745
+ description: Size of the file in bytes
746
+ mimeType:
747
+ type: string
748
+ example: image/jpeg
749
+ description: MIME type of the file
750
+ uploadedAt:
751
+ type: string
752
+ format: date-time
753
+ example: "2024-01-15T10:30:00Z"
754
+ description: ISO timestamp when the file was uploaded
755
+ url:
756
+ type: string
757
+ example: "/api/storage/buckets/avatars/objects/user123.jpg"
758
+ description: URL to download the file
759
+ required:
760
+ - bucket
761
+ - key
762
+ - size
763
+ - uploadedAt
764
+ - url
765
+
766
+ Pagination:
767
+ type: object
768
+ properties:
769
+ limit:
770
+ type: integer
771
+ example: 100
772
+ offset:
773
+ type: integer
774
+ example: 0
775
+ total:
776
+ type: integer
777
+ example: 1
778
+ required:
779
+ - limit
780
+ - offset
781
+ - total
782
+
783
+ UploadStrategy:
784
+ type: object
785
+ required:
786
+ - method
787
+ - uploadUrl
788
+ - key
789
+ - confirmRequired
790
+ properties:
791
+ method:
792
+ type: string
793
+ enum: [presigned, direct]
794
+ description: Upload method - presigned for S3, direct for local storage
795
+ example: presigned
796
+ uploadUrl:
797
+ type: string
798
+ description: URL to upload the file to
799
+ example: https://s3-bucket.amazonaws.com/
800
+ fields:
801
+ type: object
802
+ description: Form fields for presigned POST (S3 only)
803
+ additionalProperties: true
804
+ example:
805
+ bucket: my-s3-bucket
806
+ key: app-key/avatars/profile.jpg
807
+ X-Amz-Algorithm: AWS4-HMAC-SHA256
808
+ key:
809
+ type: string
810
+ description: Generated unique key for the file
811
+ example: profile-photo-1234567890-abc123.jpg
812
+ confirmRequired:
813
+ type: boolean
814
+ description: Whether upload confirmation is required
815
+ example: true
816
+ confirmUrl:
817
+ type: string
818
+ description: URL to confirm the upload (if confirmRequired is true)
819
+ example: /api/storage/buckets/avatars/objects/profile.jpg/confirm-upload
820
+ expiresAt:
821
+ type: string
822
+ format: date-time
823
+ description: Expiration time for presigned URL (S3 only)
824
+ example: "2025-09-05T01:00:00Z"
825
+
826
+ DownloadStrategy:
827
+ type: object
828
+ required:
829
+ - method
830
+ - url
831
+ properties:
832
+ method:
833
+ type: string
834
+ enum: [presigned, direct]
835
+ description: |
836
+ Download method:
837
+ - `direct`: Direct URL access (S3 public buckets or local storage)
838
+ - `presigned`: Secure URL with signature and expiration (S3 private buckets)
839
+ example: direct
840
+ url:
841
+ type: string
842
+ description: URL to download the file from
843
+ example: https://s3-bucket.s3.us-east-2.amazonaws.com/app-key/public-assets/logo.png
844
+ expiresAt:
845
+ type: string
846
+ format: date-time
847
+ description: Expiration time for presigned URLs (only present when method is 'presigned')
848
+ example: "2025-09-05T01:00:00Z"
849
+ headers:
850
+ type: object
851
+ description: Optional headers to include in the download request
852
+ additionalProperties: true
853
+
854
+ ErrorResponse:
855
+ type: object
856
+ required:
857
+ - error
858
+ - message
859
+ - statusCode
860
+ properties:
861
+ error:
862
+ type: string
863
+ description: Error code for programmatic handling
864
+ example: "VALIDATION_ERROR"
865
+ message:
866
+ type: string
867
+ description: Human-readable error message
868
+ example: "Invalid request"
869
+ statusCode:
870
+ type: integer
871
+ description: HTTP status code
872
+ example: 400
873
+ nextActions:
874
+ type: string
875
+ description: Suggested action to resolve the error
876
876
  example: "Check your request parameters"