insforge 0.3.3 → 1.2.10

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 (507) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.cursor/rules/cursor-rules.mdc +94 -0
  3. package/.dockerignore +3 -0
  4. package/.env.example +33 -4
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
  6. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
  8. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  9. package/.github/workflows/build-image.yml +2 -1
  10. package/.github/workflows/e2e.yml +63 -0
  11. package/CHANGELOG.md +41 -0
  12. package/CLAUDE_PLUGIN.md +104 -0
  13. package/CODE_OF_CONDUCT.md +128 -0
  14. package/CONTRIBUTING.md +1 -1
  15. package/Dockerfile +4 -1
  16. package/README.md +66 -18
  17. package/assets/mcpInstallv2.png +0 -0
  18. package/assets/sampleResponse.png +0 -0
  19. package/auth/index.html +13 -0
  20. package/auth/package.json +28 -0
  21. package/auth/public/favicon.ico +0 -0
  22. package/auth/src/App.tsx +33 -0
  23. package/auth/src/components/ErrorCard.tsx +37 -0
  24. package/auth/src/components/Layout.tsx +13 -0
  25. package/auth/src/index.css +19 -0
  26. package/auth/src/lib/broadcastService.ts +115 -0
  27. package/auth/src/lib/utils.ts +11 -0
  28. package/auth/src/main.tsx +22 -0
  29. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  30. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  31. package/auth/src/pages/SignInPage.tsx +57 -0
  32. package/auth/src/pages/SignUpPage.tsx +57 -0
  33. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  34. package/auth/src/vite-env.d.ts +10 -0
  35. package/auth/tsconfig.json +32 -0
  36. package/auth/tsconfig.node.json +11 -0
  37. package/auth/vite.config.ts +25 -0
  38. package/backend/package.json +9 -9
  39. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  40. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  41. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
  42. package/backend/src/api/routes/auth/index.routes.ts +570 -0
  43. package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
  44. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
  45. package/backend/src/api/routes/database/index.routes.ts +13 -0
  46. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
  47. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
  48. package/backend/src/api/routes/docs/index.routes.ts +76 -0
  49. package/backend/src/api/routes/functions/index.routes.ts +188 -0
  50. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  51. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
  52. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  53. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
  54. package/backend/src/api/routes/usage/index.routes.ts +89 -0
  55. package/backend/src/infra/config/app.config.ts +51 -0
  56. package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
  57. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  58. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  59. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  60. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  61. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  62. package/backend/src/infra/security/token.manager.ts +125 -0
  63. package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
  64. package/backend/src/providers/ai/openrouter.provider.ts +377 -0
  65. package/backend/src/providers/email/base.provider.ts +41 -0
  66. package/backend/src/providers/email/cloud.provider.ts +187 -0
  67. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  68. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  69. package/backend/src/providers/logs/local.provider.ts +185 -0
  70. package/backend/src/providers/oauth/base.provider.ts +29 -0
  71. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  72. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  73. package/backend/src/providers/oauth/github.provider.ts +208 -0
  74. package/backend/src/providers/oauth/google.provider.ts +249 -0
  75. package/backend/src/providers/oauth/index.ts +7 -0
  76. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  77. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  78. package/backend/src/providers/oauth/x.provider.ts +202 -0
  79. package/backend/src/providers/storage/base.provider.ts +29 -0
  80. package/backend/src/providers/storage/local.provider.ts +103 -0
  81. package/backend/src/providers/storage/s3.provider.ts +313 -0
  82. package/backend/src/server.ts +70 -74
  83. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  84. package/backend/src/services/ai/ai-model.service.ts +60 -0
  85. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  86. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  87. package/backend/src/services/ai/helpers.ts +64 -0
  88. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  89. package/backend/src/services/ai/index.ts +13 -0
  90. package/backend/src/services/auth/auth-config.service.ts +250 -0
  91. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  92. package/backend/src/services/auth/auth.service.ts +1136 -0
  93. package/backend/src/services/auth/index.ts +4 -0
  94. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  95. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  96. package/backend/src/services/database/database-table.service.ts +811 -0
  97. package/backend/src/services/email/email.service.ts +75 -0
  98. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  99. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  100. package/backend/src/services/logs/log.service.ts +73 -0
  101. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  102. package/backend/src/services/storage/storage.service.ts +617 -0
  103. package/backend/src/services/usage/usage.service.ts +149 -0
  104. package/backend/src/types/auth.ts +66 -2
  105. package/backend/src/types/email.ts +8 -0
  106. package/backend/src/types/error-constants.ts +4 -0
  107. package/backend/src/types/logs.ts +0 -29
  108. package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
  109. package/backend/src/utils/environment.ts +9 -3
  110. package/backend/src/utils/logger.ts +20 -2
  111. package/backend/src/utils/seed.ts +150 -57
  112. package/backend/src/utils/sql-parser.ts +1 -1
  113. package/backend/src/utils/utils.ts +114 -0
  114. package/backend/src/utils/validations.ts +40 -4
  115. package/backend/tests/local/test-ai-config.sh +129 -0
  116. package/backend/tests/local/test-ai-usage.sh +80 -0
  117. package/backend/tests/local/test-auth-router.sh +1 -1
  118. package/backend/tests/local/test-e2e.sh +1 -1
  119. package/backend/tests/local/test-functions.sh +123 -0
  120. package/backend/tests/local/test-logs.sh +132 -0
  121. package/backend/tests/local/test-public-bucket.sh +3 -3
  122. package/backend/tests/local/test-secrets.sh +14 -12
  123. package/backend/tests/local/test-traditional-rest.sh +2 -2
  124. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  125. package/backend/tests/test-config.sh +37 -1
  126. package/backend/tests/unit/cloud-token.test.ts +48 -0
  127. package/backend/tests/unit/constant.test.ts +8 -0
  128. package/backend/tests/unit/email.test.ts +372 -0
  129. package/backend/tests/unit/environment.test.ts +59 -0
  130. package/backend/tests/unit/helpers.test.ts +63 -0
  131. package/backend/tests/unit/logger.test.ts +22 -0
  132. package/backend/tests/unit/rate-limit.test.ts +154 -0
  133. package/backend/tests/unit/response.test.ts +58 -0
  134. package/backend/tests/unit/sql-parser.test.ts +74 -0
  135. package/backend/tests/unit/uuid.test.ts +21 -0
  136. package/backend/tests/unit/validations.test.ts +80 -0
  137. package/backend/tsconfig.json +1 -1
  138. package/backend/vitest.config.ts +11 -0
  139. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  140. package/claude-plugin/README.md +133 -0
  141. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  142. package/docker-compose.prod.yml +60 -4
  143. package/docker-compose.yml +65 -4
  144. package/docker-init/db/db-init.sql +6 -34
  145. package/docker-init/logs/vector.yml +236 -0
  146. package/docs/README.md +44 -0
  147. package/docs/changelog.mdx +67 -0
  148. package/docs/core-concepts/ai/architecture.mdx +373 -0
  149. package/docs/core-concepts/ai/sdk.mdx +213 -0
  150. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  151. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  152. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  153. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  154. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  155. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  156. package/docs/core-concepts/database/architecture.mdx +256 -0
  157. package/docs/core-concepts/database/sdk.mdx +382 -0
  158. package/docs/core-concepts/functions/architecture.mdx +105 -0
  159. package/docs/core-concepts/functions/sdk.mdx +184 -0
  160. package/docs/core-concepts/storage/architecture.mdx +243 -0
  161. package/docs/core-concepts/storage/sdk.mdx +253 -0
  162. package/docs/deployment/README.md +94 -0
  163. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  164. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  165. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  166. package/docs/deployment/deploy-to-render.md +441 -0
  167. package/docs/docs.json +210 -0
  168. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  169. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  170. package/docs/examples/framework-guides/react.mdx +165 -0
  171. package/docs/examples/framework-guides/svelte.mdx +153 -0
  172. package/docs/examples/framework-guides/vue.mdx +159 -0
  173. package/docs/examples/overview.mdx +67 -0
  174. package/docs/favicon.svg +19 -0
  175. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  176. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  177. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  178. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  179. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  180. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  181. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  182. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  183. package/docs/images/checks-passed.png +0 -0
  184. package/docs/images/dashboard-connect-expanded.png +0 -0
  185. package/docs/images/dashboard-connect.png +0 -0
  186. package/docs/images/hero-dark.png +0 -0
  187. package/docs/images/hero-light.png +0 -0
  188. package/docs/images/icons/ai.svg +4 -0
  189. package/docs/images/icons/auth.svg +1 -0
  190. package/docs/images/icons/database.svg +1 -0
  191. package/docs/images/icons/function.svg +1 -0
  192. package/docs/images/icons/storage.svg +1 -0
  193. package/docs/images/logos/nextjs.svg +4 -0
  194. package/docs/images/logos/nuxt.svg +4 -0
  195. package/docs/images/logos/react.svg +5 -0
  196. package/docs/images/logos/svelte.svg +4 -0
  197. package/docs/images/logos/vue.svg +5 -0
  198. package/docs/images/mcp-install.png +0 -0
  199. package/docs/images/onboarding-mcp.png +0 -0
  200. package/docs/insforge-instructions-sdk.md +55 -374
  201. package/docs/introduction.mdx +45 -0
  202. package/docs/logo/dark.svg +22 -0
  203. package/docs/logo/light.svg +20 -0
  204. package/docs/partnership.mdx +647 -0
  205. package/docs/quickstart.mdx +83 -0
  206. package/docs/showcase/2048-arena.png +0 -0
  207. package/docs/showcase/framegen-cloud.png +0 -0
  208. package/docs/showcase/line-connect-race.png +0 -0
  209. package/docs/showcase/moment-vibe.png +0 -0
  210. package/docs/showcase/national-flags.png +0 -0
  211. package/docs/showcase/pokemon-vibe.png +0 -0
  212. package/docs/showcase/pure-browse-buy.png +0 -0
  213. package/docs/showcase.mdx +52 -0
  214. package/docs/snippets/sdk-installation.mdx +22 -0
  215. package/docs/snippets/service-icons.mdx +27 -0
  216. package/eslint.config.js +10 -3
  217. package/frontend/package.json +10 -4
  218. package/frontend/src/App.tsx +13 -82
  219. package/frontend/src/assets/icons/connected.svg +3 -0
  220. package/frontend/src/assets/icons/loader.svg +9 -0
  221. package/frontend/src/assets/logos/apple.svg +4 -0
  222. package/frontend/src/assets/logos/discord.svg +1 -1
  223. package/frontend/src/assets/logos/facebook.svg +3 -0
  224. package/frontend/src/assets/logos/instagram.svg +2 -0
  225. package/frontend/src/assets/logos/linkedin.svg +3 -0
  226. package/frontend/src/assets/logos/microsoft.svg +1 -0
  227. package/frontend/src/assets/logos/spotify.svg +17 -0
  228. package/frontend/src/assets/logos/tiktok.svg +6 -0
  229. package/frontend/src/assets/logos/x.svg +3 -0
  230. package/frontend/src/components/Checkbox.tsx +27 -29
  231. package/frontend/src/components/CodeBlock.tsx +55 -2
  232. package/frontend/src/components/CodeEditor.tsx +92 -0
  233. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  234. package/frontend/src/components/ConnectCTA.tsx +38 -0
  235. package/frontend/src/components/CopyButton.tsx +52 -15
  236. package/frontend/src/components/ErrorState.tsx +1 -2
  237. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  238. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  239. package/frontend/src/components/JsonHighlight.tsx +21 -9
  240. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  241. package/frontend/src/components/PromptDialog.tsx +1 -4
  242. package/frontend/src/components/SearchInput.tsx +1 -2
  243. package/frontend/src/components/Stepper.tsx +53 -0
  244. package/frontend/src/components/ThemeToggle.tsx +3 -3
  245. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  246. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  247. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  248. package/frontend/src/components/datagrid/index.ts +23 -0
  249. package/frontend/src/components/index.ts +23 -30
  250. package/frontend/src/components/layout/AppHeader.tsx +133 -92
  251. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  252. package/frontend/src/components/layout/Layout.tsx +12 -23
  253. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  254. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  255. package/frontend/src/components/layout/index.ts +5 -0
  256. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  257. package/frontend/src/components/radix/index.ts +22 -0
  258. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  259. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  260. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  261. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  262. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  263. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  264. package/frontend/src/features/ai/components/index.ts +6 -0
  265. package/frontend/src/features/ai/helpers.ts +57 -71
  266. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  267. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  268. package/frontend/src/features/ai/page/AIPage.tsx +67 -79
  269. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  270. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  271. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
  272. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  273. package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
  274. package/frontend/src/features/auth/components/index.ts +5 -0
  275. package/frontend/src/features/auth/helpers.tsx +200 -0
  276. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  277. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  278. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  279. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  280. package/frontend/src/features/auth/index.ts +3 -2
  281. package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
  282. package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
  283. package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
  284. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  285. package/frontend/src/features/auth/services/config.service.ts +19 -0
  286. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  287. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  288. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  289. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  290. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  291. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  292. package/frontend/src/features/dashboard/components/index.ts +4 -0
  293. package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
  294. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  295. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  296. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  297. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  298. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  299. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  300. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  301. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  302. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  303. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  304. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  305. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  306. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  307. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  308. package/frontend/src/features/database/components/TableForm.tsx +28 -15
  309. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  310. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  311. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  312. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  313. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  314. package/frontend/src/features/database/components/index.ts +19 -0
  315. package/frontend/src/features/database/constants.ts +28 -2
  316. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  317. package/frontend/src/features/database/helpers.ts +2 -2
  318. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  319. package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
  320. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  321. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  322. package/frontend/src/features/database/hooks/useTables.ts +131 -0
  323. package/frontend/src/features/database/index.ts +6 -1
  324. package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
  325. package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
  326. package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
  327. package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
  328. package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
  329. package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
  330. package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
  331. package/frontend/src/features/database/services/advance.service.ts +66 -0
  332. package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
  333. package/frontend/src/features/database/services/table.service.ts +64 -0
  334. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  335. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  336. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  337. package/frontend/src/features/database/templates/index.ts +34 -0
  338. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  339. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  340. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  341. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  342. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  343. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  344. package/frontend/src/features/functions/components/index.ts +5 -0
  345. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  346. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  347. package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
  348. package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
  349. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  350. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  351. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  352. package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
  353. package/frontend/src/features/login/page/LoginPage.tsx +16 -23
  354. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  355. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  356. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  357. package/frontend/src/features/logs/components/index.ts +2 -0
  358. package/frontend/src/features/logs/helpers.ts +24 -0
  359. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  360. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  361. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  362. package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
  363. package/frontend/src/features/logs/index.ts +8 -2
  364. package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
  365. package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
  366. package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
  367. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  368. package/frontend/src/features/logs/services/log.service.ts +15 -110
  369. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  370. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  371. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  372. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  373. package/frontend/src/features/onboard/components/index.ts +4 -0
  374. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  375. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  376. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  377. package/frontend/src/features/onboard/index.ts +13 -3
  378. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  379. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  380. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  381. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  382. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  383. package/frontend/src/features/storage/components/index.ts +12 -0
  384. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  385. package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
  386. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  387. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  388. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  389. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  390. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  391. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  392. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
  393. package/frontend/src/index.css +1 -0
  394. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  395. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  396. package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
  397. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  398. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  399. package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
  400. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  401. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  402. package/frontend/src/lib/utils/menuItems.ts +183 -0
  403. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  404. package/frontend/src/lib/utils/utils.ts +19 -1
  405. package/frontend/src/vite-env.d.ts +1 -0
  406. package/frontend/vite.config.ts +5 -3
  407. package/functions/server.ts +28 -3
  408. package/functions/worker-template.js +15 -4
  409. package/i18n/README.ar.md +130 -0
  410. package/i18n/README.de.md +130 -0
  411. package/i18n/README.es.md +154 -0
  412. package/i18n/README.fr.md +134 -0
  413. package/i18n/README.hi.md +129 -0
  414. package/i18n/README.ja.md +174 -0
  415. package/i18n/README.ko.md +137 -0
  416. package/i18n/README.pt-BR.md +131 -0
  417. package/i18n/README.ru.md +129 -0
  418. package/i18n/README.zh-CN.md +133 -0
  419. package/openapi/ai.yaml +31 -4
  420. package/openapi/auth.yaml +827 -146
  421. package/package.json +16 -7
  422. package/shared-schemas/package.json +1 -1
  423. package/shared-schemas/src/ai-api.schema.ts +34 -58
  424. package/shared-schemas/src/ai.schema.ts +5 -0
  425. package/shared-schemas/src/auth-api.schema.ts +154 -8
  426. package/shared-schemas/src/auth.schema.ts +42 -6
  427. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  428. package/shared-schemas/src/database-api.schema.ts +3 -3
  429. package/shared-schemas/src/database.schema.ts +1 -1
  430. package/shared-schemas/src/index.ts +1 -0
  431. package/shared-schemas/src/logs-api.schema.ts +7 -1
  432. package/shared-schemas/src/logs.schema.ts +26 -0
  433. package/shared-schemas/src/metadata.schema.ts +9 -4
  434. package/test-gemini.sh +35 -0
  435. package/test-usage-admin.sh +57 -0
  436. package/test-usage.sh +50 -0
  437. package/zeabur/README.md +13 -0
  438. package/zeabur/template.yml +1032 -0
  439. package/.github/workflows/deploy-aws.yml +0 -130
  440. package/backend/src/api/routes/agent.ts +0 -29
  441. package/backend/src/api/routes/auth.oauth.ts +0 -482
  442. package/backend/src/api/routes/auth.ts +0 -386
  443. package/backend/src/api/routes/docs.ts +0 -66
  444. package/backend/src/api/routes/functions.ts +0 -183
  445. package/backend/src/api/routes/openapi.ts +0 -82
  446. package/backend/src/api/routes/usage.ts +0 -96
  447. package/backend/src/core/ai/client.ts +0 -242
  448. package/backend/src/core/ai/model.ts +0 -117
  449. package/backend/src/core/auth/auth.ts +0 -780
  450. package/backend/src/core/database/table.ts +0 -772
  451. package/backend/src/core/documentation/agent.ts +0 -689
  452. package/backend/src/core/documentation/openapi.ts +0 -856
  453. package/backend/src/core/logs/analytics.ts +0 -76
  454. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  455. package/backend/src/core/storage/storage.ts +0 -923
  456. package/backend/src/utils/cloud-token.ts +0 -39
  457. package/backend/src/utils/helpers.ts +0 -49
  458. package/backend/src/utils/uuid.ts +0 -9
  459. package/backend/tests/manual/test-better-auth.sh +0 -303
  460. package/docker-init/db/logs.sql +0 -9
  461. package/frontend/README.md +0 -112
  462. package/frontend/src/components/datagrid/index.tsx +0 -20
  463. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  464. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  465. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  466. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  467. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  468. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  469. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  470. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  471. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  472. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  473. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  474. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  475. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  476. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  477. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  478. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  479. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  480. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  481. package/frontend/src/features/metadata/index.ts +0 -0
  482. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  483. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  484. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  485. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  486. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  487. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  488. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  489. package/frontend/src/features/onboard/types.ts +0 -8
  490. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  491. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  492. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  493. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  494. /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
  495. /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
  496. /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
  497. /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
  498. /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
  499. /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
  500. /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
  501. /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
  502. /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
  503. /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
  504. /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
  505. /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
  506. /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
  507. /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
