@realtimex/folio 0.1.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/.env.example +20 -0
- package/README.md +63 -0
- package/api/server.ts +130 -0
- package/api/src/config/index.ts +96 -0
- package/api/src/middleware/auth.ts +128 -0
- package/api/src/middleware/errorHandler.ts +88 -0
- package/api/src/middleware/index.ts +4 -0
- package/api/src/middleware/rateLimit.ts +71 -0
- package/api/src/middleware/validation.ts +58 -0
- package/api/src/routes/accounts.ts +142 -0
- package/api/src/routes/baseline-config.ts +124 -0
- package/api/src/routes/chat.ts +154 -0
- package/api/src/routes/health.ts +61 -0
- package/api/src/routes/index.ts +35 -0
- package/api/src/routes/ingestions.ts +275 -0
- package/api/src/routes/migrate.ts +112 -0
- package/api/src/routes/policies.ts +121 -0
- package/api/src/routes/processing.ts +90 -0
- package/api/src/routes/rules.ts +11 -0
- package/api/src/routes/sdk.ts +100 -0
- package/api/src/routes/settings.ts +80 -0
- package/api/src/routes/setup.ts +389 -0
- package/api/src/routes/stats.ts +81 -0
- package/api/src/routes/tts.ts +190 -0
- package/api/src/services/BaselineConfigService.ts +208 -0
- package/api/src/services/ChatService.ts +204 -0
- package/api/src/services/GoogleDriveService.ts +331 -0
- package/api/src/services/GoogleSheetsService.ts +1107 -0
- package/api/src/services/IngestionService.ts +1187 -0
- package/api/src/services/ModelCapabilityService.ts +248 -0
- package/api/src/services/PolicyEngine.ts +1625 -0
- package/api/src/services/PolicyLearningService.ts +527 -0
- package/api/src/services/PolicyLoader.ts +249 -0
- package/api/src/services/RAGService.ts +391 -0
- package/api/src/services/SDKService.ts +249 -0
- package/api/src/services/supabase.ts +113 -0
- package/api/src/utils/Actuator.ts +284 -0
- package/api/src/utils/actions/ActionHandler.ts +34 -0
- package/api/src/utils/actions/AppendToGSheetAction.ts +260 -0
- package/api/src/utils/actions/AutoRenameAction.ts +58 -0
- package/api/src/utils/actions/CopyAction.ts +120 -0
- package/api/src/utils/actions/CopyToGDriveAction.ts +64 -0
- package/api/src/utils/actions/LogCsvAction.ts +48 -0
- package/api/src/utils/actions/NotifyAction.ts +39 -0
- package/api/src/utils/actions/RenameAction.ts +57 -0
- package/api/src/utils/actions/WebhookAction.ts +58 -0
- package/api/src/utils/actions/utils.ts +293 -0
- package/api/src/utils/llmResponse.ts +61 -0
- package/api/src/utils/logger.ts +67 -0
- package/bin/folio-deploy.js +12 -0
- package/bin/folio-setup.js +45 -0
- package/bin/folio.js +65 -0
- package/dist/api/server.js +106 -0
- package/dist/api/src/config/index.js +81 -0
- package/dist/api/src/middleware/auth.js +93 -0
- package/dist/api/src/middleware/errorHandler.js +73 -0
- package/dist/api/src/middleware/index.js +4 -0
- package/dist/api/src/middleware/rateLimit.js +43 -0
- package/dist/api/src/middleware/validation.js +54 -0
- package/dist/api/src/routes/accounts.js +110 -0
- package/dist/api/src/routes/baseline-config.js +91 -0
- package/dist/api/src/routes/chat.js +114 -0
- package/dist/api/src/routes/health.js +52 -0
- package/dist/api/src/routes/index.js +31 -0
- package/dist/api/src/routes/ingestions.js +207 -0
- package/dist/api/src/routes/migrate.js +91 -0
- package/dist/api/src/routes/policies.js +86 -0
- package/dist/api/src/routes/processing.js +75 -0
- package/dist/api/src/routes/rules.js +8 -0
- package/dist/api/src/routes/sdk.js +80 -0
- package/dist/api/src/routes/settings.js +68 -0
- package/dist/api/src/routes/setup.js +315 -0
- package/dist/api/src/routes/stats.js +62 -0
- package/dist/api/src/routes/tts.js +178 -0
- package/dist/api/src/services/BaselineConfigService.js +168 -0
- package/dist/api/src/services/ChatService.js +166 -0
- package/dist/api/src/services/GoogleDriveService.js +280 -0
- package/dist/api/src/services/GoogleSheetsService.js +795 -0
- package/dist/api/src/services/IngestionService.js +990 -0
- package/dist/api/src/services/ModelCapabilityService.js +179 -0
- package/dist/api/src/services/PolicyEngine.js +1353 -0
- package/dist/api/src/services/PolicyLearningService.js +397 -0
- package/dist/api/src/services/PolicyLoader.js +159 -0
- package/dist/api/src/services/RAGService.js +295 -0
- package/dist/api/src/services/SDKService.js +212 -0
- package/dist/api/src/services/supabase.js +72 -0
- package/dist/api/src/utils/Actuator.js +225 -0
- package/dist/api/src/utils/actions/ActionHandler.js +1 -0
- package/dist/api/src/utils/actions/AppendToGSheetAction.js +191 -0
- package/dist/api/src/utils/actions/AutoRenameAction.js +49 -0
- package/dist/api/src/utils/actions/CopyAction.js +112 -0
- package/dist/api/src/utils/actions/CopyToGDriveAction.js +55 -0
- package/dist/api/src/utils/actions/LogCsvAction.js +42 -0
- package/dist/api/src/utils/actions/NotifyAction.js +32 -0
- package/dist/api/src/utils/actions/RenameAction.js +51 -0
- package/dist/api/src/utils/actions/WebhookAction.js +51 -0
- package/dist/api/src/utils/actions/utils.js +237 -0
- package/dist/api/src/utils/llmResponse.js +63 -0
- package/dist/api/src/utils/logger.js +51 -0
- package/dist/assets/index-DzN8-j-e.css +1 -0
- package/dist/assets/index-Uy-ai3Dh.js +113 -0
- package/dist/favicon.svg +31 -0
- package/dist/folio-logo.svg +46 -0
- package/dist/index.html +14 -0
- package/docs-dev/FPE-spec.md +196 -0
- package/docs-dev/folio-prd.md +47 -0
- package/docs-dev/foundation-checklist.md +30 -0
- package/docs-dev/hybrid-routing-architecture.md +205 -0
- package/docs-dev/ingestion-engine.md +69 -0
- package/docs-dev/port-from-email-automator.md +32 -0
- package/docs-dev/tech-spec.md +98 -0
- package/index.html +13 -0
- package/package.json +101 -0
- package/public/favicon.svg +31 -0
- package/public/folio-logo.svg +46 -0
- package/scripts/dev-task.mjs +51 -0
- package/scripts/get-latest-migration-timestamp.mjs +34 -0
- package/scripts/migrate.sh +91 -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 +64 -0
- package/supabase/functions/_shared/auth.ts +35 -0
- package/supabase/functions/_shared/cors.ts +12 -0
- package/supabase/functions/_shared/supabaseAdmin.ts +17 -0
- package/supabase/functions/api-v1-settings/index.ts +66 -0
- package/supabase/functions/setup/index.ts +91 -0
- package/supabase/migrations/20260223000000_initial_foundation.sql +136 -0
- package/supabase/migrations/20260223000001_add_migration_rpc.sql +10 -0
- package/supabase/migrations/20260224000002_add_init_state_view.sql +20 -0
- package/supabase/migrations/20260224000003_port_user_creation_parity.sql +139 -0
- package/supabase/migrations/20260224000004_add_avatars_storage.sql +26 -0
- package/supabase/migrations/20260224000005_add_tts_and_embed_settings.sql +24 -0
- package/supabase/migrations/20260224000006_add_policies_table.sql +48 -0
- package/supabase/migrations/20260224000007_fix_migration_rpc.sql +9 -0
- package/supabase/migrations/20260224000008_add_ingestions_table.sql +42 -0
- package/supabase/migrations/20260225000000_setup_compatible_mode.sql +119 -0
- package/supabase/migrations/20260225000001_restore_ingestions.sql +49 -0
- package/supabase/migrations/20260225000002_add_ingestion_trace.sql +2 -0
- package/supabase/migrations/20260225000003_add_baseline_configs.sql +35 -0
- package/supabase/migrations/20260226000000_add_processing_events.sql +26 -0
- package/supabase/migrations/20260226000001_add_ingestion_file_hash.sql +10 -0
- package/supabase/migrations/20260226000002_add_dynamic_rag.sql +150 -0
- package/supabase/migrations/20260226000003_add_ingestion_summary.sql +4 -0
- package/supabase/migrations/20260226000004_add_ingestion_tags.sql +7 -0
- package/supabase/migrations/20260226000005_add_chat_tables.sql +60 -0
- package/supabase/migrations/20260227000000_harden_chat_messages_rls.sql +25 -0
- package/supabase/migrations/20260228000000_add_vision_model_capabilities.sql +8 -0
- package/supabase/migrations/20260228000001_add_policy_match_feedback.sql +51 -0
- package/supabase/migrations/29991231235959_test_migration.sql +0 -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.api.json +16 -0
- package/tsconfig.json +25 -0
- package/vite.config.ts +146 -0
|
@@ -0,0 +1,76 @@
|
|
|
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>Confirm your new email address</h2>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="content">
|
|
63
|
+
<p>Hello,</p>
|
|
64
|
+
<p>
|
|
65
|
+
You've requested to change your email address for Folio.
|
|
66
|
+
Please click the button below to confirm this change.
|
|
67
|
+
</p>
|
|
68
|
+
<p>
|
|
69
|
+
<a href="{{ .ConfirmationURL }}auth-callback.html" class="button">Confirm new email</a>
|
|
70
|
+
</p>
|
|
71
|
+
<p>The Folio team</p>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</body>
|
|
75
|
+
|
|
76
|
+
</html>
|
|
@@ -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 Folio</h2>
|
|
44
|
+
|
|
45
|
+
<p>Hi there,</p>
|
|
46
|
+
|
|
47
|
+
<p>Your Folio 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 Folio 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 did not 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>Folio 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 did not 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 Folio Password</h2>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="content">
|
|
63
|
+
<p>Hello,</p>
|
|
64
|
+
<p>
|
|
65
|
+
We received a request to reset the password for the Folio
|
|
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 Folio
|
|
75
|
+
administrator immediately.
|
|
76
|
+
</p>
|
|
77
|
+
<p>The Folio team</p>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</body>
|
|
81
|
+
|
|
82
|
+
</html>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"target": "ESNext",
|
|
7
|
+
"outDir": "dist/api",
|
|
8
|
+
"noEmit": false,
|
|
9
|
+
"declaration": false,
|
|
10
|
+
"allowJs": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"rootDir": "api"
|
|
13
|
+
},
|
|
14
|
+
"include": ["api/**/*"],
|
|
15
|
+
"exclude": ["node_modules", "dist"]
|
|
16
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
|
6
|
+
"allowJs": false,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"allowSyntheticDefaultImports": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"module": "ESNext",
|
|
13
|
+
"moduleResolution": "Node",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"jsx": "react-jsx",
|
|
18
|
+
"types": ["vite/client"],
|
|
19
|
+
"baseUrl": ".",
|
|
20
|
+
"paths": {
|
|
21
|
+
"@/*": ["src/*"]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"include": ["src", "api", "tests"]
|
|
25
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
4
|
+
import { execSync } from "node:child_process";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import pkg from "./package.json";
|
|
7
|
+
|
|
8
|
+
function getLatestMigrationTimestamp() {
|
|
9
|
+
try {
|
|
10
|
+
return execSync("node ./scripts/get-latest-migration-timestamp.mjs", {
|
|
11
|
+
encoding: "utf8"
|
|
12
|
+
}).trim();
|
|
13
|
+
} catch {
|
|
14
|
+
return "unknown";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default defineConfig({
|
|
19
|
+
define: {
|
|
20
|
+
"import.meta.env.VITE_APP_VERSION": JSON.stringify(pkg.version),
|
|
21
|
+
"import.meta.env.VITE_LATEST_MIGRATION_TIMESTAMP": JSON.stringify(getLatestMigrationTimestamp())
|
|
22
|
+
},
|
|
23
|
+
plugins: [
|
|
24
|
+
react(),
|
|
25
|
+
tailwindcss(),
|
|
26
|
+
{
|
|
27
|
+
name: "api-migrate",
|
|
28
|
+
configureServer(server) {
|
|
29
|
+
server.middlewares.use("/api/migrate", async (req, res, next) => {
|
|
30
|
+
if (req.method !== "POST") return next();
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
// Parse request body
|
|
34
|
+
const buffers = [];
|
|
35
|
+
for await (const chunk of req) {
|
|
36
|
+
buffers.push(chunk);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
+
let body: any = {};
|
|
41
|
+
try {
|
|
42
|
+
body = JSON.parse(Buffer.concat(buffers).toString());
|
|
43
|
+
} catch {
|
|
44
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
45
|
+
res.end(JSON.stringify({ error: "Invalid JSON in request body" }));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const { projectRef, accessToken } = body;
|
|
50
|
+
|
|
51
|
+
if (!projectRef) {
|
|
52
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
53
|
+
res.end(JSON.stringify({ error: "projectRef is required" }));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Set up streaming response (SSE style for logs)
|
|
58
|
+
res.writeHead(200, {
|
|
59
|
+
"Content-Type": "text/event-stream",
|
|
60
|
+
"Cache-Control": "no-cache",
|
|
61
|
+
"Connection": "keep-alive"
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const sendEvent = (type: string, data: string) => {
|
|
65
|
+
res.write(`data: ${JSON.stringify({ type, data })}\n\n`);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
sendEvent("info", "🚀 Starting migration (Development Mode)...");
|
|
69
|
+
|
|
70
|
+
const { spawn } = await import("node:child_process");
|
|
71
|
+
const scriptPath = path.join(process.cwd(), "scripts", "migrate.sh");
|
|
72
|
+
|
|
73
|
+
const migrationProcess = spawn("bash", [scriptPath], {
|
|
74
|
+
env: {
|
|
75
|
+
...process.env,
|
|
76
|
+
SUPABASE_PROJECT_ID: projectRef,
|
|
77
|
+
SUPABASE_ACCESS_TOKEN: accessToken
|
|
78
|
+
},
|
|
79
|
+
cwd: process.cwd(),
|
|
80
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
migrationProcess.stdout.on("data", (data) => {
|
|
84
|
+
const lines = data.toString().split("\n");
|
|
85
|
+
lines.forEach((line: string) => {
|
|
86
|
+
if (line.trim()) sendEvent("stdout", line);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
migrationProcess.stderr.on("data", (data) => {
|
|
91
|
+
const lines = data.toString().split("\n");
|
|
92
|
+
lines.forEach((line: string) => {
|
|
93
|
+
if (line.trim()) sendEvent("stderr", line);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
migrationProcess.on("close", (code) => {
|
|
98
|
+
if (code === 0) {
|
|
99
|
+
sendEvent("info", "✅ Migration completed successfully!");
|
|
100
|
+
sendEvent("done", "success");
|
|
101
|
+
} else {
|
|
102
|
+
sendEvent("error", `❌ Migration failed with exit code: ${code}`);
|
|
103
|
+
sendEvent("done", "failed");
|
|
104
|
+
}
|
|
105
|
+
res.end();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
migrationProcess.on("error", (error) => {
|
|
109
|
+
sendEvent("error", `❌ Failed to start migration: ${error.message}`);
|
|
110
|
+
sendEvent("done", "failed");
|
|
111
|
+
res.end();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
req.on("close", () => {
|
|
115
|
+
if (!migrationProcess.killed) {
|
|
116
|
+
migrationProcess.kill();
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error("[Migration API] Error:", error);
|
|
121
|
+
if (!res.headersSent) {
|
|
122
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
123
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
server: {
|
|
131
|
+
port: 5173,
|
|
132
|
+
proxy: {
|
|
133
|
+
"/api": {
|
|
134
|
+
target: "http://localhost:3006",
|
|
135
|
+
changeOrigin: true,
|
|
136
|
+
timeout: 600_000,
|
|
137
|
+
proxyTimeout: 600_000
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
resolve: {
|
|
142
|
+
alias: {
|
|
143
|
+
"@": path.resolve(__dirname, "./src")
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|