@semiont/cli 0.2.26 → 0.2.27
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/dist/cli.mjs +35 -20
- package/dist/templates/cdk/app-stack.ts +4 -4
- package/dist/templates/docker-compose.yml +53 -0
- package/dist/templates/envoy.yaml +152 -0
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -17811,9 +17811,7 @@ var init_frontend_provision = __esm({
|
|
|
17811
17811
|
}
|
|
17812
17812
|
const nextAuthSecret = crypto3.randomBytes(32).toString("base64");
|
|
17813
17813
|
const config2 = service.config;
|
|
17814
|
-
const frontendUrl = config2.url;
|
|
17815
17814
|
const port = config2.port;
|
|
17816
|
-
const semiontEnv = service.environment;
|
|
17817
17815
|
const siteName = config2.siteName;
|
|
17818
17816
|
const backendService = service.environmentConfig.services["backend"];
|
|
17819
17817
|
if (!backendService) {
|
|
@@ -17823,14 +17821,14 @@ var init_frontend_provision = __esm({
|
|
|
17823
17821
|
metadata: { serviceType: "frontend" }
|
|
17824
17822
|
};
|
|
17825
17823
|
}
|
|
17826
|
-
|
|
17827
|
-
if (!backendUrl) {
|
|
17824
|
+
if (!backendService.port) {
|
|
17828
17825
|
return {
|
|
17829
17826
|
success: false,
|
|
17830
|
-
error: "Backend
|
|
17827
|
+
error: "Backend port not configured",
|
|
17831
17828
|
metadata: { serviceType: "frontend" }
|
|
17832
17829
|
};
|
|
17833
17830
|
}
|
|
17831
|
+
const backendUrl = `http://localhost:${backendService.port}`;
|
|
17834
17832
|
if (!siteName) {
|
|
17835
17833
|
return {
|
|
17836
17834
|
success: false,
|
|
@@ -17839,15 +17837,37 @@ var init_frontend_provision = __esm({
|
|
|
17839
17837
|
};
|
|
17840
17838
|
}
|
|
17841
17839
|
const oauthAllowedDomains = service.environmentConfig.site?.oauthAllowedDomains || [];
|
|
17840
|
+
const frontendService = service.environmentConfig.services["frontend"];
|
|
17841
|
+
if (!frontendService) {
|
|
17842
|
+
return {
|
|
17843
|
+
success: false,
|
|
17844
|
+
error: "Frontend service not found in environment configuration",
|
|
17845
|
+
metadata: { serviceType: "frontend" }
|
|
17846
|
+
};
|
|
17847
|
+
}
|
|
17848
|
+
if (!frontendService.publicURL) {
|
|
17849
|
+
return {
|
|
17850
|
+
success: false,
|
|
17851
|
+
error: "Frontend publicURL not configured - required for NextAuth",
|
|
17852
|
+
metadata: { serviceType: "frontend" }
|
|
17853
|
+
};
|
|
17854
|
+
}
|
|
17855
|
+
const frontendUrl = frontendService.publicURL;
|
|
17856
|
+
const allowedOrigins = [];
|
|
17857
|
+
if (frontendService.allowedOrigins && Array.isArray(frontendService.allowedOrigins)) {
|
|
17858
|
+
allowedOrigins.push(...frontendService.allowedOrigins);
|
|
17859
|
+
}
|
|
17860
|
+
const publicUrl = new URL(frontendService.publicURL);
|
|
17861
|
+
allowedOrigins.push(publicUrl.host);
|
|
17842
17862
|
const envUpdates = {
|
|
17843
17863
|
"NODE_ENV": "development",
|
|
17844
17864
|
"PORT": port.toString(),
|
|
17845
17865
|
"NEXTAUTH_URL": frontendUrl,
|
|
17846
17866
|
"NEXTAUTH_SECRET": nextAuthSecret,
|
|
17847
|
-
"
|
|
17848
|
-
"NEXT_PUBLIC_API_URL": backendUrl,
|
|
17867
|
+
"SERVER_API_URL": backendUrl,
|
|
17849
17868
|
"NEXT_PUBLIC_SITE_NAME": siteName,
|
|
17850
|
-
"NEXT_PUBLIC_OAUTH_ALLOWED_DOMAINS": oauthAllowedDomains.join(",")
|
|
17869
|
+
"NEXT_PUBLIC_OAUTH_ALLOWED_DOMAINS": oauthAllowedDomains.join(","),
|
|
17870
|
+
"NEXT_PUBLIC_ALLOWED_ORIGINS": allowedOrigins.join(",")
|
|
17851
17871
|
};
|
|
17852
17872
|
if (fs20.existsSync(envExamplePath)) {
|
|
17853
17873
|
let envContent = fs20.readFileSync(envExamplePath, "utf-8");
|
|
@@ -17879,11 +17899,8 @@ PORT=${port}
|
|
|
17879
17899
|
NEXTAUTH_URL=${frontendUrl}
|
|
17880
17900
|
NEXTAUTH_SECRET=${nextAuthSecret}
|
|
17881
17901
|
|
|
17882
|
-
#
|
|
17883
|
-
|
|
17884
|
-
|
|
17885
|
-
# Backend API URL (from backend.publicURL in environment config)
|
|
17886
|
-
NEXT_PUBLIC_API_URL=${backendUrl}
|
|
17902
|
+
# Backend API URL for server-side calls (uses localhost for POSIX platform)
|
|
17903
|
+
SERVER_API_URL=${backendUrl}
|
|
17887
17904
|
|
|
17888
17905
|
# Site name (from frontend.siteName in environment config)
|
|
17889
17906
|
NEXT_PUBLIC_SITE_NAME=${siteName}
|
|
@@ -17977,7 +17994,7 @@ This directory contains runtime files for the frontend service.
|
|
|
17977
17994
|
## Configuration
|
|
17978
17995
|
|
|
17979
17996
|
Edit \`.env.local\` to configure:
|
|
17980
|
-
- API URL (
|
|
17997
|
+
- Server API URL (SERVER_API_URL) - set to localhost for POSIX platform
|
|
17981
17998
|
- Port (PORT)
|
|
17982
17999
|
- Other environment-specific settings
|
|
17983
18000
|
|
|
@@ -24938,8 +24955,6 @@ var init_ecs_publish = __esm({
|
|
|
24938
24955
|
const buildEnv = { ...process.env };
|
|
24939
24956
|
if (service.name === "frontend") {
|
|
24940
24957
|
const domain2 = envConfig.site.domain || service.config?.domain || (service.environment === "production" ? "semiont.com" : `${service.environment}.semiont.com`);
|
|
24941
|
-
const apiUrl = `https://${domain2}`;
|
|
24942
|
-
buildEnv.NEXT_PUBLIC_API_URL = apiUrl;
|
|
24943
24958
|
buildEnv.NEXT_PUBLIC_APP_NAME = envConfig.site.siteName || "Semiont";
|
|
24944
24959
|
buildEnv.NEXT_PUBLIC_SITE_NAME = envConfig.site.siteName || "Semiont";
|
|
24945
24960
|
buildEnv.NEXT_PUBLIC_DOMAIN = domain2;
|
|
@@ -24948,9 +24963,9 @@ var init_ecs_publish = __esm({
|
|
|
24948
24963
|
buildEnv.NEXT_TELEMETRY_DISABLED = "1";
|
|
24949
24964
|
if (!service.quiet && service.verbose) {
|
|
24950
24965
|
printInfo(`Frontend build configuration:`);
|
|
24951
|
-
printInfo(` API URL: ${apiUrl}`);
|
|
24952
24966
|
printInfo(` Domain: ${domain2}`);
|
|
24953
24967
|
printInfo(` Site Name: ${buildEnv.NEXT_PUBLIC_SITE_NAME}`);
|
|
24968
|
+
printInfo(` API Routing: ALB routes /resources/*, /annotations/*, etc. to backend (runtime)`);
|
|
24954
24969
|
printInfo(` OAuth Domains: ${envConfig.site.oauthAllowedDomains?.join(", ") || "(none)"} (set at runtime)`);
|
|
24955
24970
|
}
|
|
24956
24971
|
}
|
|
@@ -40305,7 +40320,7 @@ var require_package = __commonJS({
|
|
|
40305
40320
|
"package.json"(exports, module) {
|
|
40306
40321
|
module.exports = {
|
|
40307
40322
|
name: "@semiont/cli",
|
|
40308
|
-
version: "0.2.
|
|
40323
|
+
version: "0.2.27",
|
|
40309
40324
|
description: "Semiont CLI - Unified environment management tool",
|
|
40310
40325
|
_comment: "AWS SDK dependencies (@aws-sdk/*) are only used by platforms/aws",
|
|
40311
40326
|
type: "module",
|
|
@@ -40370,8 +40385,8 @@ var require_package = __commonJS({
|
|
|
40370
40385
|
"@aws-sdk/client-sts": "^3.859.0",
|
|
40371
40386
|
"@aws-sdk/client-wafv2": "^3.859.0",
|
|
40372
40387
|
"@prisma/client": "^6.13.0",
|
|
40373
|
-
"@semiont/api-client": "^0.2.
|
|
40374
|
-
"@semiont/core": "^0.2.
|
|
40388
|
+
"@semiont/api-client": "^0.2.27",
|
|
40389
|
+
"@semiont/core": "^0.2.27",
|
|
40375
40390
|
"@testcontainers/postgresql": "^11.5.1",
|
|
40376
40391
|
arg: "^5.0.2",
|
|
40377
40392
|
bcrypt: "^5.1.1",
|
|
@@ -362,17 +362,17 @@ export class SemiontAppStack extends cdk.Stack {
|
|
|
362
362
|
PORT: '3000',
|
|
363
363
|
HOSTNAME: '0.0.0.0',
|
|
364
364
|
// Public environment variables (available to browser)
|
|
365
|
-
NEXT_PUBLIC_API_URL: `https://${domainName}`,
|
|
366
365
|
NEXT_PUBLIC_SITE_NAME: siteName,
|
|
367
366
|
NEXT_PUBLIC_DOMAIN: domainName,
|
|
368
367
|
// OAuth domains for server-side NextAuth validation
|
|
369
368
|
OAUTH_ALLOWED_DOMAINS: Array.isArray(oauthAllowedDomains) ? oauthAllowedDomains.join(',') : oauthAllowedDomains,
|
|
370
369
|
// NextAuth configuration
|
|
371
370
|
NEXTAUTH_URL: `https://${domainName}`,
|
|
372
|
-
// Backend URL for server-side
|
|
373
|
-
// Used by frontend's NextAuth
|
|
371
|
+
// Backend URL for server-side API calls (Service Connect DNS)
|
|
372
|
+
// Used by frontend's NextAuth and API routes for container-to-container communication
|
|
374
373
|
// This is NOT the public URL - it's the internal AWS Service Connect address
|
|
375
|
-
|
|
374
|
+
// Client-side browser calls use relative URLs - ALB routes to backend
|
|
375
|
+
SERVER_API_URL: 'http://backend:4000',
|
|
376
376
|
},
|
|
377
377
|
secrets: {
|
|
378
378
|
NEXTAUTH_SECRET: ecs.Secret.fromSecretsManager(appSecrets, 'nextAuthSecret'),
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Docker Compose configuration with Envoy proxy for local development
|
|
2
|
+
version: '3.8'
|
|
3
|
+
|
|
4
|
+
services:
|
|
5
|
+
envoy:
|
|
6
|
+
image: envoyproxy/envoy:v1.28-latest
|
|
7
|
+
ports:
|
|
8
|
+
- "80:80"
|
|
9
|
+
- "9901:9901" # Admin interface
|
|
10
|
+
volumes:
|
|
11
|
+
- ./apps/cli/templates/envoy.yaml:/etc/envoy/envoy.yaml:ro
|
|
12
|
+
depends_on:
|
|
13
|
+
- frontend
|
|
14
|
+
- backend
|
|
15
|
+
networks:
|
|
16
|
+
- semiont
|
|
17
|
+
|
|
18
|
+
frontend:
|
|
19
|
+
image: ghcr.io/the-ai-alliance/semiont-frontend:dev
|
|
20
|
+
environment:
|
|
21
|
+
- SERVER_API_URL=http://backend:4000
|
|
22
|
+
- NEXTAUTH_URL=http://localhost
|
|
23
|
+
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
|
24
|
+
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
|
|
25
|
+
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
|
|
26
|
+
networks:
|
|
27
|
+
- semiont
|
|
28
|
+
|
|
29
|
+
backend:
|
|
30
|
+
image: ghcr.io/the-ai-alliance/semiont-backend:dev
|
|
31
|
+
environment:
|
|
32
|
+
- DATABASE_URL=${DATABASE_URL}
|
|
33
|
+
- JWT_SECRET=${JWT_SECRET}
|
|
34
|
+
networks:
|
|
35
|
+
- semiont
|
|
36
|
+
|
|
37
|
+
postgres:
|
|
38
|
+
image: postgres:16-alpine
|
|
39
|
+
environment:
|
|
40
|
+
- POSTGRES_DB=semiont
|
|
41
|
+
- POSTGRES_USER=semiont
|
|
42
|
+
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
43
|
+
volumes:
|
|
44
|
+
- postgres_data:/var/lib/postgresql/data
|
|
45
|
+
networks:
|
|
46
|
+
- semiont
|
|
47
|
+
|
|
48
|
+
networks:
|
|
49
|
+
semiont:
|
|
50
|
+
driver: bridge
|
|
51
|
+
|
|
52
|
+
volumes:
|
|
53
|
+
postgres_data:
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Envoy proxy configuration for local development and Codespaces
|
|
2
|
+
# Routes traffic between frontend (Next.js) and backend (Hono API)
|
|
3
|
+
#
|
|
4
|
+
# Routing rules (order matters - first match wins):
|
|
5
|
+
# 1. /api/auth/* → frontend (NextAuth)
|
|
6
|
+
# 2. /api/cookies/* → frontend (cookie consent/export)
|
|
7
|
+
# 3. /api/resources/* → frontend (authenticated proxy for images/files)
|
|
8
|
+
# 4. /resources/* → backend (main API)
|
|
9
|
+
# 5. /annotations/* → backend (main API)
|
|
10
|
+
# 6. /admin/* → backend (main API)
|
|
11
|
+
# 7. /api/* → backend (OpenAPI docs, spec)
|
|
12
|
+
# 8. /* → frontend (Next.js pages)
|
|
13
|
+
|
|
14
|
+
static_resources:
|
|
15
|
+
listeners:
|
|
16
|
+
- name: listener_0
|
|
17
|
+
address:
|
|
18
|
+
socket_address:
|
|
19
|
+
address: 0.0.0.0
|
|
20
|
+
port_value: 80
|
|
21
|
+
filter_chains:
|
|
22
|
+
- filters:
|
|
23
|
+
- name: envoy.filters.network.http_connection_manager
|
|
24
|
+
typed_config:
|
|
25
|
+
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
|
|
26
|
+
stat_prefix: ingress_http
|
|
27
|
+
access_log:
|
|
28
|
+
- name: envoy.access_loggers.stdout
|
|
29
|
+
typed_config:
|
|
30
|
+
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
|
|
31
|
+
http_filters:
|
|
32
|
+
- name: envoy.filters.http.router
|
|
33
|
+
typed_config:
|
|
34
|
+
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
|
|
35
|
+
route_config:
|
|
36
|
+
name: local_route
|
|
37
|
+
virtual_hosts:
|
|
38
|
+
- name: local_service
|
|
39
|
+
domains: ["*"]
|
|
40
|
+
routes:
|
|
41
|
+
# Frontend Next.js API routes (must come before backend /api/*)
|
|
42
|
+
- match:
|
|
43
|
+
prefix: "/api/auth/"
|
|
44
|
+
route:
|
|
45
|
+
cluster: frontend
|
|
46
|
+
timeout: 30s
|
|
47
|
+
- match:
|
|
48
|
+
prefix: "/api/cookies/"
|
|
49
|
+
route:
|
|
50
|
+
cluster: frontend
|
|
51
|
+
timeout: 30s
|
|
52
|
+
- match:
|
|
53
|
+
prefix: "/api/resources/"
|
|
54
|
+
route:
|
|
55
|
+
cluster: frontend
|
|
56
|
+
timeout: 30s
|
|
57
|
+
|
|
58
|
+
# Backend API routes (without /api prefix)
|
|
59
|
+
- match:
|
|
60
|
+
prefix: "/resources/"
|
|
61
|
+
route:
|
|
62
|
+
cluster: backend
|
|
63
|
+
timeout: 30s
|
|
64
|
+
- match:
|
|
65
|
+
prefix: "/annotations/"
|
|
66
|
+
route:
|
|
67
|
+
cluster: backend
|
|
68
|
+
timeout: 30s
|
|
69
|
+
- match:
|
|
70
|
+
prefix: "/admin/"
|
|
71
|
+
route:
|
|
72
|
+
cluster: backend
|
|
73
|
+
timeout: 30s
|
|
74
|
+
- match:
|
|
75
|
+
prefix: "/entity-types/"
|
|
76
|
+
route:
|
|
77
|
+
cluster: backend
|
|
78
|
+
timeout: 30s
|
|
79
|
+
- match:
|
|
80
|
+
prefix: "/jobs/"
|
|
81
|
+
route:
|
|
82
|
+
cluster: backend
|
|
83
|
+
timeout: 30s
|
|
84
|
+
- match:
|
|
85
|
+
prefix: "/users/"
|
|
86
|
+
route:
|
|
87
|
+
cluster: backend
|
|
88
|
+
timeout: 30s
|
|
89
|
+
- match:
|
|
90
|
+
prefix: "/tokens/"
|
|
91
|
+
route:
|
|
92
|
+
cluster: backend
|
|
93
|
+
timeout: 30s
|
|
94
|
+
- match:
|
|
95
|
+
prefix: "/health"
|
|
96
|
+
route:
|
|
97
|
+
cluster: backend
|
|
98
|
+
timeout: 30s
|
|
99
|
+
- match:
|
|
100
|
+
prefix: "/status"
|
|
101
|
+
route:
|
|
102
|
+
cluster: backend
|
|
103
|
+
timeout: 30s
|
|
104
|
+
|
|
105
|
+
# Backend OpenAPI documentation routes
|
|
106
|
+
- match:
|
|
107
|
+
prefix: "/api/"
|
|
108
|
+
route:
|
|
109
|
+
cluster: backend
|
|
110
|
+
timeout: 30s
|
|
111
|
+
|
|
112
|
+
# Everything else goes to frontend (Next.js pages)
|
|
113
|
+
- match:
|
|
114
|
+
prefix: "/"
|
|
115
|
+
route:
|
|
116
|
+
cluster: frontend
|
|
117
|
+
timeout: 30s
|
|
118
|
+
|
|
119
|
+
clusters:
|
|
120
|
+
- name: backend
|
|
121
|
+
connect_timeout: 5s
|
|
122
|
+
type: STRICT_DNS
|
|
123
|
+
lb_policy: ROUND_ROBIN
|
|
124
|
+
load_assignment:
|
|
125
|
+
cluster_name: backend
|
|
126
|
+
endpoints:
|
|
127
|
+
- lb_endpoints:
|
|
128
|
+
- endpoint:
|
|
129
|
+
address:
|
|
130
|
+
socket_address:
|
|
131
|
+
address: backend
|
|
132
|
+
port_value: 4000
|
|
133
|
+
|
|
134
|
+
- name: frontend
|
|
135
|
+
connect_timeout: 5s
|
|
136
|
+
type: STRICT_DNS
|
|
137
|
+
lb_policy: ROUND_ROBIN
|
|
138
|
+
load_assignment:
|
|
139
|
+
cluster_name: frontend
|
|
140
|
+
endpoints:
|
|
141
|
+
- lb_endpoints:
|
|
142
|
+
- endpoint:
|
|
143
|
+
address:
|
|
144
|
+
socket_address:
|
|
145
|
+
address: frontend
|
|
146
|
+
port_value: 3000
|
|
147
|
+
|
|
148
|
+
admin:
|
|
149
|
+
address:
|
|
150
|
+
socket_address:
|
|
151
|
+
address: 0.0.0.0
|
|
152
|
+
port_value: 9901
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semiont/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.27",
|
|
4
4
|
"description": "Semiont CLI - Unified environment management tool",
|
|
5
5
|
"_comment": "AWS SDK dependencies (@aws-sdk/*) are only used by platforms/aws",
|
|
6
6
|
"type": "module",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"@aws-sdk/client-sts": "^3.859.0",
|
|
66
66
|
"@aws-sdk/client-wafv2": "^3.859.0",
|
|
67
67
|
"@prisma/client": "^6.13.0",
|
|
68
|
-
"@semiont/api-client": "0.2.
|
|
69
|
-
"@semiont/core": "0.2.
|
|
68
|
+
"@semiont/api-client": "0.2.27",
|
|
69
|
+
"@semiont/core": "0.2.27",
|
|
70
70
|
"@testcontainers/postgresql": "^11.5.1",
|
|
71
71
|
"arg": "^5.0.2",
|
|
72
72
|
"bcrypt": "^5.1.1",
|