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,27 @@
1
+ import { useEffect, useLayoutEffect, useRef } from 'react';
2
+
3
+ export function useTimeout(callback: () => void, delay: number | null): void {
4
+ const savedCallback = useRef(callback);
5
+
6
+ // Remember the latest callback if it changes.
7
+ useLayoutEffect(() => {
8
+ savedCallback.current = callback;
9
+ }, [callback]);
10
+
11
+ // Set up the timeout.
12
+ useEffect(() => {
13
+ // Don't schedule if no delay is specified.
14
+ // Note: 0 is a valid value for delay.
15
+ if (!delay && delay !== 0) {
16
+ return;
17
+ }
18
+
19
+ const id = setTimeout(() => {
20
+ savedCallback.current();
21
+ }, delay);
22
+
23
+ return () => {
24
+ clearTimeout(id);
25
+ };
26
+ }, [delay]);
27
+ }
@@ -0,0 +1,229 @@
1
+ import React, { createContext, useContext, useState, useCallback } from 'react';
2
+ import { useTimeout } from './useTimeout';
3
+ import { generateUUID } from '@/lib/utils/utils';
4
+
5
+ interface Toast {
6
+ id: string;
7
+ message: string;
8
+ type?: 'success' | 'error' | 'info' | 'warn' | 'upload';
9
+ customIcon?: React.ReactNode;
10
+ duration: number;
11
+ progress?: number;
12
+ onCancel?: () => void;
13
+ }
14
+
15
+ interface ToastContextType {
16
+ showToast: (
17
+ message: string,
18
+ type?: 'success' | 'error' | 'info' | 'warn' | 'upload',
19
+ customIcon?: React.ReactNode,
20
+ duration?: number
21
+ ) => string;
22
+ updateToast: (id: string, updates: Partial<Toast>) => void;
23
+ removeToast: (id: string) => void;
24
+ }
25
+
26
+ const DEFAULT_TOAST_DURATION = 3000; // 3 seconds
27
+
28
+ const ToastContext = createContext<ToastContextType | undefined>(undefined);
29
+
30
+ interface ToastItemProps {
31
+ toast: Toast;
32
+ onRemove: () => void;
33
+ getDefaultIcon: (type: string) => React.ReactNode;
34
+ }
35
+
36
+ function ToastItem({ toast, onRemove, getDefaultIcon }: ToastItemProps) {
37
+ // Auto remove after duration (except for upload toasts)
38
+ useTimeout(onRemove, toast.type === 'upload' ? null : toast.duration);
39
+
40
+ const baseClasses =
41
+ 'relative p-3 rounded-[8px] font-medium animate-in fade-in duration-300 flex items-center overflow-hidden border-1';
42
+
43
+ const typeClasses = {
44
+ success: 'bg-green-300 text-green-700 border-green-400',
45
+ error: 'bg-red-300 text-red-700 border-red-400',
46
+ info: 'bg-blue-300 text-blue-700 border-blue-400',
47
+ warn: 'bg-yellow-300 text-yellow-700 border-yellow-400',
48
+ upload: 'bg-neutral-100 text-zinc-950 border-neutral-800',
49
+ };
50
+
51
+ const progressBarClasses = {
52
+ success: 'bg-green-700',
53
+ error: 'bg-red-700',
54
+ info: 'bg-blue-700',
55
+ warn: 'bg-yellow-700',
56
+ upload: 'bg-neutral-700',
57
+ };
58
+
59
+ const toastType = toast.type || 'info';
60
+
61
+ return (
62
+ <div className={`${baseClasses} ${typeClasses[toastType]}`}>
63
+ <div className="flex items-center gap-2 flex-1">
64
+ {toast.customIcon || getDefaultIcon(toastType)}
65
+ <span className="flex-1 text-sm font-medium">{toast.message}</span>
66
+ {toast.type === 'upload' && toast.onCancel && (
67
+ <button
68
+ onClick={toast.onCancel}
69
+ className="text-zinc-500 hover:text-zinc-700 text-sm font-medium"
70
+ >
71
+ Cancel
72
+ </button>
73
+ )}
74
+ </div>
75
+
76
+ {/* Progress bar */}
77
+ {toast.type === 'upload' ? (
78
+ <div className="absolute bottom-0 left-0 w-full h-1 bg-neutral-300 overflow-hidden">
79
+ <div
80
+ className={`h-full ${progressBarClasses[toastType]} transition-all duration-300 ease-out`}
81
+ style={{
82
+ width: `${toast.progress || 0}%`,
83
+ }}
84
+ />
85
+ </div>
86
+ ) : (
87
+ <div className="absolute bottom-0 left-0 w-full h-1 bg-transparent overflow-hidden">
88
+ <div
89
+ className={`h-full w-full ${progressBarClasses[toastType]} animate-toast-progress origin-left`}
90
+ style={{
91
+ animationDuration: `${toast.duration}ms`,
92
+ }}
93
+ />
94
+ </div>
95
+ )}
96
+ </div>
97
+ );
98
+ }
99
+
100
+ export function ToastProvider({ children }: { children: React.ReactNode }) {
101
+ const [toasts, setToasts] = useState<Toast[]>([]);
102
+
103
+ const showToast = useCallback(
104
+ (
105
+ message: string,
106
+ type: 'success' | 'error' | 'info' | 'warn' | 'upload' = 'info',
107
+ customIcon?: React.ReactNode,
108
+ duration: number = DEFAULT_TOAST_DURATION
109
+ ) => {
110
+ const id = generateUUID();
111
+ // Set duration to 2 seconds for success toasts
112
+ const toastDuration = type === 'success' ? 2000 : duration;
113
+ const newToast: Toast = { id, message, type, customIcon, duration: toastDuration };
114
+
115
+ setToasts((prev) => [...prev, newToast]);
116
+ return id;
117
+ },
118
+ []
119
+ );
120
+
121
+ const updateToast = useCallback((id: string, updates: Partial<Toast>) => {
122
+ setToasts((prev) => prev.map((toast) => (toast.id === id ? { ...toast, ...updates } : toast)));
123
+ }, []);
124
+
125
+ const removeToast = useCallback((id: string) => {
126
+ setToasts((prev) => prev.filter((t) => t.id !== id));
127
+ }, []);
128
+
129
+ const getDefaultIcon = (type: string) => {
130
+ switch (type) {
131
+ case 'success':
132
+ return (
133
+ <svg className="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
134
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
135
+ </svg>
136
+ );
137
+ case 'error':
138
+ return (
139
+ <svg className="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
140
+ <path
141
+ strokeLinecap="round"
142
+ strokeLinejoin="round"
143
+ strokeWidth={2}
144
+ d="M6 18L18 6M6 6l12 12"
145
+ />
146
+ </svg>
147
+ );
148
+ case 'warn':
149
+ return (
150
+ <svg className="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
151
+ <path
152
+ strokeLinecap="round"
153
+ strokeLinejoin="round"
154
+ strokeWidth={2}
155
+ d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.464 0L4.35 16.5c-.77.833.192 2.5 1.732 2.5z"
156
+ />
157
+ </svg>
158
+ );
159
+ case 'upload':
160
+ return (
161
+ <svg
162
+ className="w-5 h-5 shrink-0 animate-spin"
163
+ fill="none"
164
+ viewBox="0 0 24 24"
165
+ stroke="currentColor"
166
+ strokeWidth={2}
167
+ >
168
+ <path
169
+ strokeLinecap="round"
170
+ strokeLinejoin="round"
171
+ d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
172
+ />
173
+ </svg>
174
+ );
175
+ case 'info':
176
+ default:
177
+ return (
178
+ <svg className="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
179
+ <path
180
+ strokeLinecap="round"
181
+ strokeLinejoin="round"
182
+ strokeWidth={2}
183
+ d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
184
+ />
185
+ </svg>
186
+ );
187
+ }
188
+ };
189
+
190
+ return (
191
+ <ToastContext.Provider value={{ showToast, updateToast, removeToast }}>
192
+ {children}
193
+ {/* Regular toasts - top center */}
194
+ <div className="fixed top-7.5 dark:top-20 left-1/2 transform -translate-x-1/2 z-[9999] flex flex-col gap-3 w-full max-w-[480px]">
195
+ {toasts
196
+ .filter((t) => t.type !== 'upload')
197
+ .map((toast) => (
198
+ <ToastItem
199
+ key={toast.id}
200
+ toast={toast}
201
+ onRemove={() => removeToast(toast.id)}
202
+ getDefaultIcon={getDefaultIcon}
203
+ />
204
+ ))}
205
+ </div>
206
+ {/* Upload toasts - bottom right */}
207
+ <div className="fixed bottom-4 right-4 z-[9999] w-[276px] flex flex-col">
208
+ {toasts
209
+ .filter((t) => t.type === 'upload')
210
+ .map((toast) => (
211
+ <ToastItem
212
+ key={toast.id}
213
+ toast={toast}
214
+ onRemove={() => removeToast(toast.id)}
215
+ getDefaultIcon={getDefaultIcon}
216
+ />
217
+ ))}
218
+ </div>
219
+ </ToastContext.Provider>
220
+ );
221
+ }
222
+
223
+ export function useToast() {
224
+ const context = useContext(ToastContext);
225
+ if (!context) {
226
+ throw new Error('useToast must be used within a ToastProvider');
227
+ }
228
+ return context;
229
+ }
@@ -0,0 +1,38 @@
1
+ // UI constants
2
+ export const BREAKPOINTS = {
3
+ xs: 475,
4
+ sm: 640,
5
+ md: 768,
6
+ lg: 1024,
7
+ xl: 1280,
8
+ } as const;
9
+
10
+ // Colors for stat cards
11
+ export const STAT_COLORS = {
12
+ blue: {
13
+ icon: 'text-blue-400',
14
+ bg: 'bg-blue-500/10',
15
+ },
16
+ green: {
17
+ icon: 'text-green-400',
18
+ bg: 'bg-green-500/10',
19
+ },
20
+ purple: {
21
+ icon: 'text-purple-400',
22
+ bg: 'bg-purple-500/10',
23
+ },
24
+ emerald: {
25
+ icon: 'text-emerald-400',
26
+ bg: 'bg-emerald-500/10',
27
+ },
28
+ yellow: {
29
+ icon: 'text-yellow-400',
30
+ bg: 'bg-yellow-500/10',
31
+ },
32
+ } as const;
33
+
34
+ // Storage keys
35
+ export enum StorageKeys {
36
+ AUTH_TOKEN = 'auth_token',
37
+ USER_PREFERENCES = 'user_preferences',
38
+ }
@@ -0,0 +1,165 @@
1
+ import { ColumnType } from '@insforge/shared-schemas';
2
+ import { type ClassValue, clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { z } from 'zod';
5
+ import { format, parse, isValid, parseISO } from 'date-fns';
6
+ import {
7
+ uuidSchema,
8
+ integerSchema,
9
+ floatSchema,
10
+ booleanSchema,
11
+ dateSchema,
12
+ dateTimeSchema,
13
+ jsonSchema,
14
+ stringSchema,
15
+ } from './validation-schemas';
16
+ import { v4 as uuidv4 } from 'uuid';
17
+ import type { ConvertedValue, DisplayValue, ValueConversionResult } from '@/components/datagrid';
18
+
19
+ export function cn(...inputs: ClassValue[]) {
20
+ return twMerge(clsx(inputs));
21
+ }
22
+
23
+ /**
24
+ * Convert and validate a string value based on the specified ColumnType
25
+ */
26
+ export function convertValueForColumn(
27
+ type: ColumnType | string,
28
+ value: string | null | undefined
29
+ ): ValueConversionResult {
30
+ try {
31
+ let convertedValue;
32
+
33
+ switch (type) {
34
+ case ColumnType.UUID:
35
+ convertedValue = uuidSchema.parse(value);
36
+ break;
37
+ case ColumnType.INTEGER:
38
+ convertedValue = integerSchema.parse(value);
39
+ break;
40
+ case ColumnType.FLOAT:
41
+ convertedValue = floatSchema.parse(value);
42
+ break;
43
+ case ColumnType.BOOLEAN:
44
+ convertedValue = booleanSchema.parse(value);
45
+ break;
46
+ case ColumnType.DATE:
47
+ convertedValue = dateSchema.parse(value);
48
+ break;
49
+ case ColumnType.DATETIME:
50
+ convertedValue = dateTimeSchema.parse(value);
51
+ break;
52
+ case ColumnType.JSON:
53
+ convertedValue = jsonSchema.parse(value);
54
+ break;
55
+ case ColumnType.STRING:
56
+ convertedValue = stringSchema.parse(value);
57
+ break;
58
+ default:
59
+ return {
60
+ success: false,
61
+ error: `Unsupported column type: ${type}`,
62
+ };
63
+ }
64
+
65
+ return {
66
+ success: true,
67
+ value: convertedValue,
68
+ };
69
+ } catch (error) {
70
+ if (error instanceof z.ZodError) {
71
+ return {
72
+ success: false,
73
+ error: error.errors[0]?.message || 'Validation failed',
74
+ };
75
+ }
76
+ return {
77
+ success: false,
78
+ error: error instanceof Error ? error.message : 'Unknown conversion error',
79
+ };
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Generate a UUID v4 using the uuid library
85
+ * Works in all browsers and contexts (secure and non-secure)
86
+ * Uses crypto.getRandomValues when available, falls back to Math.random
87
+ */
88
+ export function generateUUID(): string {
89
+ return uuidv4();
90
+ }
91
+
92
+ /**
93
+ * Centralized value formatter that handles all data types consistently
94
+ * Converts database values to formatted display strings for UI components
95
+ */
96
+ export function formatValueForDisplay(value: ConvertedValue, type?: ColumnType): DisplayValue {
97
+ // Handle null/undefined values
98
+ if (isEmptyValue(value)) {
99
+ return 'null';
100
+ }
101
+
102
+ // Handle different column types
103
+ switch (type) {
104
+ case ColumnType.BOOLEAN:
105
+ return value ? 'True' : 'False';
106
+
107
+ case ColumnType.DATE: {
108
+ const date = parse(String(value), 'yyyy-MM-dd', new Date());
109
+ if (!isValid(date)) {
110
+ return String(value);
111
+ }
112
+ const displayValue = format(date, 'MMM dd, yyyy');
113
+ return displayValue;
114
+ }
115
+
116
+ case ColumnType.DATETIME: {
117
+ const date = parseISO(String(value));
118
+ if (!isValid(date)) {
119
+ return String(value);
120
+ }
121
+ const displayValue = format(date, 'MMM dd, yyyy, hh:mm a');
122
+ return displayValue;
123
+ }
124
+
125
+ case ColumnType.JSON: {
126
+ try {
127
+ const parsed = typeof value === 'string' ? JSON.parse(value) : value;
128
+ const formatted =
129
+ parsed && typeof parsed === 'object' ? JSON.stringify(parsed) : String(parsed);
130
+
131
+ return formatted;
132
+ } catch {
133
+ return 'Invalid JSON';
134
+ }
135
+ }
136
+
137
+ case ColumnType.INTEGER:
138
+ case ColumnType.FLOAT: {
139
+ return String(value);
140
+ }
141
+
142
+ case ColumnType.UUID:
143
+ case ColumnType.STRING:
144
+ default: {
145
+ // Convert to string and optionally truncate
146
+ return String(value);
147
+ }
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Check if a value is considered empty for database purposes
153
+ */
154
+ export function isEmptyValue(value: unknown): boolean {
155
+ return value === null || value === undefined || value === '';
156
+ }
157
+
158
+ export const isInsForgeCloudProject = () => {
159
+ return window.location.hostname.endsWith('.insforge.app');
160
+ };
161
+
162
+ export const getBackendUrl = () => {
163
+ const isHttp = window.location.protocol === 'http:';
164
+ return isHttp ? 'http://localhost:7130' : window.location.origin;
165
+ };
@@ -0,0 +1,126 @@
1
+ import { z } from 'zod';
2
+
3
+ export const uuidSchema = z
4
+ .string()
5
+ .uuid({ message: 'Please enter a valid UUID' })
6
+ .or(z.literal('').transform(() => null))
7
+ .or(z.null());
8
+
9
+ export const integerSchema = z
10
+ .union([
11
+ z
12
+ .string()
13
+ .regex(/^-?\d+$/, { message: 'Please enter a valid integer' })
14
+ .transform((val) => {
15
+ const num = parseInt(val, 10);
16
+ if (num < -2147483648 || num > 2147483647) {
17
+ throw new Error(
18
+ 'Integer value out of range. Please enter a value between -2,147,483,648 and 2,147,483,647'
19
+ );
20
+ }
21
+ return num;
22
+ }),
23
+ z.number().int().min(-2147483648).max(2147483647),
24
+ z.literal('').transform(() => null),
25
+ z.null(),
26
+ ])
27
+ .catch(() => {
28
+ throw new Error('Please enter a valid integer');
29
+ });
30
+
31
+ export const floatSchema = z
32
+ .union([
33
+ z
34
+ .string()
35
+ .regex(/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/, {
36
+ message: 'Please enter a valid number',
37
+ })
38
+ .transform((val) => {
39
+ const num = parseFloat(val);
40
+ if (!isFinite(num)) {
41
+ throw new Error('Number value out of range');
42
+ }
43
+ if (Math.abs(num) > 1.7976931348623157e308) {
44
+ throw new Error('Number value exceeds double precision range');
45
+ }
46
+ return num;
47
+ }),
48
+ z.number().finite(),
49
+ z.literal('').transform(() => null),
50
+ z.null(),
51
+ ])
52
+ .catch(() => {
53
+ throw new Error('Please enter a valid number');
54
+ });
55
+
56
+ export const booleanSchema = z
57
+ .union([
58
+ z.boolean(),
59
+ z.string().transform((val) => {
60
+ const lower = val.toLowerCase();
61
+ if (lower === 'true') {
62
+ return true;
63
+ }
64
+ if (lower === 'false') {
65
+ return false;
66
+ }
67
+ if (lower === 'null' || lower === '') {
68
+ return null;
69
+ }
70
+ throw new Error('Please enter a valid boolean value: true, false, or leave empty');
71
+ }),
72
+ z.literal('').transform(() => null),
73
+ z.null(),
74
+ ])
75
+ .catch(() => {
76
+ throw new Error('Please enter a valid boolean value');
77
+ });
78
+
79
+ export const dateSchema = z
80
+ .union([z.string().date(), z.literal('').transform(() => null), z.null()])
81
+ .catch(() => {
82
+ throw new Error('Please enter a valid date');
83
+ });
84
+
85
+ export const dateTimeSchema = z
86
+ .union([
87
+ // ISO 8601 datetime with timezone (Z or ±HH:MM)
88
+ z.string().datetime({ offset: true }),
89
+ z.literal('').transform(() => null),
90
+ z.null(),
91
+ ])
92
+ .catch(() => {
93
+ throw new Error('Please enter a valid datetime');
94
+ });
95
+
96
+ export const jsonSchema = z
97
+ .union([
98
+ z.string().transform((val) => {
99
+ if (val === '' || val === 'null') {
100
+ return null;
101
+ }
102
+ try {
103
+ return JSON.parse(val);
104
+ } catch {
105
+ throw new Error('Please enter valid JSON');
106
+ }
107
+ }),
108
+ z.object({}).passthrough(),
109
+ z.array(z.any()),
110
+ z.null(),
111
+ ])
112
+ .catch(() => {
113
+ throw new Error('Please enter valid JSON');
114
+ });
115
+
116
+ export const stringSchema = z.union([z.string(), z.null()]);
117
+
118
+ export const emailSchema = z.string().email('Invalid email address');
119
+ export const passwordSchema = z.string().min(8, 'Password must be at least 8 characters');
120
+
121
+ export const loginFormSchema = z.object({
122
+ email: emailSchema,
123
+ password: passwordSchema,
124
+ });
125
+
126
+ export type LoginFormData = z.infer<typeof loginFormSchema>;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import { BrowserRouter } from 'react-router-dom';
4
+ import App from './App.tsx';
5
+ import './index.css';
6
+
7
+ const rootElement = document.getElementById('root');
8
+ if (rootElement) {
9
+ ReactDOM.createRoot(rootElement).render(
10
+ <React.StrictMode>
11
+ <BrowserRouter>
12
+ <App />
13
+ </BrowserRouter>
14
+ </React.StrictMode>
15
+ );
16
+ }