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,303 @@
1
+ import { useEffect } from 'react';
2
+ import { useForm, Controller, useFormState } from 'react-hook-form';
3
+ import { zodResolver } from '@hookform/resolvers/zod';
4
+ import { z } from 'zod';
5
+ import { ExternalLink } from 'lucide-react';
6
+ import { Button } from '@/components/radix/Button';
7
+ import { Input } from '@/components/radix/Input';
8
+ import { Switch } from '@/components/radix/Switch';
9
+ import {
10
+ Dialog,
11
+ DialogContent,
12
+ DialogHeader,
13
+ DialogTitle,
14
+ DialogFooter,
15
+ } from '@/components/radix/Dialog';
16
+ import WarningIcon from '@/assets/icons/warning.svg';
17
+ import { CopyButton } from '@/components/CopyButton';
18
+ import { oAuthConfigSchema, OAuthConfigSchema } from '@insforge/shared-schemas';
19
+ import { OAuthProviderInfo } from './AuthMethodTab';
20
+ import { useOAuthConfig } from '@/features/auth/hooks/useOAuthConfig';
21
+ import { getBackendUrl, isInsForgeCloudProject } from '@/lib/utils/utils';
22
+
23
+ const getCallbackUrl = (provider?: string) => {
24
+ // Use backend API URL for OAuth callback
25
+ return `${getBackendUrl()}/api/auth/oauth/${provider}/callback`;
26
+ };
27
+
28
+ interface OAuthConfigDialogProps {
29
+ provider?: OAuthProviderInfo;
30
+ isOpen: boolean;
31
+ onClose: () => void;
32
+ onSuccess?: () => void;
33
+ }
34
+
35
+ export function OAuthConfigDialog({
36
+ provider,
37
+ isOpen,
38
+ onClose,
39
+ onSuccess,
40
+ }: OAuthConfigDialogProps) {
41
+ const {
42
+ configs,
43
+ providerConfig,
44
+ createConfig,
45
+ updateConfig,
46
+ isCreating,
47
+ isUpdating,
48
+ setSelectedProvider,
49
+ isLoadingProvider,
50
+ } = useOAuthConfig();
51
+
52
+ const form = useForm<OAuthConfigSchema & { clientSecret?: string }>({
53
+ resolver: zodResolver(oAuthConfigSchema.extend({ clientSecret: z.string().optional() })),
54
+ defaultValues: {
55
+ provider: provider?.id || 'google',
56
+ clientId: '',
57
+ clientSecret: '',
58
+ useSharedKey: false,
59
+ },
60
+ });
61
+
62
+ const useSharedKey = form.watch('useSharedKey');
63
+ const clientId = form.watch('clientId');
64
+ const clientSecret = form.watch('clientSecret');
65
+
66
+ // Use useFormState hook for better reactivity
67
+ const { isDirty } = useFormState({
68
+ control: form.control,
69
+ });
70
+
71
+ // Set selected provider and refetch when dialog opens
72
+ useEffect(() => {
73
+ if (isOpen && provider) {
74
+ setSelectedProvider(provider.id);
75
+ }
76
+ }, [configs, isOpen, provider, setSelectedProvider]);
77
+
78
+ // Load OAuth configuration after fetching
79
+ useEffect(() => {
80
+ if (isOpen && provider && !isLoadingProvider) {
81
+ if (providerConfig) {
82
+ form.reset({
83
+ provider: provider.id,
84
+ clientId: providerConfig.clientId || '',
85
+ clientSecret: providerConfig.clientSecret || '',
86
+ useSharedKey: providerConfig.useSharedKey || false,
87
+ });
88
+ } else {
89
+ form.reset({
90
+ provider: provider.id,
91
+ clientId: '',
92
+ clientSecret: '',
93
+ useSharedKey: isInsForgeCloudProject(),
94
+ });
95
+ }
96
+ }
97
+ }, [isOpen, provider, providerConfig, form, isLoadingProvider]);
98
+
99
+ const handleSubmitData = (data: OAuthConfigSchema & { clientSecret?: string }) => {
100
+ if (!provider) {
101
+ return;
102
+ }
103
+
104
+ try {
105
+ if (providerConfig) {
106
+ // Update existing config
107
+ updateConfig({
108
+ provider: provider.id,
109
+ config: data.useSharedKey
110
+ ? { useSharedKey: true }
111
+ : {
112
+ clientId: data.clientId,
113
+ clientSecret: data.clientSecret,
114
+ useSharedKey: false,
115
+ },
116
+ });
117
+ } else {
118
+ // Create new config
119
+ createConfig({
120
+ provider: provider.id,
121
+ clientId: data.useSharedKey ? undefined : data.clientId,
122
+ clientSecret: data.useSharedKey ? undefined : clientSecret,
123
+ useSharedKey: data.useSharedKey,
124
+ });
125
+ }
126
+
127
+ // Call success callback if provided
128
+ if (onSuccess) {
129
+ onSuccess();
130
+ }
131
+ // Close dialog
132
+ onClose();
133
+ } catch (error) {
134
+ console.error('Error saving OAuth config:', error);
135
+ }
136
+ };
137
+
138
+ const handleSubmit = () => {
139
+ void handleSubmitData(form.getValues());
140
+ };
141
+
142
+ const saving = isCreating || isUpdating;
143
+
144
+ // Use RHF's built-in validation and dirty state
145
+ const isDisabled = () => {
146
+ if (saving) {
147
+ return true;
148
+ }
149
+
150
+ // In update mode, require dirty state
151
+ if (providerConfig && !isDirty) {
152
+ return true;
153
+ }
154
+
155
+ // If using shared keys, always allow (no credential validation needed)
156
+ if (useSharedKey) {
157
+ return false;
158
+ }
159
+
160
+ // If NOT using shared keys, require both clientId and clientSecret
161
+ return !clientId || !clientSecret;
162
+ };
163
+
164
+ return (
165
+ <Dialog open={isOpen && !!provider} onOpenChange={(open) => !open && onClose()}>
166
+ <DialogContent className="max-w-[700px] dark:bg-neutral-800 dark:text-white p-0 gap-0">
167
+ <DialogHeader className="px-6 py-3 border-b border-zinc-200 dark:border-neutral-700">
168
+ <DialogTitle>{provider?.name}</DialogTitle>
169
+ </DialogHeader>
170
+ {isLoadingProvider ? (
171
+ <div className="p-6 flex items-center justify-center">
172
+ <div className="text-center">
173
+ <div className="text-sm text-gray-500 dark:text-zinc-400">
174
+ Loading OAuth configuration...
175
+ </div>
176
+ </div>
177
+ </div>
178
+ ) : (
179
+ <>
180
+ <form onSubmit={(e) => e.preventDefault()} className="flex flex-col">
181
+ <div className="space-y-6 p-6">
182
+ {/* Shared Keys Toggle */}
183
+ <div className="flex items-center justify-start gap-2">
184
+ <Controller
185
+ name="useSharedKey"
186
+ control={form.control}
187
+ render={({ field }) => {
188
+ return (
189
+ <Switch
190
+ checked={field.value}
191
+ onCheckedChange={(value) => {
192
+ field.onChange(value);
193
+ }}
194
+ />
195
+ );
196
+ }}
197
+ />
198
+ <span className="text-sm font-medium text-gray-900 dark:text-white">
199
+ Shared Keys
200
+ </span>
201
+ </div>
202
+
203
+ {useSharedKey ? (
204
+ /* Shared Keys Enabled */
205
+ <div className="space-y-6">
206
+ <p className="text-sm text-zinc-500 dark:text-neutral-400">
207
+ Shared keys are created by the InsForge team for development. It helps you get
208
+ started, but will show a InsForge logo and name on the OAuth screen.
209
+ </p>
210
+
211
+ <div className="flex items-center gap-3">
212
+ <img src={WarningIcon} alt="Warning" className="h-6 w-6" />
213
+ <span className="text-sm font-medium text-zinc-950 dark:text-white">
214
+ Shared keys should never be used in production
215
+ </span>
216
+ </div>
217
+ </div>
218
+ ) : (
219
+ /* Shared Keys Disabled */
220
+ <div className="space-y-3">
221
+ <div className="flex items-center gap-2">
222
+ <ExternalLink className="h-4 w-4 text-blue-600 dark:text-blue-400" />
223
+ <a
224
+ href={provider?.setupUrl}
225
+ target="_blank"
226
+ rel="noopener noreferrer"
227
+ className="text-sm text-blue-600 dark:text-blue-400 hover:text-blue-800 font-medium underline"
228
+ >
229
+ Create a {provider?.name.split(' ')[0]} OAuth App
230
+ </a>
231
+ <span className="text-sm font-normal text-zinc-950 dark:text-white">
232
+ {' '}
233
+ and set the callback url to:
234
+ </span>
235
+ </div>
236
+
237
+ <div className="space-x-3">
238
+ <div className="flex items-center gap-2">
239
+ <code className="flex items-center py-1 px-3 bg-blue-100 dark:bg-neutral-700 text-blue-800 dark:text-blue-300 font-mono break-all rounded-md text-sm">
240
+ {getCallbackUrl(provider?.id)}
241
+ </code>
242
+ <CopyButton className="h-9" text={getCallbackUrl(provider?.id)} />
243
+ </div>
244
+ </div>
245
+ </div>
246
+ )}
247
+ </div>
248
+ {!useSharedKey && (
249
+ <div className="space-y-6 p-6 border-t border-zinc-200 dark:border-neutral-700">
250
+ <div className="flex flex-row items-center justify-between gap-10">
251
+ <label className="text-sm text-zinc-950 dark:text-white">Client ID</label>
252
+ <Input
253
+ type="text"
254
+ {...form.register('clientId')}
255
+ placeholder={`Enter ${provider?.name.split(' ')[0]} OAuth App ID`}
256
+ className="w-[340px] dark:bg-neutral-900 dark:placeholder:text-neutral-400 dark:border-neutral-700 dark:text-white"
257
+ />
258
+ </div>
259
+
260
+ <div className="flex flex-row items-center justify-between gap-10">
261
+ <label className="text-sm text-zinc-950 dark:text-white">Client Secret</label>
262
+ <Input
263
+ type="password"
264
+ {...form.register('clientSecret')}
265
+ placeholder={`Enter ${provider?.name.split(' ')[0]} OAuth App Secret`}
266
+ className="w-[340px] dark:bg-neutral-900 dark:placeholder:text-neutral-400 dark:border-neutral-700 dark:text-white"
267
+ />
268
+ </div>
269
+ </div>
270
+ )}
271
+ </form>
272
+
273
+ <DialogFooter className="p-6 border-t border-zinc-200 dark:border-neutral-700">
274
+ <Button
275
+ type="button"
276
+ className="h-9 w-30 px-3 py-2 dark:bg-neutral-600 dark:text-white dark:border-transparent dark:hover:bg-neutral-700"
277
+ variant="outline"
278
+ onClick={onClose}
279
+ disabled={saving}
280
+ >
281
+ Cancel
282
+ </Button>
283
+ <Button
284
+ type="button"
285
+ onClick={handleSubmit}
286
+ disabled={isDisabled()}
287
+ className="h-9 w-30 px-3 py-2 dark:bg-emerald-300 dark:text-black dark:hover:bg-emerald-400"
288
+ >
289
+ {saving
290
+ ? providerConfig
291
+ ? 'Updating...'
292
+ : 'Adding...'
293
+ : providerConfig
294
+ ? 'Update'
295
+ : 'Add OAuth'}
296
+ </Button>
297
+ </DialogFooter>
298
+ </>
299
+ )}
300
+ </DialogContent>
301
+ </Dialog>
302
+ );
303
+ }
@@ -0,0 +1,15 @@
1
+ import { Lock } from 'lucide-react';
2
+
3
+ export function OAuthEmptyState() {
4
+ return (
5
+ <div className="text-center flex flex-col items-center justify-center gap-3 text-zinc-500 py-8 rounded-[8px] bg-neutral-100 dark:bg-[#333333]">
6
+ <Lock className="mx-auto h-10 w-10 text-neutral-400 dark:text-neutral-600" />
7
+ <div className="flex flex-col items-center justify-center gap-1">
8
+ <p className="text-sm font-medium text-zinc-900 dark:text-white">No Authentications Yet</p>
9
+ <p className="text-xs text-neutral-600 dark:text-neutral-400 font-medium">
10
+ Add your first authentication to get started
11
+ </p>
12
+ </div>
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,248 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { Mail, Lock, AlertCircle } from 'lucide-react';
3
+ import { authService } from '@/features/auth/services/auth.service';
4
+ import { Button, Input, Label, Alert, AlertDescription } from '@/components';
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ DialogFooter,
11
+ } from '@/components/radix/Dialog';
12
+ import ErrorIcon from '@/assets/icons/error.svg';
13
+ import { useToast } from '@/lib/hooks/useToast';
14
+ import { useUsers } from '@/features/auth/hooks/useUsers';
15
+ import { emailSchema } from '@/lib/utils/validation-schemas';
16
+ import { z } from 'zod';
17
+
18
+ interface User {
19
+ id?: string;
20
+ email: string;
21
+ password?: string;
22
+ name?: string;
23
+ }
24
+
25
+ interface UserFormDialogProps {
26
+ open: boolean;
27
+ onOpenChange: (open: boolean) => void;
28
+ user?: User | null;
29
+ }
30
+
31
+ // Validation helpers
32
+ const validateEmail = (email: string): string => {
33
+ if (!email.trim()) {
34
+ return 'Cannot leave empty';
35
+ }
36
+ try {
37
+ emailSchema.parse(email);
38
+ return '';
39
+ } catch (error) {
40
+ if (error instanceof z.ZodError) {
41
+ return 'Incorrect format';
42
+ }
43
+ return 'Invalid email';
44
+ }
45
+ };
46
+
47
+ const validatePassword = (password: string): string => {
48
+ if (!password.trim()) {
49
+ return 'Cannot leave empty';
50
+ }
51
+ return '';
52
+ };
53
+
54
+ export function UserFormDialog({ open, onOpenChange, user }: UserFormDialogProps) {
55
+ const [email, setEmail] = useState('');
56
+ const [password, setPassword] = useState('');
57
+ const [loading, setLoading] = useState(false);
58
+ const [error, setError] = useState('');
59
+
60
+ // Validation states
61
+ const [emailError, setEmailError] = useState('');
62
+ const [passwordError, setPasswordError] = useState('');
63
+ const [showValidation, setShowValidation] = useState(false);
64
+
65
+ const { showToast } = useToast();
66
+ const { refetch } = useUsers();
67
+
68
+ const isEditing = !!user;
69
+
70
+ useEffect(() => {
71
+ if (user) {
72
+ setEmail(user.email);
73
+ setPassword('');
74
+ } else {
75
+ setEmail('');
76
+ setPassword('');
77
+ }
78
+ setError('');
79
+ setEmailError('');
80
+ setPasswordError('');
81
+ setShowValidation(false);
82
+ }, [user, open]);
83
+
84
+ const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
85
+ setEmail(e.target.value);
86
+ // Clear error when user starts typing
87
+ if (emailError && showValidation) {
88
+ const error = validateEmail(e.target.value);
89
+ setEmailError(error);
90
+ }
91
+ };
92
+
93
+ const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
94
+ setPassword(e.target.value);
95
+ // Clear error when user starts typing
96
+ if (passwordError && showValidation) {
97
+ const error = validatePassword(e.target.value);
98
+ setPasswordError(error);
99
+ }
100
+ };
101
+
102
+ const handleSubmit = async (e: React.FormEvent) => {
103
+ e.preventDefault();
104
+ setError('');
105
+
106
+ // Validate all fields
107
+ const emailValidationError = validateEmail(email);
108
+ const passwordValidationError = validatePassword(password);
109
+
110
+ setEmailError(emailValidationError);
111
+ setPasswordError(passwordValidationError);
112
+ setShowValidation(true);
113
+
114
+ if (emailValidationError || passwordValidationError) {
115
+ return;
116
+ }
117
+
118
+ setLoading(true);
119
+
120
+ try {
121
+ const userData: User = { email };
122
+ if (password) {
123
+ userData.password = password;
124
+ }
125
+ if (isEditing && user?.id) {
126
+ userData.id = user.id;
127
+ }
128
+
129
+ await authService.register(userData.email, userData.password || '', userData.name);
130
+ void refetch();
131
+ onOpenChange(false);
132
+ showToast('User created successfully', 'success');
133
+ } catch (err) {
134
+ showToast(err instanceof Error ? err.message : 'Failed to create user', 'error');
135
+ } finally {
136
+ setLoading(false);
137
+ }
138
+ };
139
+
140
+ return (
141
+ <Dialog open={open} onOpenChange={onOpenChange}>
142
+ <DialogContent className="sm:max-w-[480px] dark:bg-neutral-800 dark:text-white p-0 gap-0">
143
+ <DialogHeader className="px-6 py-3 border-b border-zinc-200 dark:border-neutral-700">
144
+ <DialogTitle className="h-7">Add User</DialogTitle>
145
+ </DialogHeader>
146
+ <form
147
+ onSubmit={(e) => {
148
+ void handleSubmit(e);
149
+ }}
150
+ className="flex flex-col"
151
+ >
152
+ <div className="space-y-6 p-6">
153
+ {/* Email Field */}
154
+ <div className="flex flex-row gap-10 justify-between items-center">
155
+ <div className="flex flex-row gap-2 items-center">
156
+ <Mail className="h-5 w-5 text-neutral-500" />
157
+ <Label htmlFor="user-email" className="text-sm text-zinc-950 dark:text-neutral-50">
158
+ Email
159
+ </Label>
160
+ </div>
161
+ <div className="flex flex-col space-y-1">
162
+ <Input
163
+ id="user-email"
164
+ type="email"
165
+ placeholder="user@example.com"
166
+ value={email}
167
+ onChange={handleEmailChange}
168
+ className={`w-70 dark:bg-neutral-900 dark:placeholder:text-neutral-400 dark:border-neutral-700 dark:text-white ${emailError && showValidation ? 'border-red-500 focus:border-red-500' : ''}`}
169
+ autoFocus={false}
170
+ />
171
+ {emailError && showValidation && (
172
+ <div className="flex items-center gap-1">
173
+ <img src={ErrorIcon} alt="Error" className="h-4 w-4" />
174
+ <p className="text-xs font-medium text-red-600 dark:text-red-500">
175
+ {emailError}
176
+ </p>
177
+ </div>
178
+ )}
179
+ </div>
180
+ </div>
181
+
182
+ {/* Password Field */}
183
+ <div className="flex flex-row gap-10 justify-between items-center">
184
+ <div className="flex flex-row gap-2 items-center">
185
+ <Lock className="h-5 w-5 text-neutral-500" />
186
+ <Label
187
+ htmlFor="user-password"
188
+ className="text-sm text-zinc-950 dark:text-neutral-50"
189
+ >
190
+ Password
191
+ </Label>
192
+ </div>
193
+ <div className="flex flex-col space-y-1">
194
+ <Input
195
+ id="user-password"
196
+ type="password"
197
+ placeholder="Enter password"
198
+ value={password}
199
+ onChange={handlePasswordChange}
200
+ className={`w-70 dark:bg-neutral-900 dark:placeholder:text-neutral-400 dark:border-neutral-700 dark:text-white ${passwordError && showValidation ? 'border-red-500 focus:border-red-500' : ''}`}
201
+ />
202
+ {passwordError && showValidation && (
203
+ <div className="flex items-center gap-1">
204
+ <img src={ErrorIcon} alt="Error" className="h-4 w-4" />
205
+ <p className="text-xs font-medium text-red-600 dark:text-red-500">
206
+ {passwordError}
207
+ </p>
208
+ </div>
209
+ )}
210
+ </div>
211
+ </div>
212
+
213
+ {/* Error Alert */}
214
+ {error && (
215
+ <div className="mx-6 mb-6 shrink-0">
216
+ <Alert variant="destructive">
217
+ <AlertCircle className="h-4 w-4" />
218
+ <AlertDescription>{error}</AlertDescription>
219
+ </Alert>
220
+ </div>
221
+ )}
222
+ </div>
223
+ {/* Footer Buttons */}
224
+ <DialogFooter className="p-6 border-t border-zinc-200 dark:border-neutral-700">
225
+ <Button
226
+ type="button"
227
+ variant="outline"
228
+ onClick={() => onOpenChange(false)}
229
+ disabled={loading}
230
+ className="h-9 w-30 px-3 py-2 dark:bg-neutral-600 dark:border-transparent dark:text-white dark:hover:bg-neutral-700"
231
+ >
232
+ Cancel
233
+ </Button>
234
+ <Button
235
+ type="submit"
236
+ disabled={loading || email === '' || password === ''}
237
+ className="h-9 w-30 px-3 py-2 bg-zinc-950 hover:bg-zinc-800 text-white disabled:opacity-50 disabled:cursor-not-allowed dark:bg-emerald-300 dark:text-black dark:hover:bg-emerald-400"
238
+ >
239
+ Add
240
+ </Button>
241
+ </DialogFooter>
242
+ </form>
243
+ </DialogContent>
244
+ </Dialog>
245
+ );
246
+ }
247
+
248
+ export default UserFormDialog;