insforge 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/.dockerignore +58 -0
  2. package/.env.example +49 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.yml +83 -0
  4. package/.github/ISSUE_TEMPLATE/config.yml +11 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.yml +79 -0
  6. package/.github/copilot-instructions.md +147 -0
  7. package/.github/workflows/build-image.yml +65 -0
  8. package/.github/workflows/ci-premerge-check.yml +24 -0
  9. package/.github/workflows/deploy-aws.yml +130 -0
  10. package/.github/workflows/lint-and-format.yml +33 -0
  11. package/.prettierignore +65 -0
  12. package/.prettierrc +9 -0
  13. package/CHANGELOG.md +3 -0
  14. package/CONTRIBUTING.md +126 -0
  15. package/Dockerfile +27 -0
  16. package/GITHUB_OAUTH_SETUP.md +49 -0
  17. package/GOOGLE_OAUTH_SETUP.md +148 -0
  18. package/LICENSE +201 -0
  19. package/README.md +134 -0
  20. package/assets/Dark.svg +23 -0
  21. package/assets/archDiagram.png +0 -0
  22. package/assets/banner.png +0 -0
  23. package/assets/mcpInstallv2.png +0 -0
  24. package/assets/sampleResponse.png +0 -0
  25. package/assets/signin.png +0 -0
  26. package/assets/userflow.png +0 -0
  27. package/backend/migrations/000_create-base-tables.sql +142 -0
  28. package/backend/migrations/001_create-helper-functions.sql +41 -0
  29. package/backend/migrations/002_rename-auth-tables.sql +30 -0
  30. package/backend/migrations/003_create-users-table.sql +56 -0
  31. package/backend/migrations/004_add-reload-postgrest-func.sql +24 -0
  32. package/backend/migrations/005_enable-project-admin-modify-users.sql +30 -0
  33. package/backend/migrations/006_modify-ai-usage-table.sql +25 -0
  34. package/backend/migrations/007_drop-metadata-table.sql +2 -0
  35. package/backend/migrations/008_add-system-tables.sql +77 -0
  36. package/backend/migrations/009_add-function-secrets.sql +24 -0
  37. package/backend/migrations/010_modify-ai-config-modalities.sql +93 -0
  38. package/backend/migrations/011_refactor-secrets-table.sql +15 -0
  39. package/backend/migrations/012_add-storage-uploaded-by.sql +8 -0
  40. package/backend/package.json +75 -0
  41. package/backend/src/api/middleware/auth.ts +240 -0
  42. package/backend/src/api/middleware/error.ts +231 -0
  43. package/backend/src/api/middleware/upload.ts +59 -0
  44. package/backend/src/api/routes/agent.ts +29 -0
  45. package/backend/src/api/routes/ai.ts +472 -0
  46. package/backend/src/api/routes/auth.oauth.ts +482 -0
  47. package/backend/src/api/routes/auth.ts +386 -0
  48. package/backend/src/api/routes/database.advance.ts +275 -0
  49. package/backend/src/api/routes/database.records.ts +246 -0
  50. package/backend/src/api/routes/database.tables.ts +161 -0
  51. package/backend/src/api/routes/docs.ts +66 -0
  52. package/backend/src/api/routes/functions.ts +183 -0
  53. package/backend/src/api/routes/logs.ts +150 -0
  54. package/backend/src/api/routes/metadata.ts +160 -0
  55. package/backend/src/api/routes/openapi.ts +82 -0
  56. package/backend/src/api/routes/secrets.ts +199 -0
  57. package/backend/src/api/routes/storage.ts +547 -0
  58. package/backend/src/api/routes/usage.ts +96 -0
  59. package/backend/src/core/ai/chat.ts +207 -0
  60. package/backend/src/core/ai/client.ts +242 -0
  61. package/backend/src/core/ai/config.ts +187 -0
  62. package/backend/src/core/ai/image.ts +156 -0
  63. package/backend/src/core/ai/model.ts +117 -0
  64. package/backend/src/core/ai/usage.ts +290 -0
  65. package/backend/src/core/auth/auth.ts +781 -0
  66. package/backend/src/core/auth/oauth.ts +398 -0
  67. package/backend/src/core/database/advance.ts +1074 -0
  68. package/backend/src/core/database/manager.ts +178 -0
  69. package/backend/src/core/database/table.ts +772 -0
  70. package/backend/src/core/documentation/agent.ts +689 -0
  71. package/backend/src/core/documentation/openapi.ts +856 -0
  72. package/backend/src/core/functions/functions.ts +310 -0
  73. package/backend/src/core/logs/analytics.ts +76 -0
  74. package/backend/src/core/logs/audit.ts +255 -0
  75. package/backend/src/core/logs/providers/base.provider.ts +83 -0
  76. package/backend/src/core/logs/providers/cloudwatch.provider.ts +510 -0
  77. package/backend/src/core/logs/providers/localdb.provider.ts +246 -0
  78. package/backend/src/core/secrets/encryption.ts +58 -0
  79. package/backend/src/core/secrets/secrets.ts +410 -0
  80. package/backend/src/core/socket/socket.ts +388 -0
  81. package/backend/src/core/socket/types.ts +79 -0
  82. package/backend/src/core/storage/storage.ts +923 -0
  83. package/backend/src/server.ts +288 -0
  84. package/backend/src/types/ai.ts +46 -0
  85. package/backend/src/types/auth.ts +90 -0
  86. package/backend/src/types/database.ts +136 -0
  87. package/backend/src/types/error-constants.ts +86 -0
  88. package/backend/src/types/logs.ts +47 -0
  89. package/backend/src/types/profile.ts +55 -0
  90. package/backend/src/types/storage.ts +23 -0
  91. package/backend/src/utils/cloud-token.ts +39 -0
  92. package/backend/src/utils/constants.ts +1 -0
  93. package/backend/src/utils/environment.ts +35 -0
  94. package/backend/src/utils/helpers.ts +49 -0
  95. package/backend/src/utils/logger.ts +13 -0
  96. package/backend/src/utils/response.ts +62 -0
  97. package/backend/src/utils/seed.ts +205 -0
  98. package/backend/src/utils/sql-parser.ts +63 -0
  99. package/backend/src/utils/uuid.ts +9 -0
  100. package/backend/src/utils/validations.ts +129 -0
  101. package/backend/tests/README.md +134 -0
  102. package/backend/tests/cleanup-all-test-data.sh +231 -0
  103. package/backend/tests/cloud/test-s3-multitenant.sh +132 -0
  104. package/backend/tests/local/comprehensive-curl-tests.sh +156 -0
  105. package/backend/tests/local/test-auth-router.sh +144 -0
  106. package/backend/tests/local/test-database-router.sh +222 -0
  107. package/backend/tests/local/test-e2e.sh +241 -0
  108. package/backend/tests/local/test-fk-errors.sh +97 -0
  109. package/backend/tests/local/test-id-field.sh +201 -0
  110. package/backend/tests/local/test-public-bucket.sh +265 -0
  111. package/backend/tests/local/test-secrets.sh +248 -0
  112. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -0
  113. package/backend/tests/local/test-traditional-rest.sh +209 -0
  114. package/backend/tests/manual/README.md +51 -0
  115. package/backend/tests/manual/create-large-table-simple.sql +11 -0
  116. package/backend/tests/manual/seed-large-table.sql +101 -0
  117. package/backend/tests/manual/setup-large-table-extras.sql +34 -0
  118. package/backend/tests/manual/test-better-auth.sh +303 -0
  119. package/backend/tests/manual/test-bulk-upsert.sh +410 -0
  120. package/backend/tests/manual/test-database-advance.sh +297 -0
  121. package/backend/tests/manual/test-postgrest-stability.sh +192 -0
  122. package/backend/tests/manual/test-rawsql-export-import.sh +412 -0
  123. package/backend/tests/manual/test-universal-storage.sh +264 -0
  124. package/backend/tests/manual/test-users.sql +18 -0
  125. package/backend/tests/run-all-tests.sh +140 -0
  126. package/backend/tests/setup.ts +22 -0
  127. package/backend/tests/test-config.sh +303 -0
  128. package/backend/tsconfig.json +23 -0
  129. package/backend/tsup.config.ts +18 -0
  130. package/backend/vitest.config.ts +22 -0
  131. package/docker-compose.prod.yml +145 -0
  132. package/docker-compose.yml +167 -0
  133. package/docker-init/db/db-init.sql +125 -0
  134. package/docker-init/db/jwt.sql +5 -0
  135. package/docker-init/db/logs.sql +9 -0
  136. package/docker-init/db/postgresql.conf +17 -0
  137. package/docs/deprecated/insforge-auth-api.md +215 -0
  138. package/docs/deprecated/insforge-auth-sdk.md +100 -0
  139. package/docs/deprecated/insforge-db-api.md +359 -0
  140. package/docs/deprecated/insforge-db-sdk.md +140 -0
  141. package/docs/deprecated/insforge-debug-sdk.md +157 -0
  142. package/docs/deprecated/insforge-debug.md +65 -0
  143. package/docs/deprecated/insforge-instructions.md +124 -0
  144. package/docs/deprecated/insforge-project.md +118 -0
  145. package/docs/deprecated/insforge-storage-api.md +279 -0
  146. package/docs/deprecated/insforge-storage-sdk.md +159 -0
  147. package/docs/insforge-instructions-sdk.md +407 -0
  148. package/eslint.config.js +317 -0
  149. package/examples/oauth/frontend-oauth-example.html +251 -0
  150. package/examples/response-examples.md +444 -0
  151. package/frontend/README.md +112 -0
  152. package/frontend/components.json +17 -0
  153. package/frontend/index.html +13 -0
  154. package/frontend/package.json +63 -0
  155. package/frontend/public/favicon.ico +0 -0
  156. package/frontend/src/App.tsx +106 -0
  157. package/frontend/src/assets/icons/checkbox_checked.svg +6 -0
  158. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -0
  159. package/frontend/src/assets/icons/checked.svg +3 -0
  160. package/frontend/src/assets/icons/error.svg +3 -0
  161. package/frontend/src/assets/icons/pencil.svg +4 -0
  162. package/frontend/src/assets/icons/refresh.svg +4 -0
  163. package/frontend/src/assets/icons/step_active.svg +3 -0
  164. package/frontend/src/assets/icons/step_inactive.svg +11 -0
  165. package/frontend/src/assets/icons/warning.svg +3 -0
  166. package/frontend/src/assets/logos/amazon.svg +1 -0
  167. package/frontend/src/assets/logos/claude_code.svg +3 -0
  168. package/frontend/src/assets/logos/cline.svg +6 -0
  169. package/frontend/src/assets/logos/cursor.svg +20 -0
  170. package/frontend/src/assets/logos/discord.svg +9 -0
  171. package/frontend/src/assets/logos/gemini.svg +19 -0
  172. package/frontend/src/assets/logos/github.svg +5 -0
  173. package/frontend/src/assets/logos/google.svg +13 -0
  174. package/frontend/src/assets/logos/grok.svg +10 -0
  175. package/frontend/src/assets/logos/insforge_dark.svg +15 -0
  176. package/frontend/src/assets/logos/insforge_light.svg +15 -0
  177. package/frontend/src/assets/logos/openai.svg +10 -0
  178. package/frontend/src/assets/logos/roo_code.svg +9 -0
  179. package/frontend/src/assets/logos/trae.svg +3 -0
  180. package/frontend/src/assets/logos/windsurf.svg +10 -0
  181. package/frontend/src/components/ButtonWithLoading.tsx +27 -0
  182. package/frontend/src/components/Checkbox.tsx +61 -0
  183. package/frontend/src/components/CodeBlock.tsx +32 -0
  184. package/frontend/src/components/ConfirmDialog.tsx +96 -0
  185. package/frontend/src/components/CopyButton.tsx +69 -0
  186. package/frontend/src/components/DeleteActionButton.tsx +42 -0
  187. package/frontend/src/components/EmptyState.tsx +41 -0
  188. package/frontend/src/components/ErrorState.tsx +35 -0
  189. package/frontend/src/components/FeatureSidebar.tsx +126 -0
  190. package/frontend/src/components/FeatureSidebarItem.tsx +101 -0
  191. package/frontend/src/components/JsonHighlight.tsx +61 -0
  192. package/frontend/src/components/LoadingState.tsx +16 -0
  193. package/frontend/src/components/PaginationControls.tsx +54 -0
  194. package/frontend/src/components/PromptDialog.tsx +68 -0
  195. package/frontend/src/components/SearchInput.tsx +90 -0
  196. package/frontend/src/components/SelectionClearButton.tsx +26 -0
  197. package/frontend/src/components/Stepper.tsx +139 -0
  198. package/frontend/src/components/ThemeToggle.tsx +58 -0
  199. package/frontend/src/components/TypeBadge.tsx +20 -0
  200. package/frontend/src/components/datagrid/DataGrid.tsx +264 -0
  201. package/frontend/src/components/datagrid/DefaultCellRenderer.tsx +114 -0
  202. package/frontend/src/components/datagrid/IdCell.tsx +44 -0
  203. package/frontend/src/components/datagrid/SortableHeader.tsx +74 -0
  204. package/frontend/src/components/datagrid/cell-editors/BooleanCellEditor.tsx +54 -0
  205. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +483 -0
  206. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +362 -0
  207. package/frontend/src/components/datagrid/cell-editors/TextCellEditor.tsx +38 -0
  208. package/frontend/src/components/datagrid/cell-editors/index.ts +14 -0
  209. package/frontend/src/components/datagrid/cell-editors/types.ts +43 -0
  210. package/frontend/src/components/datagrid/datagridTypes.tsx +72 -0
  211. package/frontend/src/components/datagrid/index.tsx +20 -0
  212. package/frontend/src/components/index.ts +39 -0
  213. package/frontend/src/components/layout/AppHeader.tsx +146 -0
  214. package/frontend/src/components/layout/AppSidebar.tsx +190 -0
  215. package/frontend/src/components/layout/CloudLayout.tsx +95 -0
  216. package/frontend/src/components/layout/Layout.tsx +43 -0
  217. package/frontend/src/components/radix/Alert.tsx +45 -0
  218. package/frontend/src/components/radix/AlertDialog.tsx +115 -0
  219. package/frontend/src/components/radix/Avatar.tsx +45 -0
  220. package/frontend/src/components/radix/Badge.tsx +33 -0
  221. package/frontend/src/components/radix/Button.tsx +50 -0
  222. package/frontend/src/components/radix/Card.tsx +58 -0
  223. package/frontend/src/components/radix/Dialog.tsx +98 -0
  224. package/frontend/src/components/radix/DropdownMenu.tsx +185 -0
  225. package/frontend/src/components/radix/Form.tsx +167 -0
  226. package/frontend/src/components/radix/Input.tsx +22 -0
  227. package/frontend/src/components/radix/Label.tsx +19 -0
  228. package/frontend/src/components/radix/Popover.tsx +29 -0
  229. package/frontend/src/components/radix/ScrollArea.tsx +44 -0
  230. package/frontend/src/components/radix/Select.tsx +151 -0
  231. package/frontend/src/components/radix/Separator.tsx +26 -0
  232. package/frontend/src/components/radix/Sheet.tsx +119 -0
  233. package/frontend/src/components/radix/Skeleton.tsx +7 -0
  234. package/frontend/src/components/radix/Switch.tsx +29 -0
  235. package/frontend/src/components/radix/Tabs.tsx +50 -0
  236. package/frontend/src/components/radix/Textarea.tsx +21 -0
  237. package/frontend/src/components/radix/Tooltip.tsx +28 -0
  238. package/frontend/src/features/ai/components/AIConfigCard.tsx +154 -0
  239. package/frontend/src/features/ai/components/AIConfigDialog.tsx +76 -0
  240. package/frontend/src/features/ai/components/AIConfigForm.tsx +222 -0
  241. package/frontend/src/features/ai/components/AIEmptyState.tsx +18 -0
  242. package/frontend/src/features/ai/components/fields/ModalityField.tsx +87 -0
  243. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +134 -0
  244. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +33 -0
  245. package/frontend/src/features/ai/helpers.ts +155 -0
  246. package/frontend/src/features/ai/hooks/useAIConfigs.ts +221 -0
  247. package/frontend/src/features/ai/hooks/useAIUsage.ts +77 -0
  248. package/frontend/src/features/ai/page/AIPage.tsx +178 -0
  249. package/frontend/src/features/ai/services/ai.service.ts +148 -0
  250. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +106 -0
  251. package/frontend/src/features/auth/components/AuthMethodTab.tsx +238 -0
  252. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +303 -0
  253. package/frontend/src/features/auth/components/OAuthEmptyState.tsx +15 -0
  254. package/frontend/src/features/auth/components/UserFormDialog.tsx +248 -0
  255. package/frontend/src/features/auth/components/UsersDataGrid.tsx +183 -0
  256. package/frontend/src/features/auth/components/UsersTab.tsx +114 -0
  257. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +129 -0
  258. package/frontend/src/features/auth/hooks/useUsers.ts +57 -0
  259. package/frontend/src/features/auth/index.ts +9 -0
  260. package/frontend/src/features/auth/page/AuthenticationPage.tsx +169 -0
  261. package/frontend/src/features/auth/services/auth.service.ts +112 -0
  262. package/frontend/src/features/auth/services/oauth.service.ts +49 -0
  263. package/frontend/src/features/dashboard/page/DashboardPage.tsx +194 -0
  264. package/frontend/src/features/database/components/ColumnTypeSelect.tsx +64 -0
  265. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +282 -0
  266. package/frontend/src/features/database/components/ForeignKeyCell.tsx +187 -0
  267. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +378 -0
  268. package/frontend/src/features/database/components/LinkRecordModal.tsx +288 -0
  269. package/frontend/src/features/database/components/RecordFormDialog.tsx +164 -0
  270. package/frontend/src/features/database/components/RecordFormField.tsx +568 -0
  271. package/frontend/src/features/database/components/TableEmptyState.tsx +21 -0
  272. package/frontend/src/features/database/components/TableForm.tsx +656 -0
  273. package/frontend/src/features/database/components/TableFormColumn.tsx +137 -0
  274. package/frontend/src/features/database/components/TableListSkeleton.tsx +9 -0
  275. package/frontend/src/features/database/components/TableSidebar.tsx +47 -0
  276. package/frontend/src/features/database/constants.ts +26 -0
  277. package/frontend/src/features/database/helpers.ts +125 -0
  278. package/frontend/src/features/database/hooks/UseLinkModal.tsx +78 -0
  279. package/frontend/src/features/database/index.ts +12 -0
  280. package/frontend/src/features/database/page/DatabasePage.tsx +626 -0
  281. package/frontend/src/features/database/schema.ts +25 -0
  282. package/frontend/src/features/database/services/database.service.ts +216 -0
  283. package/frontend/src/features/functions/components/FunctionEmptyState.tsx +15 -0
  284. package/frontend/src/features/functions/components/FunctionRow.tsx +71 -0
  285. package/frontend/src/features/functions/components/FunctionViewer.tsx +46 -0
  286. package/frontend/src/features/functions/components/FunctionsContent.tsx +88 -0
  287. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -0
  288. package/frontend/src/features/functions/components/SecretEmptyState.tsx +23 -0
  289. package/frontend/src/features/functions/components/SecretRow.tsx +68 -0
  290. package/frontend/src/features/functions/components/SecretsContent.tsx +120 -0
  291. package/frontend/src/features/functions/hooks/useFunctions.ts +106 -0
  292. package/frontend/src/features/functions/page/FunctionsPage.tsx +28 -0
  293. package/frontend/src/features/functions/services/functions.service.ts +48 -0
  294. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +87 -0
  295. package/frontend/src/features/login/components/PrivateRoute.tsx +24 -0
  296. package/frontend/src/features/login/page/CloudLoginPage.tsx +93 -0
  297. package/frontend/src/features/login/page/LoginPage.tsx +174 -0
  298. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +313 -0
  299. package/frontend/src/features/logs/components/LogsTable.tsx +199 -0
  300. package/frontend/src/features/logs/hooks/useAuditLogs.ts +39 -0
  301. package/frontend/src/features/logs/index.ts +5 -0
  302. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +530 -0
  303. package/frontend/src/features/logs/page/AuditsPage.tsx +192 -0
  304. package/frontend/src/features/logs/services/log.service.ts +171 -0
  305. package/frontend/src/features/metadata/hooks/useMetadata.ts +53 -0
  306. package/frontend/src/features/metadata/index.ts +0 -0
  307. package/frontend/src/features/metadata/page/MetadataPage.tsx +136 -0
  308. package/frontend/src/features/metadata/services/metadata.service.ts +17 -0
  309. package/frontend/src/features/onboard/components/CompletionCard.tsx +41 -0
  310. package/frontend/src/features/onboard/components/OnboardButton.tsx +84 -0
  311. package/frontend/src/features/onboard/components/StepContent.tsx +91 -0
  312. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +53 -0
  313. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +35 -0
  314. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +144 -0
  315. package/frontend/src/features/onboard/components/mcp/index.ts +4 -0
  316. package/frontend/src/features/onboard/components/mcp/mcp-helper.tsx +98 -0
  317. package/frontend/src/features/onboard/index.ts +3 -0
  318. package/frontend/src/features/onboard/page/OnBoardPage.tsx +104 -0
  319. package/frontend/src/features/onboard/types.ts +8 -0
  320. package/frontend/src/features/secrets/hooks/useSecrets.ts +139 -0
  321. package/frontend/src/features/secrets/services/secrets.service.ts +57 -0
  322. package/frontend/src/features/storage/components/BucketEmptyState.tsx +19 -0
  323. package/frontend/src/features/storage/components/BucketFormDialog.tsx +194 -0
  324. package/frontend/src/features/storage/components/BucketListSkeleton.tsx +17 -0
  325. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +287 -0
  326. package/frontend/src/features/storage/components/StorageDataGrid.tsx +239 -0
  327. package/frontend/src/features/storage/components/StorageManager.tsx +236 -0
  328. package/frontend/src/features/storage/components/StorageSidebar.tsx +44 -0
  329. package/frontend/src/features/storage/components/UploadToast.tsx +46 -0
  330. package/frontend/src/features/storage/index.ts +3 -0
  331. package/frontend/src/features/storage/page/StoragePage.tsx +553 -0
  332. package/frontend/src/features/storage/services/storage.service.ts +144 -0
  333. package/frontend/src/features/visualizer/components/AuthNode.tsx +107 -0
  334. package/frontend/src/features/visualizer/components/BucketNode.tsx +34 -0
  335. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +359 -0
  336. package/frontend/src/features/visualizer/components/TableNode.tsx +152 -0
  337. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +24 -0
  338. package/frontend/src/features/visualizer/components/index.ts +5 -0
  339. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +127 -0
  340. package/frontend/src/index.css +248 -0
  341. package/frontend/src/lib/api/client.ts +163 -0
  342. package/frontend/src/lib/contexts/AuthContext.tsx +157 -0
  343. package/frontend/src/lib/contexts/OnboardStepContext.tsx +68 -0
  344. package/frontend/src/lib/contexts/SocketContext.tsx +303 -0
  345. package/frontend/src/lib/contexts/ThemeContext.tsx +125 -0
  346. package/frontend/src/lib/hooks/useAuth.ts +4 -0
  347. package/frontend/src/lib/hooks/useConfirm.ts +55 -0
  348. package/frontend/src/lib/hooks/useInterval.ts +27 -0
  349. package/frontend/src/lib/hooks/useMediaQuery.ts +59 -0
  350. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +29 -0
  351. package/frontend/src/lib/hooks/usePagination.ts +27 -0
  352. package/frontend/src/lib/hooks/useTimeout.ts +27 -0
  353. package/frontend/src/lib/hooks/useToast.tsx +229 -0
  354. package/frontend/src/lib/utils/constants.ts +38 -0
  355. package/frontend/src/lib/utils/utils.ts +165 -0
  356. package/frontend/src/lib/utils/validation-schemas.ts +126 -0
  357. package/frontend/src/main.tsx +16 -0
  358. package/frontend/src/rdg.css +194 -0
  359. package/frontend/src/vite-env.d.ts +12 -0
  360. package/frontend/tailwind.config.js +97 -0
  361. package/frontend/tsconfig.json +26 -0
  362. package/frontend/tsconfig.node.json +10 -0
  363. package/frontend/vite.config.ts +37 -0
  364. package/frontend/vitest.config.ts +36 -0
  365. package/functions/deno.json +25 -0
  366. package/functions/server.ts +290 -0
  367. package/functions/worker-template.js +126 -0
  368. package/openapi/ai.yaml +689 -0
  369. package/openapi/auth.yaml +563 -0
  370. package/openapi/functions.yaml +476 -0
  371. package/openapi/health.yaml +30 -0
  372. package/openapi/logs.yaml +224 -0
  373. package/openapi/metadata.yaml +178 -0
  374. package/openapi/records.yaml +382 -0
  375. package/openapi/secrets.yaml +371 -0
  376. package/openapi/storage.yaml +876 -0
  377. package/openapi/tables.yaml +464 -0
  378. package/package.json +88 -0
  379. package/shared-schemas/package.json +31 -0
  380. package/shared-schemas/src/ai-api.schema.ts +167 -0
  381. package/shared-schemas/src/ai.schema.ts +54 -0
  382. package/shared-schemas/src/auth-api.schema.ts +193 -0
  383. package/shared-schemas/src/auth.schema.ts +94 -0
  384. package/shared-schemas/src/database-api.schema.ts +259 -0
  385. package/shared-schemas/src/database.schema.ts +69 -0
  386. package/shared-schemas/src/functions-api.schema.ts +25 -0
  387. package/shared-schemas/src/functions.schema.ts +16 -0
  388. package/shared-schemas/src/index.ts +13 -0
  389. package/shared-schemas/src/logs-api.schema.ts +49 -0
  390. package/shared-schemas/src/logs.schema.ts +14 -0
  391. package/shared-schemas/src/metadata.schema.ts +56 -0
  392. package/shared-schemas/src/storage-api.schema.ts +65 -0
  393. package/shared-schemas/src/storage.schema.ts +19 -0
  394. package/shared-schemas/tsconfig.json +21 -0
  395. package/tsconfig.json +8 -0
