@odvi/create-dtt-framework 0.1.8 → 0.1.9
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/package.json +1 -1
- package/template/.env.example +117 -106
- package/template/docs/framework/environment-variables.md +52 -0
- package/template/src/config/env.ts +5 -0
- package/template/src/features/health-check/config.ts +7 -0
- package/template/src/server/api/routes/health/aws-s3.ts +59 -0
- package/template/src/server/api/routes/health/index.ts +7 -3
package/package.json
CHANGED
package/template/.env.example
CHANGED
|
@@ -1,106 +1,117 @@
|
|
|
1
|
-
# Since the ".env" file is gitignored, you can use the ".env.example" file to
|
|
2
|
-
# build a new ".env" file when you clone the repo. Keep this file up-to-date
|
|
3
|
-
# when you add new variables to `.env`.
|
|
4
|
-
|
|
5
|
-
# This file will be committed to version control, so make sure not to have any
|
|
6
|
-
# secrets in it. If you are cloning this repo, create a copy of this file named
|
|
7
|
-
# ".env" and populate it with your secrets.
|
|
8
|
-
|
|
9
|
-
# When adding additional environment variables, the schema in "/src/env.js"
|
|
10
|
-
# should be updated accordingly.
|
|
11
|
-
|
|
12
|
-
# ========================================
|
|
13
|
-
# App Configuration
|
|
14
|
-
# ========================================
|
|
15
|
-
# The base URL of your application. Used for redirects, webhooks, and callbacks.
|
|
16
|
-
# In development: http://localhost:3000
|
|
17
|
-
# In production: https://your-domain.com
|
|
18
|
-
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
19
|
-
|
|
20
|
-
# ========================================
|
|
21
|
-
# Clerk Authentication
|
|
22
|
-
# ========================================
|
|
23
|
-
# Clerk publishable key - used on the client side for authentication
|
|
24
|
-
# Get this from your Clerk Dashboard > API Keys > Publishable Key
|
|
25
|
-
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx
|
|
26
|
-
|
|
27
|
-
# Clerk secret key - used on the server side for authentication
|
|
28
|
-
# Get this from your Clerk Dashboard > API Keys > Secret Key
|
|
29
|
-
CLERK_SECRET_KEY=sk_test_xxx
|
|
30
|
-
|
|
31
|
-
# Clerk webhook secret - used to verify webhook events from Clerk
|
|
32
|
-
# Get this from your Clerk Dashboard > Webhooks > Add Endpoint > Signing Secret
|
|
33
|
-
CLERK_WEBHOOK_SECRET=whsec_xxx
|
|
34
|
-
|
|
35
|
-
# URL path for the sign-in page
|
|
36
|
-
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
|
37
|
-
|
|
38
|
-
# URL path for the sign-up page
|
|
39
|
-
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
|
40
|
-
|
|
41
|
-
# Where to redirect users after successful sign-in
|
|
42
|
-
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/health
|
|
43
|
-
|
|
44
|
-
# Where to redirect users after successful sign-up
|
|
45
|
-
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/health
|
|
46
|
-
|
|
47
|
-
# ========================================
|
|
48
|
-
# Supabase
|
|
49
|
-
# ========================================
|
|
50
|
-
# Supabase project URL - found in your Supabase project settings
|
|
51
|
-
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
|
|
52
|
-
|
|
53
|
-
# Supabase anonymous/public key - safe to expose on client side
|
|
54
|
-
# Found in your Supabase project settings under API keys
|
|
55
|
-
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJxxx
|
|
56
|
-
|
|
57
|
-
# Supabase service role key - full admin access, keep secret!
|
|
58
|
-
# Found in your Supabase project settings under API keys
|
|
59
|
-
SUPABASE_SERVICE_ROLE_KEY=eyJxxx
|
|
60
|
-
|
|
61
|
-
# PostgreSQL connection string for Drizzle ORM
|
|
62
|
-
# Use Supabase's Transaction mode pooler for better performance
|
|
63
|
-
# Format: postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
64
|
-
DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
65
|
-
|
|
66
|
-
# ========================================
|
|
67
|
-
# Snowflake Data Warehouse
|
|
68
|
-
# ========================================
|
|
69
|
-
# Snowflake account identifier (e.g., ef19411.ap-southeast-1)
|
|
70
|
-
SNOWFLAKE_ACCOUNT=ef19411.ap-southeast-1
|
|
71
|
-
|
|
72
|
-
# Snowflake warehouse to use
|
|
73
|
-
SNOWFLAKE_WAREHOUSE=COMPUTE_WH
|
|
74
|
-
|
|
75
|
-
# Snowflake role
|
|
76
|
-
SNOWFLAKE_ROLE=ACCOUNTADMIN
|
|
77
|
-
|
|
78
|
-
# Authentication method (SNOWFLAKE_JWT for Key Pair Auth)
|
|
79
|
-
SNOWFLAKE_AUTHENTICATOR=SNOWFLAKE_JWT
|
|
80
|
-
|
|
81
|
-
# Snowflake username
|
|
82
|
-
SNOWFLAKE_USERNAME=APP_USER_WITH_KEY_AUTH
|
|
83
|
-
|
|
84
|
-
# Private Key for Authentication (PEM format)
|
|
85
|
-
SNOWFLAKE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
|
|
86
|
-
...
|
|
87
|
-
-----END PRIVATE KEY-----"
|
|
88
|
-
|
|
89
|
-
# Passphrase for the Private Key (if encrypted)
|
|
90
|
-
SNOWFLAKE_PRIVATE_KEY_PASSPHRASE="<password>"
|
|
91
|
-
|
|
92
|
-
# Enable logging (optional)
|
|
93
|
-
SNOWFLAKE_LOGGING=true
|
|
94
|
-
|
|
95
|
-
# ========================================
|
|
96
|
-
#
|
|
97
|
-
# ========================================
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
#
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
#
|
|
105
|
-
|
|
106
|
-
|
|
1
|
+
# Since the ".env" file is gitignored, you can use the ".env.example" file to
|
|
2
|
+
# build a new ".env" file when you clone the repo. Keep this file up-to-date
|
|
3
|
+
# when you add new variables to `.env`.
|
|
4
|
+
|
|
5
|
+
# This file will be committed to version control, so make sure not to have any
|
|
6
|
+
# secrets in it. If you are cloning this repo, create a copy of this file named
|
|
7
|
+
# ".env" and populate it with your secrets.
|
|
8
|
+
|
|
9
|
+
# When adding additional environment variables, the schema in "/src/env.js"
|
|
10
|
+
# should be updated accordingly.
|
|
11
|
+
|
|
12
|
+
# ========================================
|
|
13
|
+
# App Configuration
|
|
14
|
+
# ========================================
|
|
15
|
+
# The base URL of your application. Used for redirects, webhooks, and callbacks.
|
|
16
|
+
# In development: http://localhost:3000
|
|
17
|
+
# In production: https://your-domain.com
|
|
18
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
19
|
+
|
|
20
|
+
# ========================================
|
|
21
|
+
# Clerk Authentication
|
|
22
|
+
# ========================================
|
|
23
|
+
# Clerk publishable key - used on the client side for authentication
|
|
24
|
+
# Get this from your Clerk Dashboard > API Keys > Publishable Key
|
|
25
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx
|
|
26
|
+
|
|
27
|
+
# Clerk secret key - used on the server side for authentication
|
|
28
|
+
# Get this from your Clerk Dashboard > API Keys > Secret Key
|
|
29
|
+
CLERK_SECRET_KEY=sk_test_xxx
|
|
30
|
+
|
|
31
|
+
# Clerk webhook secret - used to verify webhook events from Clerk
|
|
32
|
+
# Get this from your Clerk Dashboard > Webhooks > Add Endpoint > Signing Secret
|
|
33
|
+
CLERK_WEBHOOK_SECRET=whsec_xxx
|
|
34
|
+
|
|
35
|
+
# URL path for the sign-in page
|
|
36
|
+
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
|
37
|
+
|
|
38
|
+
# URL path for the sign-up page
|
|
39
|
+
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
|
40
|
+
|
|
41
|
+
# Where to redirect users after successful sign-in
|
|
42
|
+
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/health
|
|
43
|
+
|
|
44
|
+
# Where to redirect users after successful sign-up
|
|
45
|
+
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/health
|
|
46
|
+
|
|
47
|
+
# ========================================
|
|
48
|
+
# Supabase
|
|
49
|
+
# ========================================
|
|
50
|
+
# Supabase project URL - found in your Supabase project settings
|
|
51
|
+
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
|
|
52
|
+
|
|
53
|
+
# Supabase anonymous/public key - safe to expose on client side
|
|
54
|
+
# Found in your Supabase project settings under API keys
|
|
55
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJxxx
|
|
56
|
+
|
|
57
|
+
# Supabase service role key - full admin access, keep secret!
|
|
58
|
+
# Found in your Supabase project settings under API keys
|
|
59
|
+
SUPABASE_SERVICE_ROLE_KEY=eyJxxx
|
|
60
|
+
|
|
61
|
+
# PostgreSQL connection string for Drizzle ORM
|
|
62
|
+
# Use Supabase's Transaction mode pooler for better performance
|
|
63
|
+
# Format: postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
64
|
+
DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
|
|
65
|
+
|
|
66
|
+
# ========================================
|
|
67
|
+
# Snowflake Data Warehouse
|
|
68
|
+
# ========================================
|
|
69
|
+
# Snowflake account identifier (e.g., ef19411.ap-southeast-1)
|
|
70
|
+
SNOWFLAKE_ACCOUNT=ef19411.ap-southeast-1
|
|
71
|
+
|
|
72
|
+
# Snowflake warehouse to use
|
|
73
|
+
SNOWFLAKE_WAREHOUSE=COMPUTE_WH
|
|
74
|
+
|
|
75
|
+
# Snowflake role
|
|
76
|
+
SNOWFLAKE_ROLE=ACCOUNTADMIN
|
|
77
|
+
|
|
78
|
+
# Authentication method (SNOWFLAKE_JWT for Key Pair Auth)
|
|
79
|
+
SNOWFLAKE_AUTHENTICATOR=SNOWFLAKE_JWT
|
|
80
|
+
|
|
81
|
+
# Snowflake username
|
|
82
|
+
SNOWFLAKE_USERNAME=APP_USER_WITH_KEY_AUTH
|
|
83
|
+
|
|
84
|
+
# Private Key for Authentication (PEM format)
|
|
85
|
+
SNOWFLAKE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
|
|
86
|
+
...
|
|
87
|
+
-----END PRIVATE KEY-----"
|
|
88
|
+
|
|
89
|
+
# Passphrase for the Private Key (if encrypted)
|
|
90
|
+
SNOWFLAKE_PRIVATE_KEY_PASSPHRASE="<password>"
|
|
91
|
+
|
|
92
|
+
# Enable logging (optional)
|
|
93
|
+
SNOWFLAKE_LOGGING=true
|
|
94
|
+
|
|
95
|
+
# ========================================
|
|
96
|
+
# AWS S3 (Optional)
|
|
97
|
+
# ========================================
|
|
98
|
+
# AWS Access Key ID for S3 access
|
|
99
|
+
AWS_ACCESS_KEY_ID=AKIA...
|
|
100
|
+
|
|
101
|
+
# AWS Secret Access Key for S3 access
|
|
102
|
+
AWS_ACCESS_SECRET_KEY=wJalr...
|
|
103
|
+
|
|
104
|
+
# AWS Region where your S3 buckets are located (e.g., us-east-1)
|
|
105
|
+
AWS_REGION=us-east-1
|
|
106
|
+
|
|
107
|
+
# ========================================
|
|
108
|
+
# NextBank API (Placeholder)
|
|
109
|
+
# ========================================
|
|
110
|
+
# Base URL for the NextBank API endpoint
|
|
111
|
+
NEXTBANK_API=https://api.nextbank.com
|
|
112
|
+
|
|
113
|
+
# Username for NextBank Basic Authentication
|
|
114
|
+
NEXTBANK_API_USERNAME=user
|
|
115
|
+
|
|
116
|
+
# Password for NextBank Basic Authentication
|
|
117
|
+
NEXTBANK_API_PASSWORD=pass
|
|
@@ -97,6 +97,19 @@ SNOWFLAKE_SCHEMA=PUBLIC
|
|
|
97
97
|
# Snowflake role name
|
|
98
98
|
SNOWFLAKE_ROLE=ANALYST
|
|
99
99
|
|
|
100
|
+
# ============================================
|
|
101
|
+
# AWS S3 (Optional)
|
|
102
|
+
# ============================================
|
|
103
|
+
|
|
104
|
+
# AWS Access Key ID
|
|
105
|
+
AWS_ACCESS_KEY_ID=AKIA...
|
|
106
|
+
|
|
107
|
+
# AWS Secret Access Key
|
|
108
|
+
AWS_ACCESS_SECRET_KEY=wJalr...
|
|
109
|
+
|
|
110
|
+
# AWS Region (e.g., us-east-1, ap-southeast-1)
|
|
111
|
+
AWS_REGION=us-east-1
|
|
112
|
+
|
|
100
113
|
# ============================================
|
|
101
114
|
# NextBank (Placeholder - Optional)
|
|
102
115
|
# ============================================
|
|
@@ -418,6 +431,45 @@ SNOWFLAKE_ROLE=ANALYST
|
|
|
418
431
|
|
|
419
432
|
---
|
|
420
433
|
|
|
434
|
+
### AWS S3 Variables (Optional)
|
|
435
|
+
|
|
436
|
+
#### AWS_ACCESS_KEY_ID
|
|
437
|
+
|
|
438
|
+
**Purpose:** AWS Access Key ID for S3 access
|
|
439
|
+
|
|
440
|
+
**Where to find:** AWS IAM Console → Users → Security credentials
|
|
441
|
+
|
|
442
|
+
**Example:**
|
|
443
|
+
```bash
|
|
444
|
+
AWS_ACCESS_KEY_ID=AKIA...
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
#### AWS_ACCESS_SECRET_KEY
|
|
448
|
+
|
|
449
|
+
**Purpose:** AWS Secret Access Key for S3 access
|
|
450
|
+
|
|
451
|
+
**Where to find:** AWS IAM Console → Users → Security credentials (only visible when created)
|
|
452
|
+
|
|
453
|
+
**Example:**
|
|
454
|
+
```bash
|
|
455
|
+
AWS_ACCESS_SECRET_KEY=wJalr...
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
**Notes:**
|
|
459
|
+
- Never commit to version control
|
|
460
|
+
- Ensure the user has appropriate S3 permissions (e.g., `AmazonS3ReadOnlyAccess` or custom policy)
|
|
461
|
+
|
|
462
|
+
#### AWS_REGION
|
|
463
|
+
|
|
464
|
+
**Purpose:** AWS Region where your S3 buckets are located
|
|
465
|
+
|
|
466
|
+
**Example:**
|
|
467
|
+
```bash
|
|
468
|
+
AWS_REGION=us-east-1
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
421
473
|
### NextBank Variables (Placeholder)
|
|
422
474
|
|
|
423
475
|
**Note:** NextBank is a placeholder integration. These variables are optional and not currently used.
|
|
@@ -30,6 +30,11 @@ const envSchema = z.object({
|
|
|
30
30
|
NEXTBANK_API: z.string().url().optional(),
|
|
31
31
|
NEXTBANK_API_USERNAME: z.string().optional(),
|
|
32
32
|
NEXTBANK_API_PASSWORD: z.string().optional(),
|
|
33
|
+
|
|
34
|
+
// AWS S3 (optional)
|
|
35
|
+
AWS_ACCESS_KEY_ID: z.string().optional(),
|
|
36
|
+
AWS_ACCESS_SECRET_KEY: z.string().optional(),
|
|
37
|
+
AWS_REGION: z.string().optional(),
|
|
33
38
|
})
|
|
34
39
|
|
|
35
40
|
export const env = envSchema.parse(process.env)
|
|
@@ -52,6 +52,13 @@ export const SERVICES = [
|
|
|
52
52
|
{ name: 'Ping API', endpoint: '/nextbank/ping' },
|
|
53
53
|
],
|
|
54
54
|
},
|
|
55
|
+
{
|
|
56
|
+
name: 'AWS S3',
|
|
57
|
+
icon: 'cloud',
|
|
58
|
+
checks: [
|
|
59
|
+
{ name: 'Connect', endpoint: '/aws-s3/connect' },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
55
62
|
{
|
|
56
63
|
name: 'Framework',
|
|
57
64
|
icon: 'code',
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Hono } from 'hono'
|
|
2
|
+
import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3'
|
|
3
|
+
import { env } from '@/config/env'
|
|
4
|
+
|
|
5
|
+
export const awsS3HealthRoutes = new Hono()
|
|
6
|
+
|
|
7
|
+
awsS3HealthRoutes.get('/connect', async (c) => {
|
|
8
|
+
const start = performance.now()
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
// Check if credentials are configured
|
|
12
|
+
if (!env.AWS_ACCESS_KEY_ID || !env.AWS_ACCESS_SECRET_KEY || !env.AWS_REGION) {
|
|
13
|
+
return c.json({
|
|
14
|
+
status: 'warning',
|
|
15
|
+
responseTimeMs: Math.round(performance.now() - start),
|
|
16
|
+
message: 'AWS S3 credentials not configured - skipping connection check',
|
|
17
|
+
data: {
|
|
18
|
+
skipped: true,
|
|
19
|
+
reason: 'Missing AWS_ACCESS_KEY_ID, AWS_ACCESS_SECRET_KEY, or AWS_REGION',
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const s3Client = new S3Client({
|
|
25
|
+
region: env.AWS_REGION,
|
|
26
|
+
credentials: {
|
|
27
|
+
accessKeyId: env.AWS_ACCESS_KEY_ID,
|
|
28
|
+
secretAccessKey: env.AWS_ACCESS_SECRET_KEY,
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// Try to list buckets to verify connectivity and credentials
|
|
33
|
+
const command = new ListBucketsCommand({})
|
|
34
|
+
const response = await s3Client.send(command)
|
|
35
|
+
|
|
36
|
+
return c.json({
|
|
37
|
+
status: 'healthy',
|
|
38
|
+
responseTimeMs: Math.round(performance.now() - start),
|
|
39
|
+
message: 'Successfully connected to AWS S3',
|
|
40
|
+
data: {
|
|
41
|
+
region: env.AWS_REGION,
|
|
42
|
+
bucketCount: response.Buckets?.length ?? 0,
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
} catch (error) {
|
|
46
|
+
return c.json(
|
|
47
|
+
{
|
|
48
|
+
status: 'error',
|
|
49
|
+
responseTimeMs: Math.round(performance.now() - start),
|
|
50
|
+
error: error instanceof Error ? error.message : 'Failed to connect to AWS S3',
|
|
51
|
+
data: {
|
|
52
|
+
details: error instanceof Error ? error.stack : undefined,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
500
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
@@ -6,6 +6,7 @@ import { edgeFunctionsHealthRoutes } from './edge-functions'
|
|
|
6
6
|
import { snowflakeHealthRoutes } from './snowflake'
|
|
7
7
|
import { nextbankHealthRoutes } from './nextbank'
|
|
8
8
|
import { frameworkHealthRoutes } from './framework'
|
|
9
|
+
import { awsS3HealthRoutes } from './aws-s3'
|
|
9
10
|
|
|
10
11
|
export const healthRoutes = new Hono()
|
|
11
12
|
|
|
@@ -16,6 +17,7 @@ healthRoutes.route('/edge', edgeFunctionsHealthRoutes)
|
|
|
16
17
|
healthRoutes.route('/snowflake', snowflakeHealthRoutes)
|
|
17
18
|
healthRoutes.route('/nextbank', nextbankHealthRoutes)
|
|
18
19
|
healthRoutes.route('/framework', frameworkHealthRoutes)
|
|
20
|
+
healthRoutes.route('/aws-s3', awsS3HealthRoutes)
|
|
19
21
|
|
|
20
22
|
healthRoutes.get('/all', async (c) => {
|
|
21
23
|
const start = performance.now()
|
|
@@ -38,6 +40,7 @@ healthRoutes.get('/all', async (c) => {
|
|
|
38
40
|
{ name: 'Snowflake Query', url: `${baseUrl}/api/health/snowflake/query` },
|
|
39
41
|
{ name: 'NextBank Ping', url: `${baseUrl}/api/health/nextbank/ping` },
|
|
40
42
|
{ name: 'NextBank Auth', url: `${baseUrl}/api/health/nextbank/auth` },
|
|
43
|
+
{ name: 'AWS S3 Connect', url: `${baseUrl}/api/health/aws-s3/connect` },
|
|
41
44
|
]
|
|
42
45
|
|
|
43
46
|
// Run all checks in parallel
|
|
@@ -46,7 +49,7 @@ healthRoutes.get('/all', async (c) => {
|
|
|
46
49
|
const checkStart = performance.now()
|
|
47
50
|
try {
|
|
48
51
|
const response = await fetch(check.url, {
|
|
49
|
-
method: check.method
|
|
52
|
+
method: check.method ?? 'GET',
|
|
50
53
|
headers: {
|
|
51
54
|
'Content-Type': 'application/json',
|
|
52
55
|
// Forward auth header if present
|
|
@@ -60,7 +63,7 @@ healthRoutes.get('/all', async (c) => {
|
|
|
60
63
|
|
|
61
64
|
return {
|
|
62
65
|
name: check.name,
|
|
63
|
-
status: response.ok ? data.status
|
|
66
|
+
status: response.ok ? data.status ?? 'healthy' : 'error',
|
|
64
67
|
responseTimeMs: Math.round(performance.now() - checkStart),
|
|
65
68
|
httpStatus: response.status,
|
|
66
69
|
data,
|
|
@@ -85,12 +88,13 @@ healthRoutes.get('/all', async (c) => {
|
|
|
85
88
|
edge: results.filter((r) => r.status === 'fulfilled' && r.value.name.includes('Edge')),
|
|
86
89
|
snowflake: results.filter((r) => r.status === 'fulfilled' && r.value.name.includes('Snowflake')),
|
|
87
90
|
nextbank: results.filter((r) => r.status === 'fulfilled' && r.value.name.includes('NextBank')),
|
|
91
|
+
awsS3: results.filter((r) => r.status === 'fulfilled' && r.value.name.includes('AWS S3')),
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
// Determine overall status
|
|
91
95
|
const allResults = results.map((r) => (r.status === 'fulfilled' ? r.value : null))
|
|
92
96
|
const hasErrors = allResults.some((r) => r && (r.status === 'error' || r.httpStatus >= 400))
|
|
93
|
-
const allHealthy = allResults.every((r) => r
|
|
97
|
+
const allHealthy = allResults.every((r) => r?.status === 'healthy')
|
|
94
98
|
|
|
95
99
|
return c.json({
|
|
96
100
|
status: hasErrors ? 'unhealthy' : allHealthy ? 'healthy' : 'partial',
|