insforge 1.3.0 ā 1.4.8
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.
- package/CHANGELOG.md +2 -0
- package/auth/package.json +5 -3
- package/auth/src/lib/broadcastService.ts +115 -117
- package/auth/src/lib/insforge.ts +8 -0
- package/auth/src/main.tsx +2 -4
- package/auth/src/pages/SignInPage.tsx +60 -60
- package/auth/src/pages/SignUpPage.tsx +60 -60
- package/auth/src/pages/VerifyEmailPage.tsx +18 -0
- package/auth/tsconfig.json +2 -1
- package/backend/package.json +10 -6
- package/backend/src/api/middlewares/rate-limiters.ts +127 -127
- package/backend/src/api/routes/ai/index.routes.ts +475 -468
- package/backend/src/api/routes/auth/index.routes.ts +85 -32
- package/backend/src/api/routes/auth/oauth.routes.ts +11 -6
- package/backend/src/api/routes/database/index.routes.ts +2 -0
- package/backend/src/api/routes/database/records.routes.ts +39 -175
- package/backend/src/api/routes/database/rpc.routes.ts +69 -0
- package/backend/src/api/routes/deployments/index.routes.ts +192 -0
- package/backend/src/api/routes/docs/index.routes.ts +3 -2
- package/backend/src/api/routes/email/index.routes.ts +35 -35
- package/backend/src/api/routes/functions/index.routes.ts +3 -3
- package/backend/src/api/routes/metadata/index.routes.ts +26 -0
- package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
- package/backend/src/infra/database/database.manager.ts +0 -10
- package/backend/src/infra/database/migrations/018_schema-rework.sql +441 -0
- package/backend/src/infra/database/migrations/019_create-deployments-table.sql +36 -0
- package/backend/src/infra/database/migrations/020_add-audio-modality.sql +11 -0
- package/backend/src/infra/database/migrations/bootstrap/bootstrap-migrations.js +103 -0
- package/backend/src/infra/security/token.manager.ts +1 -4
- package/backend/src/providers/ai/openrouter.provider.ts +12 -3
- package/backend/src/providers/database/base.provider.ts +39 -0
- package/backend/src/providers/database/cloud.provider.ts +159 -0
- package/backend/src/providers/deployments/vercel.provider.ts +516 -0
- package/backend/src/server.ts +19 -7
- package/backend/src/services/ai/ai-config.service.ts +6 -6
- package/backend/src/services/ai/ai-model.service.ts +60 -60
- package/backend/src/services/ai/ai-usage.service.ts +7 -7
- package/backend/src/services/ai/chat-completion.service.ts +415 -220
- package/backend/src/services/ai/helpers.ts +64 -64
- package/backend/src/services/ai/index.ts +13 -13
- package/backend/src/services/auth/auth-config.service.ts +4 -4
- package/backend/src/services/auth/auth-otp.service.ts +6 -6
- package/backend/src/services/auth/auth.service.ts +134 -74
- package/backend/src/services/auth/index.ts +4 -4
- package/backend/src/services/auth/oauth-config.service.ts +12 -12
- package/backend/src/services/database/database-advance.service.ts +19 -55
- package/backend/src/services/database/database-table.service.ts +38 -85
- package/backend/src/services/database/postgrest-proxy.service.ts +165 -0
- package/backend/src/services/deployments/deployment.service.ts +693 -0
- package/backend/src/services/functions/function.service.ts +61 -41
- package/backend/src/services/logs/audit.service.ts +10 -10
- package/backend/src/services/secrets/secret.service.ts +101 -27
- package/backend/src/services/storage/storage.service.ts +30 -30
- package/backend/src/services/usage/usage.service.ts +6 -6
- package/backend/src/types/ai.ts +8 -0
- package/backend/src/types/auth.ts +5 -1
- package/backend/src/types/database.ts +2 -0
- package/backend/src/types/deployments.ts +33 -0
- package/backend/src/types/storage.ts +1 -1
- package/backend/src/types/webhooks.ts +45 -0
- package/backend/src/utils/cookies.ts +34 -35
- package/backend/src/utils/environment.ts +0 -14
- package/backend/src/utils/s3-config-loader.ts +64 -64
- package/backend/src/utils/seed.ts +334 -301
- package/backend/src/utils/sql-parser.ts +126 -0
- package/backend/src/utils/utils.ts +114 -114
- package/backend/src/utils/validations.ts +10 -10
- package/backend/tests/local/test-rpc.sh +141 -0
- package/backend/tests/local/test-secrets.sh +1 -1
- package/backend/tests/manual/test-ai-model-plugins.sh +258 -0
- package/backend/tests/manual/test-rawsql-modes.sh +24 -24
- package/backend/tests/unit/database-advance.test.ts +326 -0
- package/backend/tests/unit/helpers.test.ts +2 -2
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +13 -10
- package/docker-compose.prod.yml +1 -1
- package/docker-compose.yml +1 -1
- package/docs/agent-docs/deployment.md +79 -0
- package/docs/changelog.mdx +165 -72
- package/docs/core-concepts/ai/architecture.mdx +1 -23
- package/docs/core-concepts/ai/sdk.mdx +26 -1
- package/docs/core-concepts/authentication/architecture.mdx +6 -8
- package/docs/core-concepts/authentication/sdk.mdx +387 -91
- package/docs/core-concepts/authentication/ui-components/customization.mdx +460 -256
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +50 -24
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +18 -19
- package/docs/core-concepts/authentication/ui-components/react.mdx +26 -19
- package/docs/core-concepts/database/architecture.mdx +58 -21
- package/docs/core-concepts/database/pgvector.mdx +138 -0
- package/docs/core-concepts/database/sdk.mdx +17 -17
- package/docs/core-concepts/deployments/architecture.mdx +152 -0
- package/docs/core-concepts/email/architecture.mdx +4 -2
- package/docs/core-concepts/functions/architecture.mdx +1 -1
- package/docs/core-concepts/functions/sdk.mdx +0 -1
- package/docs/core-concepts/realtime/architecture.mdx +1 -1
- package/docs/core-concepts/storage/architecture.mdx +1 -1
- package/docs/core-concepts/storage/sdk.mdx +25 -25
- package/docs/docs.json +14 -6
- package/docs/favicon.png +0 -0
- package/docs/favicon.svg +3 -18
- package/docs/images/changelog/dec-2025/apple-oauth.mp4 +0 -0
- package/docs/images/changelog/dec-2025/moreModels.png +0 -0
- package/docs/images/changelog/dec-2025/multi-region.webp +0 -0
- package/docs/images/changelog/dec-2025/postgres-connection.webp +0 -0
- package/docs/images/changelog/dec-2025/realtime2.png +0 -0
- package/docs/images/mcp-setup/CC-MCP-1.mp4 +0 -0
- package/docs/images/mcp-setup/CC-MCP-2.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-1.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-2.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-3.mp4 +0 -0
- package/docs/images/mcp-setup/claude-code-connect.png +0 -0
- package/docs/images/mcp-setup/cline-1.png +0 -0
- package/docs/images/mcp-setup/cline-2.png +0 -0
- package/docs/images/mcp-setup/cline-3.png +0 -0
- package/docs/images/mcp-setup/connect-project.png +0 -0
- package/docs/images/mcp-setup/copilot-1.png +0 -0
- package/docs/images/mcp-setup/copilot-2.png +0 -0
- package/docs/images/mcp-setup/copilot-3.png +0 -0
- package/docs/images/mcp-setup/mcp-json-1.png +0 -0
- package/docs/images/mcp-setup/mcp-json-2.png +0 -0
- package/docs/images/mcp-setup/qoder-1.png +0 -0
- package/docs/images/mcp-setup/qoder-2.png +0 -0
- package/docs/images/mcp-setup/roocode-1.png +0 -0
- package/docs/images/mcp-setup/roocode-2.png +0 -0
- package/docs/images/mcp-setup/trae-1.png +0 -0
- package/docs/images/mcp-setup/trae-2.png +0 -0
- package/docs/images/mcp-setup/trae-3.png +0 -0
- package/docs/images/mcp-setup/trae-4.png +0 -0
- package/docs/images/mcp-setup/trae-5.png +0 -0
- package/docs/images/mcp-setup/windsurf-1.png +0 -0
- package/docs/images/mcp-setup/windsurf-2.png +0 -0
- package/docs/insforge-instructions-sdk.md +7 -3
- package/docs/introduction.mdx +9 -8
- package/docs/mcp-setup.mdx +332 -0
- package/docs/oauth-server.mdx +563 -0
- package/docs/partnership.mdx +79 -10
- package/docs/quickstart.mdx +1 -1
- package/docs/vscode-extension.mdx +74 -0
- package/eslint.config.js +1 -0
- package/examples/response-examples.md +1 -1
- package/frontend/package.json +1 -1
- package/frontend/src/App.tsx +8 -3
- package/frontend/src/assets/logos/antigravity.svg +1 -0
- package/frontend/src/assets/logos/copilot.svg +10 -0
- package/frontend/src/assets/logos/deepseek.svg +139 -0
- package/frontend/src/assets/logos/kiro.svg +9 -0
- package/frontend/src/assets/logos/qoder.svg +4 -0
- package/frontend/src/assets/logos/qwen.svg +15 -0
- package/frontend/src/components/CodeBlock.tsx +2 -2
- package/frontend/src/components/ConnectCTA.tsx +3 -2
- package/frontend/src/components/datagrid/DataGrid.tsx +90 -62
- package/frontend/src/components/datagrid/datagridTypes.tsx +2 -1
- package/frontend/src/components/datagrid/index.ts +1 -1
- package/frontend/src/components/index.ts +0 -1
- package/frontend/src/components/layout/AppHeader.tsx +4 -27
- package/frontend/src/components/layout/AppSidebar.tsx +85 -100
- package/frontend/src/components/layout/Layout.tsx +34 -32
- package/frontend/src/components/layout/PrimaryMenu.tsx +12 -4
- package/frontend/src/components/radix/Select.tsx +151 -151
- package/frontend/src/features/ai/components/AIConfigCard.tsx +200 -200
- package/frontend/src/features/ai/components/AIEmptyState.tsx +23 -23
- package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +102 -101
- package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -135
- package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -51
- package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -118
- package/frontend/src/features/ai/components/index.ts +6 -6
- package/frontend/src/features/ai/helpers.ts +147 -141
- package/frontend/src/features/ai/pages/AIPage.tsx +166 -166
- package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +55 -31
- package/frontend/src/features/auth/components/index.ts +5 -5
- package/frontend/src/features/auth/pages/AuthMethodsPage.tsx +275 -275
- package/frontend/src/features/dashboard/pages/DashboardPage.tsx +1 -1
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +0 -2
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +38 -11
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +18 -8
- package/frontend/src/features/database/components/LinkRecordModal.tsx +61 -13
- package/frontend/src/features/database/components/RecordFormField.tsx +1 -1
- package/frontend/src/features/database/components/TableSidebar.tsx +0 -3
- package/frontend/src/features/database/components/TablesEmptyState.tsx +1 -1
- package/frontend/src/features/database/components/TemplatePreview.tsx +1 -2
- package/frontend/src/features/database/constants.ts +16 -28
- package/frontend/src/features/database/hooks/useCSVImport.ts +3 -2
- package/frontend/src/features/database/hooks/useRawSQL.ts +3 -2
- package/frontend/src/features/database/hooks/useTables.ts +5 -7
- package/frontend/src/features/database/pages/FunctionsPage.tsx +0 -5
- package/frontend/src/features/database/pages/IndexesPage.tsx +0 -5
- package/frontend/src/features/database/pages/PoliciesPage.tsx +0 -5
- package/frontend/src/features/database/pages/SQLEditorPage.tsx +2 -2
- package/frontend/src/features/database/pages/TriggersPage.tsx +0 -5
- package/frontend/src/features/database/services/advance.service.ts +1 -15
- package/frontend/src/features/database/services/record.service.ts +4 -20
- package/frontend/src/features/database/services/table.service.ts +1 -4
- package/frontend/src/features/database/templates/ai-chatbot.ts +6 -6
- package/frontend/src/features/database/templates/ecommerce-platform.ts +2 -2
- package/frontend/src/features/database/templates/instagram-clone.ts +10 -10
- package/frontend/src/features/database/templates/notion-clone.ts +8 -8
- package/frontend/src/features/database/templates/reddit-clone.ts +10 -10
- package/frontend/src/features/deployments/components/DeploymentRow.tsx +93 -0
- package/frontend/src/features/deployments/components/DeploymentsEmptyState.tsx +15 -0
- package/frontend/src/features/deployments/hooks/useDeployments.ts +157 -0
- package/frontend/src/features/deployments/pages/DeploymentsPage.tsx +318 -0
- package/frontend/src/features/deployments/services/deployments.service.ts +63 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +72 -72
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -56
- package/frontend/src/features/functions/components/SecretRow.tsx +3 -3
- package/frontend/src/features/functions/components/index.ts +5 -5
- package/frontend/src/features/functions/hooks/useFunctions.ts +5 -4
- package/frontend/src/features/functions/hooks/useSecrets.ts +6 -9
- package/frontend/src/features/functions/pages/SecretsPage.tsx +118 -118
- package/frontend/src/features/functions/services/function.service.ts +8 -25
- package/frontend/src/features/functions/services/secret.service.ts +23 -41
- package/frontend/src/features/login/pages/CloudLoginPage.tsx +125 -118
- package/frontend/src/features/logs/components/LogDetailPanel.tsx +41 -0
- package/frontend/src/features/logs/components/LogsDataGrid.tsx +32 -1
- package/frontend/src/features/logs/components/index.ts +1 -0
- package/frontend/src/features/logs/pages/LogsPage.tsx +36 -6
- package/frontend/src/features/onboard/components/ApiCredentialsSection.tsx +59 -0
- package/frontend/src/features/onboard/components/ConnectionStringSection.tsx +180 -0
- package/frontend/src/features/onboard/components/McpConnectionSection.tsx +159 -0
- package/frontend/src/features/onboard/components/OnboardingController.tsx +68 -0
- package/frontend/src/features/onboard/components/OnboardingModal.tsx +121 -267
- package/frontend/src/features/onboard/components/ShowPasswordButton.tsx +21 -0
- package/frontend/src/features/onboard/components/index.ts +9 -4
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +1 -1
- package/frontend/src/features/onboard/components/mcp/QoderDeeplinkGenerator.tsx +36 -0
- package/frontend/src/features/onboard/components/mcp/helpers.tsx +123 -98
- package/frontend/src/features/onboard/components/mcp/index.ts +4 -3
- package/frontend/src/features/onboard/index.ts +17 -13
- package/frontend/src/features/settings/pages/SettingsPage.tsx +349 -0
- package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +21 -8
- package/frontend/src/features/visualizer/pages/VisualizerPage.tsx +10 -1
- package/frontend/src/index.css +249 -249
- package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
- package/frontend/src/lib/hooks/useMetadata.ts +45 -1
- package/frontend/src/lib/hooks/useModal.tsx +2 -0
- package/frontend/src/lib/routing/AppRoutes.tsx +103 -99
- package/frontend/src/lib/services/metadata.service.ts +20 -3
- package/frontend/src/lib/utils/menuItems.ts +223 -207
- package/frontend/src/lib/utils/utils.ts +196 -196
- package/functions/server.ts +315 -315
- package/functions/worker-template.js +1 -1
- package/openapi/ai.yaml +115 -5
- package/openapi/auth.yaml +97 -17
- package/openapi/logs.yaml +0 -2
- package/openapi/metadata.yaml +0 -2
- package/openapi/records.yaml +21 -21
- package/openapi/tables.yaml +1 -2
- package/package.json +1 -1
- package/shared-schemas/package.json +1 -1
- package/shared-schemas/src/ai-api.schema.ts +251 -143
- package/shared-schemas/src/ai.schema.ts +63 -63
- package/shared-schemas/src/auth-api.schema.ts +34 -6
- package/shared-schemas/src/auth.schema.ts +17 -10
- package/shared-schemas/src/cloud-events.schema.ts +26 -0
- package/shared-schemas/src/deployments-api.schema.ts +55 -0
- package/shared-schemas/src/deployments.schema.ts +30 -0
- package/shared-schemas/src/docs.schema.ts +8 -2
- package/shared-schemas/src/email-api.schema.ts +30 -30
- package/shared-schemas/src/functions-api.schema.ts +13 -4
- package/shared-schemas/src/functions.schema.ts +1 -1
- package/shared-schemas/src/index.ts +22 -18
- package/shared-schemas/src/metadata.schema.ts +30 -4
- package/shared-schemas/src/secrets-api.schema.ts +44 -0
- package/shared-schemas/src/secrets.schema.ts +15 -0
- package/zeabur/README.md +13 -0
- package/zeabur/template.yml +20 -51
- package/backend/src/types/profile.ts +0 -55
- package/frontend/src/components/ProjectInfoModal.tsx +0 -128
|
@@ -1,301 +1,334 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
logger.warn('ā ļø Admin credentials not configured - check ADMIN_EMAIL and ADMIN_PASSWORD');
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
} catch (error) {
|
|
148
|
-
logger.
|
|
149
|
-
error: error instanceof Error ? error.message : String(error),
|
|
150
|
-
});
|
|
151
|
-
// Don't throw
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
{
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
1
|
+
import bcrypt from 'bcryptjs';
|
|
2
|
+
import { DatabaseManager } from '@/infra/database/database.manager.js';
|
|
3
|
+
import { TokenManager } from '@/infra/security/token.manager.js';
|
|
4
|
+
import { AIConfigService } from '@/services/ai/ai-config.service.js';
|
|
5
|
+
import { isCloudEnvironment } from '@/utils/environment.js';
|
|
6
|
+
import logger from '@/utils/logger.js';
|
|
7
|
+
import { SecretService } from '@/services/secrets/secret.service.js';
|
|
8
|
+
import { OAuthConfigService } from '@/services/auth/oauth-config.service.js';
|
|
9
|
+
import { OAuthProvidersSchema, aiConfigurationInputSchema } from '@insforge/shared-schemas';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { AuthConfigService } from '@/services/auth/auth-config.service.js';
|
|
12
|
+
import { fetchS3Config } from '@/utils/s3-config-loader.js';
|
|
13
|
+
import { ADMIN_ID } from '@/utils/constants.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Seeds the admin user if it doesn't exist in the database
|
|
17
|
+
* Creates an admin user with is_project_admin = true
|
|
18
|
+
*/
|
|
19
|
+
async function seedAdminUser(adminEmail: string, adminPassword: string): Promise<void> {
|
|
20
|
+
if (!adminEmail || !adminPassword) {
|
|
21
|
+
logger.warn('ā ļø Admin credentials not configured - check ADMIN_EMAIL and ADMIN_PASSWORD');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const dbManager = DatabaseManager.getInstance();
|
|
26
|
+
const pool = dbManager.getPool();
|
|
27
|
+
const client = await pool.connect();
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
// Check if admin user already exists
|
|
31
|
+
const existingAdmin = await client.query('SELECT id FROM auth.users WHERE id = $1', [ADMIN_ID]);
|
|
32
|
+
|
|
33
|
+
if (existingAdmin.rows.length > 0) {
|
|
34
|
+
logger.info(`ā
Admin configured: ${adminEmail}`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Hash password and create admin user
|
|
39
|
+
const hashedPassword = await bcrypt.hash(adminPassword, 10);
|
|
40
|
+
const profile = JSON.stringify({ name: 'Administrator' });
|
|
41
|
+
|
|
42
|
+
await client.query(
|
|
43
|
+
`INSERT INTO auth.users (id, email, password, profile, email_verified, is_project_admin, is_anonymous, created_at, updated_at)
|
|
44
|
+
VALUES ($1, $2, $3, $4::jsonb, true, true, false, NOW(), NOW())
|
|
45
|
+
ON CONFLICT (id) DO NOTHING`,
|
|
46
|
+
[ADMIN_ID, adminEmail, hashedPassword, profile]
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
logger.info(`ā
Admin user seeded: ${adminEmail}`);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
logger.error('Failed to seed admin user', {
|
|
52
|
+
error: error instanceof Error ? error.message : String(error),
|
|
53
|
+
});
|
|
54
|
+
// Don't throw - this is not critical for app startup if admin already exists
|
|
55
|
+
} finally {
|
|
56
|
+
client.release();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Seeds default AI configurations from S3 config
|
|
62
|
+
*/
|
|
63
|
+
async function seedDefaultAIConfigs(): Promise<void> {
|
|
64
|
+
const aiConfigService = AIConfigService.getInstance();
|
|
65
|
+
|
|
66
|
+
const existingConfigs = await aiConfigService.findAll();
|
|
67
|
+
if (existingConfigs.length) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const defaultModels =
|
|
72
|
+
await fetchS3Config<z.infer<typeof aiConfigurationInputSchema>[]>('default-ai-models.json');
|
|
73
|
+
|
|
74
|
+
if (!defaultModels || defaultModels.length === 0) {
|
|
75
|
+
logger.warn('ā ļø No default AI models configured - add via dashboard or check S3 config');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const parsed = aiConfigurationInputSchema.array().safeParse(defaultModels);
|
|
80
|
+
if (!parsed.success) {
|
|
81
|
+
logger.error('ā Invalid AI models configuration from S3', {
|
|
82
|
+
error: parsed.error.message,
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const validatedModels = parsed.data;
|
|
88
|
+
for (const model of validatedModels) {
|
|
89
|
+
await aiConfigService.create(
|
|
90
|
+
model.inputModality,
|
|
91
|
+
model.outputModality,
|
|
92
|
+
model.provider,
|
|
93
|
+
model.modelId,
|
|
94
|
+
model.systemPrompt
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
logger.info(`ā
Default AI models configured (${validatedModels.length} models)`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Seeds default auth configuration for cloud environments
|
|
103
|
+
* Enables email verification with code-based verification method
|
|
104
|
+
* Only inserts config if table is empty (first startup, never configured)
|
|
105
|
+
*/
|
|
106
|
+
async function seedDefaultAuthConfig(): Promise<void> {
|
|
107
|
+
const dbManager = DatabaseManager.getInstance();
|
|
108
|
+
const pool = dbManager.getPool();
|
|
109
|
+
const client = await pool.connect();
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const result = await client.query('SELECT COUNT(*) as count FROM auth.configs');
|
|
113
|
+
const hasConfig = result.rows.length > 0 && Number(result.rows[0].count) > 0;
|
|
114
|
+
|
|
115
|
+
if (hasConfig) {
|
|
116
|
+
const authConfigService = AuthConfigService.getInstance();
|
|
117
|
+
const currentConfig = await authConfigService.getAuthConfig();
|
|
118
|
+
logger.info(
|
|
119
|
+
'ā
Email verification configured:',
|
|
120
|
+
currentConfig.requireEmailVerification ? 'enabled' : 'disabled'
|
|
121
|
+
);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Table is empty - this is first startup, insert default cloud configuration
|
|
126
|
+
await client.query(
|
|
127
|
+
`INSERT INTO auth.configs (
|
|
128
|
+
require_email_verification,
|
|
129
|
+
password_min_length,
|
|
130
|
+
require_number,
|
|
131
|
+
require_lowercase,
|
|
132
|
+
require_uppercase,
|
|
133
|
+
require_special_char
|
|
134
|
+
) VALUES ($1, $2, $3, $4, $5, $6)
|
|
135
|
+
ON CONFLICT DO NOTHING`,
|
|
136
|
+
[
|
|
137
|
+
isCloudEnvironment(), // Enable email verification for cloud
|
|
138
|
+
6, // password_min_length
|
|
139
|
+
false, // require_number
|
|
140
|
+
false, // require_lowercase
|
|
141
|
+
false, // require_uppercase
|
|
142
|
+
false, // require_special_char
|
|
143
|
+
]
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
logger.info('ā
Email verification enabled (cloud environment)');
|
|
147
|
+
} catch (error) {
|
|
148
|
+
logger.error('Failed to seed default auth config', {
|
|
149
|
+
error: error instanceof Error ? error.message : String(error),
|
|
150
|
+
});
|
|
151
|
+
// Don't throw - this is not critical for app startup
|
|
152
|
+
} finally {
|
|
153
|
+
client.release();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Seeds default OAuth configurations for supported providers
|
|
159
|
+
*/
|
|
160
|
+
async function seedDefaultOAuthConfigs(): Promise<void> {
|
|
161
|
+
const oauthConfigService = OAuthConfigService.getInstance();
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
// Check if OAuth configs already exist
|
|
165
|
+
const existingConfigs = await oauthConfigService.getAllConfigs();
|
|
166
|
+
const existingProviders = existingConfigs.map((config) => config.provider.toLowerCase());
|
|
167
|
+
|
|
168
|
+
// Default providers to seed
|
|
169
|
+
const defaultProviders: OAuthProvidersSchema[] = ['google', 'github'];
|
|
170
|
+
|
|
171
|
+
for (const provider of defaultProviders) {
|
|
172
|
+
if (!existingProviders.includes(provider)) {
|
|
173
|
+
await oauthConfigService.createConfig({
|
|
174
|
+
provider,
|
|
175
|
+
useSharedKey: true,
|
|
176
|
+
});
|
|
177
|
+
logger.info(`ā
Default ${provider} OAuth config created`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} catch (error) {
|
|
181
|
+
logger.warn('Failed to seed OAuth configs', {
|
|
182
|
+
error: error instanceof Error ? error.message : String(error),
|
|
183
|
+
});
|
|
184
|
+
// Don't throw error as OAuth configs are optional
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Seeds OAuth configurations from local environment variables
|
|
190
|
+
*/
|
|
191
|
+
async function seedLocalOAuthConfigs(): Promise<void> {
|
|
192
|
+
const oauthConfigService = OAuthConfigService.getInstance();
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
// Check if OAuth configs already exist
|
|
196
|
+
const existingConfigs = await oauthConfigService.getAllConfigs();
|
|
197
|
+
const existingProviders = existingConfigs.map((config) => config.provider.toLowerCase());
|
|
198
|
+
|
|
199
|
+
// Environment variable mappings for OAuth providers
|
|
200
|
+
const envMappings: Array<{
|
|
201
|
+
provider: OAuthProvidersSchema;
|
|
202
|
+
clientIdEnv: string;
|
|
203
|
+
clientSecretEnv: string;
|
|
204
|
+
}> = [
|
|
205
|
+
{
|
|
206
|
+
provider: 'google',
|
|
207
|
+
clientIdEnv: 'GOOGLE_CLIENT_ID',
|
|
208
|
+
clientSecretEnv: 'GOOGLE_CLIENT_SECRET',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
provider: 'github',
|
|
212
|
+
clientIdEnv: 'GITHUB_CLIENT_ID',
|
|
213
|
+
clientSecretEnv: 'GITHUB_CLIENT_SECRET',
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
provider: 'discord',
|
|
217
|
+
clientIdEnv: 'DISCORD_CLIENT_ID',
|
|
218
|
+
clientSecretEnv: 'DISCORD_CLIENT_SECRET',
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
provider: 'linkedin',
|
|
222
|
+
clientIdEnv: 'LINKEDIN_CLIENT_ID',
|
|
223
|
+
clientSecretEnv: 'LINKEDIN_CLIENT_SECRET',
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
provider: 'microsoft',
|
|
227
|
+
clientIdEnv: 'MICROSOFT_CLIENT_ID',
|
|
228
|
+
clientSecretEnv: 'MICROSOFT_CLIENT_SECRET',
|
|
229
|
+
},
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
for (const { provider, clientIdEnv, clientSecretEnv } of envMappings) {
|
|
233
|
+
const clientId = process.env[clientIdEnv];
|
|
234
|
+
const clientSecret = process.env[clientSecretEnv];
|
|
235
|
+
|
|
236
|
+
if (clientId && clientSecret && !existingProviders.includes(provider)) {
|
|
237
|
+
await oauthConfigService.createConfig({
|
|
238
|
+
provider,
|
|
239
|
+
clientId,
|
|
240
|
+
clientSecret,
|
|
241
|
+
useSharedKey: false,
|
|
242
|
+
});
|
|
243
|
+
logger.info(`ā
${provider} OAuth config loaded from environment variables`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
} catch (error) {
|
|
247
|
+
logger.warn('Failed to seed local OAuth configs', {
|
|
248
|
+
error: error instanceof Error ? error.message : String(error),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Create api key, admin user, and default AI configs
|
|
254
|
+
export async function seedBackend(): Promise<void> {
|
|
255
|
+
const secretService = SecretService.getInstance();
|
|
256
|
+
|
|
257
|
+
const dbManager = DatabaseManager.getInstance();
|
|
258
|
+
|
|
259
|
+
const adminEmail = process.env.ADMIN_EMAIL || 'admin@example.com';
|
|
260
|
+
const adminPassword = process.env.ADMIN_PASSWORD || 'change-this-password';
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
logger.info(`\nš Insforge Backend Starting...`);
|
|
264
|
+
|
|
265
|
+
// Seed admin user if not exists
|
|
266
|
+
await seedAdminUser(adminEmail, adminPassword);
|
|
267
|
+
|
|
268
|
+
// Initialize API key (from env or generate)
|
|
269
|
+
const apiKey = await secretService.initializeApiKey();
|
|
270
|
+
|
|
271
|
+
// Get database stats
|
|
272
|
+
const tables = await dbManager.getUserTables();
|
|
273
|
+
|
|
274
|
+
logger.info(`ā
Database connected to PostgreSQL`, {
|
|
275
|
+
host: process.env.POSTGRES_HOST || 'localhost',
|
|
276
|
+
port: process.env.POSTGRES_PORT || '5432',
|
|
277
|
+
database: process.env.POSTGRES_DB || 'insforge',
|
|
278
|
+
});
|
|
279
|
+
// Database connection info is already logged above
|
|
280
|
+
|
|
281
|
+
if (tables.length) {
|
|
282
|
+
logger.info(`ā
Found ${tables.length} user tables`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// seed default configs for cloud environment
|
|
286
|
+
if (isCloudEnvironment()) {
|
|
287
|
+
await seedDefaultOAuthConfigs();
|
|
288
|
+
await seedDefaultAIConfigs();
|
|
289
|
+
await seedDefaultAuthConfig();
|
|
290
|
+
} else {
|
|
291
|
+
await seedLocalOAuthConfigs();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Initialize reserved secrets for edge functions
|
|
295
|
+
// Add INSFORGE_INTERNAL_URL for Deno-to-backend container communication
|
|
296
|
+
const insforgInternalUrl = 'http://insforge:7130';
|
|
297
|
+
const existingInternalUrlSecret = await secretService.getSecretByKey('INSFORGE_INTERNAL_URL');
|
|
298
|
+
|
|
299
|
+
if (existingInternalUrlSecret === null) {
|
|
300
|
+
await secretService.createSecret({
|
|
301
|
+
key: 'INSFORGE_INTERNAL_URL',
|
|
302
|
+
isReserved: true,
|
|
303
|
+
value: insforgInternalUrl,
|
|
304
|
+
});
|
|
305
|
+
logger.info('ā
INSFORGE_INTERNAL_URL secret initialized');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Add ANON_KEY for public edge function access
|
|
309
|
+
const existingAnonKeySecret = await secretService.getSecretByKey('ANON_KEY');
|
|
310
|
+
|
|
311
|
+
if (existingAnonKeySecret === null) {
|
|
312
|
+
const tokenManager = TokenManager.getInstance();
|
|
313
|
+
const anonToken = tokenManager.generateAnonToken();
|
|
314
|
+
|
|
315
|
+
await secretService.createSecret({
|
|
316
|
+
key: 'ANON_KEY',
|
|
317
|
+
isReserved: true,
|
|
318
|
+
value: anonToken,
|
|
319
|
+
});
|
|
320
|
+
logger.info('ā
ANON_KEY secret initialized');
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
logger.info(`API key generated: ${apiKey}`);
|
|
324
|
+
logger.info(`Setup complete:
|
|
325
|
+
- Save this API key for your apps!
|
|
326
|
+
- Dashboard: http://localhost:7131
|
|
327
|
+
- API: http://localhost:7130/api
|
|
328
|
+
`);
|
|
329
|
+
} catch (error) {
|
|
330
|
+
logger.error('Error during setup', {
|
|
331
|
+
error: error instanceof Error ? error.message : String(error),
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|