create-jerry 1.0.0 → 2.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.
- package/README.md +225 -55
- package/Templates/base/js/app.js +19 -0
- package/Templates/base/js/config/index.js +18 -0
- package/Templates/base/js/middlewares/error.middleware.js +8 -0
- package/Templates/base/js/routes/index.js +12 -0
- package/Templates/base/js/server.js +21 -0
- package/Templates/base/js/utils/asyncHandler.js +5 -0
- package/Templates/base/ts/app.ts +19 -0
- package/Templates/base/ts/config/index.ts +18 -0
- package/Templates/base/ts/middlewares/error.middleware.ts +15 -0
- package/Templates/base/ts/routes/index.ts +12 -0
- package/Templates/base/ts/server.ts +21 -0
- package/Templates/base/ts/tsconfig.json +18 -0
- package/Templates/base/ts/utils/asyncHandler.ts +5 -0
- package/Templates/db/mongodb/js/db.js +39 -0
- package/Templates/db/mongodb/ts/db.ts +50 -0
- package/Templates/db/mysql/js/db.js +58 -0
- package/Templates/db/mysql/ts/db.ts +72 -0
- package/Templates/modules/ai/js/ai.controller.js +30 -0
- package/Templates/modules/ai/js/ai.provider.js +32 -0
- package/Templates/modules/ai/js/ai.routes.js +8 -0
- package/Templates/modules/ai/js/ai.service.js +16 -0
- package/Templates/modules/ai/ts/ai.controller.ts +31 -0
- package/Templates/modules/ai/ts/ai.provider.ts +30 -0
- package/Templates/modules/ai/ts/ai.routes.ts +8 -0
- package/Templates/modules/ai/ts/ai.service.ts +16 -0
- package/Templates/modules/user/js/user.controller.js +46 -0
- package/Templates/modules/user/js/user.provider.js +25 -0
- package/Templates/modules/user/js/user.routes.js +12 -0
- package/Templates/modules/user/js/user.service.js +21 -0
- package/Templates/modules/user/ts/user.controller.ts +27 -0
- package/Templates/modules/user/ts/user.provider.ts +25 -0
- package/Templates/modules/user/ts/user.routes.ts +12 -0
- package/Templates/modules/user/ts/user.service.ts +21 -0
- package/fileCreator.js +140 -31
- package/folderCreator.js +15 -0
- package/index.js +85 -76
- package/installer.js +11 -13
- package/package.json +5 -3
- package/packageJsonCreator.js +45 -72
- package/plugins/ai.plugin.js +25 -0
- package/plugins/mongodb.plugin.js +15 -0
- package/plugins/mysql.plugin.js +15 -0
- package/plugins/pluginManager.js +18 -0
- package/Templates/db-mongo.js +0 -20
- package/Templates/db-sql.js +0 -35
- package/Templates/express.js +0 -35
- package/folderCreater.js +0 -34
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import mysql from 'mysql2/promise';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
|
|
4
|
+
dotenv.config();
|
|
5
|
+
|
|
6
|
+
const pool = mysql.createPool({
|
|
7
|
+
host: process.env.MYSQL_HOST,
|
|
8
|
+
user: process.env.MYSQL_USER,
|
|
9
|
+
password: process.env.MYSQL_PASSWORD,
|
|
10
|
+
database: process.env.MYSQL_DATABASE
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const connectDB = async (): Promise<void> => {
|
|
14
|
+
try {
|
|
15
|
+
await pool.getConnection();
|
|
16
|
+
console.log('MySQL connected');
|
|
17
|
+
} catch (err) {
|
|
18
|
+
console.error(err);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
interface User {
|
|
24
|
+
id?: number;
|
|
25
|
+
name: string;
|
|
26
|
+
email: string;
|
|
27
|
+
password: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// CRUD
|
|
31
|
+
|
|
32
|
+
export const getAllUsers = async (): Promise<User[]> => {
|
|
33
|
+
const [rows] = await pool.query('SELECT * FROM users');
|
|
34
|
+
return rows as User[];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const getUserById = async (
|
|
38
|
+
id: number
|
|
39
|
+
): Promise<User | undefined> => {
|
|
40
|
+
const [rows] = await pool.query(
|
|
41
|
+
'SELECT * FROM users WHERE id = ?',
|
|
42
|
+
[id]
|
|
43
|
+
);
|
|
44
|
+
return (rows as User[])[0];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const createUser = async (
|
|
48
|
+
data: User
|
|
49
|
+
): Promise<User | undefined> => {
|
|
50
|
+
const [result]: any = await pool.query(
|
|
51
|
+
'INSERT INTO users (name, email, password) VALUES (?, ?, ?)',
|
|
52
|
+
[data.name, data.email, data.password]
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return getUserById(result.insertId);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const updateUser = async (
|
|
59
|
+
id: number,
|
|
60
|
+
data: Partial<User>
|
|
61
|
+
): Promise<User | undefined> => {
|
|
62
|
+
await pool.query(
|
|
63
|
+
'UPDATE users SET name=?, email=?, password=? WHERE id=?',
|
|
64
|
+
[data.name, data.email, data.password, id]
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return getUserById(id);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const deleteUser = async (id: number): Promise<void> => {
|
|
71
|
+
await pool.query('DELETE FROM users WHERE id=?', [id]);
|
|
72
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { askAI } from './ai.service.js';
|
|
2
|
+
|
|
3
|
+
export const handleAIChat = async (req, res) => {
|
|
4
|
+
try {
|
|
5
|
+
const { prompt } = req.body;
|
|
6
|
+
|
|
7
|
+
if (!prompt) {
|
|
8
|
+
return res.status(400).json({
|
|
9
|
+
success: false,
|
|
10
|
+
message: 'Prompt is required'
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const response = await askAI(prompt);
|
|
15
|
+
|
|
16
|
+
res.status(200).json({
|
|
17
|
+
success: true,
|
|
18
|
+
data: response
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error(error);
|
|
23
|
+
|
|
24
|
+
res.status(500).json({
|
|
25
|
+
success: false,
|
|
26
|
+
message: 'AI request failed',
|
|
27
|
+
error: error.message
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
|
|
3
|
+
class AIProvider {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.client = null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
init() {
|
|
9
|
+
if (!process.env.OPENAI_API_KEY) {
|
|
10
|
+
throw new Error('OPENAI_API_KEY is missing in .env');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
this.client = new OpenAI({
|
|
14
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async chat(messages) {
|
|
19
|
+
if (!this.client) {
|
|
20
|
+
this.init();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const response = await this.client.chat.completions.create({
|
|
24
|
+
model: 'gpt-4o-mini',
|
|
25
|
+
messages
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return response.choices[0]?.message?.content || '';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default new AIProvider();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import aiProvider from './ai.provider.js';
|
|
2
|
+
|
|
3
|
+
export const askAI = async (userInput) => {
|
|
4
|
+
const messages = [
|
|
5
|
+
{
|
|
6
|
+
role: 'system',
|
|
7
|
+
content: 'You are a helpful backend AI assistant.'
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
role: 'user',
|
|
11
|
+
content: userInput
|
|
12
|
+
}
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
return await aiProvider.chat(messages);
|
|
16
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import { askAI } from './ai.service.js';
|
|
3
|
+
|
|
4
|
+
export const handleAIChat = async (req: Request, res: Response) => {
|
|
5
|
+
try {
|
|
6
|
+
const { prompt } = req.body;
|
|
7
|
+
|
|
8
|
+
if (!prompt) {
|
|
9
|
+
return res.status(400).json({
|
|
10
|
+
success: false,
|
|
11
|
+
message: 'Prompt is required'
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const response = await askAI(prompt);
|
|
16
|
+
|
|
17
|
+
res.status(200).json({
|
|
18
|
+
success: true,
|
|
19
|
+
data: response
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
} catch (error: any) {
|
|
23
|
+
console.error(error);
|
|
24
|
+
|
|
25
|
+
res.status(500).json({
|
|
26
|
+
success: false,
|
|
27
|
+
message: 'AI request failed',
|
|
28
|
+
error: error.message
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
|
|
3
|
+
class AIProvider {
|
|
4
|
+
private client: OpenAI | null = null;
|
|
5
|
+
|
|
6
|
+
private init() {
|
|
7
|
+
if (!process.env.OPENAI_API_KEY) {
|
|
8
|
+
throw new Error('OPENAI_API_KEY is missing in .env');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.client = new OpenAI({
|
|
12
|
+
apiKey: process.env.OPENAI_API_KEY
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async chat(messages: OpenAI.Chat.ChatCompletionMessageParam[]) {
|
|
17
|
+
if (!this.client) {
|
|
18
|
+
this.init();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const response = await this.client!.chat.completions.create({
|
|
22
|
+
model: 'gpt-4o-mini',
|
|
23
|
+
messages
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return response.choices[0]?.message?.content || '';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default new AIProvider();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import aiProvider from './ai.provider.js';
|
|
2
|
+
|
|
3
|
+
export const askAI = async (userInput: string): Promise<string> => {
|
|
4
|
+
const messages = [
|
|
5
|
+
{
|
|
6
|
+
role: 'system',
|
|
7
|
+
content: 'You are a helpful backend AI assistant.'
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
role: 'user',
|
|
11
|
+
content: userInput
|
|
12
|
+
}
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
return await aiProvider.chat(messages);
|
|
16
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as userService from './user.service.js';
|
|
2
|
+
|
|
3
|
+
export const getUsers = async (req, res) => {
|
|
4
|
+
try {
|
|
5
|
+
const users = await userService.getUsers();
|
|
6
|
+
res.json({ success: true, data: users });
|
|
7
|
+
} catch (err) {
|
|
8
|
+
res.status(500).json({ success: false, message: err.message });
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const getUser = async (req, res) => {
|
|
13
|
+
try {
|
|
14
|
+
const user = await userService.getUserById(req.params.id);
|
|
15
|
+
res.json({ success: true, data: user });
|
|
16
|
+
} catch (err) {
|
|
17
|
+
res.status(500).json({ success: false, message: err.message });
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const createUser = async (req, res) => {
|
|
22
|
+
try {
|
|
23
|
+
const user = await userService.createUser(req.body);
|
|
24
|
+
res.status(201).json({ success: true, data: user });
|
|
25
|
+
} catch (err) {
|
|
26
|
+
res.status(500).json({ success: false, message: err.message });
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const updateUser = async (req, res) => {
|
|
31
|
+
try {
|
|
32
|
+
const user = await userService.updateUser(req.params.id, req.body);
|
|
33
|
+
res.json({ success: true, data: user });
|
|
34
|
+
} catch (err) {
|
|
35
|
+
res.status(500).json({ success: false, message: err.message });
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const deleteUser = async (req, res) => {
|
|
40
|
+
try {
|
|
41
|
+
await userService.deleteUser(req.params.id);
|
|
42
|
+
res.json({ success: true, message: 'User deleted' });
|
|
43
|
+
} catch (err) {
|
|
44
|
+
res.status(500).json({ success: false, message: err.message });
|
|
45
|
+
}
|
|
46
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as db from '../../config/db.js';
|
|
2
|
+
|
|
3
|
+
class UserProvider {
|
|
4
|
+
async getAll() {
|
|
5
|
+
return await db.getAllUsers();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async getById(id) {
|
|
9
|
+
return await db.getUserById(id);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async create(data) {
|
|
13
|
+
return await db.createUser(data);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async update(id, data) {
|
|
17
|
+
return await db.updateUser(id, data);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async delete(id) {
|
|
21
|
+
return await db.deleteUser(id);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default new UserProvider();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import * as userController from './user.controller.js';
|
|
3
|
+
|
|
4
|
+
const router = express.Router();
|
|
5
|
+
|
|
6
|
+
router.get('/', userController.getUsers);
|
|
7
|
+
router.get('/:id', userController.getUser);
|
|
8
|
+
router.post('/', userController.createUser);
|
|
9
|
+
router.put('/:id', userController.updateUser);
|
|
10
|
+
router.delete('/:id', userController.deleteUser);
|
|
11
|
+
|
|
12
|
+
export default router;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import userProvider from './user.provider.js';
|
|
2
|
+
|
|
3
|
+
export const getUsers = async () => {
|
|
4
|
+
return await userProvider.getAll();
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const getUserById = async (id) => {
|
|
8
|
+
return await userProvider.getById(id);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const createUser = async (data) => {
|
|
12
|
+
return await userProvider.create(data);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const updateUser = async (id, data) => {
|
|
16
|
+
return await userProvider.update(id, data);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const deleteUser = async (id) => {
|
|
20
|
+
return await userProvider.delete(id);
|
|
21
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import * as userService from './user.service.js';
|
|
3
|
+
|
|
4
|
+
export const getUsers = async (req: Request, res: Response) => {
|
|
5
|
+
const users = await userService.getUsers();
|
|
6
|
+
res.json({ success: true, data: users });
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const getUser = async (req: Request, res: Response) => {
|
|
10
|
+
const user = await userService.getUserById(req.params.id);
|
|
11
|
+
res.json({ success: true, data: user });
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const createUser = async (req: Request, res: Response) => {
|
|
15
|
+
const user = await userService.createUser(req.body);
|
|
16
|
+
res.status(201).json({ success: true, data: user });
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const updateUser = async (req: Request, res: Response) => {
|
|
20
|
+
const user = await userService.updateUser(req.params.id, req.body);
|
|
21
|
+
res.json({ success: true, data: user });
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const deleteUser = async (req: Request, res: Response) => {
|
|
25
|
+
await userService.deleteUser(req.params.id);
|
|
26
|
+
res.json({ success: true });
|
|
27
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as db from '../../config/db.js';
|
|
2
|
+
|
|
3
|
+
class UserProvider {
|
|
4
|
+
async getAll() {
|
|
5
|
+
return await db.getAllUsers();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async getById(id: string) {
|
|
9
|
+
return await db.getUserById(id);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async create(data: any) {
|
|
13
|
+
return await db.createUser(data);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async update(id: string, data: any) {
|
|
17
|
+
return await db.updateUser(id, data);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async delete(id: string) {
|
|
21
|
+
return await db.deleteUser(id);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default new UserProvider();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import * as userController from './user.controller.js';
|
|
3
|
+
|
|
4
|
+
const router = express.Router();
|
|
5
|
+
|
|
6
|
+
router.get('/', userController.getUsers);
|
|
7
|
+
router.get('/:id', userController.getUser);
|
|
8
|
+
router.post('/', userController.createUser);
|
|
9
|
+
router.put('/:id', userController.updateUser);
|
|
10
|
+
router.delete('/:id', userController.deleteUser);
|
|
11
|
+
|
|
12
|
+
export default router;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import userProvider from './user.provider.js';
|
|
2
|
+
|
|
3
|
+
export const getUsers = async () => {
|
|
4
|
+
return await userProvider.getAll();
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const getUserById = async (id: string) => {
|
|
8
|
+
return await userProvider.getById(id);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const createUser = async (data: any) => {
|
|
12
|
+
return await userProvider.create(data);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const updateUser = async (id: string, data: any) => {
|
|
16
|
+
return await userProvider.update(id, data);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const deleteUser = async (id: string) => {
|
|
20
|
+
return await userProvider.delete(id);
|
|
21
|
+
};
|
package/fileCreator.js
CHANGED
|
@@ -1,49 +1,158 @@
|
|
|
1
|
-
import { fileURLToPath } from 'url';
|
|
2
1
|
import path from 'path';
|
|
3
|
-
import * as fs from '
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
4
5
|
|
|
5
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
7
|
const __dirname = path.dirname(__filename);
|
|
7
8
|
|
|
8
|
-
// Stable reference to your Templates folder in scaff/
|
|
9
9
|
const templateDir = path.join(__dirname, 'Templates');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if (!existsSync(templateDir)) {
|
|
12
|
+
throw new Error(`Templates folder missing at ${templateDir}`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// ---------------- HELPERS ----------------
|
|
16
|
+
|
|
17
|
+
const copyFile = async (src, dest) => {
|
|
18
|
+
const content = await fs.readFile(src);
|
|
19
|
+
await fs.mkdir(path.dirname(dest), { recursive: true });
|
|
20
|
+
await fs.writeFile(dest, content);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const copyDir = async (srcDir, destDir) => {
|
|
14
24
|
try {
|
|
15
|
-
await fs.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
const entries = await fs.readdir(srcDir, { withFileTypes: true });
|
|
26
|
+
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
const src = path.join(srcDir, entry.name);
|
|
29
|
+
const dest = path.join(destDir, entry.name);
|
|
30
|
+
|
|
31
|
+
if (entry.isDirectory()) {
|
|
32
|
+
await copyDir(src, dest);
|
|
33
|
+
} else {
|
|
34
|
+
await copyFile(src, dest);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
throw new Error(`Template missing or invalid: ${srcDir}`);
|
|
19
39
|
}
|
|
20
40
|
};
|
|
21
41
|
|
|
22
|
-
//
|
|
23
|
-
export const writeDbFiles = async (dbchoice) => {
|
|
24
|
-
const dbfile = dbchoice === 'MySQL' ? 'db-sql.js' : 'db-mongo.js';
|
|
25
|
-
const dbTemplatePath = path.join(templateDir, dbfile);
|
|
26
|
-
const targetPath = path.join(process.cwd(), 'src', 'models', 'db.js');
|
|
42
|
+
// ---------------- CORE ----------------
|
|
27
43
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
44
|
+
export const writeCoreFiles = async (langchoice) => {
|
|
45
|
+
const variant = langchoice.includes('Typescript') ? 'ts' : 'js';
|
|
46
|
+
|
|
47
|
+
const basePath = path.join(templateDir, 'base', variant);
|
|
48
|
+
|
|
49
|
+
// copy base project directly into src
|
|
50
|
+
await copyDir(
|
|
51
|
+
basePath,
|
|
52
|
+
path.join(process.cwd(), 'src')
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// tsconfig (only TS)
|
|
56
|
+
if (variant === 'ts') {
|
|
57
|
+
const tsconfigPath = path.join(basePath, 'tsconfig.json');
|
|
58
|
+
|
|
59
|
+
if (existsSync(tsconfigPath)) {
|
|
60
|
+
await copyFile(
|
|
61
|
+
tsconfigPath,
|
|
62
|
+
path.join(process.cwd(), 'tsconfig.json')
|
|
63
|
+
);
|
|
64
|
+
}
|
|
34
65
|
}
|
|
35
66
|
};
|
|
36
67
|
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
68
|
+
// ---------------- USER MODULE ----------------
|
|
69
|
+
|
|
70
|
+
export const writeUserModule = async (langchoice) => {
|
|
71
|
+
const variant = langchoice.includes('Typescript') ? 'ts' : 'js';
|
|
72
|
+
|
|
73
|
+
const src = path.join(templateDir, 'modules/user', variant);
|
|
74
|
+
const dest = path.join(process.cwd(), 'src/modules/user');
|
|
75
|
+
|
|
76
|
+
await copyDir(src, dest);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// ---------------- AI MODULE ----------------
|
|
80
|
+
|
|
81
|
+
export const writeAIModule = async (langchoice) => {
|
|
82
|
+
const variant = langchoice.includes('Typescript') ? 'ts' : 'js';
|
|
83
|
+
|
|
84
|
+
const src = path.join(templateDir, 'modules/ai', variant);
|
|
85
|
+
const dest = path.join(process.cwd(), 'src/modules/ai');
|
|
86
|
+
|
|
87
|
+
await copyDir(src, dest);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// ---------------- DB (LEGACY SAFE) ----------------
|
|
91
|
+
|
|
92
|
+
export const writeDbFiles = async (dbchoice, langchoice) => {
|
|
93
|
+
const variant = langchoice.includes('Typescript') ? 'ts' : 'js';
|
|
94
|
+
const db = dbchoice === 'MongoDB' ? 'mongodb' : 'mysql';
|
|
95
|
+
|
|
96
|
+
await copyDir(
|
|
97
|
+
path.join(templateDir, 'db', db, variant),
|
|
98
|
+
path.join(process.cwd(), 'src/config')
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// ---------------- ENV ----------------
|
|
103
|
+
|
|
104
|
+
export const writeEnvFile = async () => {
|
|
105
|
+
const content = `PORT=3000
|
|
106
|
+
|
|
107
|
+
# MongoDB
|
|
108
|
+
MONGO_URI=
|
|
109
|
+
|
|
110
|
+
# MySQL
|
|
111
|
+
MYSQL_HOST=
|
|
112
|
+
MYSQL_USER=
|
|
113
|
+
MYSQL_PASSWORD=
|
|
114
|
+
MYSQL_DATABASE=
|
|
115
|
+
|
|
116
|
+
# AI
|
|
117
|
+
OPENAI_API_KEY=
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
await fs.writeFile(path.join(process.cwd(), '.env'), content);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// ---------------- ROUTE INJECTION ----------------
|
|
124
|
+
|
|
125
|
+
export const injectRoutes = async (langchoice, injections = []) => {
|
|
126
|
+
const ext = langchoice.includes('Typescript') ? 'ts' : 'js';
|
|
127
|
+
|
|
128
|
+
const filePath = path.join(process.cwd(), `src/routes/index.${ext}`);
|
|
41
129
|
|
|
42
130
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error('❌ Failed to create app.js:', error);
|
|
131
|
+
await fs.stat(filePath);
|
|
132
|
+
} catch {
|
|
133
|
+
throw new Error(`Routes file not found: ${filePath}`);
|
|
48
134
|
}
|
|
49
|
-
|
|
135
|
+
|
|
136
|
+
let content = await fs.readFile(filePath, 'utf-8');
|
|
137
|
+
|
|
138
|
+
if (
|
|
139
|
+
!content.includes('// [IMPORT_ROUTES]') ||
|
|
140
|
+
!content.includes('// [USE_ROUTES]')
|
|
141
|
+
) {
|
|
142
|
+
throw new Error('Route placeholders missing in base template');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for (const inject of injections) {
|
|
146
|
+
content = content.replace(
|
|
147
|
+
'// [IMPORT_ROUTES]',
|
|
148
|
+
`${inject.import}\n// [IMPORT_ROUTES]`
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
content = content.replace(
|
|
152
|
+
'// [USE_ROUTES]',
|
|
153
|
+
`${inject.use}\n// [USE_ROUTES]`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
await fs.writeFile(filePath, content);
|
|
158
|
+
};
|
package/folderCreator.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
export const createProjectDir = (rawProjectName) => {
|
|
5
|
+
const projectDir = path.join(process.cwd(), rawProjectName);
|
|
6
|
+
|
|
7
|
+
if (fs.existsSync(projectDir)) {
|
|
8
|
+
throw new Error(`Folder "${rawProjectName}" already exists`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
fs.mkdirSync(projectDir);
|
|
12
|
+
console.log(`📁 Project root created: ${rawProjectName}`);
|
|
13
|
+
|
|
14
|
+
process.chdir(projectDir);
|
|
15
|
+
};
|