openwork-agent 1.0.0

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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +436 -0
  3. package/package.json +78 -0
  4. package/src/core/TechDetector.js +351 -0
  5. package/src/generators/ProjectGenerator.js +1241 -0
  6. package/src/generators/ProjectGeneratorExtensions.js +14 -0
  7. package/src/generators/TemplateMethods.js +402 -0
  8. package/src/generators/index.js +5 -0
  9. package/src/index.js +152 -0
  10. package/src/main.js +8 -0
  11. package/src/templates/common/README.md.hbs +358 -0
  12. package/src/templates/docker/index.js +518 -0
  13. package/src/templates/docker.js +58 -0
  14. package/src/templates/go/basic/api/routes/user.go.hbs +138 -0
  15. package/src/templates/go/basic/config/config.go.hbs +54 -0
  16. package/src/templates/go/basic/go.mod.hbs +8 -0
  17. package/src/templates/go/basic/main.go.hbs +70 -0
  18. package/src/templates/go/basic/models/user.go.hbs +69 -0
  19. package/src/templates/go/basic/services/user_service.go.hbs +173 -0
  20. package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/controller/UserController.java.hbs +91 -0
  21. package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/dto/ApiResponse.java.hbs +40 -0
  22. package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/model/User.java.hbs +102 -0
  23. package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/repository/UserRepository.java.hbs +20 -0
  24. package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/service/UserService.java.hbs +65 -0
  25. package/src/templates/java/basic/src/main/java/com/{{snakeCase projectName}}/{{projectName}}/{{pascalCase projectName}}Application.java.hbs +16 -0
  26. package/src/templates/node/basic/src/config/database.ts.hbs +18 -0
  27. package/src/templates/node/basic/src/controllers/UserController.ts.hbs +98 -0
  28. package/src/templates/node/basic/src/index.ts.hbs +45 -0
  29. package/src/templates/node/basic/src/middleware/errorHandler.ts.hbs +33 -0
  30. package/src/templates/node/basic/src/routes/index.ts.hbs +42 -0
  31. package/src/templates/node/basic/src/types/index.ts.hbs +18 -0
  32. package/src/templates/python/basic/config/database.py.hbs +36 -0
  33. package/src/templates/python/basic/main.py.hbs +58 -0
  34. package/src/templates/python/basic/middleware/error_handler.py.hbs +41 -0
  35. package/src/templates/python/basic/models/user.py.hbs +40 -0
  36. package/src/templates/python/basic/routes/__init__.py.hbs +12 -0
  37. package/src/templates/python/basic/routes/users.py.hbs +64 -0
  38. package/src/templates/rust/basic/Cargo.toml.hbs +39 -0
  39. package/src/templates/rust/basic/src/config/database.rs.hbs +27 -0
  40. package/src/templates/rust/basic/src/handlers/user.rs.hbs +130 -0
  41. package/src/templates/rust/basic/src/handlers/user_routes.rs.hbs +15 -0
  42. package/src/templates/rust/basic/src/main.rs.hbs +53 -0
  43. package/src/templates/rust/basic/src/models/mod.rs.hbs +79 -0
  44. package/src/templates/rust/basic/src/schema.rs.hbs +10 -0
  45. package/src/utils/FileManager.js +186 -0
  46. package/src/utils/Templates.js +231 -0