@@ -0,0 +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
410
+ main
@@ -0,0 +1,297 @@
1
+ #!/bin/bash
2
+
3
+ # Test script for database advance functionality
4
+ # Tests rawSQL, export, and import operations
5
+
6
+ # Configuration
7
+ BASE_URL="http://localhost:7130/api/database/advance"
8
+ TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUuY29tIiwicm9sZSI6InByb2plY3RfYWRtaW4iLCJpYXQiOjE3NTY0MDM2NTUsImV4cCI6MTc1NzAwODQ1NX0.UhLvS5f4vdzsR0bZLmHvQ-MX6WPoPieTZ4H7sxjRYGM"
9
+
10
+ # Colors for output
11
+ RED='\033[0;31m'
12
+ GREEN='\033[0;32m'
13
+ YELLOW='\033[1;33m'
14
+ BLUE='\033[0;34m'
15
+ NC='\033[0m' # No Color
16
+
17
+ echo "========================================="
18
+ echo "Database Advance Operations Test Script"
19
+ echo "========================================="
20
+ echo "Base URL: $BASE_URL"
21
+ echo "Testing rawSQL, export, and import operations..."
22
+ echo "========================================="
23
+ echo ""
24
+
25
+ # Function to test rawSQL endpoint
26
+ test_rawsql() {
27
+ local test_name="$1"
28
+ local request_body="$2"
29
+ local description="$3"
30
+
31
+ echo -e "${BLUE}Test: $test_name${NC}"
32
+ echo -e "${YELLOW}Description: $description${NC}"
33
+ echo "Request body: $request_body"
34
+ echo ""
35
+
36
+ # Make the API request
37
+ RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/rawsql" \
38
+ -H "Content-Type: application/json" \
39
+ -H "Authorization: Bearer $TOKEN" \
40
+ -d "$request_body" 2>&1)
41
+
42
+ # Extract HTTP code and response body
43
+ HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
44
+ RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
45
+
46
+ echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
47
+
48
+ if [ "$HTTP_CODE" = "200" ]; then
49
+ echo -e "${GREEN}✓ Request successful${NC}"
50
+ echo ""
51
+ echo -e "${BLUE}Response:${NC}"
52
+ echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
53
+ else
54
+ echo -e "${RED}✗ Request failed${NC}"
55
+ echo ""
56
+ echo -e "${RED}Response:${NC}"
57
+ echo "$RESPONSE_BODY"
58
+ fi
59
+
60
+ echo ""
61
+ echo "----------------------------------------"
62
+ echo ""
63
+ }
64
+
65
+ # Function to make API request and show results
66
+ test_export() {
67
+ local test_name="$1"
68
+ local request_body="$2"
69
+ local description="$3"
70
+
71
+ echo -e "${BLUE}Test: $test_name${NC}"
72
+ echo -e "${YELLOW}Description: $description${NC}"
73
+ echo "Request body: $request_body"
74
+ echo ""
75
+
76
+ # Make the API request
77
+ RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/export" \
78
+ -H "Content-Type: application/json" \
79
+ -H "Authorization: Bearer $TOKEN" \
80
+ -d "$request_body" 2>&1)
81
+
82
+ # Extract HTTP code and response body
83
+ HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
84
+ RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
85
+
86
+ echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
87
+
88
+ if [ "$HTTP_CODE" = "200" ]; then
89
+ echo -e "${GREEN}✓ Request successful${NC}"
90
+ echo ""
91
+ echo -e "${BLUE}Response:${NC}"
92
+ echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
93
+ else
94
+ echo -e "${RED}✗ Request failed${NC}"
95
+ echo ""
96
+ echo -e "${RED}Response:${NC}"
97
+ echo "$RESPONSE_BODY"
98
+ fi
99
+
100
+ echo ""
101
+ echo "----------------------------------------"
102
+ echo ""
103
+ }
104
+
105
+ # Function to test import endpoint with file upload
106
+ test_import() {
107
+ local test_name="$1"
108
+ local file_path="$2"
109
+ local truncate_option="$3"
110
+ local description="$4"
111
+
112
+ echo -e "${BLUE}Test: $test_name${NC}"
113
+ echo -e "${YELLOW}Description: $description${NC}"
114
+ echo "File: $file_path"
115
+ echo "Truncate: $truncate_option"
116
+ echo ""
117
+
118
+ # Check if file exists
119
+ if [ ! -f "$file_path" ]; then
120
+ echo -e "${RED}✗ File not found: $file_path${NC}"
121
+ echo ""
122
+ echo "----------------------------------------"
123
+ echo ""
124
+ return 1
125
+ fi
126
+
127
+ # Make the API request with file upload
128
+ RESPONSE=$(curl -s -w "\n:HTTP_CODE:%{http_code}" -X POST "$BASE_URL/import" \
129
+ -H "Authorization: Bearer $TOKEN" \
130
+ -F "file=@$file_path" \
131
+ -F "truncate=$truncate_option" 2>&1)
132
+
133
+ # Extract HTTP code and response body
134
+ HTTP_CODE=$(echo "$RESPONSE" | grep ":HTTP_CODE:" | cut -d: -f3)
135
+ RESPONSE_BODY=$(echo "$RESPONSE" | sed '/^:HTTP_CODE:/d')
136
+
137
+ echo -e "${BLUE}HTTP Status: $HTTP_CODE${NC}"
138
+
139
+ if [ "$HTTP_CODE" = "200" ]; then
140
+ echo -e "${GREEN}✓ Request successful${NC}"
141
+ echo ""
142
+ echo -e "${BLUE}Response:${NC}"
143
+ echo "$RESPONSE_BODY" | jq . 2>/dev/null || echo "$RESPONSE_BODY"
144
+ else
145
+ echo -e "${RED}✗ Request failed${NC}"
146
+ echo ""
147
+ echo -e "${RED}Response:${NC}"
148
+ echo "$RESPONSE_BODY"
149
+ fi
150
+
151
+ echo ""
152
+ echo "----------------------------------------"
153
+ echo ""
154
+ }
155
+
156
+ # ===========================================
157
+ # RAW SQL TESTS
158
+ # ===========================================
159
+
160
+ echo -e "${GREEN}=== RAW SQL TESTS ===${NC}"
161
+ echo ""
162
+
163
+ # Test 1: Check if posts table exists
164
+ test_rawsql \
165
+ "Check Posts Table Existence" \
166
+ '{"query": "SELECT tablename FROM pg_tables WHERE schemaname = '\''public'\'' AND tablename = '\''posts'\'';"}' \
167
+ "Verify that the posts table exists before creating index"
168
+
169
+ # Test 2: Check existing indexes on posts table
170
+ test_rawsql \
171
+ "Check Existing Indexes on Posts" \
172
+ '{"query": "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '\''posts'\'';"}' \
173
+ "List all existing indexes on the posts table"
174
+
175
+ # Test 3: Create index on posts.title column
176
+ test_rawsql \
177
+ "Create Title Index on Posts" \
178
+ '{"query": "CREATE INDEX IF NOT EXISTS idx_posts_title ON posts(title);"}' \
179
+ "Create an index on the title column of the posts table for better query performance"
180
+
181
+ # Test 4: Verify the index was created
182
+ test_rawsql \
183
+ "Verify Title Index Creation" \
184
+ '{"query": "SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '\''posts'\'' AND indexname = '\''idx_posts_title'\'';"}' \
185
+ "Confirm that the title index was successfully created"
186
+
187
+ # Test 5: Test a simple SELECT query
188
+ test_rawsql \
189
+ "Simple Select Query" \
190
+ '{"query": "SELECT COUNT(*) as total_posts FROM posts;"}' \
191
+ "Count total number of posts in the table"
192
+
193
+ echo -e "${GREEN}=== EXPORT TESTS ===${NC}"
194
+ echo ""
195
+
196
+ # Test 6: Export users table in SQL format with data
197
+ test_export \
198
+ "Users Table - SQL with Data" \
199
+ '{"tables": ["users"], "format": "sql", "includeData": true}' \
200
+ "Export users table as SQL with both schema and data"
201
+
202
+ # Test 7: Export users table in SQL format without data (schema only)
203
+ test_export \
204
+ "Users Table - SQL Schema Only" \
205
+ '{"tables": ["users"], "format": "sql", "includeData": false}' \
206
+ "Export users table as SQL with schema only, no data"
207
+
208
+ # Test 8: Export users table in JSON format with data
209
+ test_export \
210
+ "Users Table - JSON with Data" \
211
+ '{"tables": ["users"], "format": "json", "includeData": true}' \
212
+ "Export users table as JSON with both schema and data"
213
+
214
+ # Test 9: Export users table in JSON format without data (schema only)
215
+ test_export \
216
+ "Users Table - JSON Schema Only" \
217
+ '{"tables": ["users"], "format": "json", "includeData": false}' \
218
+ "Export users table as JSON with schema only, no data"
219
+
220
+ # Test 10: Export all tables in SQL format (default behavior)
221
+ test_export \
222
+ "All Tables - SQL Format" \
223
+ '{"format": "sql"}' \
224
+ "Export all tables as SQL with default settings"
225
+
226
+ # Test 11: Test with invalid table name
227
+ test_export \
228
+ "Invalid Table Name" \
229
+ '{"tables": ["nonexistent_table"], "format": "sql"}' \
230
+ "Test error handling with non-existent table"
231
+
232
+ # Test 12: Test with invalid format
233
+ test_export \
234
+ "Invalid Format" \
235
+ '{"tables": ["users"], "format": "xml"}' \
236
+ "Test validation with invalid format"
237
+
238
+ # Test 12.5: Export posts table in SQL format with data
239
+ test_export \
240
+ "All Tables - SQL with Data" \
241
+ '{"format": "sql", "includeData": false}' \
242
+ "Export all tables as SQL with both schema and data"
243
+
244
+ echo -e "${GREEN}=== IMPORT TESTS ===${NC}"
245
+ echo ""
246
+
247
+ # Define the path to the SQL file
248
+ SQL_FILE_PATH="$(dirname "$0")/test-users.sql"
249
+
250
+ # Test 13: Import users.sql without truncate
251
+ test_import \
252
+ "Import Users SQL - No Truncate" \
253
+ "$SQL_FILE_PATH" \
254
+ "false" \
255
+ "Import users table structure from SQL file without truncating existing data"
256
+
257
+ # Test 14: Import users.sql with truncate
258
+ test_import \
259
+ "Import Users SQL - With Truncate" \
260
+ "$SQL_FILE_PATH" \
261
+ "true" \
262
+ "Import users table structure from SQL file with truncating existing data"
263
+
264
+ # Test 15: Test with non-existent file
265
+ test_import \
266
+ "Import Non-existent File" \
267
+ "$(dirname "$0")/nonexistent.sql" \
268
+ "false" \
269
+ "Test error handling with non-existent SQL file"
270
+
271
+ echo "========================================="
272
+ echo "Database Advance Tests Complete"
273
+ echo "========================================="
274
+ echo ""
275
+ echo -e "${GREEN}All tests have been executed.${NC}"
276
+ echo "Check the responses above to verify all functionality."
277
+ echo ""
278
+ echo "Key things to verify:"
279
+ echo ""
280
+ echo -e "${BLUE}Raw SQL Tests:${NC}"
281
+ echo "- Posts table existence check"
282
+ echo "- Index creation and verification"
283
+ echo "- SQL execution with proper responses"
284
+ echo ""
285
+ echo -e "${BLUE}Export Tests:${NC}"
286
+ echo "- SQL exports should contain CREATE TABLE statements"
287
+ echo "- When includeData=true, INSERT statements should be present"
288
+ echo "- When includeData=false, only schema should be exported"
289
+ echo "- JSON exports should have 'schema' and 'rows' properties"
290
+ echo "- Invalid requests should return appropriate error messages"
291
+ echo ""
292
+ echo -e "${BLUE}Import Tests:${NC}"
293
+ echo "- File uploads should be processed correctly"
294
+ echo "- SQL files should be executed and tables created"
295
+ echo "- Truncate option should control data preservation"
296
+ echo "- Error handling should work for missing files"
297
+ echo "- Response should include import statistics"