@realtimex/email-automator 2.1.0
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/.env.example +35 -0
- package/LICENSE +21 -0
- package/README.md +247 -0
- package/api/server.ts +130 -0
- package/api/src/config/index.ts +102 -0
- package/api/src/middleware/auth.ts +166 -0
- package/api/src/middleware/errorHandler.ts +97 -0
- package/api/src/middleware/index.ts +4 -0
- package/api/src/middleware/rateLimit.ts +87 -0
- package/api/src/middleware/validation.ts +118 -0
- package/api/src/routes/actions.ts +214 -0
- package/api/src/routes/auth.ts +157 -0
- package/api/src/routes/emails.ts +144 -0
- package/api/src/routes/health.ts +36 -0
- package/api/src/routes/index.ts +22 -0
- package/api/src/routes/migrate.ts +76 -0
- package/api/src/routes/rules.ts +149 -0
- package/api/src/routes/settings.ts +229 -0
- package/api/src/routes/sync.ts +152 -0
- package/api/src/services/eventLogger.ts +52 -0
- package/api/src/services/gmail.ts +456 -0
- package/api/src/services/intelligence.ts +288 -0
- package/api/src/services/microsoft.ts +368 -0
- package/api/src/services/processor.ts +596 -0
- package/api/src/services/scheduler.ts +255 -0
- package/api/src/services/supabase.ts +144 -0
- package/api/src/utils/contentCleaner.ts +114 -0
- package/api/src/utils/crypto.ts +80 -0
- package/api/src/utils/logger.ts +142 -0
- package/bin/email-automator-deploy.js +79 -0
- package/bin/email-automator-setup.js +144 -0
- package/bin/email-automator.js +61 -0
- package/dist/assets/index-BQ1uMdFh.js +97 -0
- package/dist/assets/index-Dzi17fx5.css +1 -0
- package/dist/email-automator-logo.svg +51 -0
- package/dist/favicon.svg +45 -0
- package/dist/index.html +14 -0
- package/index.html +13 -0
- package/package.json +112 -0
- package/public/email-automator-logo.svg +51 -0
- package/public/favicon.svg +45 -0
- package/scripts/deploy-functions.sh +55 -0
- package/scripts/migrate.sh +177 -0
- package/src/App.tsx +622 -0
- package/src/components/AccountSettings.tsx +310 -0
- package/src/components/AccountSettingsPage.tsx +390 -0
- package/src/components/Configuration.tsx +1345 -0
- package/src/components/Dashboard.tsx +940 -0
- package/src/components/ErrorBoundary.tsx +71 -0
- package/src/components/LiveTerminal.tsx +308 -0
- package/src/components/LoadingSpinner.tsx +39 -0
- package/src/components/Login.tsx +371 -0
- package/src/components/Logo.tsx +57 -0
- package/src/components/SetupWizard.tsx +388 -0
- package/src/components/Toast.tsx +109 -0
- package/src/components/migration/MigrationBanner.tsx +97 -0
- package/src/components/migration/MigrationModal.tsx +458 -0
- package/src/components/migration/MigrationPulseIndicator.tsx +38 -0
- package/src/components/mode-toggle.tsx +24 -0
- package/src/components/theme-provider.tsx +72 -0
- package/src/components/ui/alert.tsx +66 -0
- package/src/components/ui/button.tsx +57 -0
- package/src/components/ui/card.tsx +75 -0
- package/src/components/ui/dialog.tsx +133 -0
- package/src/components/ui/input.tsx +22 -0
- package/src/components/ui/label.tsx +24 -0
- package/src/components/ui/otp-input.tsx +184 -0
- package/src/context/AppContext.tsx +422 -0
- package/src/context/MigrationContext.tsx +53 -0
- package/src/context/TerminalContext.tsx +31 -0
- package/src/core/actions.ts +76 -0
- package/src/core/auth.ts +108 -0
- package/src/core/intelligence.ts +76 -0
- package/src/core/processor.ts +112 -0
- package/src/hooks/useRealtimeEmails.ts +111 -0
- package/src/index.css +140 -0
- package/src/lib/api-config.ts +42 -0
- package/src/lib/api-old.ts +228 -0
- package/src/lib/api.ts +421 -0
- package/src/lib/migration-check.ts +264 -0
- package/src/lib/sounds.ts +120 -0
- package/src/lib/supabase-config.ts +117 -0
- package/src/lib/supabase.ts +28 -0
- package/src/lib/types.ts +166 -0
- package/src/lib/utils.ts +6 -0
- package/src/main.tsx +10 -0
- package/supabase/.env.example +15 -0
- package/supabase/.temp/cli-latest +1 -0
- package/supabase/.temp/gotrue-version +1 -0
- package/supabase/.temp/pooler-url +1 -0
- package/supabase/.temp/postgres-version +1 -0
- package/supabase/.temp/project-ref +1 -0
- package/supabase/.temp/rest-version +1 -0
- package/supabase/.temp/storage-migration +1 -0
- package/supabase/.temp/storage-version +1 -0
- package/supabase/config.toml +95 -0
- package/supabase/functions/_shared/auth-helper.ts +76 -0
- package/supabase/functions/_shared/auth.ts +33 -0
- package/supabase/functions/_shared/cors.ts +45 -0
- package/supabase/functions/_shared/encryption.ts +70 -0
- package/supabase/functions/_shared/supabaseAdmin.ts +14 -0
- package/supabase/functions/api-v1-accounts/index.ts +133 -0
- package/supabase/functions/api-v1-emails/index.ts +177 -0
- package/supabase/functions/api-v1-rules/index.ts +177 -0
- package/supabase/functions/api-v1-settings/index.ts +247 -0
- package/supabase/functions/auth-gmail/index.ts +197 -0
- package/supabase/functions/auth-microsoft/index.ts +215 -0
- package/supabase/functions/setup/index.ts +92 -0
- package/supabase/migrations/20260114000000_initial_schema.sql +81 -0
- package/supabase/migrations/20260115000000_add_user_settings.sql +49 -0
- package/supabase/migrations/20260115000001_add_auth_flow.sql +80 -0
- package/supabase/migrations/20260115000002_fix_permissions.sql +5 -0
- package/supabase/migrations/20260115000003_fix_init_state_permissions.sql +9 -0
- package/supabase/migrations/20260115000004_add_migration_rpc.sql +13 -0
- package/supabase/migrations/20260115000005_add_provider_creds.sql +7 -0
- package/supabase/migrations/20260115000006_backfill_profiles.sql +22 -0
- package/supabase/migrations/20260116000000_add_sync_scope.sql +15 -0
- package/supabase/migrations/20260116000001_per_account_sync_scope.sql +19 -0
- package/supabase/migrations/20260116000002_add_llm_api_key.sql +5 -0
- package/supabase/migrations/20260117000000_refactor_integrations.sql +36 -0
- package/supabase/migrations/20260117000001_add_processing_events.sql +30 -0
- package/supabase/migrations/20260117000002_multi_actions.sql +15 -0
- package/supabase/migrations/20260117000003_seed_default_rules.sql +77 -0
- package/supabase/migrations/20260117000004_rule_instructions.sql +5 -0
- package/supabase/migrations/20260117000005_rule_attachments.sql +7 -0
- package/supabase/migrations/20260117000006_setup_storage.sql +32 -0
- package/supabase/migrations/20260117000007_add_system_logs.sql +26 -0
- package/supabase/migrations/20260117000008_link_logs_to_accounts.sql +8 -0
- package/supabase/migrations/20260117000009_convert_toggles_to_rules.sql +28 -0
- package/supabase/migrations/20260117000010_add_atomic_action_append.sql +13 -0
- package/supabase/migrations/20260117000011_add_profile_avatar.sql +4 -0
- package/supabase/migrations/20260117000012_setup_avatars_storage.sql +26 -0
- package/supabase/templates/confirmation.html +76 -0
- package/supabase/templates/email-change.html +76 -0
- package/supabase/templates/invite.html +72 -0
- package/supabase/templates/magic-link.html +68 -0
- package/supabase/templates/recovery.html +82 -0
- package/tsconfig.json +36 -0
- package/vite.config.ts +162 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
font-family: Arial, sans-serif;
|
|
8
|
+
background-color: #f4f4f4;
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.container {
|
|
14
|
+
width: 100%;
|
|
15
|
+
max-width: 600px;
|
|
16
|
+
margin: 0 auto;
|
|
17
|
+
background-color: #ffffff;
|
|
18
|
+
padding: 20px;
|
|
19
|
+
border-radius: 8px;
|
|
20
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.content {
|
|
24
|
+
padding: 20px;
|
|
25
|
+
line-height: 1.6;
|
|
26
|
+
color: #555555;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.content p {
|
|
30
|
+
margin: 0 0 10px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h2,
|
|
34
|
+
h3 {
|
|
35
|
+
color: #333333;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
38
|
+
</head>
|
|
39
|
+
|
|
40
|
+
<body>
|
|
41
|
+
<div class="container">
|
|
42
|
+
<div class="content">
|
|
43
|
+
<h2>Welcome to Email Automator</h2>
|
|
44
|
+
|
|
45
|
+
<p>Hi there,</p>
|
|
46
|
+
|
|
47
|
+
<p>Your Email Automator account has been successfully created!</p>
|
|
48
|
+
|
|
49
|
+
<h3>How to Access Your Account</h3>
|
|
50
|
+
|
|
51
|
+
<ol style="line-height: 1.8">
|
|
52
|
+
<li>Open the Email Automator application.</li>
|
|
53
|
+
<li>Select <strong>“Login with Email Code (OTP)”</strong>.</li>
|
|
54
|
+
<li>Enter your email address: <strong>{{ .Email }}</strong>.</li>
|
|
55
|
+
<li>Check your inbox for a 6-digit verification code.</li>
|
|
56
|
+
<li>Enter the code in the app when prompted.</li>
|
|
57
|
+
<li>Create a password to complete setup.</li>
|
|
58
|
+
</ol>
|
|
59
|
+
|
|
60
|
+
<h3>Need Help?</h3>
|
|
61
|
+
|
|
62
|
+
<p>If you have any questions, please contact your administrator.</p>
|
|
63
|
+
|
|
64
|
+
<p style="color: #666; font-size: 12px">
|
|
65
|
+
If you didn’t request this account, please reach out to your
|
|
66
|
+
administrator immediately.
|
|
67
|
+
</p>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</body>
|
|
71
|
+
|
|
72
|
+
</html>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
font-family: Arial, sans-serif;
|
|
8
|
+
background-color: #f4f4f4;
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.container {
|
|
14
|
+
width: 100%;
|
|
15
|
+
max-width: 600px;
|
|
16
|
+
margin: 0 auto;
|
|
17
|
+
background-color: #ffffff;
|
|
18
|
+
padding: 20px;
|
|
19
|
+
border-radius: 8px;
|
|
20
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.content {
|
|
24
|
+
padding: 20px;
|
|
25
|
+
line-height: 1.6;
|
|
26
|
+
color: #555555;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.content p {
|
|
30
|
+
margin: 0 0 10px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h2 {
|
|
34
|
+
color: #333333;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.otp-code {
|
|
38
|
+
font-size: 24px;
|
|
39
|
+
font-weight: bold;
|
|
40
|
+
letter-spacing: 4px;
|
|
41
|
+
color: #007bff;
|
|
42
|
+
margin: 20px 0;
|
|
43
|
+
text-align: center;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
46
|
+
</head>
|
|
47
|
+
|
|
48
|
+
<body>
|
|
49
|
+
<div class="container">
|
|
50
|
+
<div class="content">
|
|
51
|
+
<h2>Email Automator Magic OTP</h2>
|
|
52
|
+
|
|
53
|
+
<p>Hi there,</p>
|
|
54
|
+
|
|
55
|
+
<p>Use the following verification code to log in to your account:</p>
|
|
56
|
+
|
|
57
|
+
<div class="otp-code">{{ .Token }}</div>
|
|
58
|
+
|
|
59
|
+
<p>This code will expire in 1 hour.</p>
|
|
60
|
+
|
|
61
|
+
<p>
|
|
62
|
+
If you didn't request this code, you can safely ignore this email.
|
|
63
|
+
</p>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</body>
|
|
67
|
+
|
|
68
|
+
</html>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
font-family: Arial, sans-serif;
|
|
8
|
+
background-color: #f4f4f4;
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.container {
|
|
14
|
+
width: 100%;
|
|
15
|
+
max-width: 600px;
|
|
16
|
+
margin: 0 auto;
|
|
17
|
+
background-color: #ffffff;
|
|
18
|
+
padding: 20px;
|
|
19
|
+
border-radius: 8px;
|
|
20
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.header {
|
|
24
|
+
text-align: center;
|
|
25
|
+
padding: 10px 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.header h2 {
|
|
29
|
+
margin: 0;
|
|
30
|
+
color: #333333;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.content {
|
|
34
|
+
padding: 20px;
|
|
35
|
+
line-height: 1.6;
|
|
36
|
+
color: #555555;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.content p {
|
|
40
|
+
margin: 0 0 10px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.button {
|
|
44
|
+
display: block;
|
|
45
|
+
width: 200px;
|
|
46
|
+
margin: 20px auto;
|
|
47
|
+
padding: 10px;
|
|
48
|
+
text-align: center;
|
|
49
|
+
background-color: #007bff;
|
|
50
|
+
color: #ffffff !important;
|
|
51
|
+
text-decoration: none;
|
|
52
|
+
border-radius: 5px;
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
|
|
57
|
+
<body>
|
|
58
|
+
<div class="container">
|
|
59
|
+
<div class="header">
|
|
60
|
+
<h2>Reset Your Email Automator Password</h2>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="content">
|
|
63
|
+
<p>Hello,</p>
|
|
64
|
+
<p>
|
|
65
|
+
We've received a request to reset the password for the Email Automator
|
|
66
|
+
account associated with the email {{ .Email }}. No changes have been
|
|
67
|
+
made to your account yet.
|
|
68
|
+
</p>
|
|
69
|
+
<p>You can reset your password by clicking the button below.</p>
|
|
70
|
+
<p>
|
|
71
|
+
<a href="{{ .ConfirmationURL }}auth-callback.html" class="button">Reset your password</a>
|
|
72
|
+
</p>
|
|
73
|
+
<p>
|
|
74
|
+
If you did not request a new password, please contact the Email Automator
|
|
75
|
+
Email Automator administrator immediately.
|
|
76
|
+
</p>
|
|
77
|
+
<p>The Email Automator team</p>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</body>
|
|
81
|
+
|
|
82
|
+
</html>
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": [
|
|
6
|
+
"DOM",
|
|
7
|
+
"DOM.Iterable",
|
|
8
|
+
"ESNext"
|
|
9
|
+
],
|
|
10
|
+
"allowJs": false,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"allowSyntheticDefaultImports": true,
|
|
14
|
+
"strict": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"module": "ESNext",
|
|
17
|
+
"moduleResolution": "Node",
|
|
18
|
+
"resolveJsonModule": true,
|
|
19
|
+
"isolatedModules": true,
|
|
20
|
+
"noEmit": true,
|
|
21
|
+
"jsx": "react-jsx",
|
|
22
|
+
"types": [
|
|
23
|
+
"vite/client"
|
|
24
|
+
],
|
|
25
|
+
"baseUrl": ".",
|
|
26
|
+
"paths": {
|
|
27
|
+
"@/*": [
|
|
28
|
+
"src/*"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"include": [
|
|
33
|
+
"src",
|
|
34
|
+
"api"
|
|
35
|
+
]
|
|
36
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
4
|
+
import { spawn } from 'child_process';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
// https://vitejs.dev/config/
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
plugins: [
|
|
10
|
+
react(),
|
|
11
|
+
tailwindcss(),
|
|
12
|
+
{
|
|
13
|
+
name: 'api-migrate',
|
|
14
|
+
configureServer(server) {
|
|
15
|
+
server.middlewares.use('/api/migrate', async (req, res, next) => {
|
|
16
|
+
if (req.method !== 'POST') return next();
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
// Parse request body
|
|
20
|
+
const buffers = [];
|
|
21
|
+
for await (const chunk of req) {
|
|
22
|
+
buffers.push(chunk);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let body = {};
|
|
26
|
+
try {
|
|
27
|
+
body = JSON.parse(Buffer.concat(buffers).toString());
|
|
28
|
+
} catch {
|
|
29
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
30
|
+
res.end(JSON.stringify({ error: 'Invalid JSON in request body' }));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { projectRef, dbPassword, accessToken } = body;
|
|
35
|
+
|
|
36
|
+
// Validation
|
|
37
|
+
if (!projectRef) {
|
|
38
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
39
|
+
res.end(JSON.stringify({ error: 'projectRef is required' }));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Set up streaming response
|
|
44
|
+
res.writeHead(200, {
|
|
45
|
+
'Content-Type': 'text/plain',
|
|
46
|
+
'Transfer-Encoding': 'chunked',
|
|
47
|
+
'Cache-Control': 'no-cache',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const log = (msg) => res.write(`${msg}\n`);
|
|
51
|
+
|
|
52
|
+
log('🚀 Starting migration (Development Mode)...');
|
|
53
|
+
log('');
|
|
54
|
+
|
|
55
|
+
// Prepare environment
|
|
56
|
+
const env = {
|
|
57
|
+
...process.env,
|
|
58
|
+
SUPABASE_PROJECT_ID: projectRef,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
if (accessToken) {
|
|
62
|
+
env.SUPABASE_ACCESS_TOKEN = accessToken;
|
|
63
|
+
log('🔑 Using provided access token');
|
|
64
|
+
} else if (dbPassword) {
|
|
65
|
+
env.SUPABASE_DB_PASSWORD = dbPassword;
|
|
66
|
+
log('🔑 Using provided database password');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
log('');
|
|
70
|
+
log('─'.repeat(60));
|
|
71
|
+
log('');
|
|
72
|
+
|
|
73
|
+
// Path to migration script
|
|
74
|
+
const scriptPath = path.join(process.cwd(), 'scripts', 'migrate.sh');
|
|
75
|
+
|
|
76
|
+
// Execute migration script
|
|
77
|
+
const migrationProcess = spawn('bash', [scriptPath], {
|
|
78
|
+
env,
|
|
79
|
+
cwd: process.cwd(),
|
|
80
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
let hasError = false;
|
|
84
|
+
|
|
85
|
+
// Stream stdout
|
|
86
|
+
migrationProcess.stdout.on('data', (data) => {
|
|
87
|
+
const lines = data.toString().split('\n');
|
|
88
|
+
lines.forEach((line) => {
|
|
89
|
+
if (line.trim()) log(line);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Stream stderr
|
|
94
|
+
migrationProcess.stderr.on('data', (data) => {
|
|
95
|
+
const lines = data.toString().split('\n');
|
|
96
|
+
lines.forEach((line) => {
|
|
97
|
+
if (line.trim()) {
|
|
98
|
+
if (line.toLowerCase().includes('error') || line.toLowerCase().includes('failed')) {
|
|
99
|
+
log(`❌ ${line}`);
|
|
100
|
+
hasError = true;
|
|
101
|
+
} else {
|
|
102
|
+
log(`⚠️ ${line}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Handle completion
|
|
109
|
+
migrationProcess.on('close', (code) => {
|
|
110
|
+
log('');
|
|
111
|
+
log('─'.repeat(60));
|
|
112
|
+
log('');
|
|
113
|
+
|
|
114
|
+
if (code === 0 && !hasError) {
|
|
115
|
+
log('✅ Migration completed successfully!');
|
|
116
|
+
log('');
|
|
117
|
+
log('🎉 Your database is now ready to use.');
|
|
118
|
+
} else {
|
|
119
|
+
log(`❌ Migration failed with exit code: ${code}`);
|
|
120
|
+
log('');
|
|
121
|
+
log('💡 Ensure Supabase CLI is installed: npm install');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
res.end();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Handle errors
|
|
128
|
+
migrationProcess.on('error', (error) => {
|
|
129
|
+
log('');
|
|
130
|
+
log(`❌ Failed to start migration: ${error.message}`);
|
|
131
|
+
res.end();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Handle client disconnect
|
|
135
|
+
req.on('close', () => {
|
|
136
|
+
if (!migrationProcess.killed) {
|
|
137
|
+
migrationProcess.kill();
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error('[Migration API] Error:', error);
|
|
142
|
+
if (!res.headersSent) {
|
|
143
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
144
|
+
res.end(JSON.stringify({ error: 'Internal server error' }));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
server: {
|
|
152
|
+
port: 3000,
|
|
153
|
+
proxy: {
|
|
154
|
+
'/api': 'http://localhost:3001'
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
resolve: {
|
|
158
|
+
alias: {
|
|
159
|
+
"@": path.resolve(__dirname, "./src"),
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
});
|