oneurai-cli 1.0.2

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/bin/index.js ADDED
@@ -0,0 +1,354 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import chalk from 'chalk';
5
+ import inquirer from 'inquirer';
6
+ import axios from 'axios';
7
+ import Conf from 'conf';
8
+ import ora from 'ora';
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+ import archiver from 'archiver';
12
+ import FormData from 'form-data';
13
+ import { execSync } from 'child_process'; // 👈 ضف هذا السطر
14
+ import { createRequire } from 'module'; // 👈 وهذا عشان نقرأ إصدارنا الحالي
15
+ const require = createRequire(import.meta.url);
16
+ const packageJson = require('../package.json'); // قراءة ملف package
17
+ import AdmZip from 'adm-zip';
18
+
19
+ const program = new Command();
20
+ const config = new Conf({ projectName: 'one-cli' });
21
+
22
+ const API_URL = 'https://oneurai.com/api';
23
+
24
+ // --- دالة مساعدة لجلب بيانات المستخدم ---
25
+ async function ensureUsername(token) {
26
+ let username = config.get('username');
27
+ if (username) return username;
28
+
29
+ try {
30
+ const response = await axios.get(`${API_URL}/user`, {
31
+ headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' }
32
+ });
33
+ username = response.data.username || response.data.name;
34
+ config.set('username', username);
35
+ return username;
36
+ } catch (error) {
37
+ return 'user';
38
+ }
39
+ }
40
+
41
+ program
42
+ .name('one')
43
+ .description('Oneurai CLI - Official Tool')
44
+ .version('1.0.0');
45
+
46
+ // --- HELLO ---
47
+ program
48
+ .command('hello')
49
+ .description('Check connection')
50
+ .action(async () => {
51
+ console.log(chalk.green.bold('Welcome to Oneurai CLI! 🚀'));
52
+ const token = config.get('auth_token');
53
+
54
+ if (!token) {
55
+ console.log(chalk.yellow('Not logged in. Run: one login'));
56
+ return;
57
+ }
58
+
59
+ const spinner = ora('Checking connection...').start();
60
+ try {
61
+ config.delete('username');
62
+ const username = await ensureUsername(token);
63
+ spinner.succeed(chalk.cyan(`Connected as: ${chalk.bold(username)} ✅`));
64
+ } catch (error) {
65
+ spinner.fail(chalk.red('Connection failed.'));
66
+ }
67
+ });
68
+
69
+ // --- LOGIN ---
70
+ program
71
+ .command('login')
72
+ .description('Authenticate')
73
+ .action(async () => {
74
+ console.log(chalk.blue.bold('🔐 Authenticate with Oneurai.com'));
75
+
76
+ const answers = await inquirer.prompt([
77
+ {
78
+ type: 'password',
79
+ name: 'token',
80
+ message: 'Paste your Access Token:',
81
+ validate: input => input.length > 5 || 'Invalid token.'
82
+ }
83
+ ]);
84
+
85
+ const spinner = ora('Verifying...').start();
86
+
87
+ try {
88
+ const response = await axios.get(`${API_URL}/user`, {
89
+ headers: {
90
+ 'Authorization': `Bearer ${answers.token}`,
91
+ 'Accept': 'application/json'
92
+ }
93
+ });
94
+
95
+ config.set('auth_token', answers.token);
96
+
97
+ const username = response.data.username || response.data.name;
98
+ config.set('username', username);
99
+
100
+ spinner.succeed(chalk.green(`Success! Logged in as ${chalk.bold(username)}`));
101
+
102
+ } catch (error) {
103
+ spinner.fail(chalk.red('Login failed.'));
104
+ }
105
+ });
106
+
107
+ // --- LOGOUT ---
108
+ program.command('logout').action(() => {
109
+ config.delete('auth_token');
110
+ config.delete('username');
111
+ console.log(chalk.green('Logged out.'));
112
+ });
113
+
114
+ // --- INIT (المعدل والمضمون) ---
115
+ program
116
+ .command('init')
117
+ .description('Create project')
118
+ .action(async () => {
119
+ const token = config.get('auth_token');
120
+ if (!token) return console.log(chalk.red('Please login first.'));
121
+
122
+ if (fs.existsSync('./oneurai.json')) {
123
+ return console.log(chalk.yellow('⚠️ oneurai.json already exists.'));
124
+ }
125
+
126
+ const username = await ensureUsername(token);
127
+
128
+ console.log(chalk.blue.bold('⚡ Create New Oneurai Project'));
129
+
130
+ const answers = await inquirer.prompt([
131
+ {
132
+ type: 'input',
133
+ name: 'title',
134
+ message: 'Project Title:',
135
+ validate: input => input.length > 2 || 'Min 2 chars.'
136
+ },
137
+ {
138
+ type: 'input',
139
+ name: 'slug',
140
+ message: 'Project Slug:',
141
+ default: (answers) => answers.title.toLowerCase().replace(/ /g, '-'),
142
+ validate: input => /^[a-z0-9-_]+$/.test(input) || 'Use letters, numbers, dashes.'
143
+ },
144
+ {
145
+ type: 'confirm',
146
+ name: 'is_public',
147
+ message: 'Is this project Public (Open Source)?',
148
+ default: true
149
+ }
150
+ ]);
151
+
152
+ const spinner = ora('Creating...').start();
153
+
154
+ try {
155
+ const response = await axios.post(`${API_URL}/projects/create`, {
156
+ title: answers.title,
157
+ slug: answers.slug,
158
+ is_public: answers.is_public
159
+ }, {
160
+ headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' }
161
+ });
162
+
163
+ const projectConfig = {
164
+ name: response.data.project.slug,
165
+ id: response.data.project.id,
166
+ created_at: new Date().toISOString(),
167
+ // ✅ تم إضافة oneurai.json للقائمة الافتراضية هنا
168
+ ignore: ['node_modules', '.git', '.env', 'storage', 'vendor', '*.zip', 'oneurai.json']
169
+ };
170
+
171
+ fs.writeFileSync('./oneurai.json', JSON.stringify(projectConfig, null, 2));
172
+
173
+ spinner.succeed(chalk.green(`Created: ${response.data.project.title}`));
174
+
175
+ console.log(chalk.cyan(`🔗 Link: https://oneurai.com/project/${username}/${response.data.project.slug}`));
176
+ console.log(chalk.gray('Run "one push" to deploy.'));
177
+
178
+ } catch (error) {
179
+ spinner.fail(chalk.red('Failed.'));
180
+ if (error.response && error.response.data.errors) {
181
+ console.error(chalk.red(JSON.stringify(error.response.data.errors)));
182
+ } else if (error.response) {
183
+ console.error(chalk.red(JSON.stringify(error.response.data)));
184
+ } else {
185
+ console.error(chalk.red(error.message));
186
+ }
187
+ }
188
+ });
189
+
190
+ // --- PUSH ---
191
+ program
192
+ .command('push')
193
+ .description('Deploy files')
194
+ .action(async () => {
195
+ const token = config.get('auth_token');
196
+ if (!token) return console.log(chalk.red('Please login first.'));
197
+
198
+ if (!fs.existsSync('./oneurai.json')) return console.log(chalk.red('Run: one init'));
199
+
200
+ const username = await ensureUsername(token);
201
+ const projectConfig = JSON.parse(fs.readFileSync('./oneurai.json', 'utf-8'));
202
+ console.log(chalk.blue.bold(`🚀 Deploying ${projectConfig.name}...`));
203
+
204
+ const spinner = ora('Compressing...').start();
205
+
206
+ const output = fs.createWriteStream('project.zip');
207
+ const archive = archiver('zip', { zlib: { level: 9 } });
208
+
209
+ output.on('close', async () => {
210
+ spinner.text = 'Uploading...';
211
+
212
+ try {
213
+ const form = new FormData();
214
+ form.append('project_name', projectConfig.name);
215
+ form.append('file', fs.createReadStream('project.zip'));
216
+
217
+ await axios.post(`${API_URL}/deploy`, form, {
218
+ headers: { ...form.getHeaders(), 'Authorization': `Bearer ${token}` },
219
+ maxContentLength: Infinity,
220
+ maxBodyLength: Infinity
221
+ });
222
+
223
+ fs.unlinkSync('project.zip');
224
+ spinner.succeed(chalk.green('Deployed successfully! ☁️'));
225
+
226
+ console.log(chalk.cyan(`\n🔗 View project: https://oneurai.com/project/${username}/${projectConfig.name}`));
227
+
228
+ } catch (error) {
229
+ if (fs.existsSync('project.zip')) fs.unlinkSync('project.zip');
230
+ spinner.fail(chalk.red('Deployment failed ❌'));
231
+ if(error.response) console.error(chalk.red(error.response.data.message));
232
+ }
233
+ });
234
+
235
+ archive.on('error', (err) => { throw err; });
236
+ archive.pipe(output);
237
+
238
+ // ✅ التعديل هنا: دمج قائمة التجاهل مع oneurai.json وإجبار استبعاده
239
+ const ignoreList = projectConfig.ignore || ['node_modules/**', '.git/**'];
240
+
241
+ // نضيف oneurai.json للقائمة إذا لم يكن موجوداً
242
+ if (!ignoreList.includes('oneurai.json')) {
243
+ ignoreList.push('oneurai.json');
244
+ }
245
+
246
+ archive.glob('**/*', {
247
+ cwd: process.cwd(),
248
+ ignore: ignoreList
249
+ });
250
+
251
+ archive.finalize();
252
+ });
253
+
254
+ program
255
+ .command('update')
256
+ .description('Update CLI to the latest version')
257
+ .action(async () => {
258
+ console.log(chalk.blue.bold('🔄 Checking for updates...'));
259
+ const spinner = ora('Contacting server...').start();
260
+
261
+ try {
262
+ // 1. جلب رقم الإصدار الأحدث من السيرفر
263
+ // تأكد أنك أنشأت الملف في سيرفرك في المسار public/cli/version.json
264
+ const response = await axios.get('https://oneurai.com/cli/version.json');
265
+ const latestVersion = response.data.version;
266
+ const currentVersion = packageJson.version;
267
+
268
+ if (latestVersion === currentVersion) {
269
+ spinner.succeed(chalk.green('You are already on the latest version! ✅'));
270
+ return;
271
+ }
272
+
273
+ spinner.info(chalk.yellow(`New version found: ${latestVersion} (Current: ${currentVersion})`));
274
+ spinner.start('Installing update...');
275
+
276
+ // 2. تنفيذ أمر التحديث السحري
277
+ // هذا الأمر يخلي npm يحمل الملف من سيرفرك ويثبته فوق النسخة الحالية
278
+ execSync('npm install -g https://oneurai.com/cli/one-latest.tgz', { stdio: 'inherit' });
279
+
280
+ spinner.succeed(chalk.green(`Successfully updated to v${latestVersion} 🚀`));
281
+ console.log(chalk.gray('Please restart your terminal to apply changes.'));
282
+
283
+ } catch (error) {
284
+ spinner.fail(chalk.red('Update failed.'));
285
+ if (error.response && error.response.status === 404) {
286
+ console.error(chalk.red('Update server not found (404). Check files on server.'));
287
+ } else {
288
+ console.error(chalk.red(error.message));
289
+ }
290
+ }
291
+ });
292
+
293
+ program
294
+ .command('get <slug>')
295
+ .description('Download (Clone) a project from Oneurai')
296
+ .action(async (slug) => {
297
+ const token = config.get('auth_token');
298
+ if (!token) return console.log(chalk.red('Please login first.'));
299
+
300
+ // التحقق هل المجلد موجود مسبقاً؟
301
+ if (fs.existsSync(slug)) {
302
+ return console.log(chalk.red(`❌ Directory "${slug}" already exists. Please delete it or choose another location.`));
303
+ }
304
+
305
+ const spinner = ora(`Fetching project "${slug}"...`).start();
306
+
307
+ try {
308
+ // 1. طلب الملف المضغوط
309
+ const response = await axios({
310
+ method: 'get',
311
+ url: `${API_URL}/projects/${slug}/download`,
312
+ headers: { Authorization: `Bearer ${token}` },
313
+ responseType: 'arraybuffer'
314
+ });
315
+
316
+ spinner.text = 'Unzipping files...';
317
+
318
+ // 2. إنشاء المجلد
319
+ fs.mkdirSync(slug);
320
+
321
+ // 3. حفظ الملف وفك الضغط
322
+ const zipPath = path.join(slug, 'temp_project.zip');
323
+ fs.writeFileSync(zipPath, response.data);
324
+
325
+ const zip = new AdmZip(zipPath);
326
+ zip.extractAllTo(slug, true);
327
+
328
+ // 4. تنظيف
329
+ fs.unlinkSync(zipPath);
330
+
331
+ // ✅ حذفنا كود إنشاء oneurai.json من هنا
332
+
333
+ spinner.succeed(chalk.green(`Successfully downloaded "${slug}"! 📦`));
334
+
335
+ // تعليمات واضحة للمستخدم
336
+ console.log(chalk.cyan(`\nNext steps:`));
337
+ console.log(chalk.white(` 1. cd ${slug}`));
338
+ console.log(chalk.white(` 2. one init (to link this folder)`)); // 👈 تذكير بالـ init
339
+
340
+ } catch (error) {
341
+ if (fs.existsSync(slug)) {
342
+ fs.rmSync(slug, { recursive: true, force: true });
343
+ }
344
+
345
+ spinner.fail(chalk.red('Download failed.'));
346
+
347
+ if (error.response && error.response.status === 404) {
348
+ console.error(chalk.red('❌ Project not found or access denied.'));
349
+ } else {
350
+ console.error(chalk.red(error.message));
351
+ }
352
+ }
353
+ });
354
+ program.parse(process.argv);
Binary file
Binary file
Binary file
package/oneurai.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "testcli",
3
+ "created_at": "2025-12-31T17:46:57.009Z",
4
+ "ignore": [
5
+ "node_modules",
6
+ ".git",
7
+ ".env"
8
+ ]
9
+ }
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "oneurai-cli",
3
+ "version": "1.0.2",
4
+ "description": "Oneurai CLI Tool",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "one": "./bin/index.js"
9
+ },
10
+ "scripts": {
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [],
14
+ "author": "",
15
+ "license": "ISC",
16
+ "dependencies": {
17
+ "adm-zip": "^0.5.16",
18
+ "archiver": "^7.0.1",
19
+ "axios": "^1.13.2",
20
+ "chalk": "^5.6.2",
21
+ "commander": "^14.0.2",
22
+ "conf": "^15.0.2",
23
+ "form-data": "^4.0.5",
24
+ "inquirer": "^13.1.0",
25
+ "ora": "^9.0.0"
26
+ }
27
+ }