@vention/vention-cli 0.6.1 → 0.8.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/cli.esm.js CHANGED
@@ -165,6 +165,9 @@ const shouldIgnoreFileSystemNode = (nodeName, ignoredNodes) => {
165
165
  }
166
166
  return false;
167
167
  };
168
+ const getSafeAppName = (appName) => {
169
+ return appName.replace(/[^a-zA-Z0-9-_]/g, "_");
170
+ };
168
171
  const serializeFileSystem = (sourceDirectory, ignoredFileSystemNodes, shouldBase64Encoded) => {
169
172
  const fileSystemNode = {};
170
173
  const directoryContents = fs.readdirSync(sourceDirectory);
@@ -228,12 +231,17 @@ const checkIfDirectoryExists = async (directory) => {
228
231
  .catch(() => false);
229
232
  return exists;
230
233
  };
234
+ const checkIfAppDirectoryExists = async (appName, targetDirectory) => {
235
+ const safeAppName = appName.replace(/[^a-zA-Z0-9-_]/g, "_");
236
+ const appDirectoryPath = path.join(targetDirectory, safeAppName);
237
+ return await checkIfDirectoryExists(appDirectoryPath);
238
+ };
231
239
  const writeApplicationToDisk = async (appName, sourceCode, targetDirectory, overwriteExisting = false) => {
232
240
  if (overwriteExisting) {
233
241
  await createFileSystemFromJson(sourceCode, targetDirectory);
234
242
  return targetDirectory;
235
243
  }
236
- const safeAppName = appName.replace(/[^a-zA-Z0-9-_]/g, "_");
244
+ const safeAppName = getSafeAppName(appName);
237
245
  const appDirectoryPath = path.join(targetDirectory, safeAppName);
238
246
  await createFileSystemFromJson(sourceCode, appDirectoryPath);
239
247
  return appDirectoryPath;
@@ -249,6 +257,7 @@ const getAppFromDigitalTwin = async (session, appId, appName) => {
249
257
  const allApplications = await getAllApplicationsWithSourceCode(session);
250
258
  const targetApp = allApplications.find((app) => app.id === appId);
251
259
  if (!targetApp) {
260
+ console.log();
252
261
  console.error(chalk.red(`Application "${appName}" (ID: ${appId}) not found in the digital twin.`));
253
262
  process.exit(1);
254
263
  }
@@ -264,14 +273,17 @@ const createNewAppDirectory = async (session, currentDir) => {
264
273
  process.exit(1);
265
274
  }
266
275
  const linkedAllocation = await checkIfDesignHasLiveAllocation(session, session.linkedDesignId);
276
+ console.log();
267
277
  console.log(chalk.blue(`You are currently linked to design: ${linkedAllocation === null || linkedAllocation === void 0 ? void 0 : linkedAllocation.designName}`));
268
278
  if (!linkedAllocation) {
279
+ console.log();
269
280
  console.error(chalk.red("Sorry, it seems you do not have that design open with the MachineLogic tab selected."));
270
281
  console.error(chalk.red("Please go to your browser, open your design, and navigate to the MachineLogic page."));
271
282
  process.exit(1);
272
283
  }
273
284
  const availableApps = await getAvailableAppsFromDigitalTwin(session);
274
285
  if (availableApps.length === 0) {
286
+ console.log();
275
287
  console.log(chalk.yellow("No machine code applications found in the digital twin"));
276
288
  process.exit(1);
277
289
  }
@@ -282,11 +294,22 @@ const createNewAppDirectory = async (session, currentDir) => {
282
294
  value: app,
283
295
  })),
284
296
  });
297
+ console.log();
285
298
  console.log(chalk.blue(`\nPulling application "${selectedApp.name}"...`));
286
299
  if (!selectedApp.sourceCode) {
300
+ console.log();
287
301
  console.log(chalk.yellow("No source code found for this application."));
288
302
  process.exit(1);
289
303
  }
