@realtimex/email-automator 2.9.7 → 2.10.2
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/api/src/middleware/rateLimit.ts +1 -1
- package/api/src/routes/index.ts +0 -2
- package/dist/api/src/middleware/rateLimit.js +1 -1
- package/dist/api/src/routes/index.js +0 -2
- package/dist/assets/{index-DIRxy7SL.js → index-BIKlTtjm.js} +26 -26
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/scripts/migrate.sh +17 -16
- package/supabase/.temp/pooler-url +1 -1
- package/supabase/.temp/project-ref +1 -1
- package/supabase/functions/setup/index.ts +25 -8
- package/supabase/migrations/20260120100000_fix_auth_triggers.sql +44 -0
- package/api/src/routes/deploy.ts +0 -140
- package/dist/api/src/routes/deploy.js +0 -121
- package/scripts/deploy-functions.sh +0 -154
package/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Email Automator</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BIKlTtjm.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-SRvHiNrG.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/package.json
CHANGED
package/scripts/migrate.sh
CHANGED
|
@@ -135,29 +135,30 @@ else
|
|
|
135
135
|
fi
|
|
136
136
|
|
|
137
137
|
echo "---------------------------------------------------------"
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if [
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if [[ "$func_name" != "_shared" && "$func_name" != .* ]]; then
|
|
138
|
+
echo "⚡ Deploying Edge Functions..."
|
|
139
|
+
# Deploys API logic explicitly for each function to ensure they are all deployed
|
|
140
|
+
# We skip _shared and hidden folders
|
|
141
|
+
if [ -d "supabase/functions" ]; then
|
|
142
|
+
for func in supabase/functions/*; do
|
|
143
|
+
if [ -d "$func" ]; then
|
|
144
|
+
func_name=$(basename "$func")
|
|
145
|
+
# Skip _shared, hidden folders, and empty directories
|
|
146
|
+
if [[ "$func_name" != "_shared" && "$func_name" != .* ]]; then
|
|
147
|
+
# Check if index.ts exists before deploying
|
|
148
|
+
if [ -f "$func/index.ts" ]; then
|
|
150
149
|
echo " Deploying $func_name..."
|
|
151
150
|
if ! $SUPABASE_CMD functions deploy "$func_name" --no-verify-jwt; then
|
|
152
151
|
echo "❌ Error: Failed to deploy function '$func_name'."
|
|
153
152
|
exit 1
|
|
154
153
|
fi
|
|
154
|
+
else
|
|
155
|
+
echo " ⏭️ Skipping $func_name (no index.ts found)"
|
|
155
156
|
fi
|
|
156
157
|
fi
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
fi
|
|
159
|
+
done
|
|
160
|
+
else
|
|
161
|
+
echo "⚠️ Warning: supabase/functions directory not found. Skipping function deployment."
|
|
161
162
|
fi
|
|
162
163
|
|
|
163
164
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
postgresql://postgres.
|
|
1
|
+
postgresql://postgres.xliwllwuhwneaqmwfvqc@aws-1-us-east-1.pooler.supabase.com:5432/postgres
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
xliwllwuhwneaqmwfvqc
|
|
@@ -5,6 +5,13 @@ import { corsHeaders, createErrorResponse } from "../_shared/cors.ts";
|
|
|
5
5
|
async function createFirstUser(req: Request) {
|
|
6
6
|
try {
|
|
7
7
|
const { email, password, first_name, last_name } = await req.json();
|
|
8
|
+
console.log(`[Setup] Starting setup for ${email}`);
|
|
9
|
+
|
|
10
|
+
// Check if SUPABASE_SERVICE_ROLE_KEY is set
|
|
11
|
+
if (!Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')) {
|
|
12
|
+
console.error("[Setup] SUPABASE_SERVICE_ROLE_KEY is missing!");
|
|
13
|
+
return createErrorResponse(500, "SUPABASE_SERVICE_ROLE_KEY is missing in Edge Function environment");
|
|
14
|
+
}
|
|
8
15
|
|
|
9
16
|
// Check if any users exist
|
|
10
17
|
const { count, error: countError } = await supabaseAdmin
|
|
@@ -12,15 +19,17 @@ async function createFirstUser(req: Request) {
|
|
|
12
19
|
.select("*", { count: "exact", head: true });
|
|
13
20
|
|
|
14
21
|
if (countError) {
|
|
15
|
-
console.error("Error checking profiles:", countError);
|
|
16
|
-
return createErrorResponse(500,
|
|
22
|
+
console.error("[Setup] Error checking profiles table:", countError);
|
|
23
|
+
return createErrorResponse(500, `Database error checking profiles: ${countError.message} (code: ${countError.code})`);
|
|
17
24
|
}
|
|
18
25
|
|
|
26
|
+
console.log(`[Setup] Existing profiles count: ${count}`);
|
|
19
27
|
if (count && count > 0) {
|
|
20
28
|
return createErrorResponse(403, "First user already exists");
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
// Create user with admin API (bypasses signup restrictions)
|
|
32
|
+
console.log("[Setup] Creating admin user...");
|
|
24
33
|
const { data, error: userError } = await supabaseAdmin.auth.admin.createUser({
|
|
25
34
|
email,
|
|
26
35
|
password,
|
|
@@ -29,10 +38,12 @@ async function createFirstUser(req: Request) {
|
|
|
29
38
|
});
|
|
30
39
|
|
|
31
40
|
if (userError || !data?.user) {
|
|
32
|
-
console.error("Error creating
|
|
33
|
-
return createErrorResponse(500, `Failed to create
|
|
41
|
+
console.error("[Setup] Error creating auth user:", userError);
|
|
42
|
+
return createErrorResponse(500, `Failed to create auth user: ${userError?.message || 'Unknown error'}`);
|
|
34
43
|
}
|
|
35
44
|
|
|
45
|
+
console.log(`[Setup] User created successfully: ${data.user.id}. Creating profile...`);
|
|
46
|
+
|
|
36
47
|
// Explicitly create profile as admin (trigger may not fire with admin.createUser in some configs)
|
|
37
48
|
// Use upsert to handle case where trigger did fire
|
|
38
49
|
const { error: profileError } = await supabaseAdmin
|
|
@@ -46,18 +57,24 @@ async function createFirstUser(req: Request) {
|
|
|
46
57
|
}, { onConflict: 'id' });
|
|
47
58
|
|
|
48
59
|
if (profileError) {
|
|
49
|
-
console.error("Error creating profile:", profileError);
|
|
60
|
+
console.error("[Setup] Error creating profile row:", profileError);
|
|
50
61
|
// Profile creation failed - this is critical for is_initialized
|
|
51
|
-
return createErrorResponse(500, `User created but profile failed: ${profileError.message}`);
|
|
62
|
+
return createErrorResponse(500, `User created but profile record failed: ${profileError.message} (code: ${profileError.code})`);
|
|
52
63
|
}
|
|
53
64
|
|
|
65
|
+
console.log("[Setup] Profile created successfully. Verification...");
|
|
66
|
+
|
|
54
67
|
// Verify the profile was created
|
|
55
|
-
const { count: profileCount } = await supabaseAdmin
|
|
68
|
+
const { count: profileCount, error: verifyError } = await supabaseAdmin
|
|
56
69
|
.from("profiles")
|
|
57
70
|
.select("*", { count: "exact", head: true })
|
|
58
71
|
.eq("id", data.user.id);
|
|
59
72
|
|
|
60
|
-
|
|
73
|
+
if (verifyError) {
|
|
74
|
+
console.warn("[Setup] Final verification failed:", verifyError);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log("[Setup] Setup completed successfully");
|
|
61
78
|
|
|
62
79
|
return new Response(
|
|
63
80
|
JSON.stringify({
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
-- Fix Auth triggers by setting robust search_path
|
|
2
|
+
-- This resolves "Database error creating new user" (unexpected_failure) during setup
|
|
3
|
+
|
|
4
|
+
CREATE OR REPLACE FUNCTION public.handle_new_user()
|
|
5
|
+
RETURNS TRIGGER
|
|
6
|
+
LANGUAGE plpgsql
|
|
7
|
+
SECURITY DEFINER SET search_path = public
|
|
8
|
+
AS $$
|
|
9
|
+
DECLARE
|
|
10
|
+
profile_count int;
|
|
11
|
+
BEGIN
|
|
12
|
+
SELECT count(id) INTO profile_count
|
|
13
|
+
FROM public.profiles;
|
|
14
|
+
|
|
15
|
+
INSERT INTO public.profiles (id, first_name, last_name, email, is_admin)
|
|
16
|
+
VALUES (
|
|
17
|
+
new.id,
|
|
18
|
+
new.raw_user_meta_data ->> 'first_name',
|
|
19
|
+
new.raw_user_meta_data ->> 'last_name',
|
|
20
|
+
new.email,
|
|
21
|
+
-- If it's the first user, make them admin. Otherwise, standard user.
|
|
22
|
+
CASE WHEN profile_count > 0 THEN false ELSE true END
|
|
23
|
+
);
|
|
24
|
+
RETURN new;
|
|
25
|
+
END;
|
|
26
|
+
$$;
|
|
27
|
+
|
|
28
|
+
CREATE OR REPLACE FUNCTION public.handle_update_user()
|
|
29
|
+
RETURNS TRIGGER
|
|
30
|
+
LANGUAGE plpgsql
|
|
31
|
+
SECURITY DEFINER SET search_path = public
|
|
32
|
+
AS $$
|
|
33
|
+
BEGIN
|
|
34
|
+
UPDATE public.profiles
|
|
35
|
+
SET
|
|
36
|
+
first_name = new.raw_user_meta_data ->> 'first_name',
|
|
37
|
+
last_name = new.raw_user_meta_data ->> 'last_name',
|
|
38
|
+
email = new.email,
|
|
39
|
+
updated_at = now()
|
|
40
|
+
WHERE id = new.id;
|
|
41
|
+
|
|
42
|
+
RETURN new;
|
|
43
|
+
END;
|
|
44
|
+
$$;
|
package/api/src/routes/deploy.ts
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { Router } from 'express';
|
|
2
|
-
import { spawn } from 'child_process';
|
|
3
|
-
import { asyncHandler } from '../middleware/errorHandler.js';
|
|
4
|
-
import { validateBody, schemas } from '../middleware/validation.js';
|
|
5
|
-
import { config } from '../config/index.js';
|
|
6
|
-
import { createLogger } from '../utils/logger.js';
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
|
|
9
|
-
const router = Router();
|
|
10
|
-
const logger = createLogger('DeployRoutes');
|
|
11
|
-
|
|
12
|
-
// Deploy Edge Functions
|
|
13
|
-
router.post('/',
|
|
14
|
-
validateBody(schemas.migrate), // Reuse migrate schema (same credentials needed)
|
|
15
|
-
asyncHandler(async (req, res) => {
|
|
16
|
-
const { projectRef, dbPassword, accessToken } = req.body;
|
|
17
|
-
|
|
18
|
-
logger.info('Starting Edge Functions deployment', { projectRef });
|
|
19
|
-
|
|
20
|
-
res.setHeader('Content-Type', 'text/plain');
|
|
21
|
-
res.setHeader('Transfer-Encoding', 'chunked');
|
|
22
|
-
|
|
23
|
-
const sendLog = (message: string) => {
|
|
24
|
-
res.write(message + '\n');
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
sendLog('🚀 Starting Edge Functions deployment...');
|
|
29
|
-
sendLog('');
|
|
30
|
-
|
|
31
|
-
const scriptPath = join(config.scriptsDir, 'deploy-functions.sh');
|
|
32
|
-
|
|
33
|
-
const env = {
|
|
34
|
-
...process.env,
|
|
35
|
-
SUPABASE_PROJECT_ID: projectRef,
|
|
36
|
-
SUPABASE_DB_PASSWORD: dbPassword || '',
|
|
37
|
-
SUPABASE_ACCESS_TOKEN: accessToken || '',
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
if (accessToken) {
|
|
41
|
-
sendLog('✓ Using Supabase access token for authentication');
|
|
42
|
-
} else {
|
|
43
|
-
sendLog('✓ Using database password for authentication');
|
|
44
|
-
}
|
|
45
|
-
sendLog('');
|
|
46
|
-
|
|
47
|
-
const child = spawn('bash', [scriptPath], {
|
|
48
|
-
env,
|
|
49
|
-
cwd: config.rootDir,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
let hasError = false;
|
|
53
|
-
|
|
54
|
-
child.stdout.on('data', (data) => {
|
|
55
|
-
const lines = data.toString().split('\n');
|
|
56
|
-
lines.forEach((line: string) => {
|
|
57
|
-
if (line.trim()) {
|
|
58
|
-
sendLog(line);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
child.stderr.on('data', (data) => {
|
|
64
|
-
const lines = data.toString().split('\n');
|
|
65
|
-
lines.forEach((line: string) => {
|
|
66
|
-
if (line.trim()) {
|
|
67
|
-
// Check for error patterns
|
|
68
|
-
if (
|
|
69
|
-
line.includes('error') ||
|
|
70
|
-
line.includes('Error') ||
|
|
71
|
-
line.includes('ERROR') ||
|
|
72
|
-
line.includes('failed')
|
|
73
|
-
) {
|
|
74
|
-
sendLog(`❌ ${line}`);
|
|
75
|
-
hasError = true;
|
|
76
|
-
} else {
|
|
77
|
-
sendLog(`⚠️ ${line}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
child.on('close', (code) => {
|
|
84
|
-
sendLog('');
|
|
85
|
-
sendLog('─'.repeat(60));
|
|
86
|
-
|
|
87
|
-
if (code === 0 && !hasError) {
|
|
88
|
-
sendLog('');
|
|
89
|
-
sendLog('✅ Edge Functions deployed successfully!');
|
|
90
|
-
sendLog('RESULT: success');
|
|
91
|
-
sendLog('');
|
|
92
|
-
sendLog('🎉 Your API endpoints are now live.');
|
|
93
|
-
logger.info('Deployment completed successfully', { projectRef });
|
|
94
|
-
} else {
|
|
95
|
-
sendLog('');
|
|
96
|
-
sendLog(`❌ Deployment failed with exit code: ${code}`);
|
|
97
|
-
sendLog('RESULT: failure');
|
|
98
|
-
sendLog('');
|
|
99
|
-
sendLog('💡 Troubleshooting tips:');
|
|
100
|
-
sendLog(' 1. Verify your Supabase credentials are correct');
|
|
101
|
-
sendLog(' 2. Ensure you are logged in: supabase login');
|
|
102
|
-
sendLog(' 3. Check if Supabase CLI is installed (npm install -g supabase)');
|
|
103
|
-
sendLog(' 4. Review the error messages above for specific issues');
|
|
104
|
-
logger.error('Deployment failed', new Error(`Exit code: ${code}`), { projectRef });
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
res.end();
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
child.on('error', (error) => {
|
|
111
|
-
sendLog('');
|
|
112
|
-
sendLog(`❌ Failed to run deployment: ${error.message}`);
|
|
113
|
-
sendLog('RESULT: failure');
|
|
114
|
-
sendLog('');
|
|
115
|
-
sendLog('💡 This usually means:');
|
|
116
|
-
sendLog(' - Bash is not available on your system');
|
|
117
|
-
sendLog(' - The deployment script is not executable');
|
|
118
|
-
sendLog(' - There are permission issues');
|
|
119
|
-
logger.error('Deployment spawn error', error);
|
|
120
|
-
res.end();
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
// Handle client disconnect
|
|
124
|
-
req.on('close', () => {
|
|
125
|
-
if (!child.killed) {
|
|
126
|
-
child.kill();
|
|
127
|
-
logger.info('Deployment process terminated - client disconnected');
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
} catch (error: any) {
|
|
131
|
-
sendLog('');
|
|
132
|
-
sendLog(`❌ Server error: ${error.message}`);
|
|
133
|
-
sendLog('RESULT: failure');
|
|
134
|
-
logger.error('Deployment error', error);
|
|
135
|
-
res.end();
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
export default router;
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { Router } from 'express';
|
|
2
|
-
import { spawn } from 'child_process';
|
|
3
|
-
import { asyncHandler } from '../middleware/errorHandler.js';
|
|
4
|
-
import { validateBody, schemas } from '../middleware/validation.js';
|
|
5
|
-
import { config } from '../config/index.js';
|
|
6
|
-
import { createLogger } from '../utils/logger.js';
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
const router = Router();
|
|
9
|
-
const logger = createLogger('DeployRoutes');
|
|
10
|
-
// Deploy Edge Functions
|
|
11
|
-
router.post('/', validateBody(schemas.migrate), // Reuse migrate schema (same credentials needed)
|
|
12
|
-
asyncHandler(async (req, res) => {
|
|
13
|
-
const { projectRef, dbPassword, accessToken } = req.body;
|
|
14
|
-
logger.info('Starting Edge Functions deployment', { projectRef });
|
|
15
|
-
res.setHeader('Content-Type', 'text/plain');
|
|
16
|
-
res.setHeader('Transfer-Encoding', 'chunked');
|
|
17
|
-
const sendLog = (message) => {
|
|
18
|
-
res.write(message + '\n');
|
|
19
|
-
};
|
|
20
|
-
try {
|
|
21
|
-
sendLog('🚀 Starting Edge Functions deployment...');
|
|
22
|
-
sendLog('');
|
|
23
|
-
const scriptPath = join(config.scriptsDir, 'deploy-functions.sh');
|
|
24
|
-
const env = {
|
|
25
|
-
...process.env,
|
|
26
|
-
SUPABASE_PROJECT_ID: projectRef,
|
|
27
|
-
SUPABASE_DB_PASSWORD: dbPassword || '',
|
|
28
|
-
SUPABASE_ACCESS_TOKEN: accessToken || '',
|
|
29
|
-
};
|
|
30
|
-
if (accessToken) {
|
|
31
|
-
sendLog('✓ Using Supabase access token for authentication');
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
sendLog('✓ Using database password for authentication');
|
|
35
|
-
}
|
|
36
|
-
sendLog('');
|
|
37
|
-
const child = spawn('bash', [scriptPath], {
|
|
38
|
-
env,
|
|
39
|
-
cwd: config.rootDir,
|
|
40
|
-
});
|
|
41
|
-
let hasError = false;
|
|
42
|
-
child.stdout.on('data', (data) => {
|
|
43
|
-
const lines = data.toString().split('\n');
|
|
44
|
-
lines.forEach((line) => {
|
|
45
|
-
if (line.trim()) {
|
|
46
|
-
sendLog(line);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
child.stderr.on('data', (data) => {
|
|
51
|
-
const lines = data.toString().split('\n');
|
|
52
|
-
lines.forEach((line) => {
|
|
53
|
-
if (line.trim()) {
|
|
54
|
-
// Check for error patterns
|
|
55
|
-
if (line.includes('error') ||
|
|
56
|
-
line.includes('Error') ||
|
|
57
|
-
line.includes('ERROR') ||
|
|
58
|
-
line.includes('failed')) {
|
|
59
|
-
sendLog(`❌ ${line}`);
|
|
60
|
-
hasError = true;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
sendLog(`⚠️ ${line}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
child.on('close', (code) => {
|
|
69
|
-
sendLog('');
|
|
70
|
-
sendLog('─'.repeat(60));
|
|
71
|
-
if (code === 0 && !hasError) {
|
|
72
|
-
sendLog('');
|
|
73
|
-
sendLog('✅ Edge Functions deployed successfully!');
|
|
74
|
-
sendLog('RESULT: success');
|
|
75
|
-
sendLog('');
|
|
76
|
-
sendLog('🎉 Your API endpoints are now live.');
|
|
77
|
-
logger.info('Deployment completed successfully', { projectRef });
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
sendLog('');
|
|
81
|
-
sendLog(`❌ Deployment failed with exit code: ${code}`);
|
|
82
|
-
sendLog('RESULT: failure');
|
|
83
|
-
sendLog('');
|
|
84
|
-
sendLog('💡 Troubleshooting tips:');
|
|
85
|
-
sendLog(' 1. Verify your Supabase credentials are correct');
|
|
86
|
-
sendLog(' 2. Ensure you are logged in: supabase login');
|
|
87
|
-
sendLog(' 3. Check if Supabase CLI is installed (npm install -g supabase)');
|
|
88
|
-
sendLog(' 4. Review the error messages above for specific issues');
|
|
89
|
-
logger.error('Deployment failed', new Error(`Exit code: ${code}`), { projectRef });
|
|
90
|
-
}
|
|
91
|
-
res.end();
|
|
92
|
-
});
|
|
93
|
-
child.on('error', (error) => {
|
|
94
|
-
sendLog('');
|
|
95
|
-
sendLog(`❌ Failed to run deployment: ${error.message}`);
|
|
96
|
-
sendLog('RESULT: failure');
|
|
97
|
-
sendLog('');
|
|
98
|
-
sendLog('💡 This usually means:');
|
|
99
|
-
sendLog(' - Bash is not available on your system');
|
|
100
|
-
sendLog(' - The deployment script is not executable');
|
|
101
|
-
sendLog(' - There are permission issues');
|
|
102
|
-
logger.error('Deployment spawn error', error);
|
|
103
|
-
res.end();
|
|
104
|
-
});
|
|
105
|
-
// Handle client disconnect
|
|
106
|
-
req.on('close', () => {
|
|
107
|
-
if (!child.killed) {
|
|
108
|
-
child.kill();
|
|
109
|
-
logger.info('Deployment process terminated - client disconnected');
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
sendLog('');
|
|
115
|
-
sendLog(`❌ Server error: ${error.message}`);
|
|
116
|
-
sendLog('RESULT: failure');
|
|
117
|
-
logger.error('Deployment error', error);
|
|
118
|
-
res.end();
|
|
119
|
-
}
|
|
120
|
-
}));
|
|
121
|
-
export default router;
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# ==============================================================================
|
|
4
|
-
# EMAIL AUTOMATOR EDGE FUNCTIONS DEPLOYMENT
|
|
5
|
-
# ==============================================================================
|
|
6
|
-
#
|
|
7
|
-
# DESCRIPTION:
|
|
8
|
-
# This script deploys all Edge Functions to your Supabase project.
|
|
9
|
-
# It can be run standalone or called by the API server.
|
|
10
|
-
#
|
|
11
|
-
# PREREQUISITES:
|
|
12
|
-
# 1. Supabase CLI installed (global or local via npm)
|
|
13
|
-
# 2. You must be logged in (run: 'supabase login')
|
|
14
|
-
# 3. You need your Supabase Project Reference ID
|
|
15
|
-
# 4. You need your Database Password or Access Token
|
|
16
|
-
#
|
|
17
|
-
# USAGE:
|
|
18
|
-
# Standalone:
|
|
19
|
-
# ./deploy-functions.sh
|
|
20
|
-
#
|
|
21
|
-
# Via environment variables (used by API):
|
|
22
|
-
# SUPABASE_PROJECT_ID=xxx SUPABASE_ACCESS_TOKEN=yyy ./deploy-functions.sh
|
|
23
|
-
#
|
|
24
|
-
# ==============================================================================
|
|
25
|
-
|
|
26
|
-
set -e
|
|
27
|
-
|
|
28
|
-
echo "🚀 Deploying Email Automator Edge Functions..."
|
|
29
|
-
echo ""
|
|
30
|
-
|
|
31
|
-
# Prefer bundled Supabase CLI from node_modules to keep version locked
|
|
32
|
-
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
33
|
-
ROOT_DIR=$(cd "$SCRIPT_DIR/.." && pwd)
|
|
34
|
-
|
|
35
|
-
find_supabase_bin() {
|
|
36
|
-
local dir="$ROOT_DIR"
|
|
37
|
-
while [ "$dir" != "/" ]; do
|
|
38
|
-
local candidate="$dir/node_modules/.bin/supabase"
|
|
39
|
-
if [ -x "$candidate" ]; then
|
|
40
|
-
echo "$candidate"
|
|
41
|
-
return 0
|
|
42
|
-
fi
|
|
43
|
-
dir=$(dirname "$dir")
|
|
44
|
-
done
|
|
45
|
-
return 1
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
SUPABASE_BIN=$(find_supabase_bin || true)
|
|
49
|
-
|
|
50
|
-
if [ -n "$SUPABASE_BIN" ]; then
|
|
51
|
-
SUPABASE_CMD="$SUPABASE_BIN"
|
|
52
|
-
echo "✅ Using bundled Supabase CLI: $SUPABASE_BIN"
|
|
53
|
-
elif command -v supabase &> /dev/null; then
|
|
54
|
-
# Fallback to global if bundled CLI is not available
|
|
55
|
-
echo "✅ Found global Supabase CLI"
|
|
56
|
-
SUPABASE_CMD="supabase"
|
|
57
|
-
elif command -v npx &> /dev/null; then
|
|
58
|
-
# Last resort: npx (will not download)
|
|
59
|
-
echo "ℹ️ Bundled CLI not found. Falling back to npx."
|
|
60
|
-
SUPABASE_CMD="npx --no-install supabase"
|
|
61
|
-
else
|
|
62
|
-
echo "❌ Error: Neither 'npx' nor 'supabase' CLI is available"
|
|
63
|
-
echo " Please ensure Node.js is installed (for npx)"
|
|
64
|
-
echo " Or install Supabase CLI globally: npm install -g supabase"
|
|
65
|
-
exit 1
|
|
66
|
-
fi
|
|
67
|
-
|
|
68
|
-
cd "$ROOT_DIR"
|
|
69
|
-
|
|
70
|
-
echo ""
|
|
71
|
-
|
|
72
|
-
# Get project ID from environment or prompt
|
|
73
|
-
if [ -z "$SUPABASE_PROJECT_ID" ]; then
|
|
74
|
-
echo "─────────────────────────────────────────────────────────"
|
|
75
|
-
echo "👉 Enter your Supabase Project Reference ID:"
|
|
76
|
-
echo " (Found in Supabase Dashboard > Project Settings > General)"
|
|
77
|
-
read -p " Project ID: " SUPABASE_PROJECT_ID
|
|
78
|
-
fi
|
|
79
|
-
|
|
80
|
-
if [ -z "$SUPABASE_PROJECT_ID" ]; then
|
|
81
|
-
echo "❌ Error: Project ID is required to proceed."
|
|
82
|
-
exit 1
|
|
83
|
-
fi
|
|
84
|
-
|
|
85
|
-
# Link to project if not already linked
|
|
86
|
-
echo "─────────────────────────────────────────────────────────"
|
|
87
|
-
echo "🔗 Linking to Supabase Project: $SUPABASE_PROJECT_ID"
|
|
88
|
-
|
|
89
|
-
# If we have an access token, use it for linking
|
|
90
|
-
if [ -n "$SUPABASE_ACCESS_TOKEN" ]; then
|
|
91
|
-
echo "🔑 Using access token for authentication"
|
|
92
|
-
export SUPABASE_ACCESS_TOKEN
|
|
93
|
-
$SUPABASE_CMD link --project-ref "$SUPABASE_PROJECT_ID"
|
|
94
|
-
elif [ -n "$SUPABASE_DB_PASSWORD" ]; then
|
|
95
|
-
echo "🔑 Using database password for authentication"
|
|
96
|
-
export SUPABASE_DB_PASSWORD
|
|
97
|
-
$SUPABASE_CMD link --project-ref "$SUPABASE_PROJECT_ID"
|
|
98
|
-
else
|
|
99
|
-
echo "🔑 NOTE: If asked, please enter your DATABASE PASSWORD."
|
|
100
|
-
$SUPABASE_CMD link --project-ref "$SUPABASE_PROJECT_ID"
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
echo ""
|
|
104
|
-
echo "─────────────────────────────────────────────────────────"
|
|
105
|
-
echo "📦 Deploying Edge Functions..."
|
|
106
|
-
echo ""
|
|
107
|
-
|
|
108
|
-
# Deploy each function
|
|
109
|
-
FUNCTIONS=(
|
|
110
|
-
"auth-gmail"
|
|
111
|
-
"auth-microsoft"
|
|
112
|
-
"api-v1-accounts"
|
|
113
|
-
"api-v1-emails"
|
|
114
|
-
"api-v1-rules"
|
|
115
|
-
"api-v1-settings"
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
DEPLOYED=0
|
|
119
|
-
FAILED=0
|
|
120
|
-
|
|
121
|
-
for func in "${FUNCTIONS[@]}"; do
|
|
122
|
-
echo " 📦 Deploying $func..."
|
|
123
|
-
if $SUPABASE_CMD functions deploy "$func" --no-verify-jwt; then
|
|
124
|
-
((DEPLOYED++))
|
|
125
|
-
else
|
|
126
|
-
echo " ❌ Failed to deploy $func"
|
|
127
|
-
((FAILED++))
|
|
128
|
-
fi
|
|
129
|
-
done
|
|
130
|
-
|
|
131
|
-
echo ""
|
|
132
|
-
echo "─────────────────────────────────────────────────────────"
|
|
133
|
-
|
|
134
|
-
if [ $FAILED -eq 0 ]; then
|
|
135
|
-
echo "✅ All Edge Functions deployed successfully!"
|
|
136
|
-
echo " Deployed: $DEPLOYED functions"
|
|
137
|
-
else
|
|
138
|
-
echo "⚠️ Deployment completed with errors"
|
|
139
|
-
echo " Deployed: $DEPLOYED functions"
|
|
140
|
-
echo " Failed: $FAILED functions"
|
|
141
|
-
exit 1
|
|
142
|
-
fi
|
|
143
|
-
|
|
144
|
-
echo ""
|
|
145
|
-
echo "⚠️ Don't forget to set environment variables in Supabase Dashboard:"
|
|
146
|
-
echo " Settings > Edge Functions > Add secret"
|
|
147
|
-
echo ""
|
|
148
|
-
echo "Required secrets:"
|
|
149
|
-
echo " - TOKEN_ENCRYPTION_KEY"
|
|
150
|
-
echo " - GMAIL_CLIENT_ID"
|
|
151
|
-
echo " - GMAIL_CLIENT_SECRET"
|
|
152
|
-
echo " - MS_GRAPH_CLIENT_ID"
|
|
153
|
-
echo " - MS_GRAPH_CLIENT_SECRET"
|
|
154
|
-
echo ""
|