dolphin-server-modules 2.7.0 → 2.8.1
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 +2 -1
- package/dist/adapters/mongoose/index.js +1 -4
- package/dist/adapters/mongoose/index.js.map +1 -1
- package/dist/adapters/mongoose/index.test.js +2 -4
- package/dist/adapters/mongoose/index.test.js.map +1 -1
- package/dist/adapters/mongoose/integration.test.js +19 -54
- package/dist/adapters/mongoose/integration.test.js.map +1 -1
- package/dist/auth/auth.js +23 -29
- package/dist/auth/auth.js.map +1 -1
- package/dist/auth/auth.test.js +5 -10
- package/dist/auth/auth.test.js.map +1 -1
- package/dist/authController/authController.js +8 -48
- package/dist/authController/authController.js.map +1 -1
- package/dist/authController/authController.test.js +121 -123
- package/dist/authController/authController.test.js.map +1 -1
- package/dist/bin/cli.js +149 -596
- package/dist/bin/cli.js.map +1 -1
- package/dist/controller/controller.js +4 -11
- package/dist/controller/controller.js.map +1 -1
- package/dist/controller/controller.test.js +4 -6
- package/dist/controller/controller.test.js.map +1 -1
- package/dist/curd/crud.js +4 -11
- package/dist/curd/crud.js.map +1 -1
- package/dist/curd/crud.test.js +2 -4
- package/dist/curd/crud.test.js.map +1 -1
- package/dist/demo-server.js +21 -59
- package/dist/demo-server.js.map +1 -1
- package/dist/djson/djson.js +10 -22
- package/dist/djson/djson.js.map +1 -1
- package/dist/djson/djson.test.js +149 -184
- package/dist/djson/djson.test.js.map +1 -1
- package/dist/dolphin-bench.js +4 -9
- package/dist/dolphin-bench.js.map +1 -1
- package/dist/hard-performance-test.js +9 -14
- package/dist/hard-performance-test.js.map +1 -1
- package/dist/index.js +4 -20
- package/dist/index.js.map +1 -1
- package/dist/middleware/zod.js +9 -15
- package/dist/middleware/zod.js.map +1 -1
- package/dist/middleware/zod.test.js +12 -14
- package/dist/middleware/zod.test.js.map +1 -1
- package/dist/performance-test.js +9 -14
- package/dist/performance-test.js.map +1 -1
- package/dist/real-test-mongoose.js +17 -22
- package/dist/real-test-mongoose.js.map +1 -1
- package/dist/realtime/codec.js +3 -8
- package/dist/realtime/codec.js.map +1 -1
- package/dist/realtime/core.js +20 -64
- package/dist/realtime/core.js.map +1 -1
- package/dist/realtime/index.js +4 -20
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime/plugins.js +6 -12
- package/dist/realtime/plugins.js.map +1 -1
- package/dist/realtime/realtime.test.js +10 -45
- package/dist/realtime/realtime.test.js.map +1 -1
- package/dist/realtime/trie.js +1 -5
- package/dist/realtime/trie.js.map +1 -1
- package/dist/router/router.js +1 -4
- package/dist/router/router.js.map +1 -1
- package/dist/router/router.test.js +9 -11
- package/dist/router/router.test.js.map +1 -1
- package/dist/server/server.js +12 -18
- package/dist/server/server.js.map +1 -1
- package/dist/server/server.test.js +21 -26
- package/dist/server/server.test.js.map +1 -1
- package/dist/services/ai-service.d.ts +16 -0
- package/dist/services/ai-service.js +141 -0
- package/dist/services/ai-service.js.map +1 -0
- package/dist/signaling/index.js +4 -9
- package/dist/signaling/index.js.map +1 -1
- package/dist/signaling/signaling.test.js +13 -15
- package/dist/signaling/signaling.test.js.map +1 -1
- package/dist/swagger/swagger.js +3 -8
- package/dist/swagger/swagger.js.map +1 -1
- package/dist/swagger/swagger.test.js +10 -12
- package/dist/swagger/swagger.test.js.map +1 -1
- package/dist/templates/index.d.ts +9 -0
- package/dist/templates/index.js +112 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/test-2fa-real.js +6 -11
- package/dist/test-2fa-real.js.map +1 -1
- package/dist/test-dolphin.js +6 -8
- package/dist/test-dolphin.js.map +1 -1
- package/dist/utils/ui.d.ts +10 -0
- package/dist/utils/ui.js +36 -0
- package/dist/utils/ui.js.map +1 -0
- package/package.json +2 -1
- package/scripts/client.js +3 -1
package/dist/bin/cli.js
CHANGED
|
@@ -1,636 +1,189 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
-
};
|
|
39
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
const fs_1 = __importDefault(require("fs"));
|
|
41
|
-
const path_1 = __importDefault(require("path"));
|
|
42
|
-
const https_1 = __importDefault(require("https"));
|
|
43
|
-
const server_1 = require("../server/server");
|
|
44
|
-
const core_1 = require("../realtime/core");
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { createServer } from 'http';
|
|
5
|
+
import { AIService } from '../services/ai-service.js';
|
|
6
|
+
import { CLIUI } from '../utils/ui.js';
|
|
7
|
+
import { TEMPLATES } from '../templates/index.js';
|
|
45
8
|
const args = process.argv.slice(2);
|
|
46
|
-
const command = args[0];
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
export async function connectDB(models = {}) {
|
|
58
|
-
const uri = process.env.MONGO_URI || 'mongodb://localhost:27017/dolphin_db';
|
|
59
|
-
await mongoose.connect(uri);
|
|
60
|
-
console.log('✅ MongoDB Connected');
|
|
61
|
-
|
|
62
|
-
return createMongooseAdapter({
|
|
63
|
-
models: { ...models }
|
|
9
|
+
const command = args[0] || 'help';
|
|
10
|
+
// Simple .env loader
|
|
11
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
12
|
+
if (fs.existsSync(envPath)) {
|
|
13
|
+
const envContent = fs.readFileSync(envPath, 'utf8');
|
|
14
|
+
envContent.split('\n').forEach(line => {
|
|
15
|
+
const [key, ...valueParts] = line.split('=');
|
|
16
|
+
if (key && valueParts.length > 0) {
|
|
17
|
+
process.env[key.trim()] = valueParts.join('=').trim();
|
|
18
|
+
}
|
|
64
19
|
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
host: process.env.DB_HOST,
|
|
71
|
-
dialect: 'mysql' // or 'postgres', 'sqlite'
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
await sequelize.authenticate();
|
|
76
|
-
console.log('✅ SQL Database Connected');
|
|
77
|
-
} catch (error) {
|
|
78
|
-
console.error('❌ Unable to connect to the database:', error);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return sequelize;
|
|
82
|
-
}`,
|
|
83
|
-
auth: `import { createDolphinAuthController } from 'dolphin-server-modules/auth-controller';
|
|
84
|
-
import { createDolphinRouter } from 'dolphin-server-modules/router';
|
|
85
|
-
|
|
86
|
-
export function setupAuth(dbAdapter, config) {
|
|
87
|
-
const router = createDolphinRouter();
|
|
88
|
-
const auth = createDolphinAuthController(dbAdapter, config);
|
|
89
|
-
|
|
90
|
-
router.post('/register', auth.register);
|
|
91
|
-
router.post('/login', auth.login);
|
|
92
|
-
router.post('/refresh', auth.refresh);
|
|
93
|
-
router.get('/me', auth.requireAuth, (ctx) => ctx.json(ctx.req.user));
|
|
94
|
-
|
|
95
|
-
return router;
|
|
96
|
-
}`,
|
|
97
|
-
crud: (name) => `import { createCRUD } from 'dolphin-server-modules/crud';
|
|
98
|
-
|
|
99
|
-
export function setup${name}CRUD(dbAdapter) {
|
|
100
|
-
const service = createCRUD(dbAdapter, { enforceOwnership: false });
|
|
101
|
-
const COLLECTION = '${name}';
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
getAll: async (ctx) => ctx.json(await service.read(COLLECTION, ctx.query)),
|
|
105
|
-
getOne: async (ctx) => ctx.json(await service.readOne(COLLECTION, ctx.params.id)),
|
|
106
|
-
create: async (ctx) => ctx.json(await service.create(COLLECTION, ctx.body)),
|
|
107
|
-
update: async (ctx) => ctx.json(await service.updateOne(COLLECTION, ctx.params.id, ctx.body)),
|
|
108
|
-
delete: async (ctx) => ctx.json(await service.deleteOne(COLLECTION, ctx.params.id))
|
|
109
|
-
};
|
|
110
|
-
}`,
|
|
111
|
-
authModel: `import mongoose from 'mongoose';
|
|
112
|
-
|
|
113
|
-
const UserSchema = new mongoose.Schema({
|
|
114
|
-
email: { type: String, required: true, unique: true },
|
|
115
|
-
password: { type: String, required: true },
|
|
116
|
-
name: { type: String },
|
|
117
|
-
role: { type: String, default: 'user' },
|
|
118
|
-
is2FAEnabled: { type: Boolean, default: false },
|
|
119
|
-
twoFASecret: { type: String },
|
|
120
|
-
recoveryCodes: [{ type: String }],
|
|
121
|
-
createdAt: { type: Date, default: Date.now }
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
const RefreshTokenSchema = new mongoose.Schema({
|
|
125
|
-
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
|
|
126
|
-
token: { type: String, required: true },
|
|
127
|
-
expiresAt: { type: Date, required: true },
|
|
128
|
-
createdAt: { type: Date, default: Date.now }
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
export const User = mongoose.model('User', UserSchema);
|
|
132
|
-
export const RefreshToken = mongoose.model('RefreshToken', RefreshTokenSchema);`
|
|
20
|
+
}
|
|
21
|
+
const aiConfig = {
|
|
22
|
+
apiKey: (process.env.DOLPHIN_AI_KEY || process.env.GEMINI_API_KEY || '').trim(),
|
|
23
|
+
baseUrl: process.env.DOLPHIN_AI_BASE_URL,
|
|
24
|
+
model: process.env.DOLPHIN_AI_MODEL
|
|
133
25
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const content = fs_1.default.readFileSync(envPath, 'utf8');
|
|
138
|
-
content.split(/\r?\n/).forEach(line => {
|
|
139
|
-
const trimmedLine = line.trim();
|
|
140
|
-
if (!trimmedLine || trimmedLine.startsWith('#'))
|
|
141
|
-
return;
|
|
142
|
-
const [key, ...valueParts] = trimmedLine.split('=');
|
|
143
|
-
if (key && valueParts.length > 0) {
|
|
144
|
-
const value = valueParts.join('=').trim().replace(/^["']|["']$/g, '');
|
|
145
|
-
process.env[key.trim()] = value;
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
26
|
+
if (!aiConfig.apiKey && ['generate', 'generate-full', 'chat'].includes(command)) {
|
|
27
|
+
CLIUI.error('API Key not found! Please set DOLPHIN_AI_KEY or GEMINI_API_KEY in your .env file.');
|
|
28
|
+
process.exit(1);
|
|
149
29
|
}
|
|
30
|
+
const ai = new AIService(aiConfig);
|
|
150
31
|
async function run() {
|
|
151
|
-
loadEnv();
|
|
152
32
|
switch (command) {
|
|
33
|
+
case 'serve':
|
|
34
|
+
const port = parseInt(args.find(arg => arg.startsWith('--port='))?.split('=')[1] || '3000');
|
|
35
|
+
CLIUI.heading(`Dolphin Dev Server starting on port ${port}`);
|
|
36
|
+
const server = createServer((req, res) => {
|
|
37
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
38
|
+
res.end('Dolphin Server is swimming!\n');
|
|
39
|
+
});
|
|
40
|
+
server.listen(port, () => {
|
|
41
|
+
CLIUI.success(`Server is live at http://localhost:${port}`);
|
|
42
|
+
});
|
|
43
|
+
break;
|
|
153
44
|
case 'generate':
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
45
|
+
const prompt = args.slice(1).join(' ');
|
|
46
|
+
if (!prompt)
|
|
47
|
+
return CLIUI.error('Usage: dolphin generate "your prompt"');
|
|
48
|
+
CLIUI.startSpinner('AI is generating code');
|
|
49
|
+
try {
|
|
50
|
+
const response = await ai.request(prompt, "Return ONLY raw JavaScript code. No markdown.");
|
|
51
|
+
const cleanCode = response.replace(/```javascript|```js|```/g, '').trim();
|
|
52
|
+
fs.writeFileSync(path.join(process.cwd(), 'ai-generated.js'), cleanCode);
|
|
53
|
+
CLIUI.stopSpinner(true, 'File generated: ai-generated.js');
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
CLIUI.stopSpinner(false, e.message);
|
|
165
57
|
}
|
|
166
|
-
const fallbackModels = ['gemini-flash-latest', 'gemini-2.0-flash', 'gemini-2.5-flash', 'gemini-pro-latest'];
|
|
167
|
-
const modelsToTry = [requestedModel, ...fallbackModels.filter(m => m !== requestedModel)];
|
|
168
|
-
const versions = ['v1beta', 'v1'];
|
|
169
|
-
const tryGenerate = (modelIndex, versionIndex) => {
|
|
170
|
-
if (modelIndex >= modelsToTry.length) {
|
|
171
|
-
console.log('❌ All AI models failed. Please ensure Generative Language API is enabled in Google AI Studio for your key.');
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (versionIndex >= versions.length) {
|
|
175
|
-
return tryGenerate(modelIndex + 1, 0);
|
|
176
|
-
}
|
|
177
|
-
const currentModel = modelsToTry[modelIndex];
|
|
178
|
-
const currentVersion = versions[versionIndex];
|
|
179
|
-
console.log(`🤖 AI (${currentModel} via ${currentVersion}) is swimming with Dolphin...`);
|
|
180
|
-
const aiData = JSON.stringify({
|
|
181
|
-
contents: [{ parts: [{ text: `Generate a production-ready Node.js file using dolphin-server-modules.
|
|
182
|
-
Rules:
|
|
183
|
-
1. Use ESM 'import' instead of 'require'.
|
|
184
|
-
2. Use 'const app = createDolphinServer();' from 'dolphin-server-modules/server'.
|
|
185
|
-
3. Use unified context '(ctx) => { ... }' instead of '(req, res)'.
|
|
186
|
-
4. Return objects directly for JSON response.
|
|
187
|
-
5. No markdown backticks, no explanations.
|
|
188
|
-
Context: ${prompt}. Return ONLY raw JS code.` }] }]
|
|
189
|
-
});
|
|
190
|
-
const options = {
|
|
191
|
-
hostname: 'generativelanguage.googleapis.com',
|
|
192
|
-
path: `/${currentVersion}/models/${currentModel}:generateContent?key=${encodeURIComponent(apiKey)}`,
|
|
193
|
-
method: 'POST',
|
|
194
|
-
headers: { 'Content-Type': 'application/json' }
|
|
195
|
-
};
|
|
196
|
-
const req = https_1.default.request(options, (res) => {
|
|
197
|
-
let body = '';
|
|
198
|
-
res.on('data', (d) => body += d);
|
|
199
|
-
res.on('end', () => {
|
|
200
|
-
try {
|
|
201
|
-
const json = JSON.parse(body);
|
|
202
|
-
if (json.error) {
|
|
203
|
-
console.log(`⚠️ ${currentModel} (${currentVersion}) unavailable. Error: ${json.error.status}. Trying next...`);
|
|
204
|
-
tryGenerate(modelIndex, versionIndex + 1);
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const rawCode = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
|
208
|
-
if (rawCode) {
|
|
209
|
-
const codeMatch = rawCode.match(/(\/\*[\s\S]*?\*\/|\/\/.*|[\s\S])*?(import|const|let|var|app|function)[\s\S]*/);
|
|
210
|
-
const code = (codeMatch ? codeMatch[0] : rawCode).replace(/```javascript|```js|```/g, '').trim();
|
|
211
|
-
fs_1.default.writeFileSync(path_1.default.join(process.cwd(), 'ai-generated-app.js'), code);
|
|
212
|
-
console.log(`✅ Success! Code generated using ${currentModel} in ai-generated-app.js`);
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
tryGenerate(modelIndex, versionIndex + 1);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
catch (e) {
|
|
219
|
-
tryGenerate(modelIndex, versionIndex + 1);
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
req.on('error', () => tryGenerate(modelIndex, versionIndex + 1));
|
|
224
|
-
req.write(aiData);
|
|
225
|
-
req.end();
|
|
226
|
-
};
|
|
227
|
-
tryGenerate(0, 0);
|
|
228
58
|
break;
|
|
229
59
|
case 'generate-full':
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
const currentModel = modelsToTry[modelIndex];
|
|
253
|
-
const currentVersion = versions[versionIndex];
|
|
254
|
-
console.log(`🤖 AI (${currentModel} via ${currentVersion}) is architecting...`);
|
|
255
|
-
const aiData = JSON.stringify({
|
|
256
|
-
contents: [{ parts: [{ text: `Generate a full production-ready modular Node.js project structure using dolphin-server-modules.
|
|
257
|
-
Rules:
|
|
258
|
-
1. Return ONLY a valid JSON object.
|
|
259
|
-
2. Keys are file paths (e.g., "routes/user.js", "models/User.js", "app.js").
|
|
260
|
-
3. Values are the file contents as strings.
|
|
261
|
-
4. Use ESM 'import'.
|
|
262
|
-
5. Use 'const app = createDolphinServer();' from 'dolphin-server-modules/server' to initialize the app.
|
|
263
|
-
6. Use 'createMongooseAdapter' from 'dolphin-server-modules/adapters/mongoose' for DB connectivity.
|
|
264
|
-
7. Use 'createDolphinAuthController' from 'dolphin-server-modules/auth-controller' for all authentication logic.
|
|
265
|
-
8. Use 'createCRUD' from 'dolphin-server-modules/crud' to generate standard API services.
|
|
266
|
-
9. Create REAL Mongoose schemas in the models/ folder and export them to be used by the adapter.
|
|
267
|
-
10. Use Dolphin unified context '(ctx) => { ... }' for all route handlers.
|
|
268
|
-
11. Return objects directly for JSON response (e.g., return { success: true, data }).
|
|
269
|
-
12. Include folders: models, controllers, routes, middleware, config, services.
|
|
270
|
-
13. Ensure 'app.js' connects everything: DB -> Adapter -> Auth/CRUD -> Router -> Server.
|
|
271
|
-
Context: ${fullPrompt}.
|
|
272
|
-
Return ONLY the JSON. No markdown backticks, no text before or after.` }] }]
|
|
273
|
-
});
|
|
274
|
-
const options = {
|
|
275
|
-
hostname: 'generativelanguage.googleapis.com',
|
|
276
|
-
path: `/${currentVersion}/models/${currentModel}:generateContent?key=${encodeURIComponent(fullApiKey)}`,
|
|
277
|
-
method: 'POST',
|
|
278
|
-
headers: { 'Content-Type': 'application/json' }
|
|
279
|
-
};
|
|
280
|
-
const req = https_1.default.request(options, (res) => {
|
|
281
|
-
let body = '';
|
|
282
|
-
res.on('data', (d) => body += d);
|
|
283
|
-
res.on('end', () => {
|
|
284
|
-
try {
|
|
285
|
-
const json = JSON.parse(body);
|
|
286
|
-
if (json.error) {
|
|
287
|
-
console.log(`⚠️ ${currentModel} (${currentVersion}) error: ${json.error.message}. Trying next...`);
|
|
288
|
-
return tryGenerateFull(modelIndex, versionIndex + 1);
|
|
289
|
-
}
|
|
290
|
-
const rawJson = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
|
291
|
-
const cleanJson = rawJson.replace(/```json|```/g, '').trim();
|
|
292
|
-
const jsonMatch = cleanJson.match(/\{[\s\S]*\}/);
|
|
293
|
-
if (jsonMatch) {
|
|
294
|
-
try {
|
|
295
|
-
const files = JSON.parse(jsonMatch[0]);
|
|
296
|
-
Object.keys(files).forEach(filePath => {
|
|
297
|
-
const fullPath = path_1.default.join(process.cwd(), filePath);
|
|
298
|
-
const dirPath = path_1.default.dirname(fullPath);
|
|
299
|
-
if (!fs_1.default.existsSync(dirPath)) {
|
|
300
|
-
fs_1.default.mkdirSync(dirPath, { recursive: true });
|
|
301
|
-
}
|
|
302
|
-
fs_1.default.writeFileSync(fullPath, files[filePath]);
|
|
303
|
-
console.log(`📄 Generated: ${filePath}`);
|
|
304
|
-
});
|
|
305
|
-
console.log('✅ Full project architected successfully! 🐬');
|
|
306
|
-
}
|
|
307
|
-
catch (e) {
|
|
308
|
-
console.log('❌ Error parsing project JSON. Trying next model...');
|
|
309
|
-
tryGenerateFull(modelIndex, versionIndex + 1);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
else {
|
|
313
|
-
console.log('❌ AI failed to return valid JSON. Trying next model...');
|
|
314
|
-
tryGenerateFull(modelIndex, versionIndex + 1);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
catch (e) {
|
|
318
|
-
console.log('❌ Unexpected error. Trying next model...');
|
|
319
|
-
tryGenerateFull(modelIndex, versionIndex + 1);
|
|
320
|
-
}
|
|
321
|
-
});
|
|
60
|
+
const fullPrompt = args.slice(1).join(' ');
|
|
61
|
+
if (!fullPrompt)
|
|
62
|
+
return CLIUI.error('Usage: dolphin generate-full "project description"');
|
|
63
|
+
CLIUI.startSpinner('Architecting full project structure');
|
|
64
|
+
try {
|
|
65
|
+
const systemPrompt = `You are a Dolphin Framework expert. Generate a production-ready backend project.
|
|
66
|
+
Dolphin Patterns:
|
|
67
|
+
- controllers/ (Logic)
|
|
68
|
+
- models/ (Schemas: can be Mongoose or Sequelize)
|
|
69
|
+
- config/db.js (DB connection logic)
|
|
70
|
+
- .env (Environment variables)
|
|
71
|
+
Dolphin supports both Mongoose (MongoDB) and Sequelize (MySQL/PostgreSQL).
|
|
72
|
+
Choose the appropriate adapter based on the user's request.
|
|
73
|
+
Return ONLY a JSON object where keys are file paths and values are code content. No markdown.`;
|
|
74
|
+
const response = await ai.request(fullPrompt, systemPrompt);
|
|
75
|
+
const files = JSON.parse(response.replace(/```json|```/g, '').trim());
|
|
76
|
+
Object.entries(files).forEach(([fPath, content]) => {
|
|
77
|
+
const fullPath = path.join(process.cwd(), fPath);
|
|
78
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
79
|
+
fs.writeFileSync(fullPath, content);
|
|
80
|
+
console.log(` 📄 Created: ${fPath}`);
|
|
322
81
|
});
|
|
323
|
-
|
|
324
|
-
req.write(aiData);
|
|
325
|
-
req.end();
|
|
326
|
-
};
|
|
327
|
-
tryGenerateFull(0, 0);
|
|
328
|
-
break;
|
|
329
|
-
case 'modify':
|
|
330
|
-
const fileToModify = args[1];
|
|
331
|
-
const modifyPrompt = args.slice(2).join(' ');
|
|
332
|
-
const modifyApiKey = (process.env.GEMINI_API_KEY || '').trim();
|
|
333
|
-
if (!modifyApiKey || !fileToModify || !modifyPrompt) {
|
|
334
|
-
console.log('❌ Usage: dolphin modify <filename> "your instructions"');
|
|
335
|
-
break;
|
|
82
|
+
CLIUI.stopSpinner(true, 'Project architected successfully!');
|
|
336
83
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
console.log(`❌ File not found: ${fileToModify}`);
|
|
340
|
-
break;
|
|
84
|
+
catch (e) {
|
|
85
|
+
CLIUI.stopSpinner(false, e.message);
|
|
341
86
|
}
|
|
342
|
-
const currentCode = fs_1.default.readFileSync(filePath, 'utf8');
|
|
343
|
-
console.log(`🛠️ Modifying ${fileToModify}...`);
|
|
344
|
-
const tryModify = (modelIndex, versionIndex) => {
|
|
345
|
-
const models = ['gemini-1.5-flash-latest', 'gemini-flash-latest', 'gemini-1.5-pro-latest'];
|
|
346
|
-
const versions = ['v1beta', 'v1'];
|
|
347
|
-
if (modelIndex >= models.length) {
|
|
348
|
-
console.log('❌ Modification failed after trying all models.');
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
if (versionIndex >= versions.length) {
|
|
352
|
-
return tryModify(modelIndex + 1, 0);
|
|
353
|
-
}
|
|
354
|
-
const model = models[modelIndex];
|
|
355
|
-
const version = versions[versionIndex];
|
|
356
|
-
const aiData = JSON.stringify({
|
|
357
|
-
contents: [{ parts: [{ text: `You are an expert Dolphin Framework developer.
|
|
358
|
-
Task: Modify the following code based on the instructions.
|
|
359
|
-
Instructions: ${modifyPrompt}
|
|
360
|
-
Current Code:
|
|
361
|
-
${currentCode}
|
|
362
|
-
|
|
363
|
-
Rules:
|
|
364
|
-
1. Return ONLY the updated code.
|
|
365
|
-
2. No markdown, no explanations.
|
|
366
|
-
3. Maintain Dolphin Framework standards (ctx usage, createDolphinServer, etc.).` }] }]
|
|
367
|
-
});
|
|
368
|
-
const options = {
|
|
369
|
-
hostname: 'generativelanguage.googleapis.com',
|
|
370
|
-
path: `/${version}/models/${model}:generateContent?key=${encodeURIComponent(modifyApiKey)}`,
|
|
371
|
-
method: 'POST',
|
|
372
|
-
headers: { 'Content-Type': 'application/json' }
|
|
373
|
-
};
|
|
374
|
-
const req = https_1.default.request(options, (res) => {
|
|
375
|
-
let body = '';
|
|
376
|
-
res.on('data', (d) => body += d);
|
|
377
|
-
res.on('end', () => {
|
|
378
|
-
try {
|
|
379
|
-
const json = JSON.parse(body);
|
|
380
|
-
if (json.error) {
|
|
381
|
-
return tryModify(modelIndex, versionIndex + 1);
|
|
382
|
-
}
|
|
383
|
-
const rawCode = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
|
384
|
-
if (rawCode) {
|
|
385
|
-
const newCode = rawCode.replace(/```javascript|```js|```/g, '').trim();
|
|
386
|
-
fs_1.default.writeFileSync(filePath, newCode);
|
|
387
|
-
console.log(`✅ ${fileToModify} updated successfully!`);
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
tryModify(modelIndex, versionIndex + 1);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
catch (e) {
|
|
394
|
-
tryModify(modelIndex, versionIndex + 1);
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
});
|
|
398
|
-
req.on('error', () => tryModify(modelIndex, versionIndex + 1));
|
|
399
|
-
req.write(aiData);
|
|
400
|
-
req.end();
|
|
401
|
-
};
|
|
402
|
-
tryModify(0, 0);
|
|
403
87
|
break;
|
|
404
88
|
case 'chat':
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
89
|
+
CLIUI.heading('Dolphin Agentic AI Chat');
|
|
90
|
+
const readline = await import('readline');
|
|
91
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
92
|
+
const ask = () => {
|
|
93
|
+
rl.question('💬 You: ', async (input) => {
|
|
94
|
+
if (input.toLowerCase() === 'exit')
|
|
95
|
+
return rl.close();
|
|
96
|
+
CLIUI.startSpinner('Thinking');
|
|
97
|
+
try {
|
|
98
|
+
const reply = await ai.request(input, "You are a helpful Dolphin Framework AI Agent.");
|
|
99
|
+
CLIUI.stopSpinner(true, 'Dolphin Agent');
|
|
100
|
+
console.log(`🤖 ${reply}\n`);
|
|
101
|
+
ask();
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
CLIUI.stopSpinner(false, e.message);
|
|
105
|
+
ask();
|
|
106
|
+
}
|
|
417
107
|
});
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (input.toLowerCase() === 'exit')
|
|
421
|
-
return rl.close();
|
|
422
|
-
const systemPrompt = `You are the Dolphin Framework AI Agent.
|
|
423
|
-
You have access to the user's filesystem and shell.
|
|
424
|
-
If you need to create or modify a file, start your response with:
|
|
425
|
-
FILE_WRITE: <path>
|
|
426
|
-
<content>
|
|
427
|
-
END_FILE
|
|
428
|
-
|
|
429
|
-
If you need to run a command, start with:
|
|
430
|
-
SHELL_RUN: <command>
|
|
431
|
-
|
|
432
|
-
Current working directory: ${process.cwd()}
|
|
433
|
-
Always use Dolphin Framework standards.`;
|
|
434
|
-
const aiData = JSON.stringify({
|
|
435
|
-
contents: [{ parts: [{ text: systemPrompt + "\nUser: " + input }] }]
|
|
436
|
-
});
|
|
437
|
-
const options = {
|
|
438
|
-
hostname: 'generativelanguage.googleapis.com',
|
|
439
|
-
path: `/v1beta/models/gemini-1.5-flash-latest:generateContent?key=${encodeURIComponent(agentApiKey)}`,
|
|
440
|
-
method: 'POST',
|
|
441
|
-
headers: { 'Content-Type': 'application/json' }
|
|
442
|
-
};
|
|
443
|
-
const req = https_1.default.request(options, (res) => {
|
|
444
|
-
let body = '';
|
|
445
|
-
res.on('data', (d) => body += d);
|
|
446
|
-
res.on('end', () => {
|
|
447
|
-
try {
|
|
448
|
-
const json = JSON.parse(body);
|
|
449
|
-
const reply = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
|
450
|
-
// Handle FILE_WRITE
|
|
451
|
-
if (reply.includes('FILE_WRITE:')) {
|
|
452
|
-
const match = reply.match(/FILE_WRITE: (.*?)\n([\s\S]*?)END_FILE/);
|
|
453
|
-
if (match) {
|
|
454
|
-
const fPath = match[1].trim();
|
|
455
|
-
const content = match[2].trim().replace(/```javascript|```js|```/g, '');
|
|
456
|
-
const fullPath = path_1.default.join(process.cwd(), fPath);
|
|
457
|
-
const dir = path_1.default.dirname(fullPath);
|
|
458
|
-
if (!fs_1.default.existsSync(dir))
|
|
459
|
-
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
460
|
-
fs_1.default.writeFileSync(fullPath, content);
|
|
461
|
-
console.log(`🤖 Dolphin Agent: Created/Updated file [${fPath}]`);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
// Handle SHELL_RUN
|
|
465
|
-
if (reply.includes('SHELL_RUN:')) {
|
|
466
|
-
const cmdMatch = reply.match(/SHELL_RUN: (.*)/);
|
|
467
|
-
if (cmdMatch) {
|
|
468
|
-
const cmd = cmdMatch[1].trim();
|
|
469
|
-
console.log(`🤖 Dolphin Agent wants to run: [${cmd}]`);
|
|
470
|
-
// For safety, we just log it or we could use execSync
|
|
471
|
-
// execSync(cmd, { stdio: 'inherit' });
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
console.log(`🤖 Dolphin: ${reply.split('FILE_WRITE:')[0].split('SHELL_RUN:')[0].trim()}\n`);
|
|
475
|
-
ask();
|
|
476
|
-
}
|
|
477
|
-
catch (e) {
|
|
478
|
-
console.log('❌ Error parsing AI response.');
|
|
479
|
-
ask();
|
|
480
|
-
}
|
|
481
|
-
});
|
|
482
|
-
});
|
|
483
|
-
req.write(aiData);
|
|
484
|
-
req.end();
|
|
485
|
-
});
|
|
486
|
-
};
|
|
487
|
-
ask();
|
|
488
|
-
});
|
|
489
|
-
break;
|
|
490
|
-
case 'clean':
|
|
491
|
-
const filesToClean = ['ai-generated-app.js', 'ai-test-output.js'];
|
|
492
|
-
filesToClean.forEach(file => {
|
|
493
|
-
const filePath = path_1.default.join(process.cwd(), file);
|
|
494
|
-
if (fs_1.default.existsSync(filePath)) {
|
|
495
|
-
fs_1.default.unlinkSync(filePath);
|
|
496
|
-
console.log(`🗑️ Deleted: ${file}`);
|
|
497
|
-
}
|
|
498
|
-
});
|
|
499
|
-
console.log('✅ Cleanup complete.');
|
|
500
|
-
break;
|
|
501
|
-
case 'serve':
|
|
502
|
-
let portStr = args.find(arg => arg.startsWith('--port='))?.split('=')[1];
|
|
503
|
-
if (!portStr) {
|
|
504
|
-
const portIdx = args.indexOf('--port');
|
|
505
|
-
if (portIdx !== -1 && args[portIdx + 1])
|
|
506
|
-
portStr = args[portIdx + 1];
|
|
507
|
-
}
|
|
508
|
-
const port = parseInt(portStr || '3000');
|
|
509
|
-
const rt = new core_1.RealtimeCore({ debug: true });
|
|
510
|
-
const server = (0, server_1.createDolphinServer)({ realtime: rt });
|
|
511
|
-
server.get('/', (ctx) => ctx.html('<h1>Dolphin CLI Static Server</h1>'));
|
|
512
|
-
server.listen(port, () => console.log(`✅ Dolphin Server running at http://localhost:${port}`));
|
|
108
|
+
};
|
|
109
|
+
ask();
|
|
513
110
|
break;
|
|
514
111
|
case 'init':
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
"mongoose": "^8.0.0",
|
|
526
|
-
"zod": "^3.22.0"
|
|
527
|
-
}
|
|
528
|
-
}, null, 2));
|
|
529
|
-
console.log('✅ Created package.json with core dependencies.');
|
|
530
|
-
}
|
|
531
|
-
else {
|
|
532
|
-
console.log('⚠️ package.json already exists. Skipping...');
|
|
533
|
-
}
|
|
534
|
-
if (!fs_1.default.existsSync(path_1.default.join(process.cwd(), '.gitignore'))) {
|
|
535
|
-
fs_1.default.writeFileSync(path_1.default.join(process.cwd(), '.gitignore'), '.env\nnode_modules\ndist\n.DS_Store');
|
|
536
|
-
console.log('✅ Created .gitignore');
|
|
537
|
-
}
|
|
112
|
+
case 'init-prod':
|
|
113
|
+
CLIUI.heading('Scaffolding Production Project');
|
|
114
|
+
const dirs = ['models', 'controllers', 'routes', 'middleware', 'services', 'config'];
|
|
115
|
+
dirs.forEach(dir => {
|
|
116
|
+
const p = path.join(process.cwd(), dir);
|
|
117
|
+
if (!fs.existsSync(p))
|
|
118
|
+
fs.mkdirSync(p, { recursive: true });
|
|
119
|
+
});
|
|
120
|
+
fs.writeFileSync(path.join(process.cwd(), 'app.js'), TEMPLATES.app);
|
|
121
|
+
CLIUI.success('Folders and app.js created.');
|
|
538
122
|
break;
|
|
539
123
|
case 'add':
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
if (
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
console.log('✅ Added Sequelize (SQL) Adapter template to db-sql.js');
|
|
124
|
+
const subCommand = args[1];
|
|
125
|
+
if (subCommand === 'adapter') {
|
|
126
|
+
const type = args[2];
|
|
127
|
+
if (type === 'mongoose') {
|
|
128
|
+
const configDir = path.join(process.cwd(), 'config');
|
|
129
|
+
if (!fs.existsSync(configDir))
|
|
130
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
131
|
+
fs.writeFileSync(path.join(configDir, 'db.js'), TEMPLATES.mongoose);
|
|
132
|
+
CLIUI.success('Mongoose adapter added to config/db.js');
|
|
550
133
|
}
|
|
551
134
|
else {
|
|
552
|
-
|
|
135
|
+
CLIUI.error('Unsupported adapter. Try: dolphin add adapter mongoose');
|
|
553
136
|
}
|
|
554
137
|
}
|
|
555
|
-
else if (
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
138
|
+
else if (subCommand === 'auth') {
|
|
139
|
+
const controllerDir = path.join(process.cwd(), 'controllers');
|
|
140
|
+
const modelDir = path.join(process.cwd(), 'models');
|
|
141
|
+
if (!fs.existsSync(controllerDir))
|
|
142
|
+
fs.mkdirSync(controllerDir, { recursive: true });
|
|
143
|
+
if (!fs.existsSync(modelDir))
|
|
144
|
+
fs.mkdirSync(modelDir, { recursive: true });
|
|
145
|
+
fs.writeFileSync(path.join(controllerDir, 'auth.js'), TEMPLATES.auth);
|
|
146
|
+
fs.writeFileSync(path.join(modelDir, 'User.js'), TEMPLATES.authModel);
|
|
147
|
+
CLIUI.success('Auth controller and User model added.');
|
|
148
|
+
}
|
|
149
|
+
else if (subCommand === 'crud') {
|
|
150
|
+
const name = args[2];
|
|
151
|
+
if (!name)
|
|
152
|
+
return CLIUI.error('Usage: dolphin add crud <ModelName>');
|
|
153
|
+
const controllerDir = path.join(process.cwd(), 'controllers');
|
|
154
|
+
const modelDir = path.join(process.cwd(), 'models');
|
|
155
|
+
if (!fs.existsSync(controllerDir))
|
|
156
|
+
fs.mkdirSync(controllerDir, { recursive: true });
|
|
157
|
+
if (!fs.existsSync(modelDir))
|
|
158
|
+
fs.mkdirSync(modelDir, { recursive: true });
|
|
159
|
+
fs.writeFileSync(path.join(controllerDir, `${name.toLowerCase()}.js`), TEMPLATES.crud(name));
|
|
160
|
+
fs.writeFileSync(path.join(modelDir, `${name}.js`), TEMPLATES.crudModel(name));
|
|
161
|
+
CLIUI.success(`CRUD Controller and Model for ${name} generated successfully!`);
|
|
162
|
+
console.log(` 📄 Created: controllers/${name.toLowerCase()}.js`);
|
|
163
|
+
console.log(` 📄 Created: models/${name}.js`);
|
|
563
164
|
}
|
|
564
165
|
else {
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
break;
|
|
568
|
-
case 'mongo-auth-model':
|
|
569
|
-
const modelsDir = path_1.default.join(process.cwd(), 'models');
|
|
570
|
-
if (!fs_1.default.existsSync(modelsDir)) {
|
|
571
|
-
fs_1.default.mkdirSync(modelsDir);
|
|
572
|
-
}
|
|
573
|
-
fs_1.default.writeFileSync(path_1.default.join(modelsDir, 'auth-models.js'), TEMPLATES.authModel);
|
|
574
|
-
console.log('✅ Generated fixed Auth models (User, RefreshToken) in models/auth-models.js');
|
|
575
|
-
break;
|
|
576
|
-
case 'init-prod':
|
|
577
|
-
console.log('🚀 Scaffolding Production-Ready Dolphin Project...');
|
|
578
|
-
const dirs = ['models', 'controllers', 'routes', 'middleware', 'services', 'config'];
|
|
579
|
-
dirs.forEach(dir => {
|
|
580
|
-
const dirPath = path_1.default.join(process.cwd(), dir);
|
|
581
|
-
if (!fs_1.default.existsSync(dirPath)) {
|
|
582
|
-
fs_1.default.mkdirSync(dirPath);
|
|
583
|
-
console.log(`📁 Created: /${dir}`);
|
|
584
|
-
}
|
|
585
|
-
});
|
|
586
|
-
// Create basic files in the structure
|
|
587
|
-
fs_1.default.writeFileSync(path_1.default.join(process.cwd(), 'app.js'), TEMPLATES.app);
|
|
588
|
-
fs_1.default.writeFileSync(path_1.default.join(process.cwd(), 'config', 'db.js'), TEMPLATES.mongoose);
|
|
589
|
-
if (!fs_1.default.existsSync(path_1.default.join(process.cwd(), 'package.json'))) {
|
|
590
|
-
fs_1.default.writeFileSync(path_1.default.join(process.cwd(), 'package.json'), JSON.stringify({
|
|
591
|
-
name: path_1.default.basename(process.cwd()),
|
|
592
|
-
version: '1.0.0',
|
|
593
|
-
main: 'app.js',
|
|
594
|
-
type: 'module',
|
|
595
|
-
dependencies: {
|
|
596
|
-
"dolphin-server-modules": "^2.2.4",
|
|
597
|
-
"mongoose": "^8.0.0",
|
|
598
|
-
"zod": "^3.22.0"
|
|
599
|
-
}
|
|
600
|
-
}, null, 2));
|
|
601
|
-
}
|
|
602
|
-
if (!fs_1.default.existsSync(path_1.default.join(process.cwd(), '.gitignore'))) {
|
|
603
|
-
fs_1.default.writeFileSync(path_1.default.join(process.cwd(), '.gitignore'), '.env\nnode_modules\ndist\n.DS_Store');
|
|
604
|
-
console.log('✅ Created .gitignore');
|
|
166
|
+
CLIUI.error('Usage: dolphin add <adapter|auth|crud>');
|
|
605
167
|
}
|
|
606
|
-
console.log('✅ Production scaffolding complete. Start swimming! 🐬');
|
|
607
168
|
break;
|
|
608
169
|
case 'help':
|
|
609
170
|
default:
|
|
171
|
+
CLIUI.heading('Dolphin Framework CLI');
|
|
610
172
|
console.log(`
|
|
611
|
-
🐬 Dolphin Framework CLI
|
|
612
173
|
Commands:
|
|
613
|
-
serve Start
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
add adapter <type> Add a database adapter (mongoose, sequelize)
|
|
622
|
-
add auth Add a pre-configured Auth controller
|
|
623
|
-
add crud <Name> Add a pre-configured CRUD controller
|
|
624
|
-
mongo-auth-model Generate fixed Mongoose models for Auth (User, RefreshToken)
|
|
625
|
-
generate "prompt" --model=gemini-1.5-pro (Custom AI model support)
|
|
626
|
-
|
|
627
|
-
Options:
|
|
628
|
-
--port=3000 Specify port for serve command
|
|
174
|
+
serve Start development server
|
|
175
|
+
generate <prompt> Quick AI code generation
|
|
176
|
+
generate-full <p> Full project architecture
|
|
177
|
+
chat Interactive AI coding assistant
|
|
178
|
+
init-prod Scaffold production folder structure
|
|
179
|
+
add adapter <t> Add Mongoose/Sequelize adapter
|
|
180
|
+
add auth Add pre-built Auth controller
|
|
181
|
+
add crud <Name> Add CRUD controller for a model
|
|
629
182
|
`);
|
|
630
183
|
break;
|
|
631
184
|
}
|
|
632
185
|
}
|
|
633
186
|
run().catch(err => {
|
|
634
|
-
|
|
187
|
+
CLIUI.error(err.message);
|
|
635
188
|
});
|
|
636
189
|
//# sourceMappingURL=cli.js.map
|