304
+ const appDirectoryExists = await checkIfAppDirectoryExists(selectedApp.name, currentDir);
305
+ const safeAppName = getSafeAppName(selectedApp.name);
306
+ if (appDirectoryExists) {
307
+ console.log();
308
+ console.error(chalk.red(`You already have a directory with name "${safeAppName}" here.`));
309
+ console.error(chalk.red("If that is the machine code app you are trying to pull, please navigate to the root folder of the app and run the 'vention pull' command from there."));
310
+ console.error(chalk.red("If not, please rename that directory and try again."));
311
+ process.exit(1);
312
+ }
290
313
  const appDirectoryPath = await writeApplicationToDisk(selectedApp.name, selectedApp.sourceCode, currentDir);
291
314
  await writeMachineCodeAppDirectoryInfo(appDirectoryPath, {
292
315
  appName: selectedApp.name,
@@ -296,9 +319,10 @@ const createNewAppDirectory = async (session, currentDir) => {
296
319
  environment: session.environment,
297
320
  uuid: selectedApp.uuid,
298
321
  });
322
+ console.log();
299
323
  console.log(chalk.green(`✅ Successfully pulled "${selectedApp.name}" to: ${appDirectoryPath}`));
300
324
  console.log(chalk.blue(`📁 To navigate to your project, run:`));
301
- console.log(chalk.cyan(`cd "${appDirectoryPath}"`));
325
+ console.log(chalk.cyan(`cd "${safeAppName}"`));
302
326
  console.log(chalk.blue("💡 You can now start working on your application!"));
303
327
  };
304
328
  const updateExistingAppDirectory = async (session, projectState, currentDir) => {
@@ -306,6 +330,7 @@ const updateExistingAppDirectory = async (session, projectState, currentDir) =>
306
330
  console.log(chalk.blue(`Design ID: ${projectState.designId}, App ID: ${projectState.applicationId}`));
307
331
  const linkedAllocation = await checkIfDesignHasLiveAllocation(session, projectState.designId);
308
332
  if (!linkedAllocation) {
333
+ console.log();
309
334
  console.error(chalk.red("Sorry, it seems you do not have that design open with the MachineLogic tab selected."));
310
335
  console.error(chalk.red("Please go to your browser, open your design, and navigate to the MachineLogic page."));
311
336
  process.exit(1);
@@ -314,12 +339,25 @@ const updateExistingAppDirectory = async (session, projectState, currentDir) =>
314
339
  const appWithSourceCode = await getAppFromDigitalTwin(session, projectState.applicationId, projectState.appName);
315
340
  await writeApplicationToDisk(appWithSourceCode.name, appWithSourceCode.sourceCode, currentDir, true);
316
341
  await writeMachineCodeAppDirectoryInfo(currentDir, Object.assign(Object.assign({}, projectState), { lastPulledAt: new Date().toISOString() }));
342
+ console.log();
317
343
  console.log(chalk.green(`✅ Successfully pulled "${appWithSourceCode.name}" to: ${currentDir}`));
318
344
  console.log(chalk.blue("💡 Your project has been updated with the latest changes!"));
319
345
  };
320
346
 
321
347
  const program = new Command();
322
348
  program.name("vention").description("CLI tool for Vention").version("0.2.0");
349
+ const ventionLogo = `
350
+ ╔════════════════════════════════════════════════════════════════════════════════════════════════════════╗
351
+ ║ ║
352
+ ║ ██╗ ██╗███████╗███╗ ██╗████████╗██╗ ██████╗ ███╗ ██╗ ██████╗██╗ ██╗ ║
353
+ ║ ██║ ██║██╔════╝████╗ ██║╚══██╔══╝██║██╔═══██╗████╗ ██║ ██╔════╝██║ ██║ ║
354
+ ║ ██║ ██║█████╗ ██╔██╗ ██║ ██║ ██║██║ ██║██╔██╗ ██║ ██║ ██║ ██║ ║
355
+ ║ ╚██╗ ██╔╝██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██║██║╚██╗██║ ██║ ██║ ██║ ║
356
+ ║ ╚████╔╝ ███████╗██║ ╚████║ ██║ ██║╚██████╔╝██║ ╚████║ ╚██████╗███████╗██║ ║
357
+ ║ ╚═══╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝╚══════╝╚═╝ ║
358
+ ║ ║
359
+ ╚════════════════════════════════════════════════════════════════════════════════════════════════════════╝
360
+ `;
323
361
  program
324
362
  .command("login")
325
363
  .description("Login to Vention")
@@ -354,9 +392,11 @@ program
354
392
  : undefined;
355
393
  await saveSession(Object.assign({ environment,
356
394
  ventionSession }, (environment !== "local" ? { stytchSessionJwt, ventionIdpSession } : {})));
395
+ console.log();
357
396
  console.log(chalk.green("Successfully logged in!"));
358
397
  }
