@kodus/cli 0.0.10 → 0.0.12

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/index.js CHANGED
@@ -1,12 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { program } from "commander";
4
- import { fileURLToPath } from 'url';
5
- import { dirname, join } from 'path';
6
- import { setupEnvironment } from './src/commands/install.js';
4
+ import { setupEnvironment } from "./src/commands/install.js";
7
5
 
8
6
  // CLI version
9
- program.version("0.0.9");
7
+ program.version("0.0.12");
10
8
 
11
9
  // Install command
12
10
  program
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kodus/cli",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "CLI tool for Kodus installation and management",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -6,10 +6,13 @@ import path from "path";
6
6
  import { execSync } from "child_process";
7
7
  import { DEFAULT_CONFIG, DOCKER_NETWORKS, CRITICAL_ERRORS } from "../config/default.js";
8
8
  import {
9
- generateSecretKey,
9
+ generateBase64Secret,
10
+ generateHexSecret,
11
+ generateWebhookToken,
10
12
  generateDbPassword,
11
13
  copyTemplates,
12
14
  createDockerNetworks,
15
+ updateEnvFile,
13
16
  } from "../utils/helpers.js";
14
17
  import { fileURLToPath } from 'url';
15
18
  import { dirname } from 'path';
@@ -50,6 +53,24 @@ const waitForService = async (serviceName, successMessage, errorMessage) => {
50
53
  }
51
54
  };
52
55
 
