desen-cli 1.0.0-draft.5 → 1.0.0-draft.7

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.
@@ -1,5 +1,5 @@
1
1
 
2
2
  
3
- > desen-cli@1.0.0-draft.5 build /Users/selmanay/Desktop/desen/packages/cli
3
+ > desen-cli@1.0.0-draft.7 build /Users/selmanay/Desktop/desen/packages/cli
4
4
  > tsc
5
5
 
package/dist/index.js CHANGED
@@ -172,8 +172,9 @@ program
172
172
  <div class="card">
173
173
  <h1>šŸš€ DESEN Daemon Active</h1>
174
174
  <p>The Synchronization (Sync) server is waiting for incoming <strong>UI AST</strong> data from Figma. It can safely continue running in the background.</p>
175
- <p>To preview your design live as a standalone application using the <strong>desen</strong> render engine, open a new terminal in your project directory and run the following commands:</p>
176
- <div class="code">cd desen-workspace<br/>npm install<br/>npm run dev</div>
175
+ <p>When you press <strong>Sync to Localhost</strong> in Figma, the daemon will <strong>automatically</strong>:</p>
176
+ <div class="code">1. Validate &amp; save JSON files<br/>2. Install dependencies (if needed)<br/>3. Start dev server on port 3001<br/>4. Open your browser ✨</div>
177
+ <p style="margin-top:16px;color:#888;">Zero-touch. Just press Sync and watch the magic.</p>
177
178
  </div>
178
179
  </body>
179
180
  </html>
@@ -248,8 +249,8 @@ program
248
249
  "start": "next start"
249
250
  },
250
251
  dependencies: {
251
- "desen-core": "1.0.0-draft.5",
252
- "desen": "1.0.0-draft.5",
252
+ "desen-core": "1.0.0-draft.7",
253
+ "desen": "1.0.0-draft.7",
253
254
  "next": "14.2.3",
254
255
  "react": "18.3.1",
255
256
  "react-dom": "18.3.1"
@@ -429,7 +430,7 @@ function buildCssFromNode(layout: any, style: any, opts?: { isText?: boolean; is
429
430
 
430
431
  if (layout) {
431
432
  css.display = 'flex';
432
- css.flexDirection = layout.direction === 'row' ? 'row' : 'column';
433
+ css.flexDirection = (layout.direction === 'row' || layout.direction === 'horizontal') ? 'row' : 'column';
433
434
  if (layout.gap !== undefined && layout.gap !== 0) css.gap = layout.gap;
434
435
 
435
436
  const am: Record<string, string> = { start:'flex-start', end:'flex-end', center:'center', 'space-between':'space-between', 'space-around':'space-around', 'space-evenly':'space-evenly' };
@@ -532,11 +533,18 @@ export const registry: Record<string, React.FC<any>> = {
532
533
  element: GenericContainer,
533
534
  group: GenericContainer,
534
535
  stack: GenericContainer,
536
+ Stack: GenericContainer,
537
+ Card: GenericContainer,
538
+ Grid: GenericContainer,
539
+ Header: GenericContainer,
540
+ Footer: GenericContainer,
535
541
  text: TextComponent,
536
542
  Text: TextComponent,
537
543
  button: ButtonComponent,
544
+ Button: ButtonComponent,
538
545
  input: (props: any) => <input style={buildCssFromNode(props.layout, props.style)} placeholder={props.content || props.name} />,
539
546
  icon: (props: any) => <div style={{ ...buildCssFromNode(props.layout, props.style), display:'inline-flex', alignItems:'center', justifyContent:'center' }}>āš™ļø</div>,
547
+ Icon: (props: any) => <div style={{ ...buildCssFromNode(props.layout, props.style), display:'inline-flex', alignItems:'center', justifyContent:'center' }}>āš™ļø</div>,
540
548
  };
541
549
  `.trim());
542
550
  console.log(chalk_1.default.green(`āœ… Done! Standalone App Scaffolded.`));
@@ -551,6 +559,74 @@ export const registry: Record<string, React.FC<any>> = {
551
559
  }
552
560
  }
553
561
  } // End if(!package.json)
562
+ // ─────────────────────────────────────────────────────────
563
+ // AUTO-PILOT: npm install + npm run dev + browser open
564
+ // Zero-touch DX — developer never leaves Figma
565
+ // ─────────────────────────────────────────────────────────
566
+ const nodeModulesPath = path_1.default.join(workspaceDir, "node_modules");
567
+ const devServerPort = 3001;
568
+ const isPortInUse = (port) => {
569
+ return new Promise((resolve) => {
570
+ const net = require("net");
571
+ const tester = net.createServer()
572
+ .once("error", (err) => {
573
+ if (err.code === "EADDRINUSE")
574
+ resolve(true);
575
+ else
576
+ resolve(false);
577
+ })
578
+ .once("listening", () => {
579
+ tester.close(() => resolve(false));
580
+ })
581
+ .listen(port);
582
+ });
583
+ };
584
+ const runNpmInstallIfNeeded = async () => {
585
+ if (fs_1.default.existsSync(nodeModulesPath))
586
+ return;
587
+ console.log(chalk_1.default.blue(`\nšŸ“¦ Installing dependencies...`));
588
+ const { execSync } = require("child_process");
589
+ try {
590
+ execSync("npm install", { cwd: workspaceDir, stdio: "inherit" });
591
+ console.log(chalk_1.default.green(`āœ… Dependencies installed.`));
592
+ }
593
+ catch (e) {
594
+ console.error(chalk_1.default.red(`āŒ npm install failed: ${e.message}`));
595
+ }
596
+ };
597
+ const startDevServerIfNeeded = async () => {
598
+ const portBusy = await isPortInUse(devServerPort);
599
+ if (portBusy) {
600
+ console.log(chalk_1.default.gray(` Dev server already running on port ${devServerPort}.`));
601
+ return;
602
+ }
603
+ console.log(chalk_1.default.blue(`\nšŸš€ Starting dev server on port ${devServerPort}...`));
604
+ const { spawn } = require("child_process");
605
+ const child = spawn("npm", ["run", "dev"], {
606
+ cwd: workspaceDir,
607
+ detached: true,
608
+ stdio: "ignore"
609
+ });
610
+ child.unref();
611
+ console.log(chalk_1.default.green(`āœ… Dev server launched (PID: ${child.pid}).`));
612
+ // Wait a bit then open browser
613
+ setTimeout(() => {
614
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
615
+ const { exec } = require("child_process");
616
+ exec(`${openCmd} http://localhost:${devServerPort}`);
617
+ console.log(chalk_1.default.cyan(`🌐 Browser opened: http://localhost:${devServerPort}`));
618
+ }, 3000);
619
+ };
620
+ // Fire and forget — don't block the HTTP response
621
+ (async () => {
622
+ try {
623
+ await runNpmInstallIfNeeded();
624
+ await startDevServerIfNeeded();
625
+ }
626
+ catch (e) {
627
+ console.error(chalk_1.default.yellow(`āš ļø Auto-pilot warning: ${e.message}`));
628
+ }
629
+ })();
554
630
  res.status(200).json({ success: true, message: `Successfully saved ${savedCount} files.` });
555
631
  }
