@aifabrix/builder 2.0.0 → 2.0.3
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/README.md +5 -3
- package/bin/aifabrix.js +9 -3
- package/jest.config.integration.js +30 -0
- package/lib/app-config.js +157 -0
- package/lib/app-deploy.js +233 -82
- package/lib/app-dockerfile.js +112 -0
- package/lib/app-prompts.js +244 -0
- package/lib/app-push.js +172 -0
- package/lib/app-run.js +235 -144
- package/lib/app.js +208 -274
- package/lib/audit-logger.js +2 -0
- package/lib/build.js +177 -125
- package/lib/cli.js +76 -86
- package/lib/commands/app.js +414 -0
- package/lib/commands/login.js +304 -0
- package/lib/config.js +78 -0
- package/lib/deployer.js +225 -81
- package/lib/env-reader.js +45 -30
- package/lib/generator.js +308 -191
- package/lib/github-generator.js +67 -7
- package/lib/infra.js +156 -61
- package/lib/push.js +105 -10
- package/lib/schema/application-schema.json +30 -2
- package/lib/schema/env-config.yaml +9 -1
- package/lib/schema/infrastructure-schema.json +589 -0
- package/lib/secrets.js +229 -24
- package/lib/template-validator.js +205 -0
- package/lib/templates.js +305 -170
- package/lib/utils/api.js +329 -0
- package/lib/utils/cli-utils.js +97 -0
- package/lib/utils/compose-generator.js +185 -0
- package/lib/utils/docker-build.js +173 -0
- package/lib/utils/dockerfile-utils.js +131 -0
- package/lib/utils/environment-checker.js +125 -0
- package/lib/utils/error-formatter.js +61 -0
- package/lib/utils/health-check.js +187 -0
- package/lib/utils/logger.js +53 -0
- package/lib/utils/template-helpers.js +223 -0
- package/lib/utils/variable-transformer.js +271 -0
- package/lib/validator.js +27 -112
- package/package.json +14 -10
- package/templates/README.md +75 -3
- package/templates/applications/keycloak/Dockerfile +36 -0
- package/templates/applications/keycloak/env.template +32 -0
- package/templates/applications/keycloak/rbac.yaml +37 -0
- package/templates/applications/keycloak/variables.yaml +56 -0
- package/templates/applications/miso-controller/Dockerfile +125 -0
- package/templates/applications/miso-controller/env.template +129 -0
- package/templates/applications/miso-controller/rbac.yaml +214 -0
- package/templates/applications/miso-controller/variables.yaml +56 -0
- package/templates/github/release.yaml.hbs +5 -26
- package/templates/github/steps/npm.hbs +24 -0
- package/templates/infra/compose.yaml +6 -6
- package/templates/python/docker-compose.hbs +19 -12
- package/templates/python/main.py +80 -0
- package/templates/python/requirements.txt +4 -0
- package/templates/typescript/Dockerfile.hbs +2 -2
- package/templates/typescript/docker-compose.hbs +19 -12
- package/templates/typescript/index.ts +116 -0
- package/templates/typescript/package.json +26 -0
- package/templates/typescript/tsconfig.json +24 -0
|
@@ -8,11 +8,12 @@ services:
|
|
|
8
8
|
{{app.key}}:
|
|
9
9
|
image: {{image.name}}:{{image.tag}}
|
|
10
10
|
container_name: aifabrix-{{app.key}}
|
|
11
|
-
env_file:
|
|
11
|
+
env_file:
|
|
12
|
+
- {{envFile}}
|
|
12
13
|
ports:
|
|
13
14
|
- "{{build.localPort}}:{{port}}"
|
|
14
15
|
networks:
|
|
15
|
-
-
|
|
16
|
+
- infra_aifabrix-network
|
|
16
17
|
{{#if requiresStorage}}
|
|
17
18
|
volumes:
|
|
18
19
|
- "{{mountVolume}}:/mnt/data"
|
|
@@ -39,31 +40,37 @@ services:
|
|
|
39
40
|
- ${ADMIN_SECRETS_PATH}
|
|
40
41
|
environment:
|
|
41
42
|
POSTGRES_DB: postgres
|
|
43
|
+
PGHOST: postgres
|
|
44
|
+
PGPORT: "5432"
|
|
45
|
+
PGUSER: pgadmin
|
|
42
46
|
networks:
|
|
43
|
-
-
|
|
47
|
+
- infra_aifabrix-network
|
|
44
48
|
command: >
|
|
45
49
|
sh -c "
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
psql -d postgres -c 'GRANT ALL PRIVILEGES ON DATABASE {{app.key}} TO {{app.key}}_user;' &&
|
|
50
|
-
psql -d {{app.key}} -c 'ALTER SCHEMA public OWNER TO {{app.key}}_user;' &&
|
|
51
|
-
psql -d {{app.key}} -c 'GRANT ALL ON SCHEMA public TO {{app.key}}_user;' &&
|
|
50
|
+
export PGHOST=postgres PGPORT=5432 PGUSER=pgadmin &&
|
|
51
|
+
export PGPASSWORD="${POSTGRES_PASSWORD}" &&
|
|
52
|
+
{{#if databases}}
|
|
52
53
|
{{#each databases}}
|
|
53
|
-
{{#unless @first}}
|
|
54
54
|
echo 'Creating {{name}} database and user...' &&
|
|
55
55
|
psql -d postgres -c 'CREATE DATABASE {{name}};' || echo '{{name}} database exists' &&
|
|
56
56
|
psql -d postgres -c \"CREATE USER {{name}}_user WITH PASSWORD '{{name}}_pass123';\" || echo '{{name}}_user exists' &&
|
|
57
57
|
psql -d postgres -c 'GRANT ALL PRIVILEGES ON DATABASE {{name}} TO {{name}}_user;' &&
|
|
58
58
|
psql -d {{name}} -c 'ALTER SCHEMA public OWNER TO {{name}}_user;' &&
|
|
59
59
|
psql -d {{name}} -c 'GRANT ALL ON SCHEMA public TO {{name}}_user;' &&
|
|
60
|
-
{{/unless}}
|
|
61
60
|
{{/each}}
|
|
61
|
+
{{else}}
|
|
62
|
+
echo 'Creating {{app.key}} database and user...' &&
|
|
63
|
+
psql -d postgres -c 'CREATE DATABASE {{app.key}};' || echo '{{app.key}} database exists' &&
|
|
64
|
+
psql -d postgres -c \"CREATE USER {{app.key}}_user WITH PASSWORD '{{app.key}}_pass123';\" || echo '{{app.key}}_user exists' &&
|
|
65
|
+
psql -d postgres -c 'GRANT ALL PRIVILEGES ON DATABASE {{app.key}} TO {{app.key}}_user;' &&
|
|
66
|
+
psql -d {{app.key}} -c 'ALTER SCHEMA public OWNER TO {{app.key}}_user;' &&
|
|
67
|
+
psql -d {{app.key}} -c 'GRANT ALL ON SCHEMA public TO {{app.key}}_user;' &&
|
|
68
|
+
{{/if}}
|
|
62
69
|
echo 'Database initialization complete!'
|
|
63
70
|
"
|
|
64
71
|
restart: "no"
|
|
65
72
|
{{/if}}
|
|
66
73
|
|
|
67
74
|
networks:
|
|
68
|
-
|
|
75
|
+
infra_aifabrix-network:
|
|
69
76
|
external: true
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { Pool } from 'pg';
|
|
3
|
+
import { Request, Response } from 'express';
|
|
4
|
+
|
|
5
|
+
const app = express();
|
|
6
|
+
const PORT = process.env.PORT || 3000;
|
|
7
|
+
|
|
8
|
+
app.use(express.json());
|
|
9
|
+
|
|
10
|
+
// Database connection pool
|
|
11
|
+
let dbPool: Pool | null = null;
|
|
12
|
+
|
|
13
|
+
function initDatabase() {
|
|
14
|
+
const databaseUrl = process.env.DATABASE_URL;
|
|
15
|
+
if (!databaseUrl) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
dbPool = new Pool({
|
|
21
|
+
connectionString: databaseUrl,
|
|
22
|
+
connectionTimeoutMillis: 5000,
|
|
23
|
+
});
|
|
24
|
+
return dbPool;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error('Failed to initialize database pool:', error);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function checkDatabase(): Promise<{ connected: boolean; error?: string }> {
|
|
32
|
+
// If DATABASE_URL is not set, try to connect using individual environment variables
|
|
33
|
+
if (!dbPool && process.env.DATABASE_URL) {
|
|
34
|
+
// DATABASE_URL was set but pool initialization failed
|
|
35
|
+
return { connected: false, error: 'Database pool not initialized' };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// If no DATABASE_URL, try to create connection from individual vars
|
|
39
|
+
if (!dbPool) {
|
|
40
|
+
const host = process.env.DATABASE_HOST || process.env.DB_HOST || 'postgres';
|
|
41
|
+
const port = parseInt(process.env.DATABASE_PORT || process.env.DB_PORT || '5432', 10);
|
|
42
|
+
const database = process.env.DATABASE_NAME || process.env.DB_NAME || 'postgres';
|
|
43
|
+
const user = process.env.DATABASE_USER || process.env.DB_USER || 'pgadmin';
|
|
44
|
+
const password = process.env.DATABASE_PASSWORD || process.env.DB_PASSWORD || 'admin123';
|
|
45
|
+
|
|
46
|
+
if (!host && !database) {
|
|
47
|
+
return { connected: false, error: 'Database not configured' };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const tempPool = new Pool({
|
|
52
|
+
host,
|
|
53
|
+
port,
|
|
54
|
+
database,
|
|
55
|
+
user,
|
|
56
|
+
password,
|
|
57
|
+
connectionTimeoutMillis: 5000,
|
|
58
|
+
});
|
|
59
|
+
const client = await tempPool.connect();
|
|
60
|
+
await client.query('SELECT 1');
|
|
61
|
+
client.release();
|
|
62
|
+
await tempPool.end();
|
|
63
|
+
return { connected: true };
|
|
64
|
+
} catch (error: any) {
|
|
65
|
+
return { connected: false, error: error.message || 'Database connection failed' };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const client = await dbPool.connect();
|
|
71
|
+
await client.query('SELECT 1');
|
|
72
|
+
client.release();
|
|
73
|
+
return { connected: true };
|
|
74
|
+
} catch (error: any) {
|
|
75
|
+
return { connected: false, error: error.message || 'Database connection failed' };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Initialize database on startup
|
|
80
|
+
initDatabase();
|
|
81
|
+
|
|
82
|
+
// Health check endpoint with database connectivity check
|
|
83
|
+
app.get('/health', async (req: Request, res: Response) => {
|
|
84
|
+
const healthStatus: any = {
|
|
85
|
+
status: 'ok',
|
|
86
|
+
timestamp: new Date().toISOString()
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Check database connection if database is configured (DATABASE_URL or individual vars)
|
|
90
|
+
const databaseUrl = process.env.DATABASE_URL;
|
|
91
|
+
const databaseHost = process.env.DATABASE_HOST || process.env.DB_HOST;
|
|
92
|
+
const databaseName = process.env.DATABASE_NAME || process.env.DB_NAME;
|
|
93
|
+
|
|
94
|
+
// Only check database if database is configured
|
|
95
|
+
if (databaseUrl || databaseHost || databaseName) {
|
|
96
|
+
const dbCheck = await checkDatabase();
|
|
97
|
+
if (dbCheck.connected) {
|
|
98
|
+
healthStatus.database = 'connected';
|
|
99
|
+
} else {
|
|
100
|
+
healthStatus.database = 'error';
|
|
101
|
+
healthStatus.database_error = dbCheck.error;
|
|
102
|
+
return res.status(503).json(healthStatus);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
res.status(200).json(healthStatus);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Root endpoint
|
|
110
|
+
app.get('/', (req: Request, res: Response) => {
|
|
111
|
+
res.json({ message: 'AI Fabrix Application', version: '1.0.0' });
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
app.listen(PORT, () => {
|
|
115
|
+
console.log(`Server running on port ${PORT}`);
|
|
116
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aifabrix-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AI Fabrix application",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "ts-node --transpile-only index.ts",
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"dev": "ts-node --transpile-only index.ts"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"express": "^4.18.2",
|
|
13
|
+
"pg": "^8.11.3"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/express": "^4.17.21",
|
|
17
|
+
"@types/node": "^20.10.0",
|
|
18
|
+
"@types/pg": "^8.10.9",
|
|
19
|
+
"ts-node": "^10.9.2",
|
|
20
|
+
"typescript": "^5.3.3"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"moduleResolution": "node",
|
|
14
|
+
"types": ["node"]
|
|
15
|
+
},
|
|
16
|
+
"ts-node": {
|
|
17
|
+
"transpileOnly": true,
|
|
18
|
+
"compilerOptions": {
|
|
19
|
+
"module": "commonjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"include": ["*.ts"],
|
|
23
|
+
"exclude": ["node_modules", "dist"]
|
|
24
|
+
}
|