@@ -0,0 +1,58 @@
1
+ import { successResponse, errorResponse, paginatedResponse } from '../../src/utils/response';
2
+ import { Response } from 'express';
3
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
4
+
5
+ describe('Response Utilities', () => {
6
+ let res: Partial<Response>;
7
+
8
+ beforeEach(() => {
9
+ res = {
10
+ status: vi.fn().mockReturnThis(),
11
+ json: vi.fn().mockReturnThis(),
12
+ setHeader: vi.fn().mockReturnThis(),
13
+ };
14
+ });
15
+
16
+ it('successResponse returns data with correct status', () => {
17
+ const data = { message: 'ok' };
18
+ successResponse(res as Response, data, 201);
19
+ expect(res.status).toHaveBeenCalledWith(201);
20
+ expect(res.json).toHaveBeenCalledWith(data);
21
+ });
22
+
23
+ it('errorResponse returns error with correct status', () => {
24
+ const error = 'ERROR';
25
+ const message = 'Something went wrong';
26
+ errorResponse(res as Response, error, message, 400, 'Retry');
27
+ expect(res.status).toHaveBeenCalledWith(400);
28
+ expect(res.json).toHaveBeenCalledWith({
29
+ error,
30
+ message,
31
+ statusCode: 400,
32
+ nextActions: 'Retry',
33
+ });
34
+ });
35
+
36
+ it('paginatedResponse sets headers and status correctly', () => {
37
+ const data = [1, 2, 3];
38
+ const total = 10;
39
+ const offset = 0;
40
+
41
+ paginatedResponse(res as Response, data, total, offset);
42
+
43
+ expect(res.setHeader).toHaveBeenCalledWith('Content-Range', '0-2/10');
44
+ expect(res.setHeader).toHaveBeenCalledWith('Preference-Applied', 'count=exact');
45
+ expect(res.status).toHaveBeenCalledWith(206); // partial content
46
+ expect(res.json).toHaveBeenCalledWith(data);
47
+ });
48
+
49
+ it('paginatedResponse returns 200 when all items returned', () => {
50
+ const data = [1, 2, 3];
51
+ const total = 3;
52
+ const offset = 0;
53
+
54
+ paginatedResponse(res as Response, data, total, offset);
55
+
56
+ expect(res.status).toHaveBeenCalledWith(200);
57
+ });
58
+ });
@@ -0,0 +1,74 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { parseSQLStatements } from '../../src/utils/sql-parser';
3
+
4
+ describe('parseSQLStatements', () => {
5
+ it('splits multiple statements by semicolon', () => {
6
+ const sql = `
7
+ SELECT * FROM users;
8
+ INSERT INTO users (name) VALUES ('John');
9
+ DELETE FROM users WHERE id = 1;
10
+ `;
11
+ const result = parseSQLStatements(sql);
12
+ expect(result).toEqual([
13
+ 'SELECT * FROM users',
14
+ "INSERT INTO users (name) VALUES ('John')",
15
+ 'DELETE FROM users WHERE id = 1',
16
+ ]);
17
+ });
18
+
19
+ it('ignores line comments', () => {
20
+ const sql = `
21
+ -- This is a comment
22
+ SELECT * FROM users; -- Inline comment
23
+ `;
24
+ const result = parseSQLStatements(sql);
25
+ // Parser returns the statement with comments filtered out
26
+ expect(result).toHaveLength(1);
27
+ expect(result[0]).toContain('SELECT * FROM users');
28
+ });
29
+
30
+ it('ignores block comments', () => {
31
+ const sql = `
32
+ /* Block comment */
33
+ SELECT * FROM users;
34
+ /* Another comment */
35
+ `;
36
+ const result = parseSQLStatements(sql);
37
+ // Parser returns the statement with comments filtered out
38
+ expect(result).toHaveLength(1);
39
+ expect(result[0]).toContain('SELECT * FROM users');
40
+ });
41
+
42
+ it('handles semicolons inside string literals', () => {
43
+ const sql = `INSERT INTO messages (text) VALUES ('Hello; World')`;
44
+ const result = parseSQLStatements(sql);
45
+ // Parser includes the trailing semicolon
46
+ expect(result).toEqual([`INSERT INTO messages (text) VALUES ('Hello; World')`]);
47
+ });
48
+
49
+ it('throws error on empty input', () => {
50
+ expect(() => parseSQLStatements('')).toThrow();
51
+ });
52
+
53
+ it('returns empty array for comments-only SQL', () => {
54
+ const sql = `
55
+ -- Only comment
56
+ /* Another comment */
57
+ `;
58
+ const result = parseSQLStatements(sql);
59
+ // Parser filters out comment-only content
60
+ expect(result).toEqual([]);
61
+ });
62
+
63
+ it('trims statements and removes empty results', () => {
64
+ const sql = `
65
+ SELECT * FROM users;
66
+ -- comment
67
+ INSERT INTO users (id) VALUES (1);
68
+ `;
69
+ const result = parseSQLStatements(sql);
70
+ expect(result.length).toBeGreaterThan(0);
71
+ expect(result[0]).toContain('SELECT * FROM users');
72
+ expect(result[result.length - 1] || result[0]).toContain('INSERT INTO users');
73
+ });
74
+ });
@@ -0,0 +1,21 @@
1
+ import { describe, test, expect } from 'vitest';
2
+ import { generateUUID } from '../../src/utils/utils';
3
+
4
+ describe('generateUUID', () => {
5
+ const uuidV4Regex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
6
+
7
+ test('returns a string', () => {
8
+ const uuid = generateUUID();
9
+ expect(typeof uuid).toBe('string');
10
+ });
11
+
12
+ test('returns a valid UUID v4', () => {
13
+ const uuid = generateUUID();
14
+ expect(uuid).toMatch(uuidV4Regex);
15
+ });
16
+
17
+ test('generates unique UUIDs on multiple calls', () => {
18
+ const uuids = new Set(Array.from({ length: 10 }, () => generateUUID()));
19
+ expect(uuids.size).toBe(10);
20
+ });
21
+ });
@@ -0,0 +1,80 @@
1
+ import {
2
+ validateEmail,
3
+ validateIdentifier,
4
+ isValidIdentifier,
5
+ validateTableName,
6
+ getIdentifierErrorMessage,
7
+ escapeSqlLikePattern,
8
+ escapeRegexPattern,
9
+ } from '../../src/utils/validations';
10
+ import { AppError } from '../../src/api/middleware/error';
11
+ import { describe, test, expect } from 'vitest';
12
+
13
+ describe('Validations Utils', () => {
14
+ describe('validateEmail', () => {
15
+ test('valid email returns true', () => {
16
+ expect(validateEmail('test@example.com')).toBe(true);
17
+ });
18
+
19
+ test('invalid email returns false', () => {
20
+ expect(validateEmail('invalid-email')).toBe(false);
21
+ });
22
+ });
23
+
24
+ describe('validateIdentifier', () => {
25
+ test('valid identifier returns true', () => {
26
+ expect(validateIdentifier('my_table')).toBe(true);
27
+ });
28
+
29
+ test('empty identifier throws AppError', () => {
30
+ expect(() => validateIdentifier('')).toThrow(AppError);
31
+ });
32
+
33
+ test('identifier with quotes throws AppError', () => {
34
+ expect(() => validateIdentifier('bad"identifier')).toThrow(AppError);
35
+ });
36
+ });
37
+
38
+ describe('isValidIdentifier', () => {
39
+ test('valid identifier returns true', () => {
40
+ expect(isValidIdentifier('column1')).toBe(true);
41
+ });
42
+
43
+ test('invalid identifier returns false', () => {
44
+ expect(isValidIdentifier('')).toBe(false);
45
+ expect(isValidIdentifier('bad"identifier')).toBe(false);
46
+ });
47
+ });
48
+
49
+ describe('validateTableName', () => {
50
+ test('valid table name returns true', () => {
51
+ expect(validateTableName('users')).toBe(true);
52
+ });
53
+
54
+ test('table name starting with _ throws AppError', () => {
55
+ expect(() => validateTableName('_internal')).toThrow(AppError);
56
+ });
57
+ });
58
+
59
+ describe('getIdentifierErrorMessage', () => {
60
+ test('empty identifier returns proper message', () => {
61
+ expect(getIdentifierErrorMessage('')).toContain('cannot be empty');
62
+ });
63
+
64
+ test('bad identifier returns proper message', () => {
65
+ expect(getIdentifierErrorMessage('bad"identifier')).toContain('cannot contain quotes');
66
+ });
67
+ });
68
+
69
+ describe('escapeSqlLikePattern', () => {
70
+ test('escapes % and _ and \\', () => {
71
+ expect(escapeSqlLikePattern('50%_test\\')).toBe('50\\%\\_test\\\\');
72
+ });
73
+ });
74
+
75
+ describe('escapeRegexPattern', () => {
76
+ test('escapes regex metacharacters', () => {
77
+ expect(escapeRegexPattern('test.file(1)')).toBe('test\\.file\\(1\\)');
78
+ });
79
+ });
80
+ });
@@ -16,7 +16,7 @@
16
16
  "moduleResolution": "node",
