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,287 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { Download, ExternalLink } from 'lucide-react';
3
+ import { Dialog, DialogContent } from '@/components/radix/Dialog';
4
+ import { Button } from '@/components/radix/Button';
5
+ import { LoadingState } from '@/components';
6
+ import { storageService } from '@/features/storage/services/storage.service';
7
+ import { StorageFileSchema } from '@insforge/shared-schemas';
8
+ import { TypeBadge } from '@/components/TypeBadge';
9
+
10
+ interface FilePreviewDialogProps {
11
+ open: boolean;
12
+ onOpenChange: (open: boolean) => void;
13
+ file: StorageFileSchema | null;
14
+ bucket: string;
15
+ }
16
+
17
+ export function FilePreviewDialog({ open, onOpenChange, file, bucket }: FilePreviewDialogProps) {
18
+ const [isLoading, setIsLoading] = useState(false);
19
+ const [previewUrl, setPreviewUrl] = useState<string | null>(null);
20
+ const [error, setError] = useState<string | null>(null);
21
+
22
+ // Reset state when file changes
23
+ useEffect(() => {
24
+ if (!file || !open) {
25
+ setPreviewUrl(null);
26
+ setError(null);
27
+ return;
28
+ }
29
+
30
+ const loadPreview = () => {
31
+ if (!file) {
32
+ return;
33
+ }
34
+
35
+ setIsLoading(true);
36
+ setError(null);
37
+
38
+ try {
39
+ const fileBucket = file.bucket || bucket;
40
+ const url = storageService.getDownloadUrl(fileBucket, file.key);
41
+ setPreviewUrl(url);
42
+ } catch (err) {
43
+ const errorMessage = err instanceof Error ? err.message : 'Failed to load preview';
44
+ setError(errorMessage);
45
+ } finally {
46
+ setIsLoading(false);
47
+ }
48
+ };
49
+
50
+ void loadPreview();
51
+ }, [file, open, bucket]);
52
+
53
+ const handleDownload = () => {
54
+ if (!file || !previewUrl) {
55
+ return;
56
+ }
57
+
58
+ try {
59
+ const fileName = file.key.split('/').pop() || file.key;
60
+ const a = document.createElement('a');
61
+ a.href = previewUrl;
62
+ a.download = fileName;
63
+ document.body.appendChild(a);
64
+ a.click();
65
+ document.body.removeChild(a);
66
+ } catch {
67
+ setError('Download failed');
68
+ }
69
+ };
70
+
71
+ const openInNewTab = () => {
72
+ if (previewUrl) {
73
+ window.open(previewUrl, '_blank');
74
+ }
75
+ };
76
+
77
+ const isPreviewable = (mimeType?: string): boolean => {
78
+ if (!mimeType) {
79
+ return false;
80
+ }
81
+ return (
82
+ mimeType.startsWith('image/') ||
83
+ mimeType.startsWith('video/') ||
84
+ mimeType.startsWith('audio/') ||
85
+ mimeType.startsWith('text/') ||
86
+ mimeType === 'application/json' ||
87
+ mimeType === 'application/pdf'
88
+ );
89
+ };
90
+
91
+ const formatFileSize = (bytes: number) => {
92
+ if (bytes < 1024) {
93
+ return `${bytes} B`;
94
+ }
95
+ if (bytes < 1024 * 1024) {
96
+ return `${(bytes / 1024).toFixed(2)} KB`;
97
+ }
98
+ if (bytes < 1024 * 1024 * 1024) {
99
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
100
+ }
101
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
102
+ };
103
+
104
+ const renderPreview = () => {
105
+ if (!file) {
106
+ return null;
107
+ }
108
+
109
+ // Show empty preview template for non-previewable files or errors
110
+ if (!isPreviewable(file.mimeType) || error || !previewUrl) {
111
+ return <div className="bg-neutral-200 dark:bg-neutral-700 w-full h-full rounded" />;
112
+ }
113
+
114
+ const mimeType = file.mimeType || '';
115
+ const fileName = file.key.split('/').pop() || file.key;
116
+
117
+ if (mimeType.startsWith('image/')) {
118
+ return (
119
+ <div className="w-full h-full flex items-center justify-center">
120
+ <img
121
+ src={previewUrl}
122
+ alt={fileName}
123
+ className="max-w-full max-h-full object-contain"
124
+ onError={() => setError('Failed to load image')}
125
+ />
126
+ </div>
127
+ );
128
+ }
129
+
130
+ if (mimeType.startsWith('video/')) {
131
+ return (
132
+ <video
133
+ src={previewUrl}
134
+ controls
135
+ className="w-full h-full"
136
+ onError={() => setError('Failed to load video')}
137
+ >
138
+ Your browser does not support the video tag.
139
+ </video>
140
+ );
141
+ }
142
+
143
+ if (mimeType.startsWith('audio/')) {
144
+ return (
145
+ <div className="flex items-center justify-center w-full h-full bg-gray-200 dark:bg-transparent">
146
+ <audio
147
+ src={previewUrl}
148
+ controls
149
+ className="w-full max-w-md"
150
+ onError={() => setError('Failed to load audio')}
151
+ >
152
+ Your browser does not support the audio tag.
153
+ </audio>
154
+ </div>
155
+ );
156
+ }
157
+
158
+ if (mimeType.startsWith('text/') || mimeType === 'application/json') {
159
+ return <TextPreview url={previewUrl} />;
160
+ }
161
+
162
+ if (mimeType === 'application/pdf') {
163
+ return (
164
+ <div className="w-full h-[602px] overflow-hidden">
165
+ <iframe
166
+ src={`${previewUrl}#toolbar=0&navpanes=0`}
167
+ className="w-full h-full"
168
+ title={fileName}
169
+ onError={() => setError('Failed to load PDF')}
170
+ />
171
+ </div>
172
+ );
173
+ }
174
+
175
+ // Fallback empty preview
176
+ return (
177
+ <div className="bg-neutral-200 dark:bg-neutral-700 w-full h-full min-h-[400px] rounded" />
178
+ );
179
+ };
180
+
181
+ if (!file) {
182
+ return null;
183
+ }
184
+
185
+ const fileName = file.key.split('/').pop() || file.key;
186
+
187
+ return (
188
+ <Dialog open={open} onOpenChange={onOpenChange}>
189
+ <DialogContent className="w-[800px] max-w-[800px] p-0 flex">
190
+ <div className="w-[800px] min-h-[500px] max-h-[820px] bg-white dark:bg-neutral-800 border border-zinc-200 dark:border-neutral-700 flex flex-col">
191
+ {/* Header */}
192
+ <div className="px-6 py-3">
193
+ <div className="flex flex-col items-start gap-1">
194
+ <h2 className="text-lg font-semibold text-zinc-950 dark:text-white">{fileName}</h2>
195
+ <div className="flex items-center gap-1.5">
196
+ <span className="text-xs font-medium text-zinc-500 dark:text-neutral-400">
197
+ {formatFileSize(file.size)}
198
+ </span>
199
+ {file.mimeType && (
200
+ <TypeBadge type={file.mimeType} className="dark:bg-neutral-700" />
201
+ )}
202
+ </div>
203
+ </div>
204
+ </div>
205
+
206
+ {/* Preview Content */}
207
+ <div className="flex flex-1 overflow-hidden p-6 border-y border-zinc-200 dark:border-neutral-600">
208
+ {isLoading ? (
209
+ <div className="flex items-center justify-center w-full min-h-[400px]">
210
+ <LoadingState />
211
+ </div>
212
+ ) : (
213
+ renderPreview()
214
+ )}
215
+ </div>
216
+
217
+ {/* Footer Actions */}
218
+ <div className="px-6 py-6">
219
+ <div className="flex justify-end gap-3">
220
+ <Button
221
+ variant="outline"
222
+ className="flex-1 h-10 px-3 gap-1.5 dark:bg-neutral-600 dark:text-zinc-300 dark:border-neutral-600 dark:hover:bg-neutral-700"
223
+ onClick={handleDownload}
224
+ >
225
+ <Download className="h-5 w-5" />
226
+ <span className="text-sm font-medium dark:text-white">Download</span>
227
+ </Button>
228
+ <Button
229
+ variant="outline"
230
+ className="flex-1 h-10 px-3 gap-1.5 dark:bg-neutral-600 dark:text-zinc-300 dark:border-neutral-600 dark:hover:bg-neutral-700"
231
+ onClick={openInNewTab}
232
+ >
233
+ <ExternalLink className="h-5 w-5" />
234
+ <span className="text-sm font-medium dark:text-white">Open in new tab</span>
235
+ </Button>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </DialogContent>
240
+ </Dialog>
241
+ );
242
+ }
243
+
244
+ // Text file preview component
245
+ function TextPreview({ url }: { url: string }) {
246
+ const [content, setContent] = useState<string>('');
247
+ const [loading, setLoading] = useState(true);
248
+
249
+ useEffect(() => {
250
+ const loadTextContent = async () => {
251
+ try {
252
+ setLoading(true);
253
+ const response = await fetch(url);
254
+ if (!response.ok) {
255
+ throw new Error('Failed to load text content');
256
+ }
257
+
258
+ const text = await response.text();
259
+ // Limit content length for performance
260
+ if (text.length > 100000) {
261
+ setContent(text.substring(0, 100000) + '\n\n... (content truncated due to size)');
262
+ } else {
263
+ setContent(text);
264
+ }
265
+ } catch {
266
+ setContent('Failed to load text content');
267
+ } finally {
268
+ setLoading(false);
269
+ }
270
+ };
271
+ void loadTextContent();
272
+ }, [url]);
273
+
274
+ if (loading) {
275
+ return (
276
+ <div className="flex items-center justify-center h-full w-full min-h-[400px]">
277
+ <LoadingState />
278
+ </div>
279
+ );
280
+ }
281
+
282
+ return (
283
+ <div className="bg-neutral-50 dark:bg-neutral-800 dark:text-neutral-300 rounded p-4 w-full h-full overflow-auto">
284
+ <pre className="text-sm whitespace-pre-wrap break-words">{content}</pre>
285
+ </div>
286
+ );
287
+ }
@@ -0,0 +1,239 @@
1
+ import { useMemo } from 'react';
2
+ import {
3
+ DataGrid,
4
+ createDefaultCellRenderer,
5
+ type DataGridProps,
6
+ type RenderCellProps,
7
+ type DataGridColumn,
8
+ type DataGridRowType,
9
+ } from '@/components/datagrid';
10
+ import { Button } from '@/components/radix/Button';
11
+ import { Download, Eye, Trash2, Image, FileText, Music, Video, Archive, File } from 'lucide-react';
12
+ import { StorageFileSchema } from '@insforge/shared-schemas';
13
+
14
+ // Create a type that makes StorageFileSchema compatible with DataGridRowType
15
+ // This allows StorageFileSchema to be used with the generic DataGrid while maintaining type safety
16
+ type StorageDataGridRow = StorageFileSchema & DataGridRowType;
17
+
18
+ // Custom cell renderers for storage files
19
+ const FileNameRenderer = ({ row, column }: RenderCellProps<StorageDataGridRow>) => {
20
+ const fullPath = String(row[column.key] || '');
21
+ const fileName = fullPath.split('/').pop() || fullPath;
22
+ return (
23
+ <span
24
+ className="text-sm font-medium text-zinc-900 dark:text-zinc-300 truncate"
25
+ title={fullPath}
26
+ >
27
+ {fileName}
28
+ </span>
29
+ );
30
+ };
31
+
32
+ const FileSizeRenderer = ({ row, column }: RenderCellProps<StorageDataGridRow>) => {
33
+ const bytes = Number(row[column.key] || 0);
34
+
35
+ const formatFileSize = (bytes: number) => {
36
+ if (bytes < 1024) {
37
+ return `${bytes} B`;
38
+ }
39
+ if (bytes < 1024 * 1024) {
40
+ return `${(bytes / 1024).toFixed(2)} KB`;
41
+ }
42
+ if (bytes < 1024 * 1024 * 1024) {
43
+ return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
44
+ }
45
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
46
+ };
47
+
48
+ return <span className="text-sm text-zinc-600 dark:text-zinc-300">{formatFileSize(bytes)}</span>;
49
+ };
50
+
51
+ const MimeTypeRenderer = ({ row, column }: RenderCellProps<StorageDataGridRow>) => {
52
+ const mimeType = String(row[column.key] || 'Unknown');
53
+ const category = mimeType.split('/')[0];
54
+
55
+ // Get appropriate icon based on MIME type category
56
+ const getFileIcon = () => {
57
+ switch (category) {
58
+ case 'image':
59
+ return <Image className="h-4 w-4 text-zinc-950 dark:text-zinc-300" />;
60
+ case 'video':
61
+ return <Video className="h-4 w-4 text-zinc-950 dark:text-zinc-300" />;
62
+ case 'audio':
63
+ return <Music className="h-4 w-4 text-zinc-950 dark:text-zinc-300" />;
64
+ case 'text':
65
+ return <FileText className="h-4 w-4 text-zinc-950 dark:text-zinc-300" />;
66
+ case 'application':
67
+ // Check for specific application types
68
+ if (mimeType.includes('zip') || mimeType.includes('tar') || mimeType.includes('rar')) {
69
+ return <Archive className="h-4 w-4 text-zinc-950 dark:text-zinc-300" />;
70
+ }
71
+ if (mimeType.includes('pdf')) {
72
+ return <FileText className="h-4 w-4 text-zinc-950 dark:text-zinc-300" />;
73
+ }
74
+ return <File className="h-4 w-4 text-zinc-950 dark:text-zinc-300" />;
75
+ default:
76
+ return <File className="h-4 w-4 text-zinc-950 dark:text-zinc-300" />;
77
+ }
78
+ };
79
+
80
+ return (
81
+ <div className="flex items-center gap-2.5">
82
+ {getFileIcon()}
83
+ <span className="text-sm text-zinc-500 dark:text-zinc-300">{mimeType}</span>
84
+ </div>
85
+ );
86
+ };
87
+
88
+ // Convert storage files data to DataGrid columns
89
+ export function createStorageColumns(
90
+ onPreview?: (file: StorageFileSchema) => void,
91
+ onDownload?: (file: StorageFileSchema) => void,
92
+ onDelete?: (file: StorageFileSchema) => void,
93
+ isDownloading?: (key: string) => boolean
94
+ ): DataGridColumn<StorageDataGridRow>[] {
95
+ // Create typed cell renderers
96
+ const cellRenderers = createDefaultCellRenderer<StorageDataGridRow>();
97
+
98
+ const columns: DataGridColumn<StorageDataGridRow>[] = [
99
+ {
100
+ key: 'key',
101
+ name: 'Name',
102
+ width: '1fr',
103
+ resizable: true,
104
+ sortable: true,
105
+ renderCell: FileNameRenderer,
106
+ },
107
+ {
108
+ key: 'size',
109
+ name: 'Size',
110
+ width: '1fr',
111
+ resizable: true,
112
+ sortable: true,
113
+ renderCell: FileSizeRenderer,
114
+ },
115
+ {
116
+ key: 'mimeType',
117
+ name: 'Type',
118
+ width: '1fr',
119
+ resizable: true,
120
+ sortable: true,
121
+ renderCell: MimeTypeRenderer,
122
+ },
123
+ {
124
+ key: 'uploadedAt',
125
+ name: 'Uploaded At',
126
+ width: '1fr',
127
+ resizable: true,
128
+ sortable: true,
129
+ renderCell: cellRenderers.datetime,
130
+ },
131
+ ];
132
+
133
+ // Add actions column if any handlers are provided
134
+ if (onPreview || onDownload || onDelete) {
135
+ columns.push({
136
+ key: 'actions',
137
+ name: '',
138
+ maxWidth: 120,
139
+ resizable: false,
140
+ sortable: false,
141
+ renderCell: ({ row }: RenderCellProps<StorageDataGridRow>) => {
142
+ // Type-safe access to the key property
143
+ const fileKey = row.key || String(row['key'] || '');
144
+ const isFileDownloading = isDownloading?.(fileKey) || false;
145
+
146
+ return (
147
+ <div className="flex justify-center">
148
+ {onPreview && (
149
+ <Button
150
+ variant="ghost"
151
+ size="icon"
152
+ className="h-8 w-8"
153
+ onClick={(e) => {
154
+ e.stopPropagation();
155
+ onPreview(row as StorageFileSchema);
156
+ }}
157
+ title="Preview file"
158
+ >
159
+ <Eye className="h-4 w-4 text-zinc-500 dark:text-zinc-300" />
160
+ </Button>
161
+ )}
162
+ {onDownload && (
163
+ <Button
164
+ variant="ghost"
165
+ size="icon"
166
+ className="h-8 w-8"
167
+ onClick={(e) => {
168
+ e.stopPropagation();
169
+ onDownload(row as StorageFileSchema);
170
+ }}
171
+ disabled={isFileDownloading}
172
+ title="Download file"
173
+ >
174
+ <Download className="h-4 w-4 text-zinc-500 dark:text-zinc-300" />
175
+ </Button>
176
+ )}
177
+ {onDelete && (
178
+ <Button
179
+ variant="ghost"
180
+ size="icon"
181
+ className="h-8 w-8 hover:bg-red-50"
182
+ onClick={(e) => {
183
+ e.stopPropagation();
184
+ onDelete(row as StorageFileSchema);
185
+ }}
186
+ title="Delete file"
187
+ >
188
+ <Trash2 className="h-4 w-4 text-red-600 dark:text-red-400" />
189
+ </Button>
190
+ )}
191
+ </div>
192
+ );
193
+ },
194
+ });
195
+ }
196
+
197
+ return columns;
198
+ }
199
+
200
+ // Storage-specific DataGrid props
201
+ export interface StorageDataGridProps extends Omit<DataGridProps<StorageDataGridRow>, 'columns'> {
202
+ onPreview?: (file: StorageFileSchema) => void;
203
+ onDownload?: (file: StorageFileSchema) => void;
204
+ onDelete?: (file: StorageFileSchema) => void;
205
+ isDownloading?: (key: string) => boolean;
206
+ }
207
+
208
+ // Specialized DataGrid for storage files
209
+ export function StorageDataGrid({
210
+ onPreview,
211
+ onDownload,
212
+ onDelete,
213
+ isDownloading,
214
+ ...props
215
+ }: StorageDataGridProps) {
216
+ const columns = useMemo(
217
+ () => createStorageColumns(onPreview, onDownload, onDelete, isDownloading),
218
+ [onPreview, onDownload, onDelete, isDownloading]
219
+ );
220
+
221
+ // Ensure each row has an id for selection
222
+ const dataWithIds = useMemo(() => {
223
+ return props.data.map((file) => ({
224
+ ...file,
225
+ id: file.key, // Use key as id for selection
226
+ }));
227
+ }, [props.data]);
228
+
229
+ return (
230
+ <DataGrid<StorageDataGridRow>
231
+ {...props}
232
+ data={dataWithIds}
233
+ columns={columns}
234
+ showSelection={true}
235
+ showPagination={true}
236
+ rowKeyGetter={(row) => row.key}
237
+ />
238
+ );
239
+ }