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,410 +1,410 @@
1
- #!/bin/bash
2
-
3
- # Bulk Upsert Feature Test Script
4
- # Tests CSV/JSON bulk imports with various edge cases and upsert scenarios
5
-
6
- # Get the directory where this script is located
7
- SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
8
-
9
- # Source the test configuration
10
- source "$SCRIPT_DIR/../test-config.sh"
11
-
12
- echo "๐Ÿงช Testing bulk upsert feature..."
13
- echo "================================"
14
-
15
- # Configuration
16
- # Remove /api if it's already included in TEST_API_BASE
17
- if [[ "$TEST_API_BASE" == */api ]]; then
18
- API_BASE="$TEST_API_BASE"
19
- else
20
- API_BASE="${TEST_API_BASE}/api"
21
- fi
22
- ADMIN_EMAIL="$TEST_ADMIN_EMAIL"
23
- ADMIN_PASSWORD="$TEST_ADMIN_PASSWORD"
24
- AUTH_TOKEN=""
25
-
26
- # Dynamic table name to avoid conflicts
27
- TEST_TABLE="test_bulk_upsert_$(date +%s)"
28
- DATA_DIR="$SCRIPT_DIR/test-data/bulk-upsert"
29
-
30
- # Create test data directory
31
- mkdir -p "$DATA_DIR"
32
-
33
- # Helper function to create test files
34
- create_test_files() {
35
- echo "๐Ÿ“ Creating test data files..."
36
-
37
- # 1. Basic CSV file
38
- cat > "$DATA_DIR/products.csv" << 'EOF'
39
- sku,name,price,quantity,active
40
- PROD-001,Laptop Computer,1299.99,50,true
41
- PROD-002,Wireless Mouse,29.99,200,true
42
- PROD-003,USB-C Cable,19.99,500,false
43
- PROD-004,Monitor Stand,79.99,100,true
44
- PROD-005,Keyboard,89.99,150,true
45
- EOF
46
-
47
- # 2. CSV with special characters
48
- cat > "$DATA_DIR/special-chars.csv" << 'EOF'
49
- sku,name,description,price
50
- SPEC-001,"Product with ""quotes""","Description with ""quoted text""",99.99
51
- SPEC-002,"Product, with comma","Has a comma, in the name",149.99
52
- SPEC-003,"Multi-line
53
- Product","Description
54
- spans multiple
55
- lines",199.99
56
- SPEC-004,"Special & < > chars","Contains & < > $ % characters",49.99
57
- EOF
58
-
59
- # 3. CSV for upsert testing (contains duplicates)
60
- cat > "$DATA_DIR/upsert-test.csv" << 'EOF'
61
- sku,name,price,quantity,active
62
- PROD-001,Updated Laptop,1399.99,45,true
63
- PROD-002,Updated Mouse,34.99,180,false
64
- PROD-006,New Headphones,149.99,75,true
65
- EOF
66
-
67
- # 4. JSON array file
68
- cat > "$DATA_DIR/products.json" << 'EOF'
69
- [
70
- {
71
- "sku": "JSON-001",
72
- "name": "Smart Watch",
73
- "price": 299.99,
74
- "quantity": 30,
75
- "active": true,
76
- "metadata": {
77
- "brand": "TechCo",
78
- "warranty": "2 years"
79
- }
80
- },
81
- {
82
- "sku": "JSON-002",
83
- "name": "Bluetooth Speaker",
84
- "price": 89.99,
85
- "quantity": 100,
86
- "active": true,
87
- "metadata": {
88
- "color": "black",
89
- "waterproof": true
90
- }
91
- },
92
- {
93
- "sku": "JSON-003",
94
- "name": "Phone Case",
95
- "price": 24.99,
96
- "quantity": 250,
97
- "active": false,
98
- "metadata": null
99
- }
100
- ]
101
- EOF
102
-
103
- # 5. Single JSON object
104
- cat > "$DATA_DIR/single-product.json" << 'EOF'
105
- {
106
- "sku": "SINGLE-001",
107
- "name": "Premium Subscription",
108
- "price": 99.99,
109
- "quantity": 999,
110
- "active": true,
111
- "metadata": {
112
- "type": "subscription",
113
- "duration": "annual"
114
- }
115
- }
116
- EOF
117
-
118
- # 6. CSV with NULL values
119
- cat > "$DATA_DIR/null-values.csv" << 'EOF'
120
- sku,name,price,quantity,active
121
- NULL-001,,99.99,,true
122
- NULL-002,Product with nulls,,,false
123
- NULL-003,Only SKU and Name,,,
124
- NULL-004,Complete Product,49.99,25,true
125
- EOF
126
-
127
- # 7. Large CSV file (1000 rows)
128
- echo "sku,name,price,quantity,active" > "$DATA_DIR/large-dataset.csv"
129
- for i in $(seq 1 1000); do
130
- echo "LARGE-$(printf %04d $i),Product $i,$(echo "scale=2; $RANDOM/100" | bc),$(($RANDOM % 1000)),true" >> "$DATA_DIR/large-dataset.csv"
131
- done
132
-
133
- # 8. CSV with Unicode/Emoji
134
- cat > "$DATA_DIR/unicode.csv" << 'EOF'
135
- sku,name,price,quantity,description
136
- UNI-001,Cafรฉ โ˜• Franรงais,15.99,100,Dรฉlicieux cafรฉ
137
- UNI-002,ๅฏฟๅธ ๐Ÿฃ ใ‚ปใƒƒใƒˆ,35.99,50,ๆ–ฐ้ฎฎใช้ญš
138
- UNI-003,ะœะพัะบะฒะฐ ๐Ÿ‡ท๐Ÿ‡บ Souvenir,25.99,75,ะ ัƒััะบะธะน ััƒะฒะตะฝะธั€
139
- UNI-004,๐Ÿš€ Rocket Toy,19.99,200,Fun emoji product ๐ŸŽ‰
140
- EOF
141
-
142
- # 9. Invalid CSV (for error testing)
143
- cat > "$DATA_DIR/invalid.csv" << 'EOF'
144
- sku,name,price
145
- INV-001,Product 1,99.99,Extra Column
146
- INV-002,Missing Price
147
- INV-003
148
- EOF
149
-
150
- # 10. Empty files
151
- touch "$DATA_DIR/empty.csv"
152
- echo "[]" > "$DATA_DIR/empty.json"
153
-
154
- echo "โœ… Test files created"
155
- }
156
-
157
- # Function to login as admin
158
- login_admin() {
159
- echo "๐Ÿ” Logging in as admin..."
160
-
161
- # First check if backend is running
162
- if ! curl -s "$API_BASE/health" > /dev/null 2>&1; then
163
- echo "โŒ Backend server is not running!"
164
- echo " Please start the backend first:"
165
- echo " cd backend && npm run dev"
166
- exit 1
167
- fi
168
-
169
- local response=$(curl -s -X POST "$API_BASE/auth/admin/sessions" \
170
- -H "Content-Type: application/json" \
171
- -d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASSWORD\"}")
172
-
173
- AUTH_TOKEN=$(echo "$response" | grep -o '"accessToken":"[^"]*' | cut -d'"' -f4)
174
-
175
- if [ -z "$AUTH_TOKEN" ]; then
176
- echo "โŒ Failed to login as admin"
177
- echo " Response: $response"
178
- echo ""
179
- echo " Make sure you have the correct admin credentials:"
180
- echo " Email: $ADMIN_EMAIL"
181
- echo " Password: $ADMIN_PASSWORD"
182
- echo ""
183
- echo " You can set these with environment variables:"
184
- echo " TEST_ADMIN_EMAIL=your@email.com TEST_ADMIN_PASSWORD=yourpassword ./test-bulk-upsert.sh"
185
- exit 1
186
- fi
187
-
188
- echo "โœ… Admin login successful"
189
- }
190
-
191
- # Function to create test table
192
- create_test_table() {
193
- echo "๐Ÿ“Š Creating test table: $TEST_TABLE"
194
-
195
- local response=$(curl -s -X POST "$API_BASE/database/advance/rawsql" \
196
- -H "Authorization: Bearer $AUTH_TOKEN" \
197
- -H "Content-Type: application/json" \
198
- -d "{\"query\": \"CREATE TABLE $TEST_TABLE (id SERIAL PRIMARY KEY, sku VARCHAR(50) UNIQUE, name VARCHAR(255), description TEXT, price DECIMAL(10,2), quantity INTEGER, active BOOLEAN, metadata JSONB)\"}")
199
-
200
- if echo "$response" | grep -q "error"; then
201
- echo "โŒ Failed to create table: $response"
202
- exit 1
203
- fi
204
-
205
- echo "โœ… Table created successfully"
206
-
207
- # Register table for cleanup
208
- register_test_table "$TEST_TABLE"
209
- }
210
-
211
- # Function to test bulk upsert
212
- test_bulk_upsert() {
213
- local file_name=$1
214
- local table=$2
215
- local upsert_key=$3
216
- local description=$4
217
- local expect_failure=${5:-false}
218
-
219
- if [ "$expect_failure" != "true" ]; then
220
- echo ""
221
- echo "๐Ÿงช Test: $description"
222
- echo " File: $file_name"
223
- fi
224
-
225
- # Build form data
226
- local curl_cmd="curl -s -X POST \"$API_BASE/database/advance/bulk-upsert\" \
227
- -H \"Authorization: Bearer $AUTH_TOKEN\" \
228
- -F \"file=@$DATA_DIR/$file_name\" \
229
- -F \"table=$table\""
230
-
231
- if [ ! -z "$upsert_key" ]; then
232
- curl_cmd="$curl_cmd -F \"upsertKey=$upsert_key\""
233
- fi
234
-
235
- local response=$(eval $curl_cmd)
236
-
237
- if echo "$response" | grep -q "\"success\":true"; then
238
- local rows=$(echo "$response" | grep -o '"rowsAffected":[0-9]*' | cut -d':' -f2)
239
- local total=$(echo "$response" | grep -o '"totalRecords":[0-9]*' | cut -d':' -f2)
240
- if [ "$expect_failure" != "true" ]; then
241
- echo " โœ… Success: $rows/$total rows inserted"
242
- fi
243
- return 0
244
- else
245
- local error=$(echo "$response" | grep -o '"message":"[^"]*' | cut -d'"' -f4)
246
- if [ "$expect_failure" != "true" ]; then
247
- echo " โš ๏ธ Expected error: $error"
248
- fi
249
- return 1
250
- fi
251
- }
252
-
253
- # Function to verify data
254
- verify_data() {
255
- local expected_count=$1
256
- local description=$2
257
-
258
- echo ""
259
- echo "๐Ÿ” Verifying: $description"
260
-
261
- local response=$(curl -s -X POST "$API_BASE/database/advance/rawsql" \
262
- -H "Authorization: Bearer $AUTH_TOKEN" \
263
- -H "Content-Type: application/json" \
264
- -d "{\"query\": \"SELECT COUNT(*) as count FROM $TEST_TABLE\"}")
265
-
266
- local actual_count=$(echo "$response" | grep -o '"count":"[0-9]*' | cut -d'"' -f4)
267
-
268
- if [ "$actual_count" = "$expected_count" ]; then
269
- echo " โœ… Correct: $actual_count rows in table"
270
- else
271
- echo " โŒ Mismatch: Expected $expected_count, got $actual_count"
272
- return 1
273
- fi
274
- }
275
-
276
- # Function to check specific data
277
- check_data() {
278
- local query=$1
279
- local expected=$2
280
- local description=$3
281
-
282
- echo " ๐Ÿ” $description"
283
-
284
- local response=$(curl -s -X POST "$API_BASE/database/advance/rawsql" \
285
- -H "Authorization: Bearer $AUTH_TOKEN" \
286
- -H "Content-Type: application/json" \
287
- -d "{\"query\": \"$query\"}")
288
-
289
- if echo "$response" | grep -q "$expected"; then
290
- echo " โœ… Found: $expected"
291
- else
292
- echo " โŒ Not found: $expected"
293
- echo " Response: $response"
294
- fi
295
- }
296
-
297
- # Cleanup function
298
- cleanup() {
299
- echo ""
300
- echo "๐Ÿงน Cleaning up..."
301
-
302
- # Drop test table
303
- curl -s -X POST "$API_BASE/database/advance/rawsql" \
304
- -H "Authorization: Bearer $AUTH_TOKEN" \
305
- -H "Content-Type: application/json" \
306
- -d "{\"query\": \"DROP TABLE IF EXISTS $TEST_TABLE CASCADE\"}" > /dev/null
307
-
308
- # Remove test data directory
309
- rm -rf "$DATA_DIR"
310
-
311
- echo "โœ… Cleanup complete"
312
- }
313
-
314
- # Main test execution
315
- main() {
316
- # Setup
317
- create_test_files
318
- login_admin
319
- create_test_table
320
-
321
- echo ""
322
- echo "="
323
- echo "๐Ÿš€ RUNNING BULK UPSERT TESTS"
324
- echo "="
325
-
326
- # Test 1: Basic CSV import
327
- test_bulk_upsert "products.csv" "$TEST_TABLE" "" "Basic CSV Import"
328
- verify_data 5 "5 products imported"
329
-
330
- # Test 2: JSON array import
331
- test_bulk_upsert "products.json" "$TEST_TABLE" "sku" "JSON Array Import (with upsert)"
332
- verify_data 8 "3 new products added"
333
-
334
- # Test 3: Single JSON object
335
- test_bulk_upsert "single-product.json" "$TEST_TABLE" "sku" "Single JSON Object"
336
- verify_data 9 "1 product added"
337
-
338
- # Test 4: CSV with special characters
339
- test_bulk_upsert "special-chars.csv" "$TEST_TABLE" "sku" "Special Characters in CSV"
340
- verify_data 13 "4 products with special chars"
341
-
342
- # Test 5: Upsert test (update existing)
343
- test_bulk_upsert "upsert-test.csv" "$TEST_TABLE" "sku" "Upsert - Update Existing"
344
- verify_data 14 "1 new product, 2 updated"
345
- check_data "SELECT name, price FROM $TEST_TABLE WHERE sku='PROD-001'" "Updated Laptop" "PROD-001 was updated"
346
-
347
- # Test 6: NULL values handling
348
- test_bulk_upsert "null-values.csv" "$TEST_TABLE" "sku" "NULL Values in CSV"
349
- verify_data 18 "4 products with nulls"
350
-
351
- # Test 7: Unicode/Emoji support
352
- test_bulk_upsert "unicode.csv" "$TEST_TABLE" "sku" "Unicode and Emoji Support"
353
- verify_data 22 "4 unicode products"
354
- check_data "SELECT name FROM $TEST_TABLE WHERE sku='UNI-004'" "๐Ÿš€ Rocket Toy" "Emoji preserved"
355
-
356
- # Test 8: Error handling - empty file
357
- echo ""
358
- echo "๐Ÿงช Test: Error Handling - Empty CSV"
359
- echo " File: empty.csv"
360
- if test_bulk_upsert "empty.csv" "$TEST_TABLE" "" "Empty CSV (should fail)" true; then
361
- echo " โŒ ERROR: Empty file was accepted (should have been rejected)"
362
- else
363
- echo " โœ… Correctly rejected empty file (expected behavior)"
364
- fi
365
-
366
- # Test 9: Error handling - invalid CSV
367
- echo ""
368
- echo "๐Ÿงช Test: Error Handling - Invalid CSV"
369
- echo " File: invalid.csv"
370
- if test_bulk_upsert "invalid.csv" "$TEST_TABLE" "" "Invalid CSV (should fail)" true; then
371
- echo " โŒ ERROR: Invalid CSV was accepted (should have been rejected)"
372
- else
373
- echo " โœ… Correctly rejected invalid CSV (expected behavior)"
374
- fi
375
-
376
- # Test 10: Performance test
377
- echo ""
378
- echo "๐Ÿงช Test: Large Dataset Performance"
379
- START_TIME=$(date +%s%N)
380
- test_bulk_upsert "large-dataset.csv" "$TEST_TABLE" "sku" "1000 rows bulk insert"
381
- END_TIME=$(date +%s%N)
382
- ELAPSED=$((($END_TIME - $START_TIME) / 1000000))
383
- echo " โฑ๏ธ Time: ${ELAPSED}ms ($(echo "scale=1; 1000000/$ELAPSED" | bc) rows/sec)"
384
-
385
- echo ""
386
- echo "="
387
- echo "๐Ÿ“Š TEST SUMMARY"
388
- echo "="
389
-
390
- # Final verification
391
- local final_count=$(curl -s -X POST "$API_BASE/database/advance/rawsql" \
392
- -H "Authorization: Bearer $AUTH_TOKEN" \
393
- -H "Content-Type: application/json" \
394
- -d "{\"query\": \"SELECT COUNT(*) as count FROM $TEST_TABLE\"}" | grep -o '"count":"[0-9]*' | cut -d'"' -f4)
395
-
396
- echo "Total records in table: $final_count"
397
- echo ""
398
-
399
- # Cleanup
400
- cleanup
401
-
402
- echo ""
403
- echo "โœ… All bulk upsert tests completed!"
404
- }
405
-
406
- # Trap to ensure cleanup on exit
407
- trap cleanup EXIT
408
-
409
- # Run the tests
1
+ #!/bin/bash
2
+
3
+ # Bulk Upsert Feature Test Script
4
+ # Tests CSV/JSON bulk imports with various edge cases and upsert scenarios
5
+
6
+ # Get the directory where this script is located
7
+ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
8
+
9
+ # Source the test configuration
10
+ source "$SCRIPT_DIR/../test-config.sh"
11
+
12
+ echo "๐Ÿงช Testing bulk upsert feature..."
13
+ echo "================================"
14
+
15
+ # Configuration
16
+ # Remove /api if it's already included in TEST_API_BASE
17
+ if [[ "$TEST_API_BASE" == */api ]]; then
18
+ API_BASE="$TEST_API_BASE"
19
+ else
20
+ API_BASE="${TEST_API_BASE}/api"
21
+ fi
22
+ ADMIN_EMAIL="$TEST_ADMIN_EMAIL"
23
+ ADMIN_PASSWORD="$TEST_ADMIN_PASSWORD"
24
+ AUTH_TOKEN=""
25
+
26
+ # Dynamic table name to avoid conflicts
27
+ TEST_TABLE="test_bulk_upsert_$(date +%s)"
28
+ DATA_DIR="$SCRIPT_DIR/test-data/bulk-upsert"
29
+
30
+ # Create test data directory
31
+ mkdir -p "$DATA_DIR"
32
+
33
+ # Helper function to create test files
34
+ create_test_files() {
35
+ echo "๐Ÿ“ Creating test data files..."
36
+
37
+ # 1. Basic CSV file
38
+ cat > "$DATA_DIR/products.csv" << 'EOF'
39
+ sku,name,price,quantity,active
40
+ PROD-001,Laptop Computer,1299.99,50,true
41
+ PROD-002,Wireless Mouse,29.99,200,true
42
+ PROD-003,USB-C Cable,19.99,500,false
43
+ PROD-004,Monitor Stand,79.99,100,true
44
+ PROD-005,Keyboard,89.99,150,true
45
+ EOF
46
+
47
+ # 2. CSV with special characters
48
+ cat > "$DATA_DIR/special-chars.csv" << 'EOF'
49
+ sku,name,description,price
50
+ SPEC-001,"Product with ""quotes""","Description with ""quoted text""",99.99
51
+ SPEC-002,"Product, with comma","Has a comma, in the name",149.99
52
+ SPEC-003,"Multi-line
53
+ Product","Description
54
+ spans multiple
55
+ lines",199.99
56
+ SPEC-004,"Special & < > chars","Contains & < > $ % characters",49.99
57
+ EOF
58
+
59
+ # 3. CSV for upsert testing (contains duplicates)
60
+ cat > "$DATA_DIR/upsert-test.csv" << 'EOF'
61
+ sku,name,price,quantity,active
62
+ PROD-001,Updated Laptop,1399.99,45,true
63
+ PROD-002,Updated Mouse,34.99,180,false
64
+ PROD-006,New Headphones,149.99,75,true
65
+ EOF
66
+
67
+ # 4. JSON array file
68
+ cat > "$DATA_DIR/products.json" << 'EOF'
69
+ [
70
+ {
71
+ "sku": "JSON-001",
72
+ "name": "Smart Watch",
73
+ "price": 299.99,
74
+ "quantity": 30,
75
+ "active": true,
76
+ "metadata": {
77
+ "brand": "TechCo",
78
+ "warranty": "2 years"
79
+ }
80
+ },
81
+ {
82
+ "sku": "JSON-002",
83
+ "name": "Bluetooth Speaker",
84
+ "price": 89.99,
85
+ "quantity": 100,
86
+ "active": true,
87
+ "metadata": {
88
+ "color": "black",
89
+ "waterproof": true
90
+ }
91
+ },
92
+ {
93
+ "sku": "JSON-003",
94
+ "name": "Phone Case",
95
+ "price": 24.99,
96
+ "quantity": 250,
97
+ "active": false,
98
+ "metadata": null
99
+ }
100
+ ]
101
+ EOF
102
+
103
+ # 5. Single JSON object
104
+ cat > "$DATA_DIR/single-product.json" << 'EOF'
105
+ {
106
+ "sku": "SINGLE-001",
107
+ "name": "Premium Subscription",
108
+ "price": 99.99,
109
+ "quantity": 999,
110
+ "active": true,
111
+ "metadata": {
112
+ "type": "subscription",
113
+ "duration": "annual"
114
+ }
115
+ }
116
+ EOF
117
+
118
+ # 6. CSV with NULL values
119
+ cat > "$DATA_DIR/null-values.csv" << 'EOF'
120
+ sku,name,price,quantity,active
121
+ NULL-001,,99.99,,true
122
+ NULL-002,Product with nulls,,,false
123
+ NULL-003,Only SKU and Name,,,
124
+ NULL-004,Complete Product,49.99,25,true
125
+ EOF
126
+
127
+ # 7. Large CSV file (1000 rows)
128
+ echo "sku,name,price,quantity,active" > "$DATA_DIR/large-dataset.csv"
129
+ for i in $(seq 1 1000); do
130
+ echo "LARGE-$(printf %04d $i),Product $i,$(echo "scale=2; $RANDOM/100" | bc),$(($RANDOM % 1000)),true" >> "$DATA_DIR/large-dataset.csv"
131
+ done
132
+
133
+ # 8. CSV with Unicode/Emoji
134
+ cat > "$DATA_DIR/unicode.csv" << 'EOF'
135
+ sku,name,price,quantity,description
136
+ UNI-001,Cafรฉ โ˜• Franรงais,15.99,100,Dรฉlicieux cafรฉ
137
+ UNI-002,ๅฏฟๅธ ๐Ÿฃ ใ‚ปใƒƒใƒˆ,35.99,50,ๆ–ฐ้ฎฎใช้ญš
138
+ UNI-003,ะœะพัะบะฒะฐ ๐Ÿ‡ท๐Ÿ‡บ Souvenir,25.99,75,ะ ัƒััะบะธะน ััƒะฒะตะฝะธั€
139
+ UNI-004,๐Ÿš€ Rocket Toy,19.99,200,Fun emoji product ๐ŸŽ‰
140
+ EOF
141
+
142
+ # 9. Invalid CSV (for error testing)
143
+ cat > "$DATA_DIR/invalid.csv" << 'EOF'
144
+ sku,name,price
145
+ INV-001,Product 1,99.99,Extra Column
146
+ INV-002,Missing Price
147
+ INV-003
148
+ EOF
149
+
150
+ # 10. Empty files
151
+ touch "$DATA_DIR/empty.csv"
152
+ echo "[]" > "$DATA_DIR/empty.json"
153
+
154
+ echo "โœ… Test files created"
155
+ }
156
+
157
+ # Function to login as admin
158
+ login_admin() {
159
+ echo "๐Ÿ” Logging in as admin..."
160
+
161
+ # First check if backend is running
162
+ if ! curl -s "$API_BASE/health" > /dev/null 2>&1; then
163
+ echo "โŒ Backend server is not running!"
164
+ echo " Please start the backend first:"
165
+ echo " cd backend && npm run dev"
166
+ exit 1
167
+ fi
168
+
169
+ local response=$(curl -s -X POST "$API_BASE/auth/admin/sessions" \
170
+ -H "Content-Type: application/json" \
171
+ -d "{\"email\":\"$ADMIN_EMAIL\",\"password\":\"$ADMIN_PASSWORD\"}")
172
+
173
+ AUTH_TOKEN=$(echo "$response" | grep -o '"accessToken":"[^"]*' | cut -d'"' -f4)
174
+
175
+ if [ -z "$AUTH_TOKEN" ]; then
176
+ echo "โŒ Failed to login as admin"
177
+ echo " Response: $response"
178
+ echo ""
179
+ echo " Make sure you have the correct admin credentials:"
180
+ echo " Email: $ADMIN_EMAIL"
181
+ echo " Password: $ADMIN_PASSWORD"
182
+ echo ""
183
+ echo " You can set these with environment variables:"
184
+ echo " TEST_ADMIN_EMAIL=your@email.com TEST_ADMIN_PASSWORD=yourpassword ./test-bulk-upsert.sh"
185
+ exit 1
186
+ fi
187
+
188
+ echo "โœ… Admin login successful"
189
+ }
190
+
191
+ # Function to create test table
192
+ create_test_table() {
193
+ echo "๐Ÿ“Š Creating test table: $TEST_TABLE"
194
+
195
+ local response=$(curl -s -X POST "$API_BASE/database/advance/rawsql" \
196
+ -H "Authorization: Bearer $AUTH_TOKEN" \
197
+ -H "Content-Type: application/json" \
198
+ -d "{\"query\": \"CREATE TABLE $TEST_TABLE (id SERIAL PRIMARY KEY, sku VARCHAR(50) UNIQUE, name VARCHAR(255), description TEXT, price DECIMAL(10,2), quantity INTEGER, active BOOLEAN, metadata JSONB)\"}")
199
+
200
+ if echo "$response" | grep -q "error"; then
201
+ echo "โŒ Failed to create table: $response"
202
+ exit 1
203
+ fi
204
+
205
+ echo "โœ… Table created successfully"
206
+
207
+ # Register table for cleanup
208
+ register_test_table "$TEST_TABLE"
209
+ }
210
+
211
+ # Function to test bulk upsert
212
+ test_bulk_upsert() {
213
+ local file_name=$1
214
+ local table=$2
215
+ local upsert_key=$3
216
+ local description=$4
217
+ local expect_failure=${5:-false}
218
+
219
+ if [ "$expect_failure" != "true" ]; then
220
+ echo ""
221
+ echo "๐Ÿงช Test: $description"
222
+ echo " File: $file_name"
223
+ fi
224
+
225
+ # Build form data
226
+ local curl_cmd="curl -s -X POST \"$API_BASE/database/advance/bulk-upsert\" \
227
+ -H \"Authorization: Bearer $AUTH_TOKEN\" \
228
+ -F \"file=@$DATA_DIR/$file_name\" \
229
+ -F \"table=$table\""
230
+
231
+ if [ ! -z "$upsert_key" ]; then
232
+ curl_cmd="$curl_cmd -F \"upsertKey=$upsert_key\""
233
+ fi
234
+
235
+ local response=$(eval $curl_cmd)
236
+
237
+ if echo "$response" | grep -q "\"success\":true"; then
238
+ local rows=$(echo "$response" | grep -o '"rowsAffected":[0-9]*' | cut -d':' -f2)
239
+ local total=$(echo "$response" | grep -o '"totalRecords":[0-9]*' | cut -d':' -f2)
240
+ if [ "$expect_failure" != "true" ]; then
241
+ echo " โœ… Success: $rows/$total rows inserted"
242
+ fi
243
+ return 0
244
+ else
245
+ local error=$(echo "$response" | grep -o '"message":"[^"]*' | cut -d'"' -f4)
246
+ if [ "$expect_failure" != "true" ]; then
247
+ echo " โš ๏ธ Expected error: $error"
248
+ fi
249
+ return 1
250
+ fi
251
+ }
252
+
253
+ # Function to verify data
254
+ verify_data() {
255
+ local expected_count=$1
256
+ local description=$2
257
+
258
+ echo ""
259
+ echo "๐Ÿ” Verifying: $description"
260
+
261
+ local response=$(curl -s -X POST "$API_BASE/database/advance/rawsql" \
262
+ -H "Authorization: Bearer $AUTH_TOKEN" \
263
+ -H "Content-Type: application/json" \
264
+ -d "{\"query\": \"SELECT COUNT(*) as count FROM $TEST_TABLE\"}")
265
+
266
+ local actual_count=$(echo "$response" | grep -o '"count":"[0-9]*' | cut -d'"' -f4)
267
+
268
+ if [ "$actual_count" = "$expected_count" ]; then
269
+ echo " โœ… Correct: $actual_count rows in table"
270
+ else
271
+ echo " โŒ Mismatch: Expected $expected_count, got $actual_count"
272
+ return 1
273
+ fi
274
+ }
275
+
276
+ # Function to check specific data
277
+ check_data() {
278
+ local query=$1
279
+ local expected=$2
280
+ local description=$3
281
+
282
+ echo " ๐Ÿ” $description"
283
+
284
+ local response=$(curl -s -X POST "$API_BASE/database/advance/rawsql" \
285
+ -H "Authorization: Bearer $AUTH_TOKEN" \
286
+ -H "Content-Type: application/json" \
287
+ -d "{\"query\": \"$query\"}")
288
+
289
+ if echo "$response" | grep -q "$expected"; then
290
+ echo " โœ… Found: $expected"
291
+ else
292
+ echo " โŒ Not found: $expected"
293
+ echo " Response: $response"
294
+ fi
295
+ }
296
+
297
+ # Cleanup function
298
+ cleanup() {
299
+ echo ""
300
+ echo "๐Ÿงน Cleaning up..."
301
+
302
+ # Drop test table
303
+ curl -s -X POST "$API_BASE/database/advance/rawsql" \
304
+ -H "Authorization: Bearer $AUTH_TOKEN" \
305
+ -H "Content-Type: application/json" \
306
+ -d "{\"query\": \"DROP TABLE IF EXISTS $TEST_TABLE CASCADE\"}" > /dev/null
307
+
308
+ # Remove test data directory
309
+ rm -rf "$DATA_DIR"
310
+
311
+ echo "โœ… Cleanup complete"
312
+ }
313
+
314
+ # Main test execution
315
+ main() {
316
+ # Setup
317
+ create_test_files
318
+ login_admin
319
+ create_test_table
320
+
321
+ echo ""
322
+ echo "="
323
+ echo "๐Ÿš€ RUNNING BULK UPSERT TESTS"
324
+ echo "="
325
+
326
+ # Test 1: Basic CSV import
327
+ test_bulk_upsert "products.csv" "$TEST_TABLE" "" "Basic CSV Import"
328
+ verify_data 5 "5 products imported"
329
+
330
+ # Test 2: JSON array import
331
+ test_bulk_upsert "products.json" "$TEST_TABLE" "sku" "JSON Array Import (with upsert)"
332
+ verify_data 8 "3 new products added"
333
+
334
+ # Test 3: Single JSON object
335
+ test_bulk_upsert "single-product.json" "$TEST_TABLE" "sku" "Single JSON Object"
336
+ verify_data 9 "1 product added"
337
+
338
+ # Test 4: CSV with special characters
339
+ test_bulk_upsert "special-chars.csv" "$TEST_TABLE" "sku" "Special Characters in CSV"
340
+ verify_data 13 "4 products with special chars"
341
+
342
+ # Test 5: Upsert test (update existing)
343
+ test_bulk_upsert "upsert-test.csv" "$TEST_TABLE" "sku" "Upsert - Update Existing"
344
+ verify_data 14 "1 new product, 2 updated"
345
+ check_data "SELECT name, price FROM $TEST_TABLE WHERE sku='PROD-001'" "Updated Laptop" "PROD-001 was updated"
346
+
347
+ # Test 6: NULL values handling
348
+ test_bulk_upsert "null-values.csv" "$TEST_TABLE" "sku" "NULL Values in CSV"
349
+ verify_data 18 "4 products with nulls"
350
+
351
+ # Test 7: Unicode/Emoji support
352
+ test_bulk_upsert "unicode.csv" "$TEST_TABLE" "sku" "Unicode and Emoji Support"
353
+ verify_data 22 "4 unicode products"
354
+ check_data "SELECT name FROM $TEST_TABLE WHERE sku='UNI-004'" "๐Ÿš€ Rocket Toy" "Emoji preserved"
355
+
356
+ # Test 8: Error handling - empty file
357
+ echo ""
358
+ echo "๐Ÿงช Test: Error Handling - Empty CSV"
359
+ echo " File: empty.csv"
360
+ if test_bulk_upsert "empty.csv" "$TEST_TABLE" "" "Empty CSV (should fail)" true; then
361
+ echo " โŒ ERROR: Empty file was accepted (should have been rejected)"
362
+ else
363
+ echo " โœ… Correctly rejected empty file (expected behavior)"
364
+ fi
365
+
366
+ # Test 9: Error handling - invalid CSV
367
+ echo ""
368
+ echo "๐Ÿงช Test: Error Handling - Invalid CSV"
369
+ echo " File: invalid.csv"
370
+ if test_bulk_upsert "invalid.csv" "$TEST_TABLE" "" "Invalid CSV (should fail)" true; then
371
+ echo " โŒ ERROR: Invalid CSV was accepted (should have been rejected)"
372
+ else
373
+ echo " โœ… Correctly rejected invalid CSV (expected behavior)"
374
+ fi
375
+
376
+ # Test 10: Performance test
377
+ echo ""
378
+ echo "๐Ÿงช Test: Large Dataset Performance"
379
+ START_TIME=$(date +%s%N)
380
+ test_bulk_upsert "large-dataset.csv" "$TEST_TABLE" "sku" "1000 rows bulk insert"
381
+ END_TIME=$(date +%s%N)
382
+ ELAPSED=$((($END_TIME - $START_TIME) / 1000000))
383
+ echo " โฑ๏ธ Time: ${ELAPSED}ms ($(echo "scale=1; 1000000/$ELAPSED" | bc) rows/sec)"
384
+
385
+ echo ""
386
+ echo "="
387
+ echo "๐Ÿ“Š TEST SUMMARY"
388
+ echo "="
389
+
390
+ # Final verification
391
+ local final_count=$(curl -s -X POST "$API_BASE/database/advance/rawsql" \
392
+ -H "Authorization: Bearer $AUTH_TOKEN" \
393
+ -H "Content-Type: application/json" \
394
+ -d "{\"query\": \"SELECT COUNT(*) as count FROM $TEST_TABLE\"}" | grep -o '"count":"[0-9]*' | cut -d'"' -f4)
395
+
396
+ echo "Total records in table: $final_count"
397
+ echo ""
398
+
399
+ # Cleanup
400
+ cleanup
401
+
402
+ echo ""
403
+ echo "โœ… All bulk upsert tests completed!"
404
+ }
405
+
406
+ # Trap to ensure cleanup on exit
407
+ trap cleanup EXIT
408
+
409
+ # Run the tests
410
410
  main