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,33 @@
1
+ import * as React from 'react';
2
+ import { cva, type VariantProps } from 'class-variance-authority';
3
+
4
+ import { cn } from '@/lib/utils/utils';
5
+
6
+ const badgeVariants = cva(
7
+ 'inline-flex items-center justify-center rounded text-xs font-medium transition-colors focus:outline-none',
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
12
+ secondary:
13
+ 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
14
+ destructive:
15
+ 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
16
+ outline: 'text-foreground border border-border-gray',
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ variant: 'default',
21
+ },
22
+ }
23
+ );
24
+
25
+ export interface BadgeProps
26
+ extends React.HTMLAttributes<HTMLDivElement>,
27
+ VariantProps<typeof badgeVariants> {}
28
+
29
+ function Badge({ className, variant, ...props }: BadgeProps) {
30
+ return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
31
+ }
32
+
33
+ export { Badge, badgeVariants };
@@ -0,0 +1,50 @@
1
+ import * as React from 'react';
2
+ import { Slot } from '@radix-ui/react-slot';
3
+ import { cva, type VariantProps } from 'class-variance-authority';
4
+
5
+ import { cn } from '@/lib/utils/utils';
6
+
7
+ const buttonVariants = cva(
8
+ 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
13
+ destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
14
+ outline:
15
+ 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
16
+ secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
17
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
18
+ link: 'text-primary underline-offset-4 hover:underline',
19
+ },
20
+ size: {
21
+ default: 'h-9 px-4 py-2',
22
+ sm: 'h-8 rounded-md px-3 text-xs',
23
+ lg: 'h-10 rounded-md px-8',
24
+ icon: 'h-9 w-9',
25
+ },
26
+ },
27
+ defaultVariants: {
28
+ variant: 'default',
29
+ size: 'default',
30
+ },
31
+ }
32
+ );
33
+
34
+ export interface ButtonProps
35
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
36
+ VariantProps<typeof buttonVariants> {
37
+ asChild?: boolean;
38
+ }
39
+
40
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
41
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
42
+ const Comp = asChild ? Slot : 'button';
43
+ return (
44
+ <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
45
+ );
46
+ }
47
+ );
48
+ Button.displayName = 'Button';
49
+
50
+ export { Button, buttonVariants };
@@ -0,0 +1,58 @@
1
+ import * as React from 'react';
2
+
3
+ import { cn } from '@/lib/utils/utils';
4
+
5
+ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
6
+ ({ className, ...props }, ref) => (
7
+ <div
8
+ ref={ref}
9
+ className={cn(
10
+ 'rounded-xl border border-border-gray bg-card text-card-foreground shadow',
11
+ className
12
+ )}
13
+ {...props}
14
+ />
15
+ )
16
+ );
17
+ Card.displayName = 'Card';
18
+
19
+ const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
20
+ ({ className, ...props }, ref) => (
21
+ <div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
22
+ )
23
+ );
24
+ CardHeader.displayName = 'CardHeader';
25
+
26
+ const CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
27
+ ({ className, ...props }, ref) => (
28
+ <div
29
+ ref={ref}
30
+ className={cn('font-semibold leading-none tracking-tight', className)}
31
+ {...props}
32
+ />
33
+ )
34
+ );
35
+ CardTitle.displayName = 'CardTitle';
36
+
37
+ const CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
38
+ ({ className, ...props }, ref) => (
39
+ <div ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
40
+ )
41
+ );
42
+ CardDescription.displayName = 'CardDescription';
43
+
44
+ const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
45
+ ({ className, ...props }, ref) => (
46
+ <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
47
+ )
48
+ );
49
+ CardContent.displayName = 'CardContent';
50
+
51
+ const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
52
+ ({ className, ...props }, ref) => (
53
+ <div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />
54
+ )
55
+ );
56
+ CardFooter.displayName = 'CardFooter';
57
+
58
+ export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
@@ -0,0 +1,98 @@
1
+ import * as React from 'react';
2
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
3
+ import { X } from 'lucide-react';
4
+
5
+ import { cn } from '@/lib/utils/utils';
6
+
7
+ const Dialog = DialogPrimitive.Root;
8
+
9
+ const DialogTrigger = DialogPrimitive.Trigger;
10
+
11
+ const DialogPortal = DialogPrimitive.Portal;
12
+
13
+ const DialogClose = DialogPrimitive.Close;
14
+
15
+ const DialogOverlay = React.forwardRef<
16
+ React.ComponentRef<typeof DialogPrimitive.Overlay>,
17
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
18
+ >(({ className, ...props }, ref) => (
19
+ <DialogPrimitive.Overlay
20
+ ref={ref}
21
+ className={cn(
22
+ 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
23
+ className
24
+ )}
25
+ {...props}
26
+ />
27
+ ));
28
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
29
+
30
+ const DialogContent = React.forwardRef<
31
+ React.ComponentRef<typeof DialogPrimitive.Content>,
32
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
33
+ >(({ className, children, ...props }, ref) => (
34
+ <DialogPortal>
35
+ <DialogOverlay />
36
+ <DialogPrimitive.Content
37
+ ref={ref}
38
+ className={cn(
39
+ 'rounded-lg overflow-hidden fixed left-1/2 top-1/2 z-50 grid w-full max-w-xl -translate-x-1/2 -translate-y-1/2 gap-4 border dark:border-neutral-700 bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
40
+ className
41
+ )}
42
+ {...props}
43
+ >
44
+ {children}
45
+ <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm text-gray-400 dark:text-gray-300 transition-colors hover:text-gray-600 focus:outline-none disabled:pointer-events-none">
46
+ <X className="h-5 w-5" />
47
+ <span className="sr-only">Close</span>
48
+ </DialogPrimitive.Close>
49
+ </DialogPrimitive.Content>
50
+ </DialogPortal>
51
+ ));
52
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
53
+
54
+ const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
55
+ <div className={cn('flex flex-col text-center sm:text-left', className)} {...props} />
56
+ );
57
+ DialogHeader.displayName = 'DialogHeader';
58
+
59
+ const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
60
+ <div
61
+ className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}
62
+ {...props}
63
+ />
64
+ );
65
+ DialogFooter.displayName = 'DialogFooter';
66
+
67
+ const DialogTitle = React.forwardRef<
68
+ React.ComponentRef<typeof DialogPrimitive.Title>,
69
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
70
+ >(({ className, ...props }, ref) => (
71
+ <DialogPrimitive.Title ref={ref} className={cn('text-lg font-semibold', className)} {...props} />
72
+ ));
73
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
74
+
75
+ const DialogDescription = React.forwardRef<
76
+ React.ComponentRef<typeof DialogPrimitive.Description>,
77
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
78
+ >(({ className, ...props }, ref) => (
79
+ <DialogPrimitive.Description
80
+ ref={ref}
81
+ className={cn('text-sm text-muted-foreground', className)}
82
+ {...props}
83
+ />
84
+ ));
85
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
86
+
87
+ export {
88
+ Dialog,
89
+ DialogPortal,
90
+ DialogOverlay,
91
+ DialogClose,
92
+ DialogTrigger,
93
+ DialogContent,
94
+ DialogHeader,
95
+ DialogFooter,
96
+ DialogTitle,
97
+ DialogDescription,
98
+ };
@@ -0,0 +1,185 @@
1
+ import * as React from 'react';
2
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
3
+ import { cn } from '@/lib/utils/utils';
4
+ import { CheckIcon, ChevronRightIcon, DotFilledIcon } from '@radix-ui/react-icons';
5
+
6
+ const DropdownMenu = DropdownMenuPrimitive.Root;
7
+
8
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
9
+
10
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group;
11
+
12
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
13
+
14
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
15
+
16
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
17
+
18
+ const DropdownMenuSubTrigger = React.forwardRef<
19
+ React.ComponentRef<typeof DropdownMenuPrimitive.SubTrigger>,
20
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
21
+ inset?: boolean;
22
+ }
23
+ >(({ className, inset, children, ...props }, ref) => (
24
+ <DropdownMenuPrimitive.SubTrigger
25
+ ref={ref}
26
+ className={cn(
27
+ 'flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
28
+ inset && 'pl-8',
29
+ className
30
+ )}
31
+ {...props}
32
+ >
33
+ {children}
34
+ <ChevronRightIcon className="ml-auto" />
35
+ </DropdownMenuPrimitive.SubTrigger>
36
+ ));
37
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
38
+
39
+ const DropdownMenuSubContent = React.forwardRef<
40
+ React.ComponentRef<typeof DropdownMenuPrimitive.SubContent>,
41
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
42
+ >(({ className, ...props }, ref) => (
43
+ <DropdownMenuPrimitive.SubContent
44
+ ref={ref}
45
+ className={cn(
46
+ 'z-50 min-w-32 overflow-hidden rounded-md border border-border-gray bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--radix-dropdown-menu-content-transform-origin)',
47
+ className
48
+ )}
49
+ {...props}
50
+ />
51
+ ));
52
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
53
+
54
+ const DropdownMenuContent = React.forwardRef<
55
+ React.ComponentRef<typeof DropdownMenuPrimitive.Content>,
56
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
57
+ >(({ className, sideOffset = 4, ...props }, ref) => (
58
+ <DropdownMenuPrimitive.Portal>
59
+ <DropdownMenuPrimitive.Content
60
+ ref={ref}
61
+ sideOffset={sideOffset}
62
+ className={cn(
63
+ 'z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-32 overflow-y-auto overflow-x-hidden rounded-md border border-border-gray dark:border-transparent bg-popover p-2 text-popover-foreground shadow-md',
64
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--radix-dropdown-menu-content-transform-origin)',
65
+ className
66
+ )}
67
+ {...props}
68
+ />
69
+ </DropdownMenuPrimitive.Portal>
70
+ ));
71
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
72
+
73
+ const DropdownMenuItem = React.forwardRef<
74
+ React.ComponentRef<typeof DropdownMenuPrimitive.Item>,
75
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
76
+ inset?: boolean;
77
+ }
78
+ >(({ className, inset, ...props }, ref) => (
79
+ <DropdownMenuPrimitive.Item
80
+ ref={ref}
81
+ className={cn(
82
+ 'relative flex cursor-default select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',
83
+ inset && 'pl-8',
84
+ className
85
+ )}
86
+ {...props}
87
+ />
88
+ ));
89
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
90
+
91
+ const DropdownMenuCheckboxItem = React.forwardRef<
92
+ React.ComponentRef<typeof DropdownMenuPrimitive.CheckboxItem>,
93
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
94
+ >(({ className, children, checked, ...props }, ref) => (
95
+ <DropdownMenuPrimitive.CheckboxItem
96
+ ref={ref}
97
+ className={cn(
98
+ 'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
99
+ className
100
+ )}
101
+ checked={checked}
102
+ {...props}
103
+ >
104
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
105
+ <DropdownMenuPrimitive.ItemIndicator>
106
+ <CheckIcon className="h-4 w-4" />
107
+ </DropdownMenuPrimitive.ItemIndicator>
108
+ </span>
109
+ {children}
110
+ </DropdownMenuPrimitive.CheckboxItem>
111
+ ));
112
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
113
+
114
+ const DropdownMenuRadioItem = React.forwardRef<
115
+ React.ComponentRef<typeof DropdownMenuPrimitive.RadioItem>,
116
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
117
+ >(({ className, children, ...props }, ref) => (
118
+ <DropdownMenuPrimitive.RadioItem
119
+ ref={ref}
120
+ className={cn(
121
+ 'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
122
+ className
123
+ )}
124
+ {...props}
125
+ >
126
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
127
+ <DropdownMenuPrimitive.ItemIndicator>
128
+ <DotFilledIcon className="h-2 w-2 fill-current" />
129
+ </DropdownMenuPrimitive.ItemIndicator>
130
+ </span>
131
+ {children}
132
+ </DropdownMenuPrimitive.RadioItem>
133
+ ));
134
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
135
+
136
+ const DropdownMenuLabel = React.forwardRef<
137
+ React.ComponentRef<typeof DropdownMenuPrimitive.Label>,
138
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
139
+ inset?: boolean;
140
+ }
141
+ >(({ className, inset, ...props }, ref) => (
142
+ <DropdownMenuPrimitive.Label
143
+ ref={ref}
144
+ className={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)}
145
+ {...props}
146
+ />
147
+ ));
148
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
149
+
150
+ const DropdownMenuSeparator = React.forwardRef<
151
+ React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,
152
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
153
+ >(({ className, ...props }, ref) => (
154
+ <DropdownMenuPrimitive.Separator
155
+ ref={ref}
156
+ className={cn('-mx-1 my-1 h-px bg-muted', className)}
157
+ {...props}
158
+ />
159
+ ));
160
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
161
+
162
+ const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
163
+ return (
164
+ <span className={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...props} />
165
+ );
166
+ };
167
+ DropdownMenuShortcut.displayName = 'DropdownMenuShortcut';
168
+
169
+ export {
170
+ DropdownMenu,
171
+ DropdownMenuTrigger,
172
+ DropdownMenuContent,
173
+ DropdownMenuItem,
174
+ DropdownMenuCheckboxItem,
175
+ DropdownMenuRadioItem,
176
+ DropdownMenuLabel,
177
+ DropdownMenuSeparator,
178
+ DropdownMenuShortcut,
179
+ DropdownMenuGroup,
180
+ DropdownMenuPortal,
181
+ DropdownMenuSub,
182
+ DropdownMenuSubContent,
183
+ DropdownMenuSubTrigger,
184
+ DropdownMenuRadioGroup,
185
+ };
@@ -0,0 +1,167 @@
1
+ import * as React from 'react';
2
+ import * as LabelPrimitive from '@radix-ui/react-label';
3
+ import { Slot } from '@radix-ui/react-slot';
4
+ import {
5
+ Controller,
6
+ FormProvider,
7
+ useFormContext,
8
+ type ControllerProps,
9
+ type FieldPath,
10
+ type FieldValues,
11
+ } from 'react-hook-form';
12
+
13
+ import { cn } from '@/lib/utils/utils';
14
+ import { Label } from '@/components/radix/Label';
15
+
16
+ const Form = FormProvider;
17
+
18
+ type FormFieldContextValue<
19
+ TFieldValues extends FieldValues = FieldValues,
20
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
21
+ > = {
22
+ name: TName;
23
+ };
24
+
25
+ const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);
26
+
27
+ const FormField = <
28
+ TFieldValues extends FieldValues = FieldValues,
29
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
30
+ >({
31
+ ...props
32
+ }: ControllerProps<TFieldValues, TName>) => {
33
+ return (
34
+ <FormFieldContext.Provider value={{ name: props.name }}>
35
+ <Controller {...props} />
36
+ </FormFieldContext.Provider>
37
+ );
38
+ };
39
+
40
+ const useFormField = () => {
41
+ const fieldContext = React.useContext(FormFieldContext);
42
+ const itemContext = React.useContext(FormItemContext);
43
+ const { getFieldState, formState } = useFormContext();
44
+
45
+ const fieldState = getFieldState(fieldContext.name, formState);
46
+
47
+ if (!fieldContext) {
48
+ throw new Error('useFormField should be used within <FormField>');
49
+ }
50
+
51
+ const { id } = itemContext;
52
+
53
+ return {
54
+ id,
55
+ name: fieldContext.name,
56
+ formItemId: `${id}-form-item`,
57
+ formDescriptionId: `${id}-form-item-description`,
58
+ formMessageId: `${id}-form-item-message`,
59
+ ...fieldState,
60
+ };
61
+ };
62
+
63
+ type FormItemContextValue = {
64
+ id: string;
65
+ };
66
+
67
+ const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);
68
+
69
+ const FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
70
+ ({ className, ...props }, ref) => {
71
+ const id = React.useId();
72
+
73
+ return (
74
+ <FormItemContext.Provider value={{ id }}>
75
+ <div ref={ref} className={cn('space-y-2', className)} {...props} />
76
+ </FormItemContext.Provider>
77
+ );
78
+ }
79
+ );
80
+ FormItem.displayName = 'FormItem';
81
+
82
+ const FormLabel = React.forwardRef<
83
+ React.ComponentRef<typeof LabelPrimitive.Root>,
84
+ React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
85
+ >(({ className, ...props }, ref) => {
86
+ const { error, formItemId } = useFormField();
87
+
88
+ return (
89
+ <Label
90
+ ref={ref}
91
+ className={cn(error && 'text-destructive', className)}
92
+ htmlFor={formItemId}
93
+ {...props}
94
+ />
95
+ );
96
+ });
97
+ FormLabel.displayName = 'FormLabel';
98
+
99
+ const FormControl = React.forwardRef<
100
+ React.ComponentRef<typeof Slot>,
101
+ React.ComponentPropsWithoutRef<typeof Slot>
102
+ >(({ ...props }, ref) => {
103
+ const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
104
+
105
+ return (
106
+ <Slot
107
+ ref={ref}
108
+ id={formItemId}
109
+ aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}
110
+ aria-invalid={!!error}
111
+ {...props}
112
+ />
113
+ );
114
+ });
115
+ FormControl.displayName = 'FormControl';
116
+
117
+ const FormDescription = React.forwardRef<
118
+ HTMLParagraphElement,
119
+ React.HTMLAttributes<HTMLParagraphElement>
120
+ >(({ className, ...props }, ref) => {
121
+ const { formDescriptionId } = useFormField();
122
+
123
+ return (
124
+ <p
125
+ ref={ref}
126
+ id={formDescriptionId}
127
+ className={cn('text-[0.8rem] text-muted-foreground', className)}
128
+ {...props}
129
+ />
130
+ );
131
+ });
132
+ FormDescription.displayName = 'FormDescription';
133
+
134
+ const FormMessage = React.forwardRef<
135
+ HTMLParagraphElement,
136
+ React.HTMLAttributes<HTMLParagraphElement>
137
+ >(({ className, children, ...props }, ref) => {
138
+ const { error, formMessageId } = useFormField();
139
+ const body = error ? String(error?.message ?? '') : children;
140
+
141
+ if (!body) {
142
+ return null;
143
+ }
144
+
145
+ return (
146
+ <p
147
+ ref={ref}
148
+ id={formMessageId}
149
+ className={cn('text-[0.8rem] font-medium text-destructive', className)}
150
+ {...props}
151
+ >
152
+ {body}
153
+ </p>
154
+ );
155
+ });
156
+ FormMessage.displayName = 'FormMessage';
157
+
158
+ export {
159
+ useFormField,
160
+ Form,
161
+ FormItem,
162
+ FormLabel,
163
+ FormControl,
164
+ FormDescription,
165
+ FormMessage,
166
+ FormField,
167
+ };
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+
3
+ import { cn } from '@/lib/utils/utils';
4
+
5
+ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(
6
+ ({ className, type, ...props }, ref) => {
7
+ return (
8
+ <input
9
+ type={type}
10
+ className={cn(
11
+ 'flex w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus:border-black dark:focus:border-neutral-500 focus:outline-none! focus:ring-0! focus:ring-offset-0! disabled:cursor-not-allowed disabled:opacity-50',
12
+ className
13
+ )}
14
+ ref={ref}
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+ );
20
+ Input.displayName = 'Input';
21
+
22
+ export { Input };
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ import * as LabelPrimitive from '@radix-ui/react-label';
3
+ import { cva, type VariantProps } from 'class-variance-authority';
4
+
5
+ import { cn } from '@/lib/utils/utils';
6
+
7
+ const labelVariants = cva(
8
+ 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
9
+ );
10
+
11
+ const Label = React.forwardRef<
12
+ React.ComponentRef<typeof LabelPrimitive.Root>,
13
+ React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>
14
+ >(({ className, ...props }, ref) => (
15
+ <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
16
+ ));
17
+ Label.displayName = LabelPrimitive.Root.displayName;
18
+
19
+ export { Label };
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
3
+
4
+ import { cn } from '@/lib/utils/utils';
5
+
6
+ const Popover = PopoverPrimitive.Root;
7
+
8
+ const PopoverTrigger = PopoverPrimitive.Trigger;
9
+
10
+ const PopoverContent = React.forwardRef<
11
+ React.ComponentRef<typeof PopoverPrimitive.Content>,
12
+ React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
13
+ >(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
14
+ <PopoverPrimitive.Portal>
15
+ <PopoverPrimitive.Content
16
+ ref={ref}
17
+ align={align}
18
+ sideOffset={sideOffset}
19
+ className={cn(
20
+ 'z-50 w-72 rounded-md border border-border-gray bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
21
+ className
22
+ )}
23
+ {...props}
24
+ />
25
+ </PopoverPrimitive.Portal>
26
+ ));
27
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
28
+
29
+ export { Popover, PopoverTrigger, PopoverContent };