556
632
  catch (error) {
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "desen-cli",
3
- "version": "1.0.0-draft.5",
3
+ "version": "1.0.0-draft.7",
4
4
  "main": "dist/index.js",
5
5
  "dependencies": {
6
6
  "chalk": "^5.6.2",
7
7
  "commander": "^14.0.3",
8
8
  "express": "^4.19.2",
9
9
  "cors": "^2.8.5",
10
- "desen-core": "1.0.0-draft.5"
10
+ "desen-core": "1.0.0-draft.7"
11
11
  },
12
12
  "devDependencies": {
13
13
  "@types/cors": "^2.8.19",
package/src/index.ts CHANGED
@@ -190,8 +190,9 @@ program
190
190
  <div class="card">
191
191
  <h1>šŸš€ DESEN Daemon Active</h1>
192
192
  <p>The Synchronization (Sync) server is waiting for incoming <strong>UI AST</strong> data from Figma. It can safely continue running in the background.</p>
193
- <p>To preview your design live as a standalone application using the <strong>desen</strong> render engine, open a new terminal in your project directory and run the following commands:</p>
194
- <div class="code">cd desen-workspace<br/>npm install<br/>npm run dev</div>
193
+ <p>When you press <strong>Sync to Localhost</strong> in Figma, the daemon will <strong>automatically</strong>:</p>
194
+ <div class="code">1. Validate &amp; save JSON files<br/>2. Install dependencies (if needed)<br/>3. Start dev server on port 3001<br/>4. Open your browser ✨</div>
195
+ <p style="margin-top:16px;color:#888;">Zero-touch. Just press Sync and watch the magic.</p>
195
196
  </div>
196
197
  </body>
197
198
  </html>
@@ -274,8 +275,8 @@ program
274
275
  "start": "next start"
275
276
  },
276
277
  dependencies: {
277
- "desen-core": "1.0.0-draft.5",
278
- "desen": "1.0.0-draft.5",
278
+ "desen-core": "1.0.0-draft.7",
279
+ "desen": "1.0.0-draft.7",
279
280
  "next": "14.2.3",
280
281
  "react": "18.3.1",
281
282
  "react-dom": "18.3.1"
@@ -464,7 +465,7 @@ function buildCssFromNode(layout: any, style: any, opts?: { isText?: boolean; is
464
465
 
465
466
  if (layout) {
466
467
  css.display = 'flex';
467
- css.flexDirection = layout.direction === 'row' ? 'row' : 'column';
468
+ css.flexDirection = (layout.direction === 'row' || layout.direction === 'horizontal') ? 'row' : 'column';
468
469
  if (layout.gap !== undefined && layout.gap !== 0) css.gap = layout.gap;
469
470
 
470
471
  const am: Record<string, string> = { start:'flex-start', end:'flex-end', center:'center', 'space-between':'space-between', 'space-around':'space-around', 'space-evenly':'space-evenly' };
@@ -567,11 +568,18 @@ export const registry: Record<string, React.FC<any>> = {
567
568
  element: GenericContainer,
568
569
  group: GenericContainer,
569
570
  stack: GenericContainer,
571
+ Stack: GenericContainer,
572
+ Card: GenericContainer,
573
+ Grid: GenericContainer,
574
+ Header: GenericContainer,
575
+ Footer: GenericContainer,
570
576
  text: TextComponent,
571
577
  Text: TextComponent,
572
578
  button: ButtonComponent,
579
+ Button: ButtonComponent,
573
580
  input: (props: any) => <input style={buildCssFromNode(props.layout, props.style)} placeholder={props.content || props.name} />,
574
581
  icon: (props: any) => <div style={{ ...buildCssFromNode(props.layout, props.style), display:'inline-flex', alignItems:'center', justifyContent:'center' }}>āš™ļø</div>,
582
+ Icon: (props: any) => <div style={{ ...buildCssFromNode(props.layout, props.style), display:'inline-flex', alignItems:'center', justifyContent:'center' }}>āš™ļø</div>,
575
583
  };
576
584
  `.trim());
577
585
 
@@ -589,6 +597,77 @@ export const registry: Record<string, React.FC<any>> = {
589
597
  }
590
598
  } // End if(!package.json)
591
599
 
600
+ // ─────────────────────────────────────────────────────────
601
+ // AUTO-PILOT: npm install + npm run dev + browser open
602
+ // Zero-touch DX — developer never leaves Figma
603
+ // ─────────────────────────────────────────────────────────
604
+ const nodeModulesPath = path.join(workspaceDir, "node_modules");
605
+ const devServerPort = 3001;
606
+
607
+ const isPortInUse = (port: number): Promise<boolean> => {
608
+ return new Promise((resolve) => {
609
+ const net = require("net");
610
+ const tester = net.createServer()
611
+ .once("error", (err: any) => {
612
+ if (err.code === "EADDRINUSE") resolve(true);
613
+ else resolve(false);
614
+ })
615
+ .once("listening", () => {
616
+ tester.close(() => resolve(false));
617
+ })
618
+ .listen(port);
619
+ });
620
+ };
621
+
622
+ const runNpmInstallIfNeeded = async () => {
623
+ if (fs.existsSync(nodeModulesPath)) return;
624
+
625
+ console.log(chalk.blue(`\nšŸ“¦ Installing dependencies...`));
626
+ const { execSync } = require("child_process");
627
+ try {
628
+ execSync("npm install", { cwd: workspaceDir, stdio: "inherit" });
629
+ console.log(chalk.green(`āœ… Dependencies installed.`));
630
+ } catch (e: any) {
631
+ console.error(chalk.red(`āŒ npm install failed: ${e.message}`));
632
+ }
633
+ };
634
+
635
+ const startDevServerIfNeeded = async () => {
636
+ const portBusy = await isPortInUse(devServerPort);
637
+ if (portBusy) {
638
+ console.log(chalk.gray(` Dev server already running on port ${devServerPort}.`));
639
+ return;
640
+ }
641
+
642
+ console.log(chalk.blue(`\nšŸš€ Starting dev server on port ${devServerPort}...`));
643
+ const { spawn } = require("child_process");
644
+ const child = spawn("npm", ["run", "dev"], {
645
+ cwd: workspaceDir,
646
+ detached: true,
647
+ stdio: "ignore"
648
+ });
649
+ child.unref();
650
+ console.log(chalk.green(`āœ… Dev server launched (PID: ${child.pid}).`));
651
+
652
+ // Wait a bit then open browser
653
+ setTimeout(() => {
654
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
655
+ const { exec } = require("child_process");
656
+ exec(`${openCmd} http://localhost:${devServerPort}`);
657
+ console.log(chalk.cyan(`🌐 Browser opened: http://localhost:${devServerPort}`));
658
+ }, 3000);
659
+ };
660
+
661
+ // Fire and forget — don't block the HTTP response
662
+ (async () => {
663
+ try {
664
+ await runNpmInstallIfNeeded();
665
+ await startDevServerIfNeeded();
666
+ } catch (e: any) {
667
+ console.error(chalk.yellow(`āš ļø Auto-pilot warning: ${e.message}`));
668
+ }
669
+ })();
670
+
592
671
  res.status(200).json({ success: true, message: `Successfully saved ${savedCount} files.` });
593
672
  } catch (error: any) {
594
673
  console.error(chalk.red("āŒ Sync Error:"), error);