56
+ const copyEnvFile = async () => {
57
+ const envExamplePath = path.join(__dirname, '../../templates/.env.example');
58
+ const envPath = path.join(process.cwd(), '.env');
59
+
60
+ if (!fs.existsSync(envExamplePath)) {
61
+ console.error(chalk.red('Error: .env.example file not found in templates directory'));
62
+ process.exit(1);
63
+ }
64
+
65
+ try {
66
+ await fs.copy(envExamplePath, envPath);
67
+ console.log(chalk.green('.env file created successfully from template'));
68
+ } catch (error) {
69
+ console.error(chalk.red('Error copying .env file:', error.message));
70
+ process.exit(1);
71
+ }
72
+ };
73
+
53
74
  export const setupEnvironment = async () => {
54
75
  try {
55
76
  // Check prerequisites
@@ -81,6 +102,8 @@ export const setupEnvironment = async () => {
81
102
  process.exit(1);
82
103
  }
83
104
 
105
+ await copyEnvFile();
106
+
84
107
  // Environment type selection
85
108
  const { envType } = await inquirer.prompt([
86
109
  {
@@ -205,13 +228,15 @@ export const setupEnvironment = async () => {
205
228
  },
206
229
  ]);
207
230
 
208
- // Generate .env content
209
- const envContent = {
210
- ...DEFAULT_CONFIG,
211
- WEB_NEXTAUTH_SECRET: generateSecretKey(),
212
- WEB_JWT_SECRET_KEY: generateSecretKey(),
213
- API_JWT_SECRET: generateSecretKey(),
214
- API_JWT_REFRESHSECRET: generateSecretKey(),
231
+ // Update environment variables with generated values
232
+ const envUpdates = {
233
+ NEXTAUTH_SECRET: generateBase64Secret(),
234
+ JWT_SECRET_KEY: generateBase64Secret(),
235
+ API_CRYPTO_KEY: generateHexSecret(),
236
+ API_JWT_SECRET: generateBase64Secret(),
237
+ API_JWT_REFRESHSECRET: generateBase64Secret(),
238
+ CODE_MANAGEMENT_SECRET: generateHexSecret(),
239
+ CODE_MANAGEMENT_WEBHOOK_TOKEN: generateWebhookToken(),
215
240
  API_PG_DB_PASSWORD: generateDbPassword(),
216
241
  API_MG_DB_PASSWORD: generateDbPassword(),
217
242
  RABBITMQ_DEFAULT_PASS: generateDbPassword(),
@@ -224,15 +249,9 @@ export const setupEnvironment = async () => {
224
249
  ...gitConfig,
225
250
  };
226
251
 
227
- // Create .env file
228
- const envSpinner = ora("Creating .env file").start();
229
- const envContentString = Object.entries(envContent)
230
- .map(([key, value]) => `${key}=${value}`)
231
- .join("\n");
232
-
233
- const envPath = path.join(process.cwd(), '.env');
234
- fs.writeFileSync(envPath, envContentString);
235
- envSpinner.succeed("Created .env file");
252
+ const envSpinner = ora("Updating environment variables").start();
253
+ await updateEnvFile(envUpdates);
254
+ envSpinner.succeed("Environment variables updated");
236
255
 
237
256
  // Create Docker networks
238
257
  createDockerNetworks(DOCKER_NETWORKS);
@@ -262,6 +281,12 @@ export const setupEnvironment = async () => {
262
281
  "MongoDB failed to start"
263
282
  );
264
283
 
284
+ await waitForService(
285
+ "kodus_web",
286
+ "✓ Ready in",
287
+ "Web service failed to start"
288
+ );
289
+
265
290
  // Setup database
266
291
  const dbSpinner = ora("Setting up database").start();
267
292
  try {
@@ -315,6 +340,14 @@ export const setupEnvironment = async () => {
315
340
 
316
341
  if (startServices) {
317
342
  execSync("docker-compose up -d", { stdio: "ignore" });
343
+
344
+ // Wait for web service to be ready after restart
345
+ await waitForService(
346
+ "kodus_web",
347
+ "✓ Ready in",
348
+ "Web service failed to start"
349
+ );
350
+
318
351
  console.log(chalk.green("\nServices started successfully!"));
319
352
  }
320
353
  } catch (error) {
@@ -10,7 +10,17 @@ import { dirname } from 'path';
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = dirname(__filename);
12
12
 
13
- export const generateSecretKey = () => crypto.randomBytes(32).toString("base64");
13
+ // Base64 secret key (for JWT and auth)
14
+ export const generateBase64Secret = () => crypto.randomBytes(32).toString('base64');
15
+
16
+ // Hex secret key (for crypto and management)
17
+ export const generateHexSecret = () => crypto.randomBytes(32).toString('hex');
18
+
19
+ // URL-safe base64 secret (for webhook tokens)
20
+ export const generateWebhookToken = () => {
21
+ const base64 = crypto.randomBytes(32).toString('base64');
22
+ return base64.replace(/=/g, '').replace(/\+/g, '_').replace(/\//g, '-');
23
+ };
14
24
 
15
25
  export const generateDbPassword = () =>
16
26
  crypto
@@ -0,0 +1,142 @@
1
+ # =============================================
2
+ # Environment Configuration Example File
3
+ # Copy this file to .env and adjust the values
4
+ # =============================================
5
+
6
+ ## ---- BASIC SYSTEM CONFIGURATION ----
7
+
8
+ # Web Application Settings
9
+ WEB_NODE_ENV="self-hosted" # self-hosted, development, production
10
+ WEB_HOSTNAME_API="localhost" # API hostname
11
+ WEB_PORT_API=3001 # API port
12
+ WEB_PORT=3000 # Web application port
13
+ GLOBAL_API_CONTAINER_NAME="kodus-orchestrator" # API container name
14
+
15
+ # Authentication Settings
16
+ NEXTAUTH_URL="http://localhost:3000" # Base URL for authentication
17
+ NEXTAUTH_SECRET="" # NextAuth secret key (generate with: openssl rand -base64 32)
18
+ JWT_SECRET_KEY="" # JWT secret key (generate with: openssl rand -base64 32)
19
+
20
+ ## ---- API CONFIGURATION ----
21
+
22
+ # General API Settings
23
+ API_NODE_ENV="development" # development, production, test
24
+ API_LOG_LEVEL=error # error, warn, info, debug
25
+ API_LOG_PRETTY=true # Log formatting
26
+ API_HOST=0.0.0.0 # API host
27
+ API_PORT=3001 # API port
28
+ API_RATE_MAX_REQUEST=100 # Request rate limit
29
+ API_RATE_INTERVAL=1000 # Rate limit interval in ms
30
+ API_CLOUD_MODE=false # Enable/disable cloud mode
31
+ API_CRYPTO_KEY= # Crypto key for encryption/decryption
32
+
33
+ # JWT Configuration
34
+ API_JWT_EXPIRES_IN=365d # Token expiration time
35
+ API_JWT_SECRET=secret # JWT secret key
36
+ API_JWT_REFRESHSECRET=refreshSecret # Refresh token secret key
37
+ API_JWT_REFRESH_EXPIRES_IN=7d # Refresh token expiration time
38
+
39
+ ## ---- DATABASE CONFIGURATION ----
40
+
41
+ # PostgreSQL Settings
42
+ API_DATABASE_ENV="development" # development, production, test
43
+ API_PG_DB_HOST=db_kodus_postgres # PostgreSQL host
44
+ API_PG_DB_PORT=5432 # PostgreSQL port
45
+ API_PG_DB_USERNAME=kodusdev # Database username
46
+ API_PG_DB_PASSWORD= # Database password
47
+ API_PG_DB_DATABASE=kodus_db # Database name
48
+
49
+ # MongoDB Settings
50
+ API_MG_DB_HOST=db_kodus_mongodb # MongoDB host
51
+ API_MG_DB_PORT=27017 # MongoDB port
52
+ API_MG_DB_USERNAME=kodusdev # Database username
53
+ API_MG_DB_PASSWORD= # Database password
54
+ API_MG_DB_DATABASE=kodus # Database name
55
+ API_MG_DB_PRODUCTION_CONFIG='' # Additional production settings
56
+
57
+ ## ---- LLM API KEYS ----
58
+
59
+ # API Keys for LLM Providers
60
+ API_OPEN_AI_APIKEY= # OpenAI API key
61
+ API_GOOGLE_AI_API_KEY= # Google AI API key
62
+ API_ANTHROPIC_API_KEY= # Anthropic API key
63
+ API_NOVITA_AI_API_KEY= # Novita AI API key
64
+ API_VERTEX_AI_API_KEY= # Vertex AI API key
65
+
66
+ # Available LLM Models
67
+ API_LLM_MODEL_CHATGPT_3_5_TURBO=gpt-4o-mini
68
+ API_LLM_MODEL_CHATGPT_3_5_TURBO_16K=gpt-4o-mini
69
+ API_LLM_MODEL_CHATGPT_4=gpt-4o-mini
70
+ API_LLM_MODEL_CHATGPT_4_TURBO=gpt-4o-mini
71
+ API_LLM_MODEL_CHATGPT_4_ALL=gpt-4o
72
+ API_LLM_MODEL_CHATGPT_4_ALL_MINI=gpt-4o-mini
73
+ API_LLM_MODEL_CLAUDE_3_5_SONNET=claude-3-5-sonnet-20241022
74
+ API_LLM_MODEL_CLAUDE_3_5_SONNET_20241022=claude-3-5-sonnet-20241022
75
+ API_LLM_MODEL_GEMINI_1_5_PRO=gpt-4o-mini
76
+ API_LLM_MODEL_GEMINI_1_5_PRO_EXP=gpt-4o-mini
77
+
78
+ ## ---- CRON CONFIGURATION ----
79
+ # Format: minute hour day_of_month month day_of_week
80
+ # Example: 0 1 * * 5 = Every Friday at 01:00
81
+
82
+ API_CRON_AUTOMATION_INTERACTION_MONITOR=0 1 * * 5
83
+ API_CRON_AUTOMATION_ISSUES_DETAILS=0 1 * * 5
84
+ API_CRON_COMPILE_SPRINT=0 1 * * 5
85
+ API_CRON_METRICS=* 5 * * *
86
+ API_CRON_AUTOMATION_DAILY_CHECKIN=* 5 * * *
87
+ API_CRON_SPRINT_RETRO=* 5 * * *
88
+ API_CRON_TEAM_ARTIFACTS_WEEKLY=* 5 * * *
89
+ API_CRON_TEAM_ARTIFACTS_DAILY=* 5 * * *
90
+ API_CRON_AUTOMATION_TEAM_PROGRESS_TRACKER=* 5 * * *
91
+ API_CRON_ORGANIZATION_METRICS=* 5 * * *
92
+ API_CRON_AUTOMATION_EXECUTIVE_CHECKIN=* 5 * * *
93
+ API_CRON_ORGANIZATION_ARTIFACTS_WEEKLY=* 5 * * *
94
+ API_CRON_ORGANIZATION_ARTIFACTS_DAILY=* 5 * * *
95
+ API_CRON_ENRICH_TEAM_ARTIFACTS_WEEKLY=* 5 * * *
96
+ API_CRON_SYNC_CODE_REVIEW_REACTIONS=* 5 * * *
97
+ API_CRON_KODY_LEARNING=0 0 * * 6
98
+ API_CRON_CHECK_IF_PR_SHOULD_BE_APPROVED=/2 * * * # A CADA 2 MINUTOS;
99
+ ## ---- GIT INTEGRATIONS ----
100
+
101
+ CODE_MANAGEMENT_SECRET=
102
+ CODE_MANAGEMENT_WEBHOOK_TOKEN=
103
+
104
+ # GitHub Settings (Fill only if using GitHub)
105
+ API_GITHUB_CODE_MANAGEMENT_WEBHOOK= # GitHub webhook URL
106
+ API_GITHUB_APP_ID= # GitHub App ID
107
+ API_GITHUB_CLIENT_SECRET= # GitHub App Client Secret
108
+ API_GITHUB_PRIVATE_KEY="" # GitHub App Private Key
109
+ WEB_GITHUB_INSTALL_URL="" # GitHub App Installation URL
110
+ WEB_OAUTH_GITHUB_CLIENT_ID="" # GitHub OAuth Client ID
111
+ WEB_OAUTH_GITHUB_CLIENT_SECRET="" # GitHub OAuth Client Secret
112
+
113
+ # GitLab Settings (Fill only if using GitLab)
114
+ API_GITLAB_TOKEN_URL="https://gitlab.com/oauth/token"
115
+ API_GITLAB_CODE_MANAGEMENT_WEBHOOK= # GitLab webhook URL
116
+ WEB_GITLAB_SCOPES="read_api read_user read_repository"
117
+ WEB_GITLAB_OAUTH_URL="https://gitlab.com/oauth/authorize"
118
+ WEB_OAUTH_GITLAB_CLIENT_ID="" # GitLab OAuth Client ID
119
+ WEB_OAUTH_GITLAB_CLIENT_SECRET="" # GitLab OAuth Client Secret
120
+
121
+ # Bitbucket Settings (Fill only if using Bitbucket)
122
+ WEB_BITBUCKET_INSTALL_URL="" # Bitbucket Installation URL
123
+ GLOBAL_BITBUCKET_CODE_MANAGEMENT_WEBHOOK= # Bitbucket webhook URL
124
+
125
+ ## ---- ADDITIONAL INTEGRATIONS ----
126
+
127
+ # Communication Integrations
128
+ WEB_CONNECTION_SLACK="" # Slack connection URL
129
+ WEB_CONNECTION_DISCORD="" # Discord connection URL
130
+
131
+ # JIRA Integration
132
+ WEB_JIRA_SCOPES="read%3Aissue-type%3Ajira%20read%3Aproject%3Ajira%20read%3Aproject.property%3Ajira%20read%3Auser%3Ajira%20read%3Aapplication-role%3Ajira%20read%3Aavatar%3Ajira%20read%3Agroup%3Ajira%20read%3Aissue-type-hierarchy%3Ajira%20read%3Aproject-category%3Ajira%20read%3Aproject-version%3Ajira%20read%3Aproject.component%3Ajira%20read%3Aissue-details%3Ajira%20read%3Aaudit-log%3Ajira%20read%3Afield-configuration%3Ajira%20read%3Aissue-meta%3Ajira%20read%3Aissue-security-level%3Ajira%20read%3Aissue.vote%3Ajira%20read%3Aissue.changelog%3Ajira%20read%3Aissue%3Ajira%20read%3Astatus%3Ajira%20read%3Afield%3Ajira%20write%3Awebhook%3Ajira%20read%3Awebhook%3Ajira%20read%3Aissue-status%3Ajira%20read%3Aboard-scope.admin%3Ajira-software%20read%3Ajql%3Ajira%20delete%3Awebhook%3Ajira%20read%3Acomment.property%3Ajira%20read%3Aproject-role%3Ajira%20read%3Aepic%3Ajira-software%20read%3Aboard-scope%3Ajira-software%20read%3Asprint%3Ajira-software%20read%3Afield.default-value%3Ajira%20read%3Afield.option%3Ajira%20read%3Aissue%3Ajira-software%20read%3Acomment%3Ajira%20read%3Aattachment%3Ajira%20read%3Aissue-worklog%3Ajira%20write%3Aissue-link-type%3Ajira%20write%3Afield%3Ajira%20write%3Aworkflow%3Ajira%20write%3Aproject%3Ajira"
133
+
134
+ # Support Settings
135
+ WEB_ANALYTICS_HOSTNAME="" # Analytics hostname
136
+ WEB_SUPPORT_DOCS_URL="https://docs.kodus.io" # Documentation URL
137
+ WEB_SUPPORT_DISCORD_INVITE_URL="https://discord.gg/CceCdAke" # Discord invite URL
138
+ WEB_SUPPORT_TALK_TO_FOUNDER_URL="https://cal.com/gabrielmalinosqui/30min" # Scheduling URL
139
+
140
+ # RabbitMQ Configuration
141
+ API_RABBITMQ_URI= # RabbitMQ connection URI
142
+ API_RABBITMQ_ENABLED=false # Enable/disable RabbitMQ