cloud-ide-cide 2.0.34

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/cli.js ADDED
@@ -0,0 +1,521 @@
1
+ #!/usr/bin/env node
2
+ // above line inform the cmd to excute by node compiler
3
+ // cli.js
4
+
5
+ const { program } = require('commander');
6
+ const createProject = require('./createProject');
7
+ const startProject = require('./startProject');
8
+ const { execSync } = require('child_process');
9
+ const readline = require('readline');
10
+ const axios = require('axios');
11
+ const buildProject = require('./buildProject');
12
+ const buildWorkspace = require('./buildWorkspace');
13
+ const buildAllProjects = require('./buildAllProjects');
14
+ const watchLinkProject = require('./watchLinkProject');
15
+ const publishPackage = require('./publishPackage');
16
+ const installGlobalPackage = publishPackage.installGlobalPackage;
17
+ const uploadProject = require('./uploadProject');
18
+ const serverInit = require('./serverInit');
19
+ const path = require('path');
20
+ const pkgJson = require('./package.json');
21
+ // Load .env: package folder first, then cwd (cwd wins on duplicate keys)
22
+ require('dotenv').config({ path: path.join(__dirname, '.env') });
23
+ require('dotenv').config();
24
+
25
+
26
+ // Key to link login on browser and continous check for cli to server logged in or not
27
+ const random_key = (Math.random() * 100000).toFixed(0);
28
+
29
+ program
30
+ .name('cide')
31
+ .version(pkgJson.version, '-v, --version', 'print CLI version (≥2.0.11: [r] in build/publish re-runs same step in-session)')
32
+ .option('--skip-login', 'Skip Cloud IDE console login (offline / local; same as CLOUD_IDE_SKIP_LOGIN=true)')
33
+ .hook('preAction', () => {
34
+ const o = program.opts();
35
+ if (o.skipLogin) {
36
+ process.env.CLOUD_IDE_SKIP_LOGIN = 'true';
37
+ }
38
+ });
39
+
40
+ // new project for templets ex:- new project node
41
+ program
42
+ .command('new <project_name> <template>')
43
+ .description('Create a new project')
44
+ .option('--force', 'Pass --force to npm install after extracting the template')
45
+ .action((projectName, template, opts) => {
46
+ checkUserLoggedIn(() => {
47
+ createProject(projectName, template, opts)
48
+ });
49
+ });
50
+
51
+ // start the project
52
+ program
53
+ .command('start')
54
+ .description('Start any Cloud IDE project')
55
+ .action(() => {
56
+ checkUserLoggedIn(() => {
57
+ startProject();
58
+ })
59
+ });
60
+
61
+ const BUILD_COMMAND_HELP = `
62
+
63
+ Examples:
64
+ cide build
65
+ From the Angular workspace root (folder with cide.json): prints the same numbered list as publish, then builds selected
66
+ packages with ng build / npm run build only (no version bump, no npm publish).
67
+
68
+ cide build -p 1
69
+ Build list item [1] only (non-interactive).
70
+
71
+ cide build -p "1,4,5"
72
+ Build several packages from the list.
73
+
74
+ cide build -p all --continue-on-error
75
+ Build every package; do not stop at the first failure.
76
+
77
+ cide build -p all --resume-from 6
78
+ Resume a batch after a failure (skip steps 1–5, start at step 6).
79
+
80
+ Interactive (TTY): on failure, [r] re-runs the same ng build / npm run build for that package, then
81
+ continues to the next on success; [y] skips to next; [N] stops.
82
+
83
+ cide build cloud-ide-element -i
84
+ Legacy: single project folder under projects/ — bumps version, builds, publishes to registry,
85
+ optional root npm update (--install / --force). Do not combine with -p.
86
+
87
+ Package spec for -p / --packages (same rules as cide publish):
88
+ 1,3,5 | 1-5 | all
89
+ `;
90
+
91
+ /* build — workspace batch (like publish) or legacy single-project build+publish */
92
+ program
93
+ .command('build [project_name]')
94
+ .description(
95
+ 'Build libraries: same numbered list as publish (no publish), or legacy: one project under projects/ with bump+publish.'
96
+ )
97
+ .option('-p, --packages <spec>', '1,3,5 | 1-5 | all — when [project_name] omitted (see cide build --help)')
98
+ .option('--continue-on-error', 'Batch build: continue after a failure (non-interactive safe)')
99
+ .option('--resume-from <n>', 'Batch build: 1-based step to start from (after partial run)')
100
+ .option('-i, --install', 'Legacy only (with [project_name]): install the built package at root after publishing')
101
+ .option('--force', 'Legacy only: with --install, pass --force to npm update at workspace root')
102
+ .addHelpText('after', BUILD_COMMAND_HELP)
103
+ .action((projectName, options) => {
104
+ checkUserLoggedIn(() => {
105
+ const name = projectName != null ? String(projectName).trim() : '';
106
+ const hasPackages = options.packages != null && String(options.packages).trim() !== '';
107
+ if (name && hasPackages) {
108
+ console.error('Error: use either `cide build <project_name>` (legacy) OR `cide build -p <spec>`, not both.');
109
+ process.exitCode = 1;
110
+ return;
111
+ }
112
+ if (name) {
113
+ buildProject(name, options.install, { force: !!options.force });
114
+ return;
115
+ }
116
+ buildWorkspace(options).catch((err) => {
117
+ console.error(err);
118
+ process.exitCode = 1;
119
+ });
120
+ });
121
+ });
122
+
123
+ /* build all projects */
124
+ program
125
+ .command('build-all')
126
+ .description('Build all Cloud IDE projects (excludes main build command)')
127
+ .option('-i, --install', 'Install all built packages at root after building')
128
+ .action((options) => {
129
+ checkUserLoggedIn(() => {
130
+ buildAllProjects(options.install);
131
+ })
132
+ });
133
+
134
+ const PUBLISH_COMMAND_HELP = `
135
+
136
+ Examples:
137
+ cide publish
138
+ From the folder that contains angular cide.json. Prints the numbered list
139
+ and a "HOW TO PUBLISH" box — follow the formats shown (numbers, ranges, all, or 1=2.0.1).
140
+
141
+ cide publish -p 1 --set-version 2.0.1
142
+ Publish list item [1] with exact version 2.0.1 (no prompts).
143
+
144
+ cide publish -p "1,4,5" --bump minor
145
+ Publish [1], [4], and [5]; each gets a minor semver bump from its current version.
146
+
147
+ cide publish -p "1=2.0.1,4=1.2.0"
148
+ Publish [1] as 2.0.1 and [4] as 1.2.0 in one command.
149
+
150
+ cide publish -p all --bump patch
151
+ Publish every listed package with a patch bump.
152
+
153
+ cide publish -p 1 --set-version 2.0.1 --global 3
154
+ After publishing [1], run npm install -g for list item [3] (same numbers as the list).
155
+
156
+ cide publish -p all --bump patch --global n
157
+ Publish all, then skip global install (--global n | no | skip).
158
+
159
+ cide publish -p all --bump patch --continue-on-error
160
+ Non-interactive: if one package fails, log and keep publishing the rest.
161
+
162
+ Interactive (TTY): on failure, [r] re-runs build & publish for that package (no extra version bump),
163
+ then continues on success; [y] skips to next; [N] stops.
164
+
165
+ cide publish -p all --bump patch --resume-from 6
166
+ Skip batch steps 1–5 (already done); start at step 6 of the same -p list.
167
+
168
+ cide publish -p all --bump patch --retry-from 5
169
+ After a failure at step 5 of the same batch: retry that package without bumping again (same as --resume-from 5 --no-bump-on-resume).
170
+
171
+ cide publish -p all --bump patch --resume-from 5 --no-bump-on-resume
172
+ Same as --retry-from 5: re-run step 5 only without a second version bump (fix build/publish, then continue).
173
+
174
+ cide publish -p 1 --bump patch --force
175
+ After updating dependents, run npm install with --force in each touched folder; --global also uses --force.
176
+
177
+ Package spec for -p / --packages:
178
+ 1,3,5 several indices | 1-5 range | all everything
179
+ 1=2.0.1,4=1.0.0 per-index versions (must use = form for every entry in that spec)
180
+
181
+ --global <spec> (after publish succeeds):
182
+ Same index rules: 1,3,5 | 1-5 | all | n / no / skip to skip global install
183
+ `;
184
+
185
+ const INSTALL_GLOBAL_COMMAND_HELP = `
186
+
187
+ Examples:
188
+ cide install-global
189
+ Shows HOW TO GLOBAL INSTALL first, then the numbered list, then asks for your choice.
190
+
191
+ cide install-global -p 3
192
+ npm install -g the package shown at [3] (uses name@version from its package.json).
193
+
194
+ cide install-global -p "2,5"
195
+ Global-install [2] and [5].
196
+
197
+ cide install-global -p n
198
+ Exit without installing (non-interactive skip).
199
+
200
+ cide install-global -p 2 --force
201
+ Global-install [2] with npm install -g --force.
202
+
203
+ Index spec for -p / --packages (same as publish list numbers):
204
+ 1,3,5 | 1-5 | all | n / no / none / skip / 0 (skip)
205
+ `;
206
+
207
+ /* publish packages — interactive list, version bump, GitHub Packages, update dependents */
208
+ program
209
+ .command('publish')
210
+ .description('Publish workspace packages to GitHub Packages. Use --help for formats and examples.')
211
+ .option('-p, --packages <spec>', '1,3,5 | 1-5 | all | 1=2.0.1,4=1.0.0 (see cide publish --help)')
212
+ .option('--set-version <semver>', 'Exact version for all selected packages (ignored if spec uses n=ver)')
213
+ .option('--bump <kind>', 'patch | minor | major when --set-version not used (default: patch)')
214
+ .option('--global <spec>', 'After publish: npm install -g by list index (1,3,5 | n to skip); see --help')
215
+ .option('--force', 'Pass --force to npm install (dependents) and npm install -g (--global)')
216
+ .option('--continue-on-error', 'On failure: do not stop; continue with remaining packages (non-interactive safe)')
217
+ .option('--resume-from <n>', '1-based step in this publish batch to start from (skip earlier steps; use after partial run)')
218
+ .option(
219
+ '--retry-from <n>',
220
+ 'Retry the same step after failure: like --resume-from but skips version bump on that step (no double bump)'
221
+ )
222
+ .option(
223
+ '--no-bump-on-resume',
224
+ 'With --resume-from (step > 1): skip version bump only on the resumed step (alternative to --retry-from)'
225
+ )
226
+ .addHelpText('after', PUBLISH_COMMAND_HELP)
227
+ .action((opts) => {
228
+ checkUserLoggedIn(() => {
229
+ publishPackage(opts).catch((err) => {
230
+ console.error(err);
231
+ process.exitCode = 1;
232
+ });
233
+ });
234
+ });
235
+
236
+ program
237
+ .command('install-global')
238
+ .description('npm install -g workspace packages by list number (registry). See --help for formats.')
239
+ .option('--force', 'Pass --force to npm install -g')
240
+ .option('-p, --packages <spec>', '1 | 1,3,5 | 1-5 | all | n (see cide install-global --help)')
241
+ .addHelpText('after', INSTALL_GLOBAL_COMMAND_HELP)
242
+ .action((opts) => {
243
+ checkUserLoggedIn(() => {
244
+ installGlobalPackage(opts).catch((err) => {
245
+ console.error(err);
246
+ process.exitCode = 1;
247
+ });
248
+ });
249
+ });
250
+
251
+ const UPLOAD_COMMAND_HELP = `
252
+
253
+ Examples:
254
+ cide upload
255
+ Lists projects with upload config, pick project, pick server, upload.
256
+
257
+ cide upload -p 1
258
+ Upload project #1 (asks which server if multiple).
259
+
260
+ cide upload -p 1 --server 2
261
+ Upload project #1 to server #2 (fully non-interactive).
262
+
263
+ cide upload -p 1 --server Production
264
+ Upload project #1 to the server named "Production".
265
+
266
+ cide upload --list
267
+ List all uploadable projects and their servers.
268
+
269
+ cide upload --history
270
+ Show deployment history from a server.
271
+
272
+ cide upload --rollback
273
+ Rollback to a previous version on a server.
274
+
275
+ cide.json "upload" config (array of servers):
276
+ {
277
+ "upload": [
278
+ {
279
+ "name": "Production",
280
+ "server_url": "https://prod.example.com/.cide/scripts/upload-ui.php",
281
+ "build_path": "dist/my-app",
282
+ "app_code": "my-app",
283
+ "token": "your-deploy-token"
284
+ },
285
+ {
286
+ "name": "Staging",
287
+ "server_url": "https://staging.example.com/.cide/scripts/upload-ui.php",
288
+ "build_path": "dist/my-app",
289
+ "app_code": "my-app",
290
+ "token": "another-token"
291
+ }
292
+ ]
293
+ }
294
+
295
+ Single object format also supported (backward compatible).
296
+ Token can also be set via CIDE_UPLOAD_TOKEN environment variable.
297
+ `;
298
+
299
+ /* upload — zip build output and upload to deployment server */
300
+ program
301
+ .command('upload')
302
+ .description('Upload built code to a deployment server, view history, or rollback. Use --help for details.')
303
+ .option('-p, --packages <spec>', 'Project number from the list (e.g. 1)')
304
+ .option('-s, --server <spec>', 'Server number or name (e.g. 1 or "Production")')
305
+ .option('-m, --message <text>', 'Deploy message / changelog (shown in history)')
306
+ .option('-b, --build', 'Build before uploading (skip the prompt)')
307
+ .option('--no-build', 'Skip build, upload existing dist directly')
308
+ .option('--list', 'List all uploadable projects without uploading')
309
+ .option('--history', 'Show deployment history from the server')
310
+ .option('--rollback [version]', 'Rollback to a previous version (interactive or specify version)')
311
+ .addHelpText('after', UPLOAD_COMMAND_HELP)
312
+ .action((opts) => {
313
+ checkUserLoggedIn(() => {
314
+ uploadProject(opts).catch((err) => {
315
+ console.error(err);
316
+ process.exitCode = 1;
317
+ });
318
+ });
319
+ });
320
+
321
+ const SERVER_INIT_HELP = `
322
+
323
+ Examples:
324
+ cide server-init
325
+ Interactive: choose PHP or Node, set path & port, scaffolds .cide/ folder,
326
+ installs listener, auto-starts Node in background.
327
+
328
+ cide server-init --type node --path /home/app/api
329
+ Non-interactive setup.
330
+
331
+ cide server-init --status
332
+ Check if the Node listener is running.
333
+
334
+ cide server-init --start
335
+ Start the Node listener in background.
336
+
337
+ cide server-init --stop
338
+ Stop the Node listener.
339
+
340
+ cide server-init --restart
341
+ Restart the Node listener.
342
+ `;
343
+
344
+ /* server-init — scaffold .cide/, install listener, manage background process */
345
+ program
346
+ .command('server-init')
347
+ .description('Setup upload server (.cide/ scaffold), manage Node listener (--start/--stop/--status/--restart)')
348
+ .option('--type <type>', 'Server type: php or node')
349
+ .option('--path <dir>', 'Server root directory')
350
+ .option('--start', 'Start the Node listener in background')
351
+ .option('--stop', 'Stop the Node listener')
352
+ .option('--status', 'Check if the Node listener is running')
353
+ .option('--restart', 'Restart the Node listener')
354
+ .addHelpText('after', SERVER_INIT_HELP)
355
+ .action((opts) => {
356
+ checkUserLoggedIn(() => {
357
+ serverInit(opts).catch((err) => {
358
+ console.error(err);
359
+ process.exitCode = 1;
360
+ });
361
+ });
362
+ });
363
+
364
+ program
365
+ .command('shell')
366
+ .description('Start the interactive CloudIDE workspace shell (git, build, publish, server, npm, …)')
367
+ .action(() => {
368
+ checkUserLoggedIn(() => {
369
+ require('./cideShell').startShell();
370
+ });
371
+ });
372
+
373
+ /** watch Project and link them to main Project */
374
+ program
375
+ .command('watch <type_to> <project_name>')
376
+ .description(`Watch and link project
377
+ \n 1. watch <type_to> <project_name>
378
+ \n Result: Watch the <project_name> if any changes made in the project it build the package and link after going inside the DIST folder
379
+ \n as this done it will go to the .root and link the build package to the main project`)
380
+ .action(() => {
381
+ checkUserLoggedIn(() => {
382
+ watchLinkProject();
383
+ })
384
+ });
385
+
386
+
387
+ /**
388
+ * Skip Cloud IDE console login / browser confirmation (local dev).
389
+ * Set in .env or shell: CLOUD_IDE_SKIP_LOGIN=true (or 1)
390
+ */
391
+ function shouldSkipCloudIdeLogin() {
392
+ if (process.argv.includes('--skip-login')) return true;
393
+ try {
394
+ const o = typeof program.optsWithGlobals === 'function' ? program.optsWithGlobals() : program.opts();
395
+ if (o && o.skipLogin) return true;
396
+ } catch (_) {
397
+ /* before parse, opts may be unavailable */
398
+ }
399
+ const v = String(process.env.CLOUD_IDE_SKIP_LOGIN || '').toLowerCase();
400
+ return v === '1' || v === 'true' || v === 'yes';
401
+ }
402
+
403
+ // for every command check user is logged in or not
404
+ async function checkUserLoggedIn(callbackProcess) {
405
+ if (shouldSkipCloudIdeLogin()) {
406
+ console.log('(Cloud IDE login skipped: use --skip-login or CLOUD_IDE_SKIP_LOGIN=true)');
407
+ callbackProcess();
408
+ return;
409
+ }
410
+ if (!await loginStatusVerify()) {
411
+ // Not loggedin
412
+ console.log('');
413
+ console.log('You are not logged in.');
414
+ console.log('Do you have CloudIDEsys account (yes/no)');
415
+ // If yes the ask for userid password not then ask to register
416
+ // Set input output at line
417
+ let rl = readline.createInterface({
418
+ input: process.stdin,
419
+ output: process.stdout
420
+ });
421
+ let account_ans = new Promise((resolve, reject) => {
422
+ rl.question('> ', (answer) => {
423
+ rl.close();
424
+ resolve(answer);
425
+ });
426
+ }).then((answer) => {
427
+ if (answer.toLocaleLowerCase() === 'yes') {
428
+ // If yes then open browser
429
+ let rl_login = readline.createInterface({
430
+ input: process.stdin,
431
+ output: process.stdout
432
+ });
433
+ console.log('Would you like to Login? (yes/no)');
434
+ rl_login.question('> ', (answer) => {
435
+ if (answer === 'yes') {
436
+ // Open browser for login
437
+ console.log('Opening browser for login...');
438
+ setTimeout(() => {
439
+ openBrowserForAccountCreation(``);
440
+ }, 1000);
441
+ } else {
442
+ // Inform without login nothing is possible
443
+ console.log('Sorry to inform you that, you are not able to use Cloud IDE CLI without login!!!');
444
+ }
445
+ rl_login.close();
446
+ });
447
+ } else {
448
+ console.log('Would you like to create an account? (yes/no)');
449
+ // Set Input Output
450
+ let rl_register = readline.createInterface({
451
+ input: process.stdin,
452
+ output: process.stdout
453
+ })
454
+ // Take input
455
+ rl_register.question('> ', async (answer) => {
456
+ if (answer.toLocaleLowerCase() === 'yes') {
457
+ console.log('Opening browser for account creation...');
458
+ setTimeout(() => {
459
+ openBrowserForAccountCreation(`register?id=${random_key}`, random_key);
460
+ }, 1000);
461
+ } else {
462
+ // Inform without login nothing is possible
463
+ console.log('Sorry to inform you that, you are not able to use Cloud IDE CLI without registration!!!');
464
+ }
465
+ rl_register.close();
466
+ });
467
+ }
468
+ });
469
+ } else {
470
+ callbackProcess();
471
+ }
472
+ }
473
+
474
+ async function openBrowserForAccountCreation(open, random_key) {
475
+ try {
476
+ // URL to navigate
477
+ const url = `https://console.cloudidesys.com/${open}?id=${random_key}`; // Replace with your registration URL or desired URL
478
+ execSync(`start ${url}`, (error, stdout, stderr) => {
479
+ if (error) {
480
+ console.error('Error opening browser:', error);
481
+ }
482
+ });
483
+ // Wait for 2 min for login successfull response
484
+ setTimeout(async () => {
485
+ loginStatusVerify().then((response) => {
486
+ if (response) {
487
+ console.log(`Login Successfull ${response.print_name}, Enjoy CloudIDE CLI!`);
488
+ } else {
489
+ console.log("Somthing Went Wrong, Please Try Again!");
490
+ }
491
+ })
492
+ }, (1500 * 60))
493
+ } catch (error) {
494
+ console.log("Somthing Went Wrong, Please Check your internet Connection!");
495
+ }
496
+ }
497
+
498
+ const loginStatusVerify = () => {
499
+ return new Promise(async (resolve, reject) => {
500
+ try {
501
+ let login_response = await axios.get(`https://console.cloudidesys.com/cli?id=${random_key}&usename=${process?.env?.CLOUD_IDE_USERNAME}&secret_key=${process?.env?.CLOUD_IDE_SECRET_KEY}`);
502
+ if (login_response) {
503
+ if (login_response.data.username && login_response.data.secret_key) {
504
+ // Set username and secret key for further processing
505
+ process.env.CLOUD_IDE_USERNAME = login_response.data.username;
506
+ process.env.CLOUD_IDE_SECRET_KEY = login_response.data.secret_key;
507
+ resolve(login_response.data);
508
+ } else {
509
+ resolve(false);
510
+ }
511
+ } else {
512
+ resolve(false);
513
+ }
514
+ } catch (error) {
515
+ console.log("Somthing Went Wrong, Please Check your internet Connection!");
516
+ resolve(false);
517
+ }
518
+ });
519
+ }
520
+
521
+ program.parse(process.argv);
@@ -0,0 +1,71 @@
1
+ // createProject.js
2
+
3
+ const { execSync } = require('child_process');
4
+ const fs = require('fs');
5
+ const axios = require('axios');
6
+ const path = require('path');
7
+ const AdmZip = require('adm-zip');
8
+
9
+ async function createProject(projectName, template, options = {}) {
10
+ console.log(`Creating a new ${template} project named ${projectName}`);
11
+
12
+ //Destination path
13
+ const destinationPath = path.join(process.cwd(), projectName);
14
+
15
+ // Check wether folder already exists
16
+ let directorys_at_current_dir = fs.readdirSync('./');
17
+ if (projectName != directorys_at_current_dir.find((directorys_at_current_dir_row) => directorys_at_current_dir_row === projectName)) {
18
+
19
+ // When directory dose't exists
20
+ fs.mkdirSync(destinationPath);
21
+
22
+ // Mock API call to fetch project structure for the given template
23
+ await fetchProjectStructureFromAPI(template, projectName, destinationPath);
24
+
25
+ // Install dependencies
26
+ installDependencies(projectName);
27
+
28
+ console.log(`${template} project created successfully!`);
29
+ } else {
30
+ console.log(`${projectName} already exists!`);
31
+ }
32
+ }
33
+
34
+ async function fetchProjectStructureFromAPI(template, projectName, destinationPath) {
35
+ const apiUrl = `https://console.cloudidesys.com/cli/${template}.zip`; // API endpoint for downloading the zip file
36
+
37
+ try {
38
+ const response = await axios({
39
+ method: 'GET',
40
+ url: apiUrl,
41
+ responseType: 'arraybuffer', // Set the response type to arraybuffer
42
+ });
43
+
44
+ // Save the downloaded zip file
45
+ const zipFilePath = path.join(destinationPath, `${projectName}.zip`);
46
+ fs.writeFileSync(zipFilePath, response.data);
47
+
48
+ // Unzip the downloaded file to create project structure
49
+ const zip = new AdmZip(zipFilePath);
50
+ zip.extractAllTo(destinationPath, true);
51
+
52
+ // Remove the downloaded zip file after extraction
53
+ fs.unlinkSync(zipFilePath);
54
+
55
+ console.log(`Project '${projectName}' created successfully for ${template}.`);
56
+ } catch (err) {
57
+ console.error('Error fetching or extracting project structure:', err.message);
58
+ }
59
+ }
60
+
61
+ function installDependencies(projectName, options = {}) {
62
+ /* Switch to working directory */
63
+ process.chdir(projectName);
64
+ // Mock dependency installation logic
65
+ // Replace this with your actual dependency installation logic
66
+ const force = options.force ? ' --force' : '';
67
+ console.log(`Installing dependencies...${options.force ? ' (--force)' : ''}`);
68
+ execSync(`npm install${force}`, { stdio: 'inherit' });
69
+ }
70
+
71
+ module.exports = createProject;