@@ -0,0 +1,130 @@
1
+ use actix_web::{web, HttpResponse, Result};
2
+ use diesel::prelude::*;
3
+ use uuid::Uuid;
4
+ use chrono::Utc;
5
+
6
+ use crate::models::{User, NewUser, UpdateUser, ApiResponse, CreateUserRequest, UpdateUserRequest};
7
+ use crate::schema::users;
8
+ use crate::DbPool;
9
+
10
+ pub async fn get_users(pool: web::Data<DbPool>) -> Result<HttpResponse> {
11
+ let mut conn = pool.get().expect("Failed to get connection");
12
+
13
+ let users = web::block(move || {
14
+ users::table
15
+ .select(User::as_select())
16
+ .load::<User>(&mut conn)
17
+ })
18
+ .await
19
+ .expect("Failed to execute query");
20
+
21
+ Ok(HttpResponse::Ok().json(ApiResponse::success(users)))
22
+ }
23
+
24
+ pub async fn get_user(
25
+ path: web::Path<Uuid>,
26
+ pool: web::Data<DbPool>
27
+ ) -> Result<HttpResponse> {
28
+ let user_id = path.into_inner();
29
+ let mut conn = pool.get().expect("Failed to get connection");
30
+
31
+ let user = web::block(move || {
32
+ users::table
33
+ .filter(users::id.eq(user_id))
34
+ .select(User::as_select())
35
+ .first::<User>(&mut conn)
36
+ .optional()
37
+ })
38
+ .await
39
+ .expect("Failed to execute query");
40
+
41
+ match user {
42
+ Some(user) => Ok(HttpResponse::Ok().json(ApiResponse::success(user))),
43
+ None => Ok(HttpResponse::NotFound().json(ApiResponse::<User>::error(
44
+ "User not found".to_string()
45
+ ))),
46
+ }
47
+ }
48
+
49
+ pub async fn create_user(
50
+ user_data: web::Json<CreateUserRequest>,
51
+ pool: web::Data<DbPool>
52
+ ) -> Result<HttpResponse> {
53
+ let new_user = NewUser {
54
+ name: user_data.name.clone(),
55
+ email: user_data.email.clone(),
56
+ age: user_data.age,
57
+ };
58
+
59
+ let mut conn = pool.get().expect("Failed to get connection");
60
+
61
+ let user = web::block(move || {
62
+ diesel::insert_into(users::table)
63
+ .values(&new_user)
64
+ .returning(User::as_returning())
65
+ .get_result::<User>(&mut conn)
66
+ })
67
+ .await
68
+ .expect("Failed to execute query");
69
+
70
+ Ok(HttpResponse::Created().json(ApiResponse::success(user)))
71
+ }
72
+
73
+ pub async fn update_user(
74
+ path: web::Path<Uuid>,
75
+ user_data: web::Json<UpdateUserRequest>,
76
+ pool: web::Data<DbPool>
77
+ ) -> Result<HttpResponse> {
78
+ let user_id = path.into_inner();
79
+ let update_data = UpdateUser {
80
+ name: user_data.name.clone(),
81
+ email: user_data.email.clone(),
82
+ age: user_data.age,
83
+ updated_at: Utc::now(),
84
+ };
85
+
86
+ let mut conn = pool.get().expect("Failed to get connection");
87
+
88
+ let user = web::block(move || {
89
+ diesel::update(users::table.filter(users::id.eq(user_id)))
90
+ .set(&update_data)
91
+ .returning(User::as_returning())
92
+ .get_result::<User>(&mut conn)
93
+ .optional()
94
+ })
95
+ .await
96
+ .expect("Failed to execute query");
97
+
98
+ match user {
99
+ Some(user) => Ok(HttpResponse::Ok().json(ApiResponse::success(user))),
100
+ None => Ok(HttpResponse::NotFound().json(ApiResponse::<User>::error(
101
+ "User not found".to_string()
102
+ ))),
103
+ }
104
+ }
105
+
106
+ pub async fn delete_user(
107
+ path: web::Path<Uuid>,
108
+ pool: web::Data<DbPool>
109
+ ) -> Result<HttpResponse> {
110
+ let user_id = path.into_inner();
111
+ let mut conn = pool.get().expect("Failed to get connection");
112
+
113
+ let rows_affected = web::block(move || {
114
+ diesel::delete(users::table.filter(users::id.eq(user_id)))
115
+ .execute(&mut conn)
116
+ })
117
+ .await
118
+ .expect("Failed to execute query");
119
+
120
+ if rows_affected > 0 {
121
+ Ok(HttpResponse::Ok().json(ApiResponse::<()>::success_with_message(
122
+ (),
123
+ "User deleted successfully".to_string()
124
+ )))
125
+ } else {
126
+ Ok(HttpResponse::NotFound().json(ApiResponse::<()>::error(
127
+ "User not found".to_string()
128
+ )))
129
+ }
130
+ }
@@ -0,0 +1,15 @@
1
+ use actix_web::{web, Scope};
2
+ use uuid::Uuid;
3
+
4
+ use super::user;
5
+
6
+ pub fn config(cfg: &mut web::ServiceConfig) {
7
+ cfg.service(
8
+ web::scope("/users")
9
+ .route("", web::get().to(user::get_users))
10
+ .route("/{id}", web::get().to(user::get_user))
11
+ .route("", web::post().to(user::create_user))
12
+ .route("/{id}", web::put().to(user::update_user))
13
+ .route("/{id}", web::delete().to(user::delete_user))
14
+ );
15
+ }
@@ -0,0 +1,53 @@
1
+ use actix_web::{web, App, HttpServer, middleware::Logger};
2
+ use actix_cors::Cors;
3
+ use diesel::prelude::*;
4
+ use diesel::r2d2::{self, ConnectionManager};
5
+ use std::env;
6
+
7
+ mod config;
8
+ mod models;
9
+ mod schema;
10
+ mod handlers;
11
+ mod services;
12
+
13
+ use config::database::establish_connection;
14
+ use handlers::user_routes;
15
+
16
+ #[actix_web::main]
17
+ async fn main() -> std::io::Result<()> {
18
+ env_logger::init();
19
+ dotenv::dotenv().ok();
20
+
21
+ // Database connection
22
+ let conn_spec = establish_connection();
23
+
24
+ println!("🚀 {{pascalCase projectName}} server starting on 0.0.0.0:8080");
25
+
26
+ HttpServer::new(move || {
27
+ let cors = Cors::default()
28
+ .allow_any_origin()
29
+ .allow_any_method()
30
+ .allow_any_header()
31
+ .max_age(3600);
32
+
33
+ App::new()
34
+ .app_data(web::Data::new(conn_spec.clone()))
35
+ .wrap(cors)
36
+ .wrap(Logger::default())
37
+ .service(
38
+ web::scope("/api")
39
+ .configure(user_routes::config)
40
+ )
41
+ .route("/health", web::get().to(health_check))
42
+ })
43
+ .bind("0.0.0.0:8080")?
44
+ .run()
45
+ .await
46
+ }
47
+
48
+ async fn health_check() -> impl actix_web::Responder {
49
+ actix_web::HttpResponse::Ok().json(serde_json::json!({
50
+ "status": "OK",
51
+ "timestamp": "2024-01-01T00:00:00Z"
52
+ }))
53
+ }
@@ -0,0 +1,79 @@
1
+ use serde::{Deserialize, Serialize};
2
+ use chrono::{DateTime, Utc};
3
+ use uuid::Uuid;
4
+
5
+ #[derive(Debug, Clone, Queryable, Selectable, Serialize)]
6
+ #[diesel(table_name = crate::schema::users)]
7
+ #[diesel(check_for_backend(diesel::pg::Pg))]
8
+ pub struct User {
9
+ pub id: Uuid,
10
+ pub name: String,
11
+ pub email: String,
12
+ pub age: Option<i32>,
13
+ pub created_at: DateTime<Utc>,
14
+ pub updated_at: DateTime<Utc>,
15
+ }
16
+
17
+ #[derive(Debug, Insertable, Serialize, Deserialize)]
18
+ #[diesel(table_name = crate::schema::users)]
19
+ pub struct NewUser {
20
+ pub name: String,
21
+ pub email: String,
22
+ pub age: Option<i32>,
23
+ }
24
+
25
+ #[derive(Debug, AsChangeset, Deserialize)]
26
+ #[diesel(table_name = crate::schema::users)]
27
+ pub struct UpdateUser {
28
+ pub name: Option<String>,
29
+ pub email: Option<String>,
30
+ pub age: Option<i32>,
31
+ pub updated_at: DateTime<Utc>,
32
+ }
33
+
34
+ #[derive(Debug, Serialize, Deserialize)]
35
+ pub struct ApiResponse<T> {
36
+ pub success: bool,
37
+ pub data: Option<T>,
38
+ pub message: Option<String>,
39
+ }
40
+
41
+ impl<T> ApiResponse<T> {
42
+ pub fn success(data: T) -> Self {
43
+ Self {
44
+ success: true,
45
+ data: Some(data),
46
+ message: None,
47
+ }
48
+ }
49
+
50
+ pub fn success_with_message(data: T, message: String) -> Self {
51
+ Self {
52
+ success: true,
53
+ data: Some(data),
54
+ message: Some(message),
55
+ }
56
+ }
57
+
58
+ pub fn error(message: String) -> Self {
59
+ Self {
60
+ success: false,
61
+ data: None,
62
+ message: Some(message),
63
+ }
64
+ }
65
+ }
66
+
67
+ #[derive(Debug, Serialize, Deserialize)]
68
+ pub struct CreateUserRequest {
69
+ pub name: String,
70
+ pub email: String,
71
+ pub age: Option<i32>,
72
+ }
73
+
74
+ #[derive(Debug, Serialize, Deserialize)]
75
+ pub struct UpdateUserRequest {
76
+ pub name: Option<String>,
77
+ pub email: Option<String>,
78
+ pub age: Option<i32>,
79
+ }
@@ -0,0 +1,10 @@
1
+ diesel::table! {
2
+ users (id) {
3
+ id -> Uuid,
4
+ name -> Varchar,
5
+ email -> Varchar,
6
+ age -> Nullable<Integer>,
7
+ created_at -> Timestamp,
8
+ updated_at -> Timestamp,
9
+ }
10
+ }
@@ -0,0 +1,186 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const Handlebars = require('handlebars');
4
+
5
+ class FileManager {
6
+ constructor() {
7
+ this.registerHandlebarsHelpers();
8
+ }
9
+
10
+ registerHandlebarsHelpers() {
11
+ Handlebars.registerHelper('camelCase', (str) => {
12
+ return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => {
13
+ return index === 0 ? word.toLowerCase() : word.toUpperCase();
14
+ }).replace(/\s+/g, '');
15
+ });
16
+
17
+ Handlebars.registerHelper('pascalCase', (str) => {
18
+ return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word) => {
19
+ return word.toUpperCase();
20
+ }).replace(/\s+/g, '');
21
+ });
22
+
23
+ Handlebars.registerHelper('kebabCase', (str) => {
24
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase();
25
+ });
26
+
27
+ Handlebars.registerHelper('snakeCase', (str) => {
28
+ return str.replace(/([a-z])([A-Z])/g, '$1_$2').replace(/\s+/g, '_').toLowerCase();
29
+ });
30
+
31
+ Handlebars.registerHelper('upperCase', (str) => {
32
+ return str.toUpperCase();
33
+ });
34
+
35
+ Handlebars.registerHelper('lowerCase', (str) => {
36
+ return str.toLowerCase();
37
+ });
38
+
39
+ // Common conditional helpers
40
+ Handlebars.registerHelper('eq', (a, b) => {
41
+ return a === b;
42
+ });
43
+
44
+ Handlebars.registerHelper('ne', (a, b) => {
45
+ return a !== b;
46
+ });
47
+
48
+ Handlebars.registerHelper('gt', (a, b) => {
49
+ return a > b;
50
+ });
51
+
52
+ Handlebars.registerHelper('lt', (a, b) => {
53
+ return a < b;
54
+ });
55
+
56
+ Handlebars.registerHelper('and', (...args) => {
57
+ return args.slice(0, -1).every(Boolean);
58
+ });
59
+
60
+ Handlebars.registerHelper('or', (...args) => {
61
+ return args.slice(0, -1).some(Boolean);
62
+ });
63
+
64
+ Handlebars.registerHelper('not', (value) => {
65
+ return !value;
66
+ });
67
+ }
68
+
69
+ async copyDirectory(src, dest, config = {}) {
70
+ const items = await fs.readdir(src);
71
+
72
+ for (const item of items) {
73
+ const srcPath = path.join(src, item);
74
+ const destPath = path.join(dest, item);
75
+ const stat = await fs.stat(srcPath);
76
+
77
+ if (stat.isDirectory()) {
78
+ await fs.ensureDir(destPath);
79
+ await this.copyDirectory(srcPath, destPath, config);
80
+ } else {
81
+ if (this.shouldProcessFile(item)) {
82
+ await this.processTemplate(srcPath, destPath, config);
83
+ } else {
84
+ await fs.copy(srcPath, destPath);
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ shouldProcessFile(filename) {
91
+ const processableExtensions = ['.hbs', '.handlebars', '.txt', '.js', '.ts', '.py', '.java', '.go', '.rs', '.php', '.html', '.md'];
92
+ return processableExtensions.some(ext => filename.endsWith(ext));
93
+ }
94
+
95
+ async processTemplate(srcPath, destPath, config) {
96
+ try {
97
+ const content = await fs.readFile(srcPath, 'utf8');
98
+ const template = Handlebars.compile(content);
99
+ const processed = template(config);
100
+
101
+ // Remove .hbs extension if present
102
+ const finalDestPath = destPath.endsWith('.hbs') ? destPath.slice(0, -4) : destPath;
103
+
104
+ await fs.writeFile(finalDestPath, processed);
105
+ } catch (error) {
106
+ // If template processing fails, copy the file as-is
107
+ await fs.copy(srcPath, destPath);
108
+ }
109
+ }
110
+
111
+ async writeFileWithTemplate(templatePath, destPath, config) {
112
+ if (await fs.pathExists(templatePath)) {
113
+ await this.processTemplate(templatePath, destPath, config);
114
+ } else {
115
+ throw new Error(`Template file not found: ${templatePath}`);
116
+ }
117
+ }
118
+
119
+ async ensureDir(dirPath) {
120
+ await fs.ensureDir(dirPath);
121
+ }
122
+
123
+ async copyFile(src, dest) {
124
+ await fs.copy(src, dest);
125
+ }
126
+
127
+ async writeFile(filePath, content) {
128
+ await fs.writeFile(filePath, content);
129
+ }
130
+
131
+ async readFile(filePath) {
132
+ return await fs.readFile(filePath, 'utf8');
133
+ }
134
+
135
+ async pathExists(filePath) {
136
+ return await fs.pathExists(filePath);
137
+ }
138
+
139
+ async readdir(dirPath) {
140
+ return await fs.readdir(dirPath);
141
+ }
142
+
143
+ async stat(filePath) {
144
+ return await fs.stat(filePath);
145
+ }
146
+
147
+ createDirectoryStructure(basePath, structure) {
148
+ return Promise.all(
149
+ Object.entries(structure).map(async ([path, content]) => {
150
+ const fullPath = this.resolvePath(basePath, path);
151
+
152
+ if (typeof content === 'object' && !Array.isArray(content)) {
153
+ await fs.ensureDir(fullPath);
154
+ return this.createDirectoryStructure(fullPath, content);
155
+ } else if (Array.isArray(content)) {
156
+ await fs.ensureDir(fullPath);
157
+ return Promise.all(
158
+ content.map(item => this.createDirectoryStructure(fullPath, item))
159
+ );
160
+ } else {
161
+ await fs.ensureDir(path.dirname(fullPath));
162
+ return fs.writeFile(fullPath, content || '');
163
+ }
164
+ })
165
+ );
166
+ }
167
+
168
+ resolvePath(base, relativePath) {
169
+ return path.resolve(base, relativePath);
170
+ }
171
+
172
+ getFileExtension(filename) {
173
+ return path.extname(filename);
174
+ }
175
+
176
+ getFileName(filename) {
177
+ return path.basename(filename, path.extname(filename));
178
+ }
179
+
180
+ formatTemplate(template, data) {
181
+ const compiled = Handlebars.compile(template);
182
+ return compiled(data);
183
+ }
184
+ }
185
+
186
+ module.exports = FileManager;
@@ -0,0 +1,231 @@
1
+ // Common template files
2
+ exports.generateGitignore = function(config) {
3
+ const gitignoreContent = `
4
+ # Dependencies
5
+ node_modules/
6
+ __pycache__/
7
+ target/
8
+ build/
9
+ dist/
10
+ vendor/
11
+
12
+ # Environment variables
13
+ .env
14
+ .env.local
15
+ .env.development.local
16
+ .env.test.local
17
+ .env.production.local
18
+
19
+ # Logs
20
+ logs
21
+ *.log
22
+ npm-debug.log*
23
+ yarn-debug.log*
24
+ yarn-error.log*
25
+ lerna-debug.log*
26
+
27
+ # Runtime data
28
+ pids
29
+ *.pid
30
+ *.seed
31
+ *.pid.lock
32
+
33
+ # Coverage directory used by tools like istanbul
34
+ coverage/
35
+ *.lcov
36
+
37
+ # nyc test coverage
38
+ .nyc_output
39
+
40
+ # Dependency directories
41
+ node_modules/
42
+ jspm_packages/
43
+
44
+ # Optional npm cache directory
45
+ .npm
46
+
47
+ # Optional eslint cache
48
+ .eslintcache
49
+
50
+ # Optional REPL history
51
+ .node_repl_history
52
+
53
+ # Output of 'npm pack'
54
+ *.tgz
55
+
56
+ # Yarn Integrity file
57
+ .yarn-integrity
58
+
59
+ # dotenv environment variables file
60
+ .env
61
+ .env.test
62
+
63
+ # parcel-bundler cache (https://parceljs.org/)
64
+ .cache
65
+ .parcel-cache
66
+
67
+ # next.js build output
68
+ .next
69
+
70
+ # nuxt.js build output
71
+ .nuxt
72
+
73
+ # vuepress build output
74
+ .vuepress/dist
75
+
76
+ # Serverless directories
77
+ .serverless/
78
+
79
+ # FuseBox cache
80
+ .fusebox/
81
+
82
+ # DynamoDB Local files
83
+ .dynamodb/
84
+
85
+ # TernJS port file
86
+ .tern-port
87
+
88
+ # Stores VSCode versions used for testing VSCode extensions
89
+ .vscode-test
90
+
91
+ # IDE
92
+ .vscode/
93
+ .idea/
94
+ *.swp
95
+ *.swo
96
+
97
+ # OS
98
+ .DS_Store
99
+ Thumbs.db
100
+
101
+ # Database
102
+ *.db
103
+ *.sqlite
104
+ *.sqlite3
105
+
106
+ # Docker
107
+ .dockerignore
108
+
109
+ # Go
110
+ *.exe
111
+ *.exe~
112
+ *.dll
113
+ *.so
114
+ *.dylib
115
+ *.test
116
+ *.out
117
+
118
+ # Rust
119
+ /target/
120
+ **/*.rs.bk
121
+ Cargo.lock
122
+
123
+ # Python
124
+ __pycache__/
125
+ *.py[cod]
126
+ *$py.class
127
+ *.so
128
+ .Python
129
+ env/
130
+ venv/
131
+ ENV/
132
+ env.bak/
133
+ venv.bak/
134
+ .idea/
135
+ .vscode/
136
+
137
+ # Java
138
+ *.class
139
+ *.log
140
+ *.jar
141
+ *.war
142
+ *.ear
143
+ *.zip
144
+ *.tar.gz
145
+ *.rar
146
+
147
+ # IDE files
148
+ .metadata/
149
+ .recommenders/
150
+ .settings/
151
+ .loadpath
152
+ .factorypath
153
+ .project
154
+ .classpath
155
+ .c9/
156
+ .launch/
157
+ .settings/
158
+ .springBeans
159
+ .sts4-cache/
160
+
161
+ # Temporary files
162
+ *.tmp
163
+ *.temp
164
+ `;
165
+
166
+ return gitignoreContent;
167
+ };
168
+
169
+ exports.generateEnvExample = function(config) {
170
+ const commonEnv = `# Server Configuration
171
+ PORT=3000
172
+ NODE_ENV=development
173
+
174
+ # Database Configuration
175
+ DATABASE_URL=mongodb://localhost:27017/${config.projectName}
176
+ DB_NAME=${config.projectName}
177
+
178
+ # JWT Configuration
179
+ JWT_SECRET=your-super-secret-jwt-key
180
+ JWT_EXPIRES_IN=7d
181
+
182
+ # CORS Configuration
183
+ ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3001
184
+
185
+ # Logging
186
+ LOG_LEVEL=info
187
+
188
+ # External Services
189
+ REDIS_URL=redis://localhost:6379
190
+ SMTP_HOST=smtp.gmail.com
191
+ SMTP_PORT=587
192
+ SMTP_USER=your-email@gmail.com
193
+ SMTP_PASS=your-app-password
194
+
195
+ # File Upload
196
+ MAX_FILE_SIZE=10485760
197
+ UPLOAD_PATH=./uploads
198
+ `;
199
+
200
+ // Add technology-specific env variables
201
+ const techSpecific = {
202
+ python: `
203
+ # Python Specific
204
+ PYTHONPATH=.
205
+ DEBUG=True
206
+ CORS_ORIGINS=http://localhost:3000`,
207
+
208
+ java: `
209
+ # Java Specific
210
+ SPRING_PROFILES_ACTIVE=dev
211
+ SERVER_PORT=8080`,
212
+
213
+ go: `
214
+ # Go Specific
215
+ GIN_MODE=debug`,
216
+
217
+ rust: `
218
+ # Rust Specific
219
+ RUST_LOG=debug`,
220
+
221
+ php: `
222
+ # PHP Specific
223
+ APP_ENV=local
224
+ APP_DEBUG=true
225
+ APP_KEY=base64:your-app-key`
226
+ };
227
+
228
+ const specificEnv = techSpecific[config.technology] || '';
229
+
230
+ return commonEnv + specificEnv;
231
+ };