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,568 @@
1
+ import React, { useState } from 'react';
2
+ import { Control, Controller, FieldError, UseFormReturn } from 'react-hook-form';
3
+ import { Input } from '@/components/radix/Input';
4
+ import { Label } from '@/components/radix/Label';
5
+ import { Button } from '@/components/radix/Button';
6
+ import { Calendar, Clock, Link2, X } from 'lucide-react';
7
+ import {
8
+ BooleanCellEditor,
9
+ DateCellEditor,
10
+ JsonCellEditor,
11
+ type DatabaseRecord,
12
+ type ConvertedValue,
13
+ type UserInputValue,
14
+ } from '@/components/datagrid';
15
+ import { ColumnSchema, ColumnType } from '@insforge/shared-schemas';
16
+ import { useLinkModal } from '@/features/database/hooks/UseLinkModal';
17
+ import { convertValueForColumn, cn, formatValueForDisplay } from '@/lib/utils/utils';
18
+ import { TypeBadge } from '@/components/TypeBadge';
19
+ import { isValid, parseISO } from 'date-fns';
20
+
21
+ // Helper function to get appropriate placeholder text
22
+ function getPlaceholderText(field: ColumnSchema): string {
23
+ // Check if default value is a function
24
+ if (field.defaultValue && field.defaultValue.endsWith('()')) {
25
+ return 'Auto-generated on submit';
26
+ }
27
+ // Static default value or no default value
28
+ return field.isNullable ? 'Optional' : 'Required';
29
+ }
30
+
31
+ // Common interface for all form editors
32
+ interface BaseFormEditorProps {
33
+ nullable: boolean;
34
+ onChange: (value: ConvertedValue) => void;
35
+ hasForeignKey?: boolean;
36
+ }
37
+
38
+ // Form adapters for edit cell components
39
+ interface FormBooleanEditorProps extends BaseFormEditorProps {
40
+ value: boolean | null;
41
+ }
42
+
43
+ function FormBooleanEditor({ value, nullable, onChange, hasForeignKey }: FormBooleanEditorProps) {
44
+ const [showEditor, setShowEditor] = useState(false);
45
+
46
+ const handleValueChange = (newValue: string) => {
47
+ if (newValue === 'null') {
48
+ onChange(null);
49
+ } else {
50
+ onChange(newValue === 'true');
51
+ }
52
+ setShowEditor(false);
53
+ };
54
+
55
+ const handleCancel = () => {
56
+ setShowEditor(false);
57
+ };
58
+
59
+ if (showEditor) {
60
+ return (
61
+ <BooleanCellEditor
62
+ value={value}
63
+ nullable={nullable}
64
+ onValueChange={handleValueChange}
65
+ onCancel={handleCancel}
66
+ className="h-9 px-4 py-2 dark:bg-neutral-900 border"
67
+ />
68
+ );
69
+ }
70
+
71
+ return (
72
+ <Button
73
+ type="button"
74
+ variant="outline"
75
+ onClick={() => setShowEditor(true)}
76
+ className={`w-full justify-start h-9 dark:text-white dark:bg-neutral-900 dark:placeholder:text-neutral-400 dark:border-neutral-700 ${hasForeignKey ? 'pr-20' : ''}`}
77
+ >
78
+ {formatValueForDisplay(value, ColumnType.BOOLEAN)}
79
+ </Button>
80
+ );
81
+ }
82
+
83
+ interface FormDateEditorProps extends BaseFormEditorProps {
84
+ value: string | null;
85
+ type?: ColumnType.DATETIME | ColumnType.DATE;
86
+ field: ColumnSchema;
87
+ }
88
+
89
+ function FormDateEditor({
90
+ value,
91
+ type = ColumnType.DATETIME,
92
+ onChange,
93
+ field,
94
+ }: FormDateEditorProps) {
95
+ const [showEditor, setShowEditor] = useState(false);
96
+
97
+ const handleValueChange = (newValue: string | null) => {
98
+ if (newValue === 'null' || newValue === null) {
99
+ onChange(null);
100
+ } else {
101
+ onChange(newValue);
102
+ }
103
+ setShowEditor(false);
104
+ };
105
+
106
+ const handleCancel = () => {
107
+ setShowEditor(false);
108
+ };
109
+
110
+ const formatDisplayValue = () => {
111
+ if (!value || value === 'null') {
112
+ return getPlaceholderText(field);
113
+ }
114
+
115
+ return formatValueForDisplay(value, type);
116
+ };
117
+
118
+ const formatValue = () => {
119
+ if (!value || value === 'null') {
120
+ return null;
121
+ }
122
+
123
+ const date = parseISO(value);
124
+ return isValid(date) ? value : null;
125
+ };
126
+
127
+ if (showEditor) {
128
+ return (
129
+ <DateCellEditor
130
+ value={formatValue()}
131
+ type={type}
132
+ nullable={field.isNullable}
133
+ onValueChange={handleValueChange}
134
+ onCancel={handleCancel}
135
+ className="h-9 px-4 py-2 dark:bg-neutral-900 border dark:border-neutral-700"
136
+ />
137
+ );
138
+ }
139
+
140
+ return (
141
+ <Button
142
+ type="button"
143
+ variant="outline"
144
+ onClick={() => setShowEditor(true)}
145
+ className={cn(
146
+ 'w-full justify-start h-9 text-black dark:text-white dark:bg-neutral-900 dark:border-neutral-700',
147
+ (!value || value === 'null') && 'text-muted-foreground dark:text-neutral-400',
148
+ !!field.foreignKey && 'pr-20'
149
+ )}
150
+ >
151
+ {type === ColumnType.DATETIME ? (
152
+ <Clock className="mr-2 h-4 w-4" />
153
+ ) : (
154
+ <Calendar className="mr-2 h-4 w-4" />
155
+ )}
156
+ {formatDisplayValue()}
157
+ </Button>
158
+ );
159
+ }
160
+
161
+ interface FormNumberEditorProps extends BaseFormEditorProps {
162
+ value: number | null;
163
+ type: ColumnType.INTEGER | ColumnType.FLOAT;
164
+ tableName: string;
165
+ field: ColumnSchema;
166
+ }
167
+
168
+ function FormNumberEditor({ value, type, onChange, tableName, field }: FormNumberEditorProps) {
169
+ return (
170
+ <Input
171
+ id={`${tableName}-${field.columnName}`}
172
+ type="number"
173
+ step={type === ColumnType.INTEGER ? '1' : undefined}
174
+ value={value ?? ''}
175
+ onChange={(e) => {
176
+ const inputValue = e.target.value;
177
+ if (inputValue === '') {
178
+ // Handle empty value - let form validation handle required fields
179
+ onChange(null);
180
+ } else {
181
+ const numValue =
182
+ type === ColumnType.INTEGER ? parseInt(inputValue, 10) : parseFloat(inputValue);
183
+ onChange(isNaN(numValue) ? null : numValue);
184
+ }
185
+ }}
186
+ placeholder={getPlaceholderText(field)}
187
+ className={`dark:text-white dark:placeholder:text-neutral-400 dark:bg-neutral-900 dark:border-neutral-700 ${field.foreignKey ? 'pr-16' : ''}`}
188
+ />
189
+ );
190
+ }
191
+
192
+ interface FormJsonEditorProps extends BaseFormEditorProps {
193
+ value: string | null;
194
+ hasForeignKey: boolean;
195
+ }
196
+
197
+ function FormJsonEditor({ value, nullable, onChange, hasForeignKey }: FormJsonEditorProps) {
198
+ const [showEditor, setShowEditor] = useState(false);
199
+
200
+ const handleValueChange = (newValue: string) => {
201
+ onChange(newValue);
202
+ setShowEditor(false);
203
+ };
204
+
205
+ const handleCancel = () => {
206
+ setShowEditor(false);
207
+ };
208
+
209
+ if (showEditor) {
210
+ return (
211
+ <JsonCellEditor
212
+ value={value}
213
+ nullable={nullable}
214
+ onValueChange={handleValueChange}
215
+ onCancel={handleCancel}
216
+ className="h-9 px-4 py-2 dark:bg-neutral-900 border dark:border-neutral-700"
217
+ />
218
+ );
219
+ }
220
+
221
+ const formatDisplayValue = () => {
222
+ if (!value || value === 'null') {
223
+ return 'Empty JSON';
224
+ }
225
+
226
+ return formatValueForDisplay(value, ColumnType.JSON);
227
+ };
228
+
229
+ return (
230
+ <Button
231
+ type="button"
232
+ variant="outline"
233
+ onClick={() => setShowEditor(true)}
234
+ className={cn(
235
+ 'w-full justify-start h-9 text-black dark:text-white dark:bg-neutral-900 dark:border-neutral-700',
236
+ (!value || value === 'null') && 'text-muted-foreground dark:text-neutral-400',
237
+ hasForeignKey && 'pr-20'
238
+ )}
239
+ >
240
+ {formatDisplayValue()}
241
+ </Button>
242
+ );
243
+ }
244
+
245
+ interface RecordFormFieldProps {
246
+ field: ColumnSchema;
247
+ form: UseFormReturn<DatabaseRecord>;
248
+ tableName: string;
249
+ }
250
+
251
+ // Helper component to render field label with type badge
252
+ function FieldLabel({
253
+ field,
254
+ tableName,
255
+ children,
256
+ }: {
257
+ field: ColumnSchema;
258
+ tableName: string;
259
+ children?: React.ReactNode;
260
+ }) {
261
+ return (
262
+ <Label htmlFor={`${tableName}-${field.columnName}`} className="flex items-center gap-2">
263
+ <TypeBadge type={field.type} className="h-6 dark:bg-neutral-900 dark:border-neutral-700" />
264
+ <span className="text-sm text-black dark:text-white truncate block" title={field.columnName}>
265
+ {field.columnName}
266
+ </span>
267
+ {!field.isNullable && <span className="text-red-500 dark:text-red-400">*</span>}
268
+ {children}
269
+ </Label>
270
+ );
271
+ }
272
+
273
+ // Generic component for any field type with foreign key linking
274
+ interface FieldWithLinkProps {
275
+ field: ColumnSchema;
276
+ control: Control<DatabaseRecord>;
277
+ children: React.ReactNode;
278
+ }
279
+
280
+ function FieldWithLink({ field, control, children }: FieldWithLinkProps) {
281
+ const { openModal } = useLinkModal();
282
+
283
+ if (!field.foreignKey) {
284
+ // Regular field without foreign key
285
+ return <>{children}</>;
286
+ }
287
+
288
+ // Field with foreign key linking capability - integrated design
289
+ return (
290
+ <>
291
+ <Controller
292
+ control={control}
293
+ name={field.columnName}
294
+ render={({ field: formField }) => {
295
+ const hasLinkedValue = formField.value && formField.value !== '';
296
+ const childElement = children as React.ReactElement<{
297
+ className?: string;
298
+ value?: UserInputValue;
299
+ }>;
300
+ const existingClassName = childElement.props.className || '';
301
+ const paddingClass = hasLinkedValue ? 'pr-16' : 'pr-11';
302
+ const modifiedChildren = React.cloneElement(childElement, {
303
+ value: formField.value as UserInputValue,
304
+ className: `${existingClassName} ${paddingClass}`.trim(),
305
+ });
306
+
307
+ return (
308
+ <>
309
+ <div className="space-y-1">
310
+ <div className="relative">
311
+ {modifiedChildren}
312
+ <div className="absolute right-0 top-1/2 -translate-y-1/2 flex items-center">
313
+ {hasLinkedValue && (
314
+ <Button
315
+ type="button"
316
+ variant="ghost"
317
+ size="icon"
318
+ onClick={() => formField.onChange('')}
319
+ className="h-7 w-7 p-1 flex-shrink-0 text-zinc-500 hover:text-red-600 hover:bg-red-50 dark:text-neutral-400 dark:hover:text-red-400 dark:hover:bg-red-950/20"
320
+ title="Clear linked record"
321
+ >
322
+ <X className="h-4 w-4" />
323
+ </Button>
324
+ )}
325
+ <Button
326
+ type="button"
327
+ variant="ghost"
328
+ size="icon"
329
+ onClick={() => {
330
+ if (field.foreignKey) {
331
+ openModal({
332
+ referenceTable: field.foreignKey.referenceTable,
333
+ referenceColumn: field.foreignKey.referenceColumn,
334
+ currentValue: formField.value ? String(formField.value) : null,
335
+ onSelectRecord: (record: DatabaseRecord) => {
336
+ if (field.foreignKey) {
337
+ const referenceValue = record[field.foreignKey.referenceColumn];
338
+ const result = convertValueForColumn(
339
+ field.type,
340
+ String(referenceValue || '')
341
+ );
342
+ if (result.success) {
343
+ formField.onChange(result.value);
344
+ } else {
345
+ // Fallback to string if conversion fails
346
+ formField.onChange(String(referenceValue || ''));
347
+ }
348
+ }
349
+ },
350
+ });
351
+ }
352
+ }}
353
+ className="rounded-l-none h-9 w-9 p-2 flex-shrink-0 text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-neutral-400 dark:hover:text-neutral-200 dark:hover:bg-neutral-700 border-l border-zinc-200 dark:border-neutral-700"
354
+ title={
355
+ hasLinkedValue
356
+ ? `Change linked ${field.foreignKey?.referenceTable} record`
357
+ : `Link to ${field.foreignKey?.referenceTable} record`
358
+ }
359
+ >
360
+ <Link2 className="h-5 w-5" />
361
+ </Button>
362
+ </div>
363
+ </div>
364
+
365
+ {/* Foreign Key Relationship Info */}
366
+ <div className="text-xs text-medium text-black dark:text-neutral-400 flex items-center gap-1.5">
367
+ <span>Has a Foreign Key relation to</span>
368
+ <TypeBadge
369
+ type={`${field.foreignKey?.referenceTable}.${field.foreignKey?.referenceColumn}`}
370
+ className="dark:bg-neutral-700"
371
+ />
372
+ </div>
373
+ </div>
374
+ </>
375
+ );
376
+ }}
377
+ />
378
+ </>
379
+ );
380
+ }
381
+
382
+ export function RecordFormField({ field, form, tableName }: RecordFormFieldProps) {
383
+ const {
384
+ control,
385
+ register,
386
+ formState: { errors },
387
+ } = form;
388
+
389
+ // TODO: This is a mess, we need to clean it up. To fix in future.
390
+ const renderField = () => {
391
+ // Infer frontend type from field name and SQLite type
392
+
393
+ switch (field.type) {
394
+ case ColumnType.BOOLEAN:
395
+ return (
396
+ <div className="grid grid-cols-6 gap-x-10">
397
+ <div className="col-span-2">
398
+ <FieldLabel field={field} tableName={tableName} />
399
+ </div>
400
+ <div className="col-span-4">
401
+ <FieldWithLink field={field} control={control}>
402
+ <Controller
403
+ control={control}
404
+ name={field.columnName}
405
+ render={({ field: formField }) => (
406
+ <FormBooleanEditor
407
+ value={formField.value as boolean | null}
408
+ nullable={field.isNullable}
409
+ onChange={formField.onChange}
410
+ hasForeignKey={!!field.foreignKey}
411
+ />
412
+ )}
413
+ />
414
+ </FieldWithLink>
415
+ </div>
416
+ </div>
417
+ );
418
+
419
+ case ColumnType.INTEGER:
420
+ case ColumnType.FLOAT:
421
+ return (
422
+ <div className="grid grid-cols-6 gap-x-10">
423
+ <div className="col-span-2">
424
+ <FieldLabel field={field} tableName={tableName} />
425
+ </div>
426
+ <div className="col-span-4">
427
+ <FieldWithLink field={field} control={control}>
428
+ <Controller
429
+ control={control}
430
+ name={field.columnName}
431
+ render={({ field: formField }) => (
432
+ <FormNumberEditor
433
+ value={formField.value as number | null}
434
+ type={
435
+ field.type === ColumnType.INTEGER ? ColumnType.INTEGER : ColumnType.FLOAT
436
+ }
437
+ onChange={formField.onChange}
438
+ nullable={field.isNullable}
439
+ tableName={tableName}
440
+ field={field}
441
+ />
442
+ )}
443
+ />
444
+ </FieldWithLink>
445
+ </div>
446
+ </div>
447
+ );
448
+
449
+ case ColumnType.DATE:
450
+ case ColumnType.DATETIME:
451
+ return (
452
+ <div className="grid grid-cols-6 gap-x-10">
453
+ <div className="col-span-2">
454
+ <FieldLabel field={field} tableName={tableName} />
455
+ </div>
456
+ <div className="col-span-4">
457
+ <FieldWithLink field={field} control={control}>
458
+ <Controller
459
+ control={control}
460
+ name={field.columnName}
461
+ render={({ field: formField }) => (
462
+ <FormDateEditor
463
+ value={formField.value as string | null}
464
+ type={field.type as ColumnType.DATE | ColumnType.DATETIME}
465
+ onChange={formField.onChange}
466
+ nullable={field.isNullable}
467
+ field={field}
468
+ />
469
+ )}
470
+ />
471
+ </FieldWithLink>
472
+ </div>
473
+ </div>
474
+ );
475
+
476
+ case ColumnType.JSON:
477
+ return (
478
+ <div className="grid grid-cols-6 gap-x-10">
479
+ <div className="col-span-2">
480
+ <FieldLabel field={field} tableName={tableName} />
481
+ </div>
482
+ <div className="col-span-4">
483
+ <FieldWithLink field={field} control={control}>
484
+ <Controller
485
+ control={control}
486
+ name={field.columnName}
487
+ render={({ field: formField }) => {
488
+ return (
489
+ <FormJsonEditor
490
+ value={
491
+ typeof formField.value === 'object'
492
+ ? JSON.stringify(formField.value)
493
+ : String(formField.value || '')
494
+ }
495
+ nullable={field.isNullable}
496
+ hasForeignKey={!!field.foreignKey}
497
+ onChange={(newValue) => {
498
+ const result = convertValueForColumn(ColumnType.JSON, newValue as string);
499
+ if (result.success) {
500
+ formField.onChange(result.value as JSON);
501
+ } else {
502
+ // If parsing fails, keep the string value
503
+ formField.onChange(newValue);
504
+ }
505
+ }}
506
+ />
507
+ );
508
+ }}
509
+ />
510
+ </FieldWithLink>
511
+ </div>
512
+ </div>
513
+ );
514
+
515
+ case ColumnType.UUID:
516
+ return (
517
+ <div className="grid grid-cols-6 gap-x-10">
518
+ <div className="col-span-2">
519
+ <FieldLabel field={field} tableName={tableName} />
520
+ </div>
521
+ <div className="col-span-4">
522
+ <FieldWithLink field={field} control={control}>
523
+ <Input
524
+ id={`${tableName}-${field.columnName}`}
525
+ type="text"
526
+ {...register(field.columnName)}
527
+ placeholder={getPlaceholderText(field)}
528
+ className="dark:text-white dark:placeholder:text-neutral-400 dark:bg-neutral-900 dark:border-neutral-700"
529
+ />
530
+ </FieldWithLink>
531
+ </div>
532
+ </div>
533
+ );
534
+
535
+ case ColumnType.STRING:
536
+ default:
537
+ return (
538
+ <div className="grid grid-cols-6 gap-x-10">
539
+ <div className="col-span-2">
540
+ <FieldLabel field={field} tableName={tableName} />
541
+ </div>
542
+ <div className="col-span-4">
543
+ <FieldWithLink field={field} control={control}>
544
+ <Input
545
+ id={`${tableName}-${field.columnName}`}
546
+ type={field.columnName === 'password' ? 'password' : 'text'}
547
+ {...register(field.columnName)}
548
+ placeholder={getPlaceholderText(field)}
549
+ className="dark:text-white dark:placeholder:text-neutral-400 dark:bg-neutral-900 dark:border-neutral-700"
550
+ />
551
+ </FieldWithLink>
552
+ </div>
553
+ </div>
554
+ );
555
+ }
556
+ };
557
+
558
+ return (
559
+ <div className="space-y-2">
560
+ {renderField()}
561
+ {errors[field.columnName] && (
562
+ <p className="text-sm text-red-500 dark:text-red-400">
563
+ {(errors[field.columnName] as FieldError)?.message || `${field.columnName} is required`}
564
+ </p>
565
+ )}
566
+ </div>
567
+ );
568
+ }
@@ -0,0 +1,21 @@
1
+ import { Database } from 'lucide-react';
2
+
3
+ interface TableEmptyStateProps {
4
+ searchTerm: string;
5
+ }
6
+
7
+ export function TableEmptyState({ searchTerm }: TableEmptyStateProps) {
8
+ return (
9
+ <div className="text-center py-8">
10
+ <Database className="mx-auto h-8 w-8 text-muted-foreground mb-2.5" />
11
+ <p className="text-sm text-muted-foreground">
12
+ {searchTerm ? 'No tables found' : 'No tables yet'}
13
+ </p>
14
+ {!searchTerm && (
15
+ <p className="text-xs text-muted-foreground mt-2.5">
16
+ Create your first table to get started
17
+ </p>
18
+ )}
19
+ </div>
20
+ );
21
+ }