@superdesign/cli 0.1.0 → 0.1.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/dist/api/brand.d.ts +55 -0
- package/dist/api/designs.d.ts +28 -0
- package/dist/api/projects.d.ts +5 -0
- package/dist/api/prompts.d.ts +53 -0
- package/dist/commands/extract-brand-guide.d.ts +5 -0
- package/dist/commands/fetch-design-nodes.d.ts +5 -0
- package/dist/commands/get-design.d.ts +5 -0
- package/dist/commands/get-prompts.d.ts +5 -0
- package/dist/commands/search-prompts.d.ts +5 -0
- package/dist/index.cjs +554 -213
- package/dist/index.d.ts +3 -0
- package/dist/index.js +531 -205
- package/dist/utils/job-runner.d.ts +5 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,10 +2,11 @@ import { config as external_dotenv_config } from "dotenv";
|
|
|
2
2
|
import { fileURLToPath } from "url";
|
|
3
3
|
import { dirname, join, resolve as external_path_resolve } from "path";
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
5
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
6
6
|
import { homedir, hostname, platform, release } from "os";
|
|
7
7
|
import axios from "axios";
|
|
8
8
|
import ora from "ora";
|
|
9
|
+
import { writeFile } from "fs/promises";
|
|
9
10
|
const CONFIG_DIR_NAME = '.superdesign';
|
|
10
11
|
const CONFIG_FILE_NAME = 'config.json';
|
|
11
12
|
const EXIT_CODES = {
|
|
@@ -423,241 +424,282 @@ name: superdesign
|
|
|
423
424
|
description: Superdesign is a design agent, where it specialised in frontend UI/UX design; Use this skill before you implement any UI that require some design thinking
|
|
424
425
|
---
|
|
425
426
|
|
|
426
|
-
|
|
427
|
-
This skill provides integration with the SuperDesign platform for AI-powered design generation.
|
|
427
|
+
SuperDesign helps you (1) find design inspirations/styles and (2) optionally generate/iterate design drafts on an infinite canvas.
|
|
428
428
|
|
|
429
|
-
|
|
429
|
+
Each SuperDesign canvas run creates a new node and returns a \`previewUrl\`.
|
|
430
430
|
|
|
431
|
-
|
|
431
|
+
---
|
|
432
432
|
|
|
433
|
-
|
|
433
|
+
## Core scenarios (what this skill handles)
|
|
434
434
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
435
|
+
1. **Help me design X** (feature/page/flow)
|
|
436
|
+
2. **Set design system**
|
|
437
|
+
3. **Help me improve design of X**
|
|
438
438
|
|
|
439
|
-
|
|
440
|
-
superdesign create-project --title "My Project" --html "<html>...</html>" --json
|
|
439
|
+
---
|
|
441
440
|
|
|
442
|
-
|
|
443
|
-
superdesign create-project --title "My Project" --html-file ./index.html --json
|
|
444
|
-
\`\`\`
|
|
441
|
+
## Tooling overview
|
|
445
442
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
{
|
|
449
|
-
"projectId": "uuid",
|
|
450
|
-
"title": "My Project",
|
|
451
|
-
"projectUrl": "https://app.superdesign.ai/...",
|
|
452
|
-
"shareToken": "token"
|
|
453
|
-
}
|
|
454
|
-
\`\`\`
|
|
443
|
+
### A) Inspiration & Style Tools (generic, always available)
|
|
444
|
+
Use these to discover style direction, references, and brand context:
|
|
455
445
|
|
|
456
|
-
|
|
446
|
+
- **Search prompt library** (style/components/pages)
|
|
447
|
+
\`\`\`bash
|
|
448
|
+
superdesign search-prompts --keyword "<keyword>" --json
|
|
449
|
+
superdesign search-prompts --tags "style" --json
|
|
450
|
+
superdesign search-prompts --tags "style" --keyword "<style keyword>" --json
|
|
451
|
+
\`\`\`
|
|
457
452
|
|
|
458
|
-
|
|
453
|
+
- **Get full prompt details**
|
|
454
|
+
\`\`\`bash
|
|
455
|
+
superdesign get-prompts --slugs "<slug1,slug2,...>" --json
|
|
456
|
+
\`\`\`
|
|
459
457
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
--prompt "Create a modern hero section with gradient background" \\
|
|
465
|
-
--device desktop \\
|
|
466
|
-
--json
|
|
467
|
-
\`\`\`
|
|
458
|
+
- **Extract brand guide from a URL**
|
|
459
|
+
\`\`\`bash
|
|
460
|
+
superdesign extract-brand-guide --url https://example.com --json
|
|
461
|
+
\`\`\`
|
|
468
462
|
|
|
469
|
-
|
|
470
|
-
- \`--project-id\` (required): Project to add draft to
|
|
471
|
-
- \`--title\` (required): Draft title
|
|
472
|
-
- \`--prompt\` (required): AI generation prompt
|
|
473
|
-
- \`--device\`: Device mode (mobile, tablet, desktop)
|
|
463
|
+
### B) Canvas Design Tools (specialised, optional)
|
|
474
464
|
|
|
475
|
-
|
|
476
|
-
\`\`\`json
|
|
477
|
-
{
|
|
478
|
-
"draftId": "uuid",
|
|
479
|
-
"nodeId": "uuid",
|
|
480
|
-
"title": "Hero Section",
|
|
481
|
-
"projectUrl": "https://app.superdesign.ai/...",
|
|
482
|
-
"nodeUrl": "https://app.superdesign.ai/...?node=...",
|
|
483
|
-
"previewUrl": "https://preview.superdesign.ai/...",
|
|
484
|
-
"creditsConsumed": 1
|
|
485
|
-
}
|
|
486
|
-
\`\`\`
|
|
465
|
+
Use these when you want to explore multiple directions and show previews:
|
|
487
466
|
|
|
488
|
-
|
|
467
|
+
- Create project (supports prompt / prompt file / HTML)
|
|
468
|
+
- Create design draft
|
|
469
|
+
- Iterate design draft (replace / branch)
|
|
470
|
+
- Plan flow pages → execute flow pages
|
|
471
|
+
- Fetch nodes, export HTML
|
|
489
472
|
|
|
490
|
-
|
|
473
|
+
> Pixel-perfect HTML playground is ONLY required for Canvas workflows.
|
|
491
474
|
|
|
492
|
-
|
|
493
|
-
# Replace mode - updates the existing draft
|
|
494
|
-
superdesign iterate-design-draft \\
|
|
495
|
-
--draft-id <draft-id> \\
|
|
496
|
-
--prompt "Make the colors more vibrant" \\
|
|
497
|
-
--mode replace \\
|
|
498
|
-
--json
|
|
475
|
+
---
|
|
499
476
|
|
|
500
|
-
|
|
501
|
-
superdesign iterate-design-draft \\
|
|
502
|
-
--draft-id <draft-id> \\
|
|
503
|
-
--prompt "Try different color schemes" \\
|
|
504
|
-
--mode branch \\
|
|
505
|
-
--count 3 \\
|
|
506
|
-
--json
|
|
507
|
-
\`\`\`
|
|
477
|
+
## Always-on rules
|
|
508
478
|
|
|
509
|
-
|
|
510
|
-
-
|
|
511
|
-
-
|
|
512
|
-
-
|
|
513
|
-
-
|
|
479
|
+
- Design system should live at: \`.superdesign/design-system.md\`
|
|
480
|
+
- If \`.superdesign/design-system.md\` is missing, run **Design System Setup** first.
|
|
481
|
+
- Use \`askQuestion\` to ask high-signal questions (constraints, taste, tradeoffs).
|
|
482
|
+
- For Canvas workflows: build a simplified/pixel-perfect prototype HTML in:
|
|
483
|
+
- \`.superdesign/playgrounds/<name>.html\`
|
|
484
|
+
- Always use \`--json\` for machine parsing.
|
|
514
485
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
"nodeUrl": "https://...",
|
|
524
|
-
"previewUrl": "https://..."
|
|
525
|
-
}
|
|
526
|
-
],
|
|
527
|
-
"projectUrl": "https://...",
|
|
528
|
-
"creditsConsumed": 3
|
|
529
|
-
}
|
|
530
|
-
\`\`\`
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## Playground rules (Canvas only)
|
|
489
|
+
|
|
490
|
+
**Playground = BEFORE state (what exists now).** It provides context for SuperDesign agent.
|
|
491
|
+
**Prompt = DESIRED CHANGE (what to add/modify).**
|
|
492
|
+
|
|
493
|
+
The playground HTML must contain **ONLY UI that currently exists in the codebase**. For NEW features/sections, describe them entirely in the \`--prompt\` flag — do NOT add wireframes, placeholders, or sketches to the playground HTML.
|
|
531
494
|
|
|
532
|
-
|
|
495
|
+
- **DO NOT** design or improve anything in the playground
|
|
496
|
+
- **DO NOT** add placeholder sections like \`<!-- NEW FEATURE - DESIGN THIS -->\`
|
|
497
|
+
- **DO** create pixel-perfect replica of current UI state
|
|
498
|
+
- Valid formats:
|
|
499
|
+
- **Component-only**: isolated component with enough markup to show core UX/states
|
|
500
|
+
- **Full page**: replica of page where component operates (shows surrounding context)
|
|
501
|
+
- Save to: \`.superdesign/playgrounds/<name>.html\`
|
|
533
502
|
|
|
534
|
-
|
|
503
|
+
### Example: Adding a "Book Demo" section to home page
|
|
535
504
|
|
|
505
|
+
**BAD approach:**
|
|
506
|
+
\`\`\`html
|
|
507
|
+
<!-- playground includes a sketched Book Demo section -->
|
|
508
|
+
<section class="book-demo">
|
|
509
|
+
<!-- DESIGN THIS - Add CTA here -->
|
|
510
|
+
<h3>Book a Demo</h3>
|
|
511
|
+
<button>Schedule</button>
|
|
512
|
+
</section>
|
|
513
|
+
\`\`\`
|
|
514
|
+
|
|
515
|
+
**GOOD approach:**
|
|
516
|
+
\`\`\`html
|
|
517
|
+
<!-- playground is pure replica of existing home page (hero + projects) -->
|
|
518
|
+
<!-- NO book demo section in HTML -->
|
|
519
|
+
\`\`\`
|
|
520
|
+
Then in the iterate command:
|
|
536
521
|
\`\`\`bash
|
|
537
|
-
|
|
538
|
-
--draft-id <draft-id> \\
|
|
539
|
-
--source-node-id <node-id> \\
|
|
540
|
-
--context "E-commerce checkout flow" \\
|
|
541
|
-
--json
|
|
522
|
+
--prompt "Add a Book Demo section between the hero and projects sections. Requirements: minimal card style, horizontal layout..."
|
|
542
523
|
\`\`\`
|
|
543
524
|
|
|
544
|
-
|
|
545
|
-
- \`--draft-id\` (required): Source draft
|
|
546
|
-
- \`--source-node-id\` (required): Starting node in flow
|
|
547
|
-
- \`--context\`: Additional context for planning
|
|
525
|
+
---
|
|
548
526
|
|
|
549
|
-
|
|
550
|
-
\`\`\`json
|
|
551
|
-
{
|
|
552
|
-
"pages": [
|
|
553
|
-
{
|
|
554
|
-
"title": "Cart Review",
|
|
555
|
-
"prompt": "Create a cart review page showing..."
|
|
556
|
-
},
|
|
557
|
-
{
|
|
558
|
-
"title": "Payment",
|
|
559
|
-
"prompt": "Create a payment form with..."
|
|
560
|
-
}
|
|
561
|
-
],
|
|
562
|
-
"creditsConsumed": 1
|
|
563
|
-
}
|
|
564
|
-
\`\`\`
|
|
527
|
+
# 1) Design System Setup
|
|
565
528
|
|
|
566
|
-
###
|
|
529
|
+
### Step 0 — Ask user (one question)
|
|
567
530
|
|
|
568
|
-
|
|
531
|
+
"Do you want to **create a new design system** or **extract from the current codebase**?"
|
|
569
532
|
|
|
570
|
-
|
|
571
|
-
superdesign execute-flow-pages \\
|
|
572
|
-
--draft-id <draft-id> \\
|
|
573
|
-
--source-node-id <node-id> \\
|
|
574
|
-
--pages '[{"title":"Cart","prompt":"Create cart page"},{"title":"Payment","prompt":"Create payment form"}]' \\
|
|
575
|
-
--json
|
|
576
|
-
\`\`\`
|
|
533
|
+
### A) Extract from codebase
|
|
577
534
|
|
|
578
|
-
|
|
579
|
-
-
|
|
580
|
-
-
|
|
581
|
-
-
|
|
582
|
-
-
|
|
535
|
+
1. Investigate codebase:
|
|
536
|
+
- design tokens, typography, colors, spacing, radius, shadows
|
|
537
|
+
- motion/animation patterns
|
|
538
|
+
- example components usage + implementation patterns
|
|
539
|
+
- core product functions + key pages
|
|
540
|
+
2. Write standalone design system to:
|
|
541
|
+
- \`.superdesign/design-system.md\`
|
|
542
|
+
- Must be implementable without the codebase
|
|
583
543
|
|
|
584
|
-
|
|
585
|
-
\`\`\`json
|
|
586
|
-
{
|
|
587
|
-
"drafts": [
|
|
588
|
-
{
|
|
589
|
-
"index": 0,
|
|
590
|
-
"draftId": "uuid",
|
|
591
|
-
"nodeId": "uuid",
|
|
592
|
-
"title": "Cart",
|
|
593
|
-
"nodeUrl": "https://...",
|
|
594
|
-
"previewUrl": "https://..."
|
|
595
|
-
}
|
|
596
|
-
],
|
|
597
|
-
"projectUrl": "https://...",
|
|
598
|
-
"creditsConsumed": 2
|
|
599
|
-
}
|
|
600
|
-
\`\`\`
|
|
544
|
+
### B) Create a new design system (to improve current UI)
|
|
601
545
|
|
|
602
|
-
|
|
546
|
+
1. Investigate codebase to understand product + needed pages/components
|
|
547
|
+
2. Gather inspirations (generic tools):
|
|
548
|
+
- \`superdesign search-prompts --tags "style" --json\`
|
|
549
|
+
- \`superdesign get-prompts --slugs ... --json\`
|
|
550
|
+
- optional: \`superdesign extract-brand-guide --url ... --json\`
|
|
551
|
+
3. Interview user (\`askQuestion\`) to choose direction
|
|
552
|
+
4. Write:
|
|
553
|
+
- \`.superdesign/design-system.md\` (adapted to product + references)
|
|
603
554
|
|
|
604
|
-
|
|
555
|
+
---
|
|
605
556
|
|
|
606
|
-
|
|
607
|
-
# 1. Create project
|
|
608
|
-
PROJECT=$(superdesign create-project --title "Landing Page" --json)
|
|
609
|
-
PROJECT_ID=$(echo $PROJECT | jq -r '.projectId')
|
|
557
|
+
# 2) Designing X (feature/page/flow)
|
|
610
558
|
|
|
611
|
-
|
|
612
|
-
DRAFT=$(superdesign create-design-draft \\
|
|
613
|
-
--project-id $PROJECT_ID \\
|
|
614
|
-
--title "Hero" \\
|
|
615
|
-
--prompt "Modern SaaS landing page hero with gradient, CTA button" \\
|
|
616
|
-
--json)
|
|
559
|
+
## A) If user wants references / direction only (no canvas)
|
|
617
560
|
|
|
618
|
-
|
|
619
|
-
|
|
561
|
+
1. Ensure \`.superdesign/design-system.md\` exists (setup if missing)
|
|
562
|
+
2. Use inspiration tools to collect references:
|
|
563
|
+
- search prompts (style + component/page)
|
|
564
|
+
- get prompts (full details)
|
|
565
|
+
- extract brand guide if relevant
|
|
566
|
+
3. Provide a concrete design spec:
|
|
567
|
+
- layout + hierarchy
|
|
568
|
+
- component set + states
|
|
569
|
+
- token guidance (typography/color/spacing/radius/motion)
|
|
570
|
+
- interaction notes + edge cases
|
|
571
|
+
|
|
572
|
+
## B) If user wants visual exploration (canvas optional)
|
|
573
|
+
|
|
574
|
+
Use canvas when direction is uncertain or multiple options are needed.
|
|
575
|
+
|
|
576
|
+
### Canvas workflow — Add feature to existing page
|
|
577
|
+
|
|
578
|
+
1. Ensure \`.superdesign/design-system.md\` exists (setup if missing)
|
|
579
|
+
2. Build prototype HTML playground (simplified + pixel-perfect enough):
|
|
580
|
+
- \`.superdesign/playgrounds/<page>-<feature>.html\`
|
|
581
|
+
3. Ask targeted questions (\`askQuestion\`) about requirements + taste
|
|
582
|
+
4. Create project with playground HTML (returns \`draftId\`):
|
|
583
|
+
\`\`\`bash
|
|
584
|
+
superdesign create-project \\
|
|
585
|
+
--title "<feature>" \\
|
|
586
|
+
--html-file .superdesign/playgrounds/<file>.html \\
|
|
587
|
+
--prompt-file .superdesign/design-system.md \\
|
|
588
|
+
--json
|
|
589
|
+
\`\`\`
|
|
590
|
+
→ Note: \`draftId\` in response is the baseline draft
|
|
591
|
+
5. Branch designs from baseline (use \`draftId\` from step 4):
|
|
592
|
+
\`\`\`bash
|
|
593
|
+
superdesign iterate-design-draft \\
|
|
594
|
+
--draft-id <draftId> \\
|
|
595
|
+
--prompt "<design requirements>" \\
|
|
596
|
+
--mode branch \\
|
|
597
|
+
--count 3 \\
|
|
598
|
+
--json
|
|
599
|
+
\`\`\`
|
|
600
|
+
6. Share \`previewUrl\` → collect feedback → iterate
|
|
601
|
+
|
|
602
|
+
### Canvas workflow — Add new page
|
|
620
603
|
|
|
621
|
-
|
|
604
|
+
Same as above, but playground should include shared UI shell:
|
|
605
|
+
- nav, layout container, spacing rhythm, shared components
|
|
606
|
+
|
|
607
|
+
### Canvas workflow — Improve current UI
|
|
608
|
+
|
|
609
|
+
1. Investigate product + current UI states
|
|
610
|
+
2. Ensure design system exists
|
|
611
|
+
3. Propose improvement options:
|
|
612
|
+
- big restructure
|
|
613
|
+
- style uplift
|
|
614
|
+
- low-hanging polish
|
|
615
|
+
4. Pick one → build playground → create project (prompt-file design system) → branch drafts
|
|
616
|
+
5. Share \`previewUrl\` → iterate
|
|
617
|
+
|
|
618
|
+
### When to use create-design-draft
|
|
619
|
+
|
|
620
|
+
Only use \`create-design-draft\` when creating from scratch (no HTML baseline).
|
|
621
|
+
|
|
622
|
+
**Required in prompt:**
|
|
623
|
+
- Full page structure (header, sidebar, main content areas)
|
|
624
|
+
- Component environment/surroundings
|
|
625
|
+
- Layout context (what's above/below/beside)
|
|
622
626
|
|
|
623
627
|
\`\`\`bash
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
--
|
|
627
|
-
--prompt "
|
|
628
|
-
--
|
|
629
|
-
--count 2 \\
|
|
628
|
+
superdesign create-design-draft \\
|
|
629
|
+
--project-id <id> \\
|
|
630
|
+
--title "Feature X" \\
|
|
631
|
+
--prompt "Page has: fixed header 64px, left sidebar 240px, main content area. Design a settings panel in the main content area with..." \\
|
|
632
|
+
--device desktop \\
|
|
630
633
|
--json
|
|
631
634
|
\`\`\`
|
|
632
635
|
|
|
633
|
-
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
# Advanced usage
|
|
634
639
|
|
|
640
|
+
### Plan + generate a full user journey
|
|
641
|
+
|
|
642
|
+
Plan:
|
|
635
643
|
\`\`\`bash
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
--
|
|
639
|
-
--
|
|
640
|
-
--
|
|
641
|
-
|
|
644
|
+
superdesign plan-flow-pages \\
|
|
645
|
+
--draft-id <draftId> \\
|
|
646
|
+
--source-node-id <nodeId> \\
|
|
647
|
+
--context "<flow context>" \\
|
|
648
|
+
--json
|
|
649
|
+
\`\`\`
|
|
642
650
|
|
|
643
|
-
|
|
644
|
-
|
|
651
|
+
Execute:
|
|
652
|
+
\`\`\`bash
|
|
645
653
|
superdesign execute-flow-pages \\
|
|
646
|
-
--draft-id <
|
|
647
|
-
--source-node-id <
|
|
648
|
-
--pages "
|
|
654
|
+
--draft-id <draftId> \\
|
|
655
|
+
--source-node-id <nodeId> \\
|
|
656
|
+
--pages '[{"title":"Signup","prompt":"..."},{"title":"Payment","prompt":"..."}]' \\
|
|
649
657
|
--json
|
|
650
658
|
\`\`\`
|
|
651
659
|
|
|
660
|
+
### Get HTML reference from a draft
|
|
661
|
+
|
|
662
|
+
\`\`\`bash
|
|
663
|
+
superdesign get-design --draft-id <draftId> --output ./design.html
|
|
664
|
+
\`\`\`
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## Quick reference (key commands)
|
|
669
|
+
|
|
670
|
+
\`\`\`bash
|
|
671
|
+
# Inspirations
|
|
672
|
+
superdesign search-prompts --keyword "<keyword>" --json
|
|
673
|
+
superdesign search-prompts --tags "style" --json
|
|
674
|
+
superdesign get-prompts --slugs "<slug1,slug2>" --json
|
|
675
|
+
superdesign extract-brand-guide --url https://example.com --json
|
|
676
|
+
|
|
677
|
+
# Canvas
|
|
678
|
+
superdesign create-project --title "X" --prompt "..." --json
|
|
679
|
+
superdesign create-project --title "X" --prompt-file .superdesign/design-system.md --json
|
|
680
|
+
superdesign create-project --title "X" --html-file ./index.html --prompt-file .superdesign/design-system.md --json
|
|
652
681
|
|
|
653
|
-
|
|
682
|
+
superdesign create-design-draft --project-id <id> --title "X" --prompt "..." --device desktop --json
|
|
683
|
+
superdesign iterate-design-draft --draft-id <id> --prompt "..." --mode replace --json
|
|
684
|
+
superdesign iterate-design-draft --draft-id <id> --prompt "..." --mode branch --count 3 --json
|
|
654
685
|
|
|
655
|
-
-
|
|
656
|
-
-
|
|
657
|
-
|
|
658
|
-
- The \`previewUrl\` can be used to view designs without authentication
|
|
686
|
+
superdesign fetch-design-nodes --project-id <id> --json
|
|
687
|
+
superdesign get-design --draft-id <id> --json
|
|
688
|
+
\`\`\`
|
|
659
689
|
`;
|
|
660
690
|
}
|
|
691
|
+
function ensureGitignoreEntry(gitignorePath, entry) {
|
|
692
|
+
if (existsSync(gitignorePath)) {
|
|
693
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
694
|
+
const hasEntry = content.split('\n').some((line)=>line.trim() === entry);
|
|
695
|
+
if (hasEntry) return false;
|
|
696
|
+
const prefix = content.endsWith('\n') ? '' : '\n';
|
|
697
|
+
appendFileSync(gitignorePath, `${prefix}${entry}\n`, 'utf-8');
|
|
698
|
+
return true;
|
|
699
|
+
}
|
|
700
|
+
writeFileSync(gitignorePath, `${entry}\n`, 'utf-8');
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
661
703
|
function createInitCommand() {
|
|
662
704
|
const command = new Command('init').description('Install SuperDesign skill files for Claude Code (auto-login if needed)').option('--json', 'Output in JSON format').option('--force', 'Overwrite existing skill files').action(async (options)=>{
|
|
663
705
|
if (options.json) setJsonMode(true);
|
|
@@ -694,14 +736,19 @@ function createInitCommand() {
|
|
|
694
736
|
});
|
|
695
737
|
const skillContent = getSkillTemplate();
|
|
696
738
|
writeFileSync(skillFilePath, skillContent, 'utf-8');
|
|
739
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
740
|
+
const gitignoreEntry = '.superdesign';
|
|
741
|
+
const gitignoreUpdated = ensureGitignoreEntry(gitignorePath, gitignoreEntry);
|
|
697
742
|
if (isJsonMode()) output({
|
|
698
743
|
success: true,
|
|
699
744
|
path: skillFilePath,
|
|
745
|
+
gitignoreUpdated,
|
|
700
746
|
message: 'Skill files installed successfully'
|
|
701
747
|
});
|
|
702
748
|
else {
|
|
703
749
|
success('Skill files installed successfully!');
|
|
704
750
|
info(`\nSkill file created at: ${skillFilePath}`);
|
|
751
|
+
if (gitignoreUpdated) info(".gitignore updated to exclude .superdesign directory");
|
|
705
752
|
info('\nClaude Code will now have access to SuperDesign commands.');
|
|
706
753
|
info('Available commands:');
|
|
707
754
|
info(' - superdesign create-project');
|
|
@@ -709,6 +756,7 @@ function createInitCommand() {
|
|
|
709
756
|
info(' - superdesign iterate-design-draft');
|
|
710
757
|
info(' - superdesign plan-flow-pages');
|
|
711
758
|
info(' - superdesign execute-flow-pages');
|
|
759
|
+
info(' - superdesign extract-brand-guide');
|
|
712
760
|
}
|
|
713
761
|
} catch (err) {
|
|
714
762
|
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
@@ -729,7 +777,7 @@ async function addDraft(projectId, data) {
|
|
|
729
777
|
return response.data;
|
|
730
778
|
}
|
|
731
779
|
function createCreateProjectCommand() {
|
|
732
|
-
const command = new Command('create-project').description('Create a new SuperDesign project').requiredOption('--title <title>', 'Project title').option('--html <html>', 'Initial HTML content for first draft').option('--html-file <path>', 'Path to HTML file for first draft').option('--device <mode>', 'Device mode for draft (mobile, tablet, desktop)', 'desktop').option('--json', 'Output in JSON format').action(async (options)=>{
|
|
780
|
+
const command = new Command('create-project').description('Create a new SuperDesign project').requiredOption('--title <title>', 'Project title').option('--html <html>', 'Initial HTML content for first draft').option('--html-file <path>', 'Path to HTML file for first draft').option('--prompt <prompt>', 'System prompt for the AI agent').option('--prompt-file <path>', 'Path to markdown file containing system prompt').option('--device <mode>', 'Device mode for draft (mobile, tablet, desktop)', 'desktop').option('--json', 'Output in JSON format').option('--no-open', 'Do not open project in browser after creation').action(async (options)=>{
|
|
733
781
|
if (options.json) setJsonMode(true);
|
|
734
782
|
try {
|
|
735
783
|
if (!manager_isAuthenticated()) {
|
|
@@ -752,40 +800,43 @@ function createCreateProjectCommand() {
|
|
|
752
800
|
}
|
|
753
801
|
htmlContent = readFileSync(options.htmlFile, 'utf-8');
|
|
754
802
|
} else if (options.html) htmlContent = options.html;
|
|
803
|
+
let promptContent;
|
|
804
|
+
if (options.promptFile) {
|
|
805
|
+
if (!existsSync(options.promptFile)) {
|
|
806
|
+
output_error(`Prompt file not found: ${options.promptFile}`);
|
|
807
|
+
process.exit(EXIT_CODES.VALIDATION_ERROR);
|
|
808
|
+
}
|
|
809
|
+
promptContent = readFileSync(options.promptFile, 'utf-8');
|
|
810
|
+
} else if (options.prompt) promptContent = options.prompt;
|
|
755
811
|
startSpinner('Creating project...');
|
|
756
812
|
const project = await createProject({
|
|
757
|
-
title: options.title
|
|
758
|
-
});
|
|
759
|
-
let draftResult = null;
|
|
760
|
-
if (htmlContent) draftResult = await addDraft(project.projectId, {
|
|
761
|
-
title: 'Initial Draft',
|
|
813
|
+
title: options.title,
|
|
762
814
|
html: htmlContent,
|
|
815
|
+
prompt: promptContent,
|
|
763
816
|
deviceMode: options.device
|
|
764
817
|
});
|
|
765
818
|
succeedSpinner('Project created successfully!');
|
|
766
|
-
|
|
819
|
+
if (options.open) {
|
|
820
|
+
const urlWithLive = `${project.projectUrl}?live=1`;
|
|
821
|
+
await openBrowser(urlWithLive);
|
|
822
|
+
}
|
|
823
|
+
if (isJsonMode()) output({
|
|
767
824
|
projectId: project.projectId,
|
|
768
825
|
title: project.title,
|
|
769
826
|
projectUrl: project.projectUrl,
|
|
770
827
|
shareToken: project.shareToken,
|
|
771
|
-
...
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
nodeId: draftResult.nodeId,
|
|
775
|
-
nodeUrl: draftResult.nodeUrl,
|
|
776
|
-
previewUrl: draftResult.previewUrl
|
|
777
|
-
}
|
|
828
|
+
...project.draftId && {
|
|
829
|
+
draftId: project.draftId,
|
|
830
|
+
previewUrl: project.previewUrl
|
|
778
831
|
}
|
|
779
|
-
};
|
|
780
|
-
if (isJsonMode()) output(result);
|
|
832
|
+
});
|
|
781
833
|
else {
|
|
782
834
|
success(`Project "${project.title}" created!`);
|
|
783
835
|
info(`\nProject ID: ${project.projectId}`);
|
|
784
836
|
info(`Project URL: ${project.projectUrl}`);
|
|
785
|
-
if (
|
|
786
|
-
info(`\nDraft ID: ${
|
|
787
|
-
info(`
|
|
788
|
-
info(`Preview URL: ${draftResult.previewUrl}`);
|
|
837
|
+
if (project.draftId) {
|
|
838
|
+
info(`\nDraft ID: ${project.draftId}`);
|
|
839
|
+
info(`Preview URL: ${project.previewUrl}`);
|
|
789
840
|
}
|
|
790
841
|
}
|
|
791
842
|
} catch (err) {
|
|
@@ -894,6 +945,22 @@ function job_runner_requireAuth(isAuthenticated) {
|
|
|
894
945
|
process.exit(EXIT_CODES.AUTH_REQUIRED);
|
|
895
946
|
}
|
|
896
947
|
}
|
|
948
|
+
function handleApiError(err, failureMessage) {
|
|
949
|
+
if (err instanceof ApiClientError) {
|
|
950
|
+
if (isJsonMode()) output({
|
|
951
|
+
error: err.message,
|
|
952
|
+
code: err.code
|
|
953
|
+
});
|
|
954
|
+
else output_error(`API Error: ${err.message}`);
|
|
955
|
+
process.exit(EXIT_CODES.API_ERROR);
|
|
956
|
+
}
|
|
957
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
958
|
+
if (isJsonMode()) output({
|
|
959
|
+
error: message
|
|
960
|
+
});
|
|
961
|
+
else output_error(`${failureMessage}: ${message}`);
|
|
962
|
+
process.exit(EXIT_CODES.GENERAL_ERROR);
|
|
963
|
+
}
|
|
897
964
|
function createCreateDesignDraftCommand() {
|
|
898
965
|
const command = new Command('create-design-draft').description('Create a design draft using AI generation').requiredOption('--project-id <id>', 'Project ID').requiredOption('--title <title>', 'Draft title').requiredOption('--prompt <prompt>', 'Design prompt for AI generation').option('--device <mode>', 'Device mode (mobile, tablet, desktop)', 'desktop').option('--json', 'Output in JSON format').action(async (options)=>{
|
|
899
966
|
if (options.json) setJsonMode(true);
|
|
@@ -1081,6 +1148,260 @@ function createExecuteFlowPagesCommand() {
|
|
|
1081
1148
|
});
|
|
1082
1149
|
return command;
|
|
1083
1150
|
}
|
|
1151
|
+
async function extractBrandGuide(url) {
|
|
1152
|
+
const client = getApiClient();
|
|
1153
|
+
const response = await client.post('/external/brand/extract', {
|
|
1154
|
+
url
|
|
1155
|
+
});
|
|
1156
|
+
return response.data;
|
|
1157
|
+
}
|
|
1158
|
+
function extractDomain(url) {
|
|
1159
|
+
try {
|
|
1160
|
+
const parsed = new URL(url);
|
|
1161
|
+
return parsed.hostname.replace(/^www\./, '');
|
|
1162
|
+
} catch {
|
|
1163
|
+
return url.replace(/[^a-zA-Z0-9.-]/g, '_');
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
async function downloadFile(url, outputPath) {
|
|
1167
|
+
try {
|
|
1168
|
+
const response = await fetch(url);
|
|
1169
|
+
if (!response.ok) return false;
|
|
1170
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
1171
|
+
writeFileSync(outputPath, buffer);
|
|
1172
|
+
return true;
|
|
1173
|
+
} catch {
|
|
1174
|
+
return false;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
function createExtractBrandGuideCommand() {
|
|
1178
|
+
const command = new Command('extract-brand-guide').description('Extract brand guidelines from a website URL').requiredOption('--url <url>', 'Website URL to extract brand guide from').option('--output-dir <path>', 'Output directory (default: .superdesign/brand_styles/<domain>)').option('--json', 'Output in JSON format').action(async (options)=>{
|
|
1179
|
+
if (options.json) setJsonMode(true);
|
|
1180
|
+
job_runner_requireAuth(manager_isAuthenticated);
|
|
1181
|
+
const spinner = isJsonMode() ? null : ora('Extracting brand guide...').start();
|
|
1182
|
+
try {
|
|
1183
|
+
const result = await extractBrandGuide(options.url);
|
|
1184
|
+
if (!result.success) {
|
|
1185
|
+
if (spinner) spinner.fail('Failed to extract brand guide');
|
|
1186
|
+
if (isJsonMode()) output({
|
|
1187
|
+
success: false,
|
|
1188
|
+
error: result.error || 'Failed to extract brand guide'
|
|
1189
|
+
});
|
|
1190
|
+
else output_error(result.error || 'Failed to extract brand guide');
|
|
1191
|
+
process.exit(EXIT_CODES.API_ERROR);
|
|
1192
|
+
}
|
|
1193
|
+
if (spinner) spinner.succeed('Brand guide extracted successfully');
|
|
1194
|
+
const domain = extractDomain(options.url);
|
|
1195
|
+
const cwd = process.cwd();
|
|
1196
|
+
const outputDir = options.outputDir || join(cwd, '.superdesign', 'brand_styles', domain);
|
|
1197
|
+
mkdirSync(outputDir, {
|
|
1198
|
+
recursive: true
|
|
1199
|
+
});
|
|
1200
|
+
const jsonPath = join(outputDir, 'brand-guide.json');
|
|
1201
|
+
writeFileSync(jsonPath, JSON.stringify(result, null, 2), 'utf-8');
|
|
1202
|
+
let screenshotSaved = false;
|
|
1203
|
+
if (result.data?.screenshot?.url) {
|
|
1204
|
+
const screenshotPath = join(outputDir, 'screenshot.png');
|
|
1205
|
+
const downloadSpinner = isJsonMode() ? null : ora('Downloading screenshot...').start();
|
|
1206
|
+
screenshotSaved = await downloadFile(result.data.screenshot.url, screenshotPath);
|
|
1207
|
+
if (downloadSpinner) if (screenshotSaved) downloadSpinner.succeed('Screenshot downloaded');
|
|
1208
|
+
else downloadSpinner.warn('Could not download screenshot');
|
|
1209
|
+
}
|
|
1210
|
+
if (isJsonMode()) output({
|
|
1211
|
+
success: true,
|
|
1212
|
+
outputDir,
|
|
1213
|
+
files: {
|
|
1214
|
+
brandGuide: jsonPath,
|
|
1215
|
+
screenshot: screenshotSaved ? join(outputDir, 'screenshot.png') : null
|
|
1216
|
+
},
|
|
1217
|
+
data: result.data
|
|
1218
|
+
});
|
|
1219
|
+
else {
|
|
1220
|
+
success('Brand guide saved!');
|
|
1221
|
+
if (screenshotSaved) info(`\nScreenshot: ${join(outputDir, 'screenshot.png')}`);
|
|
1222
|
+
info(`Extracted brand style JSON: ${jsonPath}`);
|
|
1223
|
+
}
|
|
1224
|
+
} catch (err) {
|
|
1225
|
+
if (spinner) spinner.fail('Failed to extract brand guide');
|
|
1226
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
1227
|
+
if (isJsonMode()) output({
|
|
1228
|
+
success: false,
|
|
1229
|
+
error: message
|
|
1230
|
+
});
|
|
1231
|
+
else output_error(`Failed to extract brand guide: ${message}`);
|
|
1232
|
+
process.exit(EXIT_CODES.API_ERROR);
|
|
1233
|
+
}
|
|
1234
|
+
});
|
|
1235
|
+
return command;
|
|
1236
|
+
}
|
|
1237
|
+
async function searchPrompts(data) {
|
|
1238
|
+
const client = getApiClient();
|
|
1239
|
+
const response = await client.post('/external/prompts/search', data);
|
|
1240
|
+
return response.data;
|
|
1241
|
+
}
|
|
1242
|
+
async function getPrompts(data) {
|
|
1243
|
+
const client = getApiClient();
|
|
1244
|
+
const response = await client.post('/external/prompts/get', data);
|
|
1245
|
+
return response.data;
|
|
1246
|
+
}
|
|
1247
|
+
function createSearchPromptsCommand() {
|
|
1248
|
+
const command = new Command('search-prompts').description('Search public prompts in the library').option('--keyword <text>', "Search keyword (searches title and description)").option('--tags <tags>', 'Comma-separated tags to filter by').option('--limit <n>', 'Maximum number of results (default: 20, max: 100)').option('--offset <n>', 'Number of results to skip (for pagination)').option('--json', 'Output in JSON format').action(async (options)=>{
|
|
1249
|
+
if (options.json) setJsonMode(true);
|
|
1250
|
+
job_runner_requireAuth(manager_isAuthenticated);
|
|
1251
|
+
const spinner = isJsonMode() ? null : ora('Searching prompts...').start();
|
|
1252
|
+
try {
|
|
1253
|
+
const tags = options.tags ? options.tags.split(',').map((t)=>t.trim()) : void 0;
|
|
1254
|
+
const limit = options.limit ? parseInt(options.limit, 10) : 20;
|
|
1255
|
+
const offset = options.offset ? parseInt(options.offset, 10) : 0;
|
|
1256
|
+
const result = await searchPrompts({
|
|
1257
|
+
keyword: options.keyword,
|
|
1258
|
+
tags,
|
|
1259
|
+
limit,
|
|
1260
|
+
offset
|
|
1261
|
+
});
|
|
1262
|
+
if (spinner) spinner.succeed(`Found ${result.prompts.length} prompts (total: ${result.total})`);
|
|
1263
|
+
if (isJsonMode()) output(result);
|
|
1264
|
+
else if (0 === result.prompts.length) info('\nNo prompts found matching your criteria.');
|
|
1265
|
+
else {
|
|
1266
|
+
success(`\nFound ${result.prompts.length} prompts:\n`);
|
|
1267
|
+
result.prompts.forEach((prompt, index)=>{
|
|
1268
|
+
const tagsStr = prompt.tags.length > 0 ? ` [${prompt.tags.join(', ')}]` : '';
|
|
1269
|
+
console.log(`${index + 1}. "${prompt.title}"${tagsStr}`);
|
|
1270
|
+
if (prompt.description) {
|
|
1271
|
+
const desc = prompt.description.length > 100 ? prompt.description.substring(0, 97) + '...' : prompt.description;
|
|
1272
|
+
console.log(` ${desc}`);
|
|
1273
|
+
}
|
|
1274
|
+
console.log(` Views: ${prompt.viewCount} | Remixes: ${prompt.remixCount}`);
|
|
1275
|
+
if (prompt.previewUrl) console.log(` Preview: ${prompt.previewUrl}`);
|
|
1276
|
+
console.log(` Slug: ${prompt.slug}`);
|
|
1277
|
+
console.log('');
|
|
1278
|
+
});
|
|
1279
|
+
if (result.total > result.prompts.length) info(`Showing ${result.prompts.length} of ${result.total} results. Use --offset to paginate.`);
|
|
1280
|
+
}
|
|
1281
|
+
} catch (err) {
|
|
1282
|
+
if (spinner) spinner.fail('Failed to search prompts');
|
|
1283
|
+
handleApiError(err, 'Failed to search prompts');
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
return command;
|
|
1287
|
+
}
|
|
1288
|
+
function createGetPromptsCommand() {
|
|
1289
|
+
const command = new Command('get-prompts').description('Get prompts by their slugs').requiredOption('--slugs <slugs>', 'Comma-separated list of prompt slugs').option('--json', 'Output in JSON format').action(async (options)=>{
|
|
1290
|
+
if (options.json) setJsonMode(true);
|
|
1291
|
+
job_runner_requireAuth(manager_isAuthenticated);
|
|
1292
|
+
const slugs = options.slugs.split(',').map((s)=>s.trim());
|
|
1293
|
+
if (0 === slugs.length) {
|
|
1294
|
+
output_error('At least one slug is required');
|
|
1295
|
+
process.exit(EXIT_CODES.VALIDATION_ERROR);
|
|
1296
|
+
}
|
|
1297
|
+
if (slugs.length > 20) {
|
|
1298
|
+
output_error('Maximum 20 slugs allowed per request');
|
|
1299
|
+
process.exit(EXIT_CODES.VALIDATION_ERROR);
|
|
1300
|
+
}
|
|
1301
|
+
const spinner = isJsonMode() ? null : ora(`Fetching ${slugs.length} prompt(s)...`).start();
|
|
1302
|
+
try {
|
|
1303
|
+
const result = await getPrompts({
|
|
1304
|
+
slugs
|
|
1305
|
+
});
|
|
1306
|
+
if (spinner) spinner.succeed(`Retrieved ${result.prompts.length} of ${slugs.length} prompts`);
|
|
1307
|
+
if (isJsonMode()) output(result);
|
|
1308
|
+
else if (0 === result.prompts.length) info('\nNo prompts found for the provided slugs.');
|
|
1309
|
+
else {
|
|
1310
|
+
result.prompts.forEach((prompt, index)=>{
|
|
1311
|
+
if (index > 0) console.log('\n' + '='.repeat(60) + '\n');
|
|
1312
|
+
success(`Prompt: "${prompt.title}"`);
|
|
1313
|
+
info(`Slug: ${prompt.slug}`);
|
|
1314
|
+
if (prompt.tags.length > 0) info(`Tags: ${prompt.tags.join(', ')}`);
|
|
1315
|
+
if (prompt.description) console.log(`\nDescription: ${prompt.description}`);
|
|
1316
|
+
console.log('\n---');
|
|
1317
|
+
console.log(prompt.prompt);
|
|
1318
|
+
console.log('---\n');
|
|
1319
|
+
console.log(`Views: ${prompt.viewCount} | Remixes: ${prompt.remixCount}`);
|
|
1320
|
+
if (prompt.previewUrl) info(`Preview: ${prompt.previewUrl}`);
|
|
1321
|
+
if (prompt.images && prompt.images.length > 0) info(`Images: ${prompt.images.length} attached`);
|
|
1322
|
+
});
|
|
1323
|
+
const foundSlugs = result.prompts.map((p)=>p.slug);
|
|
1324
|
+
const missingSlugs = slugs.filter((s)=>!foundSlugs.includes(s));
|
|
1325
|
+
if (missingSlugs.length > 0) {
|
|
1326
|
+
console.log('');
|
|
1327
|
+
info(`Note: ${missingSlugs.length} slug(s) not found: ${missingSlugs.join(', ')}`);
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
} catch (err) {
|
|
1331
|
+
if (spinner) spinner.fail('Failed to get prompts');
|
|
1332
|
+
handleApiError(err, 'Failed to get prompts');
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
return command;
|
|
1336
|
+
}
|
|
1337
|
+
async function fetchDesignNodes(projectId) {
|
|
1338
|
+
const client = getApiClient();
|
|
1339
|
+
const response = await client.get(`/external/projects/${projectId}/design-nodes`);
|
|
1340
|
+
return response.data;
|
|
1341
|
+
}
|
|
1342
|
+
async function getDesignHtml(draftId) {
|
|
1343
|
+
const client = getApiClient();
|
|
1344
|
+
const response = await client.get(`/external/drafts/${draftId}/html`);
|
|
1345
|
+
return response.data;
|
|
1346
|
+
}
|
|
1347
|
+
function displayNode(node, index) {
|
|
1348
|
+
console.log(`${index + 1}. "${node.title}" (depth: ${node.iterationDepth})`);
|
|
1349
|
+
info(node.parentDraftId ? ` Parent: ${node.parentDraftId}` : ' Root draft');
|
|
1350
|
+
if (node.description) console.log(` ${node.description}`);
|
|
1351
|
+
info(` Preview: ${node.previewUrl}`);
|
|
1352
|
+
if (node.screenshot) info(` Screenshot: ${node.screenshot.url}`);
|
|
1353
|
+
console.log(` Created: ${node.createdAt}\n`);
|
|
1354
|
+
}
|
|
1355
|
+
function createFetchDesignNodesCommand() {
|
|
1356
|
+
const command = new Command('fetch-design-nodes').description('Get all design draft nodes for a project').requiredOption('--project-id <projectId>', 'Project ID to fetch nodes from').option('--json', 'Output in JSON format').action(async (options)=>{
|
|
1357
|
+
if (options.json) setJsonMode(true);
|
|
1358
|
+
job_runner_requireAuth(manager_isAuthenticated);
|
|
1359
|
+
const spinner = isJsonMode() ? null : ora('Fetching design nodes...').start();
|
|
1360
|
+
try {
|
|
1361
|
+
const result = await fetchDesignNodes(options.projectId);
|
|
1362
|
+
if (spinner) spinner.succeed(`Found ${result.nodes.length} design node(s)`);
|
|
1363
|
+
if (isJsonMode()) return void output(result);
|
|
1364
|
+
if (0 === result.nodes.length) return void info('\nNo design nodes found in this project.');
|
|
1365
|
+
console.log(`\nFound ${result.nodes.length} design node(s):\n`);
|
|
1366
|
+
result.nodes.forEach(displayNode);
|
|
1367
|
+
} catch (err) {
|
|
1368
|
+
if (spinner) spinner.fail('Failed to fetch design nodes');
|
|
1369
|
+
handleApiError(err, 'Failed to fetch design nodes');
|
|
1370
|
+
}
|
|
1371
|
+
});
|
|
1372
|
+
return command;
|
|
1373
|
+
}
|
|
1374
|
+
async function writeHtmlToFile(result, outputPath) {
|
|
1375
|
+
const resolvedPath = external_path_resolve(process.cwd(), outputPath);
|
|
1376
|
+
await writeFile(resolvedPath, result.htmlContent, 'utf-8');
|
|
1377
|
+
if (isJsonMode()) output({
|
|
1378
|
+
...result,
|
|
1379
|
+
savedTo: resolvedPath
|
|
1380
|
+
});
|
|
1381
|
+
else {
|
|
1382
|
+
success(`HTML written to: ${resolvedPath}`);
|
|
1383
|
+
info(`Title: ${result.title}`);
|
|
1384
|
+
info(`Draft ID: ${result.draftId}`);
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
function createGetDesignCommand() {
|
|
1388
|
+
const command = new Command('get-design').description('Get HTML content for a specific draft').requiredOption('--draft-id <draftId>', 'Draft ID to fetch').option('--json', 'Output in JSON format').option('--output <path>', 'Write HTML to file instead of stdout').action(async (options)=>{
|
|
1389
|
+
if (options.json) setJsonMode(true);
|
|
1390
|
+
job_runner_requireAuth(manager_isAuthenticated);
|
|
1391
|
+
const spinner = isJsonMode() ? null : ora('Fetching design HTML...').start();
|
|
1392
|
+
try {
|
|
1393
|
+
const result = await getDesignHtml(options.draftId);
|
|
1394
|
+
if (spinner) spinner.succeed(`Retrieved design: "${result.title}"`);
|
|
1395
|
+
if (options.output) return void await writeHtmlToFile(result, options.output);
|
|
1396
|
+
if (isJsonMode()) return void output(result);
|
|
1397
|
+
console.log(result.htmlContent);
|
|
1398
|
+
} catch (err) {
|
|
1399
|
+
if (spinner) spinner.fail('Failed to get design HTML');
|
|
1400
|
+
handleApiError(err, 'Failed to get design HTML');
|
|
1401
|
+
}
|
|
1402
|
+
});
|
|
1403
|
+
return command;
|
|
1404
|
+
}
|
|
1084
1405
|
const src_filename = fileURLToPath(import.meta.url);
|
|
1085
1406
|
const src_dirname = dirname(src_filename);
|
|
1086
1407
|
external_dotenv_config({
|
|
@@ -1098,10 +1419,15 @@ function createProgram() {
|
|
|
1098
1419
|
program.addCommand(createIterateDesignDraftCommand());
|
|
1099
1420
|
program.addCommand(createPlanFlowPagesCommand());
|
|
1100
1421
|
program.addCommand(createExecuteFlowPagesCommand());
|
|
1422
|
+
program.addCommand(createExtractBrandGuideCommand());
|
|
1423
|
+
program.addCommand(createSearchPromptsCommand());
|
|
1424
|
+
program.addCommand(createGetPromptsCommand());
|
|
1425
|
+
program.addCommand(createFetchDesignNodesCommand());
|
|
1426
|
+
program.addCommand(createGetDesignCommand());
|
|
1101
1427
|
return program;
|
|
1102
1428
|
}
|
|
1103
1429
|
async function run() {
|
|
1104
1430
|
const program = createProgram();
|
|
1105
1431
|
await program.parseAsync(process.argv);
|
|
1106
1432
|
}
|
|
1107
|
-
export { ApiClientError, addDraft, claimSession, clearConfig, createApiClient, createDraft, createProgram, createProject, createPublicApiClient, createSession, executeFlowPages, getApiClient, getApiKey, getApiUrl, getConfigDir, getConfigPath, getJobStatus, manager_isAuthenticated as isAuthenticated, isJobCompleted, isJobDone, isJobFailed, iterateDraft, loadConfig, planFlowPages, pollSession, run, saveConfig, updateConfig };
|
|
1433
|
+
export { ApiClientError, addDraft, claimSession, clearConfig, createApiClient, createDraft, createProgram, createProject, createPublicApiClient, createSession, executeFlowPages, extractBrandGuide, fetchDesignNodes, getApiClient, getApiKey, getApiUrl, getConfigDir, getConfigPath, getDesignHtml, getJobStatus, getPrompts, manager_isAuthenticated as isAuthenticated, isJobCompleted, isJobDone, isJobFailed, iterateDraft, loadConfig, planFlowPages, pollSession, run, saveConfig, searchPrompts, updateConfig };
|