17
17
  "resolveJsonModule": true,
18
18
  "allowSyntheticDefaultImports": true,
19
- "types": ["node"]
19
+ "types": ["node","vitest" ]
20
20
  },
21
21
  "include": ["src/**/*", "../shared-schemas/src/**/*"],
22
22
  "exclude": ["node_modules", "dist"]
@@ -1,6 +1,16 @@
1
1
  import { defineConfig } from 'vitest/config';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
2
6
 
3
7
  export default defineConfig({
8
+ resolve: {
9
+ alias: {
10
+ '@': path.resolve(__dirname, './src'),
11
+ '@insforge/shared-schemas': path.resolve(__dirname, '../shared-schemas/src'),
12
+ },
13
+ },
4
14
  test: {
5
15
  environment: 'node',
6
16
  globals: true,
@@ -10,6 +20,7 @@ export default defineConfig({
10
20
  reporter: ['text', 'json', 'html'],
11
21
  exclude: ['node_modules/', 'dist/', 'frontend/', 'tests/', '**/*.d.ts', '**/*.config.*'],
12
22
  },
23
+
13
24
  testTimeout: 10000,
14
25
  // Run tests sequentially to avoid database conflicts
15
26
  pool: 'forks',
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "insforge",
3
+ "version": "1.0.0",
4
+ "description": "Official InsForge plugin for Claude Code with skills, templates, and commands for building full-stack applications with InsForge BaaS",
5
+ "author": {
6
+ "name": "InsForge Team"
7
+ },
8
+ "repository": "https://github.com/InsForge/InsForge",
9
+ "homepage": "https://insforge.com",
10
+ "keywords": [
11
+ "insforge",
12
+ "baas",
13
+ "backend-as-a-service",
14
+ "postgresql",
15
+ "postgrest",
16
+ "full-stack",
17
+ "react",
18
+ "database",
19
+ "storage",
20
+ "edge-functions",
21
+ "authentication"
22
+ ],
23
+ "license": "MIT"
24
+ }
@@ -0,0 +1,133 @@
1
+ # InsForge Claude Plugin
2
+
3
+ Official Claude Code plugin for building with InsForge.
4
+
5
+ ## What's Included
6
+
7
+ **Skill: `insforge-schema-patterns`**
8
+ - Social graph patterns (follows, likes)
9
+ - Nested comments (self-referential)
10
+ - Multi-tenant patterns
11
+ - Best practices for foreign keys, indexes, and RLS
12
+
13
+ This skill automatically activates when you're designing database schemas with Claude.
14
+
15
+ ## Installation
16
+
17
+ ### Method 1: From Marketplace (Recommended)
18
+
19
+ The easiest way to install:
20
+
21
+ ```bash
22
+ # In Claude Code, run:
23
+ /plugin marketplace add InsForge/InsForge
24
+
25
+ # Then browse available plugins:
26
+ /plugin
27
+
28
+ # Select "insforge" to install
29
+ ```
30
+
31
+ ### Method 2: Direct Install
32
+
33
+ ```bash
34
+ # Create user plugins directory if needed
35
+ mkdir -p ~/.claude/plugins/user
36
+
37
+ # Clone the repository
38
+ git clone https://github.com/InsForge/InsForge.git
39
+
40
+ # Create symlink
41
+ ln -s "$(pwd)/InsForge/claude-plugin" ~/.claude/plugins/user/insforge
42
+
43
+ # Verify installation
44
+ ls -la ~/.claude/plugins/user/insforge/
45
+ ```
46
+
47
+ ### Method 3: Local Development
48
+
49
+ For contributing or testing local changes:
50
+
51
+ ```bash
52
+ # Navigate to your local InsForge repo
53
+ cd /path/to/your/InsForge
54
+
55
+ # Create user plugins directory
56
+ mkdir -p ~/.claude/plugins/user
57
+
58
+ # Symlink your local development version
59
+ ln -s "$(pwd)/claude-plugin" ~/.claude/plugins/user/insforge
60
+
61
+ # Verify
62
+ ls -la ~/.claude/plugins/user/insforge/
63
+ ```
64
+
65
+ ## Usage
66
+
67
+ Once installed, the skill automatically activates when you ask Claude about database design:
68
+
69
+ ```
70
+ You: "I need to build a social media app with follows and likes"
71
+
72
+ Claude: [Automatically loads insforge-schema-patterns skill]
73
+ "I'll use the Social Graph pattern from InsForge best practices..."
74
+ ```
75
+
76
+ No special commands needed - Claude knows when to use it!
77
+
78
+ ## What's a Skill?
79
+
80
+ Skills are folders with instructions that Claude automatically loads when relevant. They're like giving Claude domain expertise.
81
+
82
+ ## Verification
83
+
84
+ Check if the plugin is installed correctly:
85
+
86
+ ```bash
87
+ # Check plugin installation
88
+ ls -la ~/.claude/plugins/user/insforge/
89
+
90
+ # Should show:
91
+ # .claude-plugin/
92
+ # skills/
93
+ # README.md
94
+
95
+ # Check the skill is present
96
+ cat ~/.claude/plugins/user/insforge/skills/insforge-schema-patterns/SKILL.md
97
+
98
+ # Should display database schema patterns
99
+ ```
100
+
101
+ ## Test the Plugin
102
+
103
+ In Claude Code, ask a database design question:
104
+
105
+ ```
106
+ "Help me design a database for a social media app with follows and likes"
107
+ ```
108
+
109
+ Claude should automatically load the `insforge-schema-patterns` skill and provide expert schema patterns with RLS policies, indexes, and SDK examples.
110
+
111
+ ## Troubleshooting
112
+
113
+ **Plugin not found:**
114
+ ```bash
115
+ # Remove old symlink if exists
116
+ rm ~/.claude/plugins/user/insforge
117
+
118
+ # Recreate with absolute path
119
+ ln -s /absolute/path/to/InsForge/claude-plugin ~/.claude/plugins/user/insforge
120
+ ```
121
+
122
+ **Skill not loading:**
123
+ 1. Verify SKILL.md has proper frontmatter (name and description)
124
+ 2. Restart Claude Code
125
+ 3. Ask a database design question explicitly
126
+
127
+ ## Contributing
128
+
129
+ Want to add more skills? Check the [main InsForge repository](https://github.com/InsForge/InsForge).
130
+
131
+ ## License
132
+
133
+ MIT
@@ -0,0 +1,270 @@
1
+ ---
2
+ name: insforge-schema-patterns
3
+ description: Database schema patterns for InsForge including social graphs, e-commerce, content publishing, and multi-tenancy with RLS policies. Use when designing data models with relationships, foreign keys, or Row Level Security.
4
+ ---
5
+
6
+ # InsForge Schema Patterns
7
+
8
+ Expert patterns for designing PostgreSQL schemas optimized for InsForge's PostgREST backend.
9
+
10
+ ## Pattern 1: Social Graph (Follows)
11
+
12
+ **Use when:** Building social features like Twitter, Instagram, LinkedIn connections
13
+
14
+ **Schema:**
15
+ ```sql
16
+ CREATE TABLE follows (
17
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
18
+ follower_id UUID REFERENCES users(id) ON DELETE CASCADE,
19
+ following_id UUID REFERENCES users(id) ON DELETE CASCADE,
20
+ created_at TIMESTAMPTZ DEFAULT NOW(),
21
+ UNIQUE(follower_id, following_id)
22
+ );
23
+
24
+ -- Index for fast lookups
25
+ CREATE INDEX idx_follows_follower ON follows(follower_id);
26
+ CREATE INDEX idx_follows_following ON follows(following_id);
27
+
28
+ -- RLS: Users can read all follows but only create their own
29
+ ALTER TABLE follows ENABLE ROW LEVEL SECURITY;
30
+
31
+ CREATE POLICY "Anyone can read follows" ON follows
32
+ FOR SELECT USING (true);
33
+
34
+ CREATE POLICY "Users can follow others" ON follows
35
+ FOR INSERT
36
+ TO authenticated
37
+ WITH CHECK (uid() = follower_id);
38
+
39
+ CREATE POLICY "Users can unfollow" ON follows
40
+ FOR DELETE
41
+ TO authenticated
42
+ USING (uid() = follower_id);
43
+ ```
44
+
45
+ **Query with InsForge SDK:**
46
+ ```javascript
47
+ // Get users I follow with their profiles
48
+ const { data: following } = await client.database
49
+ .from('follows')
50
+ .select('*, following:following_id(id, nickname, avatar_url, bio)')
51
+ .eq('follower_id', currentUserId);
52
+
53
+ // Get my followers
54
+ const { data: followers } = await client.database
55
+ .from('follows')
56
+ .select('*, follower:follower_id(id, nickname, avatar_url, bio)')
57
+ .eq('following_id', currentUserId);
58
+
59
+ // Check if user1 follows user2
60
+ const { data: isFollowing } = await client.database
61
+ .from('follows')
62
+ .select()
63
+ .eq('follower_id', user1Id)
64
+ .eq('following_id', user2Id)
65
+ .single();
66
+
67
+ // Follow a user
68
+ await client.database
69
+ .from('follows')
70
+ .insert([{ follower_id: currentUserId, following_id: targetUserId }]);
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Pattern 2: Likes (Many-to-Many Junction Table)
76
+
77
+ **Use when:** Users can like posts, comments, or other content
78
+
79
+ **Schema:**
80
+ ```sql
81
+ CREATE TABLE likes (
82
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
83
+ user_id UUID REFERENCES users(id) ON DELETE CASCADE,
84
+ post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
85
+ created_at TIMESTAMPTZ DEFAULT NOW(),
86
+ UNIQUE(user_id, post_id) -- Prevent duplicate likes
87
+ );
88
+
89
+ CREATE INDEX idx_likes_post ON likes(post_id);
90
+ CREATE INDEX idx_likes_user ON likes(user_id);
91
+
92
+ ALTER TABLE likes ENABLE ROW LEVEL SECURITY;
93
+
94
+ CREATE POLICY "Anyone can read likes" ON likes
95
+ FOR SELECT USING (true);
96
+
97
+ CREATE POLICY "Users can like posts" ON likes
98
+ FOR INSERT
99
+ TO authenticated
100
+ WITH CHECK (uid() = user_id);
101
+
102
+ CREATE POLICY "Users can unlike their likes" ON likes
103
+ FOR DELETE
104
+ TO authenticated
105
+ USING (uid() = user_id);
106
+ ```
107
+
108
+ **Query with InsForge SDK:**
109
+ ```javascript
110
+ // Get post with like count and whether current user liked it
111
+ const { data: post } = await client.database
112
+ .from('posts')
113
+ .select(`
114
+ *,
115
+ likes(count),
116
+ user_like:likes!inner(id, user_id)
117
+ `)
118
+ .eq('id', postId)
119
+ .eq('user_like.user_id', currentUserId)
120
+ .single();
121
+
122
+ // Like a post
123
+ await client.database
124
+ .from('likes')
125
+ .insert([{ user_id: currentUserId, post_id: postId }]);
126
+
127
+ // Unlike a post
128
+ await client.database
129
+ .from('likes')
130
+ .delete()
131
+ .eq('user_id', currentUserId)
132
+ .eq('post_id', postId);
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Pattern 3: Nested Comments (Self-Referential)
138
+
139
+ **Use when:** Building comment threads, nested replies
140
+
141
+ **Schema:**
142
+ ```sql
143
+ CREATE TABLE comments (
144
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
145
+ post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
146
+ user_id UUID REFERENCES users(id) ON DELETE CASCADE,
147
+ parent_comment_id UUID REFERENCES comments(id) ON DELETE CASCADE,
148
+ content TEXT NOT NULL,
149
+ created_at TIMESTAMPTZ DEFAULT NOW(),
150
+ updated_at TIMESTAMPTZ DEFAULT NOW()
151
+ );
152
+
153
+ CREATE INDEX idx_comments_post ON comments(post_id);
154
+ CREATE INDEX idx_comments_parent ON comments(parent_comment_id);
155
+
156
+ ALTER TABLE comments ENABLE ROW LEVEL SECURITY;
157
+
158
+ CREATE POLICY "Anyone can read comments" ON comments
159
+ FOR SELECT USING (true);
160
+
161
+ CREATE POLICY "Authenticated users can comment" ON comments
162
+ FOR INSERT
163
+ TO authenticated
164
+ WITH CHECK (uid() = user_id);
165
+
166
+ CREATE POLICY "Users can edit their comments" ON comments
167
+ FOR UPDATE
168
+ TO authenticated
169
+ USING (uid() = user_id)
170
+ WITH CHECK (uid() = user_id);
171
+
172
+ CREATE POLICY "Users can delete their comments" ON comments
173
+ FOR DELETE
174
+ TO authenticated
175
+ USING (uid() = user_id);
176
+ ```
177
+
178
+ **Query with InsForge SDK:**
179
+ ```javascript
180
+ // Get top-level comments with author info
181
+ const { data: comments } = await client.database
182
+ .from('comments')
183
+ .select('*, author:user_id(nickname, avatar_url)')
184
+ .eq('post_id', postId)
185
+ .is('parent_comment_id', null)
186
+ .order('created_at', { ascending: false });
187
+
188
+ // Get replies to a comment
189
+ const { data: replies } = await client.database
190
+ .from('comments')
191
+ .select('*, author:user_id(nickname, avatar_url)')
192
+ .eq('parent_comment_id', commentId)
193
+ .order('created_at', { ascending: true });
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Pattern 4: Multi-Tenant (Organization Scoped)
199
+
200
+ **Use when:** Building SaaS apps where data is scoped to organizations/workspaces
201
+
202
+ **Schema:**
203
+ ```sql
204
+ CREATE TABLE organizations (
205
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
206
+ name TEXT NOT NULL,
207
+ created_at TIMESTAMPTZ DEFAULT NOW()
208
+ );
209
+
210
+ CREATE TABLE organization_members (
211
+ organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
212
+ user_id UUID REFERENCES users(id) ON DELETE CASCADE,
213
+ role TEXT NOT NULL CHECK (role IN ('owner', 'admin', 'member')),
214
+ joined_at TIMESTAMPTZ DEFAULT NOW(),
215
+ PRIMARY KEY (organization_id, user_id)
216
+ );
217
+
218
+ CREATE TABLE projects (
219
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
220
+ organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
221
+ name TEXT NOT NULL,
222
+ created_at TIMESTAMPTZ DEFAULT NOW()
223
+ );
224
+
225
+ -- RLS: Users can only see projects in their organizations
226
+ ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
227
+
228
+ CREATE POLICY "Users see org projects" ON projects
229
+ FOR SELECT
230
+ TO authenticated
231
+ USING (
232
+ organization_id IN (
233
+ SELECT organization_id
234
+ FROM organization_members
235
+ WHERE user_id = uid()
236
+ )
237
+ );
238
+
239
+ CREATE POLICY "Admins can create projects" ON projects
240
+ FOR INSERT
241
+ TO authenticated
242
+ WITH CHECK (
243
+ organization_id IN (
244
+ SELECT organization_id
245
+ FROM organization_members
246
+ WHERE user_id = uid()
247
+ AND role IN ('owner', 'admin')
248
+ )
249
+ );
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Best Practices
255
+
256
+ 1. **Always add indexes** on foreign key columns for performance
257
+ 2. **Use UNIQUE constraints** on junction tables to prevent duplicates
258
+ 3. **Enable RLS** on all user-facing tables
259
+ 4. **Use ON DELETE CASCADE** for automatic cleanup
260
+ 5. **Foreign key expansion** in SDK uses the syntax: `table:column(fields)`
261
+ 6. **Count aggregations** use: `table(count)`
262
+ 7. **Filter nested tables** with: `nested_table!inner()` for inner join behavior
263
+
264
+ ## Common Mistakes to Avoid
265
+
266
+ - ❌ Forgetting indexes on foreign keys → Slow queries
267
+ - ❌ Not using UNIQUE on junction tables → Duplicate likes/follows
268
+ - ❌ Missing RLS policies → Data leaks
269
+ - ❌ Using `.single()` on queries that might return multiple rows → Errors
270
+ - ❌ Not wrapping INSERT data in arrays → PostgREST error