359
398
  catch (error) {
399
+ console.log();
360
400
  console.error(chalk.red("Login failed:"), error);
361
401
  process.exit(1);
362
402
  }
@@ -373,6 +413,7 @@ program
373
413
  }
374
414
  const allocations = await getUserAllocations(session);
375
415
  if (allocations.length === 0) {
416
+ console.log();
376
417
  console.log(chalk.yellow("No active allocations found. Please open a design and navigate to the machine logic tab to activate a digital twin."));
377
418
  process.exit(1);
378
419
  }
@@ -384,9 +425,11 @@ program
384
425
  })),
385
426
  });
386
427
  await saveSession(Object.assign(Object.assign({}, session), { linkedDesignId: selectedDesign.id, linkedSessionToken: selectedDesign.sessionId }));
428
+ console.log();
387
429
  console.log(chalk.green(`\nSuccessfully linked to design "${selectedDesign.name}" (ID: ${selectedDesign.id})`));
388
430
  }
389
431
  catch (error) {
432
+ console.log();
390
433
  console.error(chalk.red("Failed to get allocations:"));
391
434
  console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
392
435
  process.exit(1);
@@ -409,14 +452,17 @@ program
409
452
  const allocations = await getUserAllocations(session);
410
453
  const linkedAllocation = allocations.find(a => a.designId === session.linkedDesignId);
411
454
  if (!linkedAllocation) {
455
+ console.log();
412
456
  console.error(chalk.red("Linked design is not currently allocated. Please check if the digital twin is running."));
413
457
  process.exit(1);
414
458
  }
415
459
  const digitalTwinResponse = await makeTestRequestToLinkedDigitalTwin(session);
460
+ console.log();
416
461
  console.log(chalk.green("Digital twin response:"));
417
462
  console.log(chalk.green(JSON.stringify(digitalTwinResponse, null, 2)));
418
463
  }
419
464
  catch (error) {
465
+ console.log();
420
466
  console.error(chalk.red("Failed to get digital twin response:"));
421
467
  console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
422
468
  process.exit(1);
@@ -443,6 +489,7 @@ program
443
489
  }
444
490
  }
445
491
  catch (error) {
492
+ console.log();
446
493
  console.error(chalk.red("Failed to pull application:"));
447
494
  console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
448
495
  process.exit(1);
@@ -461,19 +508,23 @@ program
461
508
  const currentDir = process.cwd();
462
509
  const machineCodeAppDirectoryInfo = await readMachineCodeAppDirectoryInfo(currentDir);
463
510
  if (!machineCodeAppDirectoryInfo) {
511
+ console.log();
464
512
  console.error(chalk.red("Not in a machine code application directory. Please run 'vention pull' first to create a project."));
465
513
  console.error(chalk.red("Make sure you are in the root directory of a machine code application you have created using the 'vention pull' command."));
466
514
  process.exit(1);
467
515
  }
516
+ console.log();
468
517
  console.log(chalk.blue(`Pushing changes for project: ${machineCodeAppDirectoryInfo.appName}`));
469
518
  console.log(chalk.blue(`Design ID: ${machineCodeAppDirectoryInfo.designId}, App ID: ${machineCodeAppDirectoryInfo.applicationId}`));
470
519
  const linkedAllocation = await checkIfDesignHasLiveAllocation(session, machineCodeAppDirectoryInfo.designId);
471
520
  if (!linkedAllocation) {
521
+ console.log();
472
522
  console.error(chalk.red("Sorry, it seems you do not have that design open with the MachineLogic tab selected."));
473
523
  console.error(chalk.red("Please go to your browser, open your design, and navigate to the MachineLogic page."));
474
524
  process.exit(1);
475
525
  }
476
526
  await saveSession(Object.assign(Object.assign({}, session), { linkedDesignId: machineCodeAppDirectoryInfo.designId, linkedSessionToken: linkedAllocation.sessionId }));
527
+ console.log();
477
528
  console.log(chalk.blue("Serializing local files..."));
478
529
  const ignorePatterns = getDefaultIgnorePatterns();
479
530
  const serializedSourceCode = serializeFileSystem(currentDir, ignorePatterns, true);
@@ -487,10 +538,12 @@ program
487
538
  console.log(chalk.blue("Pushing to digital twin..."));
488
539
  await pushApplicationToDigitalTwin(session, applicationToPush);
489
540
  await writeMachineCodeAppDirectoryInfo(currentDir, Object.assign(Object.assign({}, machineCodeAppDirectoryInfo), { lastPushedAt: new Date().toISOString() }));
541
+ console.log();
490
542
  console.log(chalk.green(`✅ Successfully pushed "${machineCodeAppDirectoryInfo.appName}" to digital twin`));
491
543
  console.log(chalk.blue("💡 Your changes have been uploaded!"));
492
544
  }
493
545
  catch (error) {
546
+ console.log();
494
547
  console.error(chalk.red("Failed to push application:"));
495
548
  console.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
496
549
  process.exit(1);
@@ -499,6 +552,10 @@ program
499
552
  const resolvedArgv = realpathSync(process.argv[1]);
500
553
  const resolvedUrl = new URL(import.meta.url).pathname;
501
554
  if (resolvedArgv === resolvedUrl) {
555
+ const showLogoConditions = [process.argv.length <= 2, process.argv.includes("--help"), process.argv.includes("-h")];
556
+ if (showLogoConditions.some(Boolean)) {
557
+ console.log(chalk.cyan(ventionLogo));
558
+ }
502
559
  program.parse(process.argv);
503
560
  }
504
561
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vention/vention-cli",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
4
4
  "description": "CLI tool for Vention applications",
5
5
  "type": "module",
6
6
  "repository": {
@@ -3,6 +3,9 @@ export interface FileSystemNode {
3
3
  }
4
4
  export declare const getDefaultIgnorePatterns: () => Set<string | RegExp>;
5
5
  export declare const shouldIgnoreFileSystemNode: (nodeName: string, ignoredNodes: Set<string | RegExp>) => boolean;
6
+ export declare const getSafeAppName: (appName: string) => string;
6
7
  export declare const serializeFileSystem: (sourceDirectory: string, ignoredFileSystemNodes: Set<string | RegExp>, shouldBase64Encoded: boolean) => FileSystemNode;
7
8
  export declare const createFileSystemFromJson: (fileSystemNode: FileSystemNode, targetDirectory: string) => Promise<void>;
9
+ export declare const checkIfDirectoryExists: (directory: string) => Promise<boolean>;
10
+ export declare const checkIfAppDirectoryExists: (appName: string, targetDirectory: string) => Promise<boolean>;
8
11
  export declare const writeApplicationToDisk: (appName: string, sourceCode: FileSystemNode, targetDirectory: string, overwriteExisting?: boolean) => Promise<string>;