rafters 0.0.4 → 0.0.6
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/README.md +130 -0
- package/dist/index.js +299 -80
- package/package.json +2 -1
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# rafters
|
|
2
|
+
|
|
3
|
+
Design Intelligence CLI. Scaffold tokens, add components, and serve an MCP server so AI agents build UIs with designer-level judgment instead of guessing.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx rafters init
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install globally:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add -g rafters
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
### `rafters init`
|
|
20
|
+
|
|
21
|
+
Initialize a project with design tokens. Detects your framework, scaffolds `.rafters/` with a complete token system, and generates output files.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
rafters init # Interactive setup
|
|
25
|
+
rafters init --force # Regenerate output from existing config
|
|
26
|
+
rafters init --agent # JSON output for CI/machine consumption
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Supported frameworks:** Next.js, Vite, Remix, React Router, Astro
|
|
30
|
+
|
|
31
|
+
**Export formats** (configured during init):
|
|
32
|
+
|
|
33
|
+
| Format | File | Default | Description |
|
|
34
|
+
|--------|------|---------|-------------|
|
|
35
|
+
| Tailwind CSS | `rafters.css` | Yes | CSS custom properties with `@theme` |
|
|
36
|
+
| TypeScript | `rafters.ts` | Yes | Type-safe constants with JSDoc intelligence |
|
|
37
|
+
| DTCG JSON | `rafters.json` | No | W3C Design Tokens standard format |
|
|
38
|
+
| Compiled CSS | `rafters.compiled.css` | No | Pre-processed, no build step needed |
|
|
39
|
+
|
|
40
|
+
Automatically detects and migrates existing shadcn/ui color values. Requires Tailwind v4.
|
|
41
|
+
|
|
42
|
+
### `rafters add [components...]`
|
|
43
|
+
|
|
44
|
+
Add components from the Rafters registry to your project.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
rafters add button dialog # Add specific components
|
|
48
|
+
rafters add --list # List all available components
|
|
49
|
+
rafters add --overwrite # Replace existing files
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Components include embedded design intelligence: cognitive load ratings (1-7), accessibility requirements, do/never guidance, and trust-building patterns. Dependencies are resolved automatically.
|
|
53
|
+
|
|
54
|
+
### `rafters studio`
|
|
55
|
+
|
|
56
|
+
Launch Studio for visual token editing.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
rafters studio
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Opens a Vite-powered UI where you design by doing: pick a primary color, explain why, watch the system paint your scale. Every decision is recorded with reasoning so AI agents read intent instead of guessing.
|
|
63
|
+
|
|
64
|
+
### `rafters mcp`
|
|
65
|
+
|
|
66
|
+
Start the MCP server for AI agent access via stdio transport.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
rafters mcp
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## MCP Tools
|
|
73
|
+
|
|
74
|
+
Four tools give AI agents complete design system access:
|
|
75
|
+
|
|
76
|
+
### `rafters_vocabulary`
|
|
77
|
+
|
|
78
|
+
System overview. Colors, spacing, typography, components, cognitive loads, and available patterns. Call this first to orient.
|
|
79
|
+
|
|
80
|
+
### `rafters_pattern`
|
|
81
|
+
|
|
82
|
+
Deep guidance for specific UI scenarios. Returns which components to use, which tokens to apply, accessibility requirements, and do/never rules.
|
|
83
|
+
|
|
84
|
+
**Available patterns:** `destructive-action`, `form-validation`, `empty-state`, `loading-state`, `navigation-hierarchy`, `data-table`, `modal-dialog`, `tooltip-guidance`, `card-layout`, `dropdown-actions`
|
|
85
|
+
|
|
86
|
+
### `rafters_component`
|
|
87
|
+
|
|
88
|
+
Full intelligence for a specific component. Cognitive load rating, attention economics, accessibility requirements, trust-building patterns, variants, sizes, and primitives.
|
|
89
|
+
|
|
90
|
+
### `rafters_token`
|
|
91
|
+
|
|
92
|
+
Token dependency graph, derivation rules, and human override context. Returns how a token is computed, what it depends on, and whether a designer manually overrode it (with their reasoning).
|
|
93
|
+
|
|
94
|
+
**Derivation rules:** `calc()`, `state:hover`, `scale:600`, `contrast:auto`, `invert`
|
|
95
|
+
|
|
96
|
+
## How It Works
|
|
97
|
+
|
|
98
|
+
Rafters is a Design Intelligence Protocol. AI agents don't have taste - they guess at colors, spacing, hierarchy. Rafters encodes a designer's judgment into queryable data so AI reads decisions instead of guessing.
|
|
99
|
+
|
|
100
|
+
Three layers:
|
|
101
|
+
|
|
102
|
+
- **What** (Components) - 55 React components with embedded intelligence metadata
|
|
103
|
+
- **Where** (Tokens) - 240+ tokens with dependency graph and human override tracking
|
|
104
|
+
- **Why** (Decisions) - Do/never patterns, cognitive load scores, trust patterns, accessibility requirements
|
|
105
|
+
|
|
106
|
+
The token system uses OKLCH color space, modular scales based on musical ratios, and a dependency engine that automatically derives related values. When a designer overrides a computed value, the system records the reason so AI agents respect the intent.
|
|
107
|
+
|
|
108
|
+
## Project Structure
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
.rafters/
|
|
112
|
+
config.rafters.json # Framework paths and export settings
|
|
113
|
+
tokens/
|
|
114
|
+
color.rafters.json # Color tokens with OKLCH values
|
|
115
|
+
spacing.rafters.json # Spacing scale
|
|
116
|
+
typography.rafters.json # Type scale
|
|
117
|
+
output/
|
|
118
|
+
rafters.css # Tailwind CSS export
|
|
119
|
+
rafters.ts # TypeScript constants
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Requirements
|
|
123
|
+
|
|
124
|
+
- Node.js >= 24.12.0
|
|
125
|
+
- Tailwind CSS v4
|
|
126
|
+
- React >= 19.0.0
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Command } from "commander";
|
|
|
9
9
|
|
|
10
10
|
// src/commands/add.ts
|
|
11
11
|
import { existsSync } from "fs";
|
|
12
|
-
import { access, mkdir, writeFile } from "fs/promises";
|
|
12
|
+
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
13
13
|
import { dirname, join as join2 } from "path";
|
|
14
14
|
|
|
15
15
|
// ../../node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/external.js
|
|
@@ -12730,7 +12730,7 @@ function setAgentMode(agent) {
|
|
|
12730
12730
|
}
|
|
12731
12731
|
function log(event) {
|
|
12732
12732
|
if (context.agent) {
|
|
12733
|
-
console.log(event);
|
|
12733
|
+
console.log(JSON.stringify(event));
|
|
12734
12734
|
return;
|
|
12735
12735
|
}
|
|
12736
12736
|
const eventType = event.event;
|
|
@@ -12748,13 +12748,14 @@ function log(event) {
|
|
|
12748
12748
|
}
|
|
12749
12749
|
context.spinner = ora("Generating tokens...").start();
|
|
12750
12750
|
break;
|
|
12751
|
-
case "init:shadcn_detected":
|
|
12751
|
+
case "init:shadcn_detected": {
|
|
12752
12752
|
context.spinner?.info("Found existing shadcn colors");
|
|
12753
12753
|
console.log(` Backed up: ${event.backupPath}`);
|
|
12754
12754
|
const colors = event.colorsFound;
|
|
12755
12755
|
console.log(` Colors: ${colors.light} light, ${colors.dark} dark`);
|
|
12756
12756
|
context.spinner = ora("Generating tokens...").start();
|
|
12757
12757
|
break;
|
|
12758
|
+
}
|
|
12758
12759
|
case "init:generated":
|
|
12759
12760
|
context.spinner?.succeed(`Generated ${event.tokenCount} tokens`);
|
|
12760
12761
|
context.spinner = ora("Saving registry...").start();
|
|
@@ -12782,7 +12783,18 @@ function log(event) {
|
|
|
12782
12783
|
case "init:colors_imported":
|
|
12783
12784
|
console.log(` Imported ${event.count} existing colors`);
|
|
12784
12785
|
break;
|
|
12785
|
-
case "init:
|
|
12786
|
+
case "init:exports_default":
|
|
12787
|
+
console.log(" Using default exports (agent mode)");
|
|
12788
|
+
break;
|
|
12789
|
+
case "init:exports_selected":
|
|
12790
|
+
context.spinner = ora("Generating outputs...").start();
|
|
12791
|
+
break;
|
|
12792
|
+
case "init:compiling_css":
|
|
12793
|
+
if (context.spinner) {
|
|
12794
|
+
context.spinner.text = "Compiling CSS with Tailwind...";
|
|
12795
|
+
}
|
|
12796
|
+
break;
|
|
12797
|
+
case "init:complete": {
|
|
12786
12798
|
context.spinner?.succeed("Done!");
|
|
12787
12799
|
console.log(`
|
|
12788
12800
|
Output: ${event.path}`);
|
|
@@ -12792,12 +12804,14 @@ function log(event) {
|
|
|
12792
12804
|
}
|
|
12793
12805
|
console.log("");
|
|
12794
12806
|
break;
|
|
12807
|
+
}
|
|
12795
12808
|
// Add events
|
|
12796
|
-
case "add:start":
|
|
12809
|
+
case "add:start": {
|
|
12797
12810
|
const components = event.components;
|
|
12798
12811
|
context.spinner = ora(`Adding ${components.join(", ")}...`).start();
|
|
12799
12812
|
break;
|
|
12800
|
-
|
|
12813
|
+
}
|
|
12814
|
+
case "add:installed": {
|
|
12801
12815
|
context.spinner?.succeed(`Installed ${event.component}`);
|
|
12802
12816
|
const files = event.files;
|
|
12803
12817
|
for (const file2 of files) {
|
|
@@ -12805,6 +12819,7 @@ function log(event) {
|
|
|
12805
12819
|
}
|
|
12806
12820
|
context.spinner = ora("Installing...").start();
|
|
12807
12821
|
break;
|
|
12822
|
+
}
|
|
12808
12823
|
case "add:skip":
|
|
12809
12824
|
context.spinner?.warn(`Skipped ${event.component} (already exists)`);
|
|
12810
12825
|
context.spinner = ora("Installing...").start();
|
|
@@ -12843,7 +12858,7 @@ function log(event) {
|
|
|
12843
12858
|
}
|
|
12844
12859
|
function error46(message) {
|
|
12845
12860
|
if (context.agent) {
|
|
12846
|
-
console.error({ event: "error", message });
|
|
12861
|
+
console.error(JSON.stringify({ event: "error", message }));
|
|
12847
12862
|
return;
|
|
12848
12863
|
}
|
|
12849
12864
|
context.spinner?.fail(message);
|
|
@@ -12927,39 +12942,77 @@ async function isInitialized(cwd) {
|
|
|
12927
12942
|
return false;
|
|
12928
12943
|
}
|
|
12929
12944
|
}
|
|
12945
|
+
async function loadConfig(cwd) {
|
|
12946
|
+
const paths = getRaftersPaths(cwd);
|
|
12947
|
+
try {
|
|
12948
|
+
const content = await readFile(paths.config, "utf-8");
|
|
12949
|
+
return JSON.parse(content);
|
|
12950
|
+
} catch (err) {
|
|
12951
|
+
if (existsSync(paths.config)) {
|
|
12952
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12953
|
+
log({ event: "add:warning", message: `Failed to load config: ${message}` });
|
|
12954
|
+
}
|
|
12955
|
+
return null;
|
|
12956
|
+
}
|
|
12957
|
+
}
|
|
12958
|
+
function transformPath(registryPath, config3) {
|
|
12959
|
+
if (!config3) return registryPath;
|
|
12960
|
+
if (registryPath.startsWith("components/ui/")) {
|
|
12961
|
+
return registryPath.replace("components/ui/", `${config3.componentsPath}/`);
|
|
12962
|
+
}
|
|
12963
|
+
if (registryPath.startsWith("lib/primitives/")) {
|
|
12964
|
+
return registryPath.replace("lib/primitives/", `${config3.primitivesPath}/`);
|
|
12965
|
+
}
|
|
12966
|
+
return registryPath;
|
|
12967
|
+
}
|
|
12930
12968
|
function fileExists(cwd, relativePath) {
|
|
12931
12969
|
return existsSync(join2(cwd, relativePath));
|
|
12932
12970
|
}
|
|
12933
|
-
function transformFileContent(content) {
|
|
12971
|
+
function transformFileContent(content, config3) {
|
|
12934
12972
|
let transformed = content;
|
|
12973
|
+
const componentsPath = config3?.componentsPath ?? "components/ui";
|
|
12974
|
+
const primitivesPath = config3?.primitivesPath ?? "lib/primitives";
|
|
12935
12975
|
transformed = transformed.replace(
|
|
12936
12976
|
/from\s+['"]\.\.\/\.\.\/primitives\/([^'"]+)['"]/g,
|
|
12937
|
-
|
|
12977
|
+
`from '@/${primitivesPath}/$1'`
|
|
12938
12978
|
);
|
|
12939
12979
|
transformed = transformed.replace(
|
|
12940
12980
|
/from\s+['"]\.\.\/primitives\/([^'"]+)['"]/g,
|
|
12941
|
-
|
|
12981
|
+
`from '@/${primitivesPath}/$1'`
|
|
12982
|
+
);
|
|
12983
|
+
transformed = transformed.replace(
|
|
12984
|
+
/from\s+['"]\.\/([^'"]+)['"]/g,
|
|
12985
|
+
`from '@/${componentsPath}/$1'`
|
|
12986
|
+
);
|
|
12987
|
+
const libPath = dirname(primitivesPath);
|
|
12988
|
+
transformed = transformed.replace(
|
|
12989
|
+
/from\s+['"]\.\.\/lib\/([^'"]+)['"]/g,
|
|
12990
|
+
`from '@/${libPath}/$1'`
|
|
12991
|
+
);
|
|
12992
|
+
const componentsMatch = componentsPath.match(/^(.*)components\/ui$/);
|
|
12993
|
+
const hooksPath = componentsMatch ? `${componentsMatch[1]}hooks`.replace(/^\//, "") : "hooks";
|
|
12994
|
+
transformed = transformed.replace(
|
|
12995
|
+
/from\s+['"]\.\.\/hooks\/([^'"]+)['"]/g,
|
|
12996
|
+
`from '@/${hooksPath}/$1'`
|
|
12942
12997
|
);
|
|
12943
|
-
transformed = transformed.replace(/from\s+['"]\.\/([^'"]+)['"]/g, "from '@/components/ui/$1'");
|
|
12944
|
-
transformed = transformed.replace(/from\s+['"]\.\.\/lib\/([^'"]+)['"]/g, "from '@/lib/$1'");
|
|
12945
|
-
transformed = transformed.replace(/from\s+['"]\.\.\/hooks\/([^'"]+)['"]/g, "from '@/hooks/$1'");
|
|
12946
12998
|
transformed = transformed.replace(
|
|
12947
12999
|
/from\s+['"]\.\.\/(?!lib\/|hooks\/)([^'"]+)['"]/g,
|
|
12948
|
-
|
|
13000
|
+
`from '@/${componentsPath}/$1'`
|
|
12949
13001
|
);
|
|
12950
13002
|
return transformed;
|
|
12951
13003
|
}
|
|
12952
|
-
async function installItem(cwd, item, options) {
|
|
13004
|
+
async function installItem(cwd, item, options, config3) {
|
|
12953
13005
|
const installedFiles = [];
|
|
12954
13006
|
let skipped = false;
|
|
12955
13007
|
for (const file2 of item.files) {
|
|
12956
|
-
const
|
|
12957
|
-
|
|
13008
|
+
const projectPath = transformPath(file2.path, config3);
|
|
13009
|
+
const targetPath = join2(cwd, projectPath);
|
|
13010
|
+
if (fileExists(cwd, projectPath)) {
|
|
12958
13011
|
if (!options.overwrite) {
|
|
12959
13012
|
log({
|
|
12960
13013
|
event: "add:skip",
|
|
12961
13014
|
component: item.name,
|
|
12962
|
-
file:
|
|
13015
|
+
file: projectPath,
|
|
12963
13016
|
reason: "exists"
|
|
12964
13017
|
});
|
|
12965
13018
|
skipped = true;
|
|
@@ -12967,9 +13020,9 @@ async function installItem(cwd, item, options) {
|
|
|
12967
13020
|
}
|
|
12968
13021
|
}
|
|
12969
13022
|
await mkdir(dirname(targetPath), { recursive: true });
|
|
12970
|
-
const transformedContent = transformFileContent(file2.content);
|
|
13023
|
+
const transformedContent = transformFileContent(file2.content, config3);
|
|
12971
13024
|
await writeFile(targetPath, transformedContent, "utf-8");
|
|
12972
|
-
installedFiles.push(
|
|
13025
|
+
installedFiles.push(projectPath);
|
|
12973
13026
|
}
|
|
12974
13027
|
return {
|
|
12975
13028
|
installed: installedFiles.length > 0,
|
|
@@ -13001,6 +13054,7 @@ async function add(components, options) {
|
|
|
13001
13054
|
process.exitCode = 1;
|
|
13002
13055
|
return;
|
|
13003
13056
|
}
|
|
13057
|
+
const config3 = await loadConfig(cwd);
|
|
13004
13058
|
if (components.length === 0) {
|
|
13005
13059
|
error46("No components specified. Usage: rafters add <component...>");
|
|
13006
13060
|
process.exitCode = 1;
|
|
@@ -13033,7 +13087,7 @@ async function add(components, options) {
|
|
|
13033
13087
|
const skipped = [];
|
|
13034
13088
|
for (const item of allItems) {
|
|
13035
13089
|
try {
|
|
13036
|
-
const result = await installItem(cwd, item, options);
|
|
13090
|
+
const result = await installItem(cwd, item, options, config3);
|
|
13037
13091
|
if (result.installed) {
|
|
13038
13092
|
installed.push(item.name);
|
|
13039
13093
|
log({
|
|
@@ -13089,9 +13143,10 @@ async function add(components, options) {
|
|
|
13089
13143
|
}
|
|
13090
13144
|
|
|
13091
13145
|
// src/commands/init.ts
|
|
13092
|
-
import {
|
|
13093
|
-
import {
|
|
13094
|
-
import {
|
|
13146
|
+
import { checkbox } from "@inquirer/prompts";
|
|
13147
|
+
import { existsSync as existsSync3 } from "fs";
|
|
13148
|
+
import { copyFile, mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
13149
|
+
import { join as join9, relative } from "path";
|
|
13095
13150
|
|
|
13096
13151
|
// ../design-tokens/src/generation-rules.ts
|
|
13097
13152
|
var GenerationRuleParser = class {
|
|
@@ -24121,7 +24176,7 @@ var require_volume = __commonJS({
|
|
|
24121
24176
|
var Dir_1 = require_Dir();
|
|
24122
24177
|
var resolveCrossPlatform = pathModule.resolve;
|
|
24123
24178
|
var { O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_DIRECTORY, O_SYMLINK, F_OK, COPYFILE_EXCL, COPYFILE_FICLONE_FORCE } = constants_1.constants;
|
|
24124
|
-
var { sep: sep2, relative: relative2, join:
|
|
24179
|
+
var { sep: sep2, relative: relative2, join: join12, dirname: dirname4 } = pathModule.posix ? pathModule.posix : pathModule;
|
|
24125
24180
|
var kMinPoolSpace = 128;
|
|
24126
24181
|
var EPERM = "EPERM";
|
|
24127
24182
|
var ENOENT2 = "ENOENT";
|
|
@@ -24187,7 +24242,7 @@ var require_volume = __commonJS({
|
|
|
24187
24242
|
function flatten(pathPrefix, node) {
|
|
24188
24243
|
for (const path2 in node) {
|
|
24189
24244
|
const contentOrNode = node[path2];
|
|
24190
|
-
const joinedPath =
|
|
24245
|
+
const joinedPath = join12(pathPrefix, path2);
|
|
24191
24246
|
if (typeof contentOrNode === "string" || contentOrNode instanceof buffer_1.Buffer) {
|
|
24192
24247
|
flatJSON[joinedPath] = contentOrNode;
|
|
24193
24248
|
} else if (typeof contentOrNode === "object" && contentOrNode !== null && Object.keys(contentOrNode).length > 0) {
|
|
@@ -24344,7 +24399,7 @@ var require_volume = __commonJS({
|
|
|
24344
24399
|
return null;
|
|
24345
24400
|
node = curr === null || curr === void 0 ? void 0 : curr.getNode();
|
|
24346
24401
|
if (resolveSymlinks && node.isSymlink()) {
|
|
24347
|
-
const resolvedPath = pathModule.isAbsolute(node.symlink) ? node.symlink :
|
|
24402
|
+
const resolvedPath = pathModule.isAbsolute(node.symlink) ? node.symlink : join12(pathModule.dirname(curr.getPath()), node.symlink);
|
|
24348
24403
|
steps = filenameToSteps(resolvedPath).concat(steps.slice(i + 1));
|
|
24349
24404
|
curr = this.root;
|
|
24350
24405
|
i = 0;
|
|
@@ -48960,7 +49015,7 @@ function buildColorSystem(options = {}) {
|
|
|
48960
49015
|
}
|
|
48961
49016
|
|
|
48962
49017
|
// ../design-tokens/src/persistence/node-adapter.ts
|
|
48963
|
-
import { access as access2, mkdir as mkdir2, readdir as readdir2, readFile, writeFile as writeFile2 } from "fs/promises";
|
|
49018
|
+
import { access as access2, mkdir as mkdir2, readdir as readdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
48964
49019
|
import { join as join5 } from "path";
|
|
48965
49020
|
|
|
48966
49021
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/primitives.js
|
|
@@ -49099,7 +49154,7 @@ function tagTokenizer() {
|
|
|
49099
49154
|
|
|
49100
49155
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/type.js
|
|
49101
49156
|
function typeTokenizer(spacing = "compact") {
|
|
49102
|
-
const
|
|
49157
|
+
const join12 = getJoiner(spacing);
|
|
49103
49158
|
return (spec) => {
|
|
49104
49159
|
let curlies = 0;
|
|
49105
49160
|
let lines = [];
|
|
@@ -49142,7 +49197,7 @@ function typeTokenizer(spacing = "compact") {
|
|
|
49142
49197
|
}
|
|
49143
49198
|
parts[0] = parts[0].slice(1);
|
|
49144
49199
|
parts[parts.length - 1] = parts[parts.length - 1].slice(0, -1);
|
|
49145
|
-
spec.type =
|
|
49200
|
+
spec.type = join12(parts);
|
|
49146
49201
|
return spec;
|
|
49147
49202
|
};
|
|
49148
49203
|
}
|
|
@@ -49240,9 +49295,9 @@ function nameTokenizer() {
|
|
|
49240
49295
|
|
|
49241
49296
|
// ../../node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/description.js
|
|
49242
49297
|
function descriptionTokenizer(spacing = "compact", markers = Markers) {
|
|
49243
|
-
const
|
|
49298
|
+
const join12 = getJoiner2(spacing);
|
|
49244
49299
|
return (spec) => {
|
|
49245
|
-
spec.description =
|
|
49300
|
+
spec.description = join12(spec.source, markers);
|
|
49246
49301
|
return spec;
|
|
49247
49302
|
};
|
|
49248
49303
|
}
|
|
@@ -49925,7 +49980,7 @@ var NodePersistenceAdapter = class {
|
|
|
49925
49980
|
}
|
|
49926
49981
|
async loadNamespace(namespace) {
|
|
49927
49982
|
const filePath = this.getFilePath(namespace);
|
|
49928
|
-
const content = await
|
|
49983
|
+
const content = await readFile2(filePath, "utf-8");
|
|
49929
49984
|
const json3 = JSON.parse(content);
|
|
49930
49985
|
const data = NamespaceFileSchema.parse(json3);
|
|
49931
49986
|
return data.tokens;
|
|
@@ -49985,16 +50040,19 @@ var RuleContextSchema = external_exports.object({
|
|
|
49985
50040
|
});
|
|
49986
50041
|
|
|
49987
50042
|
// src/utils/detect.ts
|
|
49988
|
-
import { readFile as
|
|
50043
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
49989
50044
|
import { join as join7 } from "path";
|
|
49990
50045
|
async function detectFramework(cwd) {
|
|
49991
50046
|
try {
|
|
49992
|
-
const content = await
|
|
50047
|
+
const content = await readFile3(join7(cwd, "package.json"), "utf-8");
|
|
49993
50048
|
const pkg = JSON.parse(content);
|
|
49994
50049
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
49995
50050
|
if (deps.next) {
|
|
49996
50051
|
return "next";
|
|
49997
50052
|
}
|
|
50053
|
+
if (deps["react-router"]) {
|
|
50054
|
+
return "react-router";
|
|
50055
|
+
}
|
|
49998
50056
|
const hasRemix = Object.keys(deps).some((dep) => dep.startsWith("@remix-run/"));
|
|
49999
50057
|
if (hasRemix) {
|
|
50000
50058
|
return "remix";
|
|
@@ -50012,7 +50070,7 @@ async function detectFramework(cwd) {
|
|
|
50012
50070
|
}
|
|
50013
50071
|
async function detectTailwindVersion(cwd) {
|
|
50014
50072
|
try {
|
|
50015
|
-
const content = await
|
|
50073
|
+
const content = await readFile3(join7(cwd, "package.json"), "utf-8");
|
|
50016
50074
|
const pkg = JSON.parse(content);
|
|
50017
50075
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
50018
50076
|
const tailwindVersion = deps.tailwindcss;
|
|
@@ -50033,7 +50091,7 @@ function isTailwindV3(version2) {
|
|
|
50033
50091
|
}
|
|
50034
50092
|
async function detectShadcn(cwd) {
|
|
50035
50093
|
try {
|
|
50036
|
-
const content = await
|
|
50094
|
+
const content = await readFile3(join7(cwd, "components.json"), "utf-8");
|
|
50037
50095
|
return JSON.parse(content);
|
|
50038
50096
|
} catch {
|
|
50039
50097
|
return null;
|
|
@@ -50095,6 +50153,79 @@ async function detectProject(cwd) {
|
|
|
50095
50153
|
};
|
|
50096
50154
|
}
|
|
50097
50155
|
|
|
50156
|
+
// src/utils/exports.ts
|
|
50157
|
+
import { execFileSync } from "child_process";
|
|
50158
|
+
import { existsSync as existsSync2 } from "fs";
|
|
50159
|
+
import { join as join8 } from "path";
|
|
50160
|
+
var DEFAULT_EXPORTS = {
|
|
50161
|
+
tailwind: true,
|
|
50162
|
+
typescript: true,
|
|
50163
|
+
dtcg: false,
|
|
50164
|
+
compiled: false
|
|
50165
|
+
};
|
|
50166
|
+
var EXPORT_CHOICES = [
|
|
50167
|
+
{
|
|
50168
|
+
name: "Tailwind CSS (web projects)",
|
|
50169
|
+
value: "tailwind",
|
|
50170
|
+
checked: true
|
|
50171
|
+
},
|
|
50172
|
+
{
|
|
50173
|
+
name: "TypeScript (type-safe constants)",
|
|
50174
|
+
value: "typescript",
|
|
50175
|
+
checked: true
|
|
50176
|
+
},
|
|
50177
|
+
{
|
|
50178
|
+
name: "DTCG JSON (Figma Tokens, Style Dictionary)",
|
|
50179
|
+
value: "dtcg",
|
|
50180
|
+
checked: false
|
|
50181
|
+
},
|
|
50182
|
+
{
|
|
50183
|
+
name: "Compiled CSS (documentation, no build step)",
|
|
50184
|
+
value: "compiled",
|
|
50185
|
+
checked: false
|
|
50186
|
+
}
|
|
50187
|
+
];
|
|
50188
|
+
var FUTURE_EXPORTS = [
|
|
50189
|
+
{
|
|
50190
|
+
name: "iOS (Swift/SwiftUI)",
|
|
50191
|
+
value: "tailwind",
|
|
50192
|
+
// placeholder
|
|
50193
|
+
checked: false,
|
|
50194
|
+
disabled: "coming soon"
|
|
50195
|
+
},
|
|
50196
|
+
{
|
|
50197
|
+
name: "Android (Compose)",
|
|
50198
|
+
value: "tailwind",
|
|
50199
|
+
// placeholder
|
|
50200
|
+
checked: false,
|
|
50201
|
+
disabled: "coming soon"
|
|
50202
|
+
}
|
|
50203
|
+
];
|
|
50204
|
+
async function generateCompiledCss(cwd, inputPath, outputPath) {
|
|
50205
|
+
const nodeModulesBin = join8(cwd, "node_modules", ".bin", "tailwindcss");
|
|
50206
|
+
const hasTailwindCli = existsSync2(nodeModulesBin);
|
|
50207
|
+
const args = ["-i", inputPath, "-o", outputPath, "--minify"];
|
|
50208
|
+
if (hasTailwindCli) {
|
|
50209
|
+
execFileSync(nodeModulesBin, args, { cwd, stdio: "pipe" });
|
|
50210
|
+
} else {
|
|
50211
|
+
try {
|
|
50212
|
+
execFileSync("pnpm", ["exec", "tailwindcss", ...args], { cwd, stdio: "pipe" });
|
|
50213
|
+
} catch {
|
|
50214
|
+
throw new Error(
|
|
50215
|
+
"Tailwind CLI not found. Install it with: pnpm add -D @tailwindcss/cli"
|
|
50216
|
+
);
|
|
50217
|
+
}
|
|
50218
|
+
}
|
|
50219
|
+
}
|
|
50220
|
+
function selectionsToConfig(selections) {
|
|
50221
|
+
return {
|
|
50222
|
+
tailwind: selections.includes("tailwind"),
|
|
50223
|
+
typescript: selections.includes("typescript"),
|
|
50224
|
+
dtcg: selections.includes("dtcg"),
|
|
50225
|
+
compiled: selections.includes("compiled")
|
|
50226
|
+
};
|
|
50227
|
+
}
|
|
50228
|
+
|
|
50098
50229
|
// src/commands/init.ts
|
|
50099
50230
|
async function backupCss(cssPath) {
|
|
50100
50231
|
const backupPath = cssPath.replace(/\.css$/, ".backup.css");
|
|
@@ -50106,25 +50237,34 @@ var CSS_LOCATIONS = {
|
|
|
50106
50237
|
next: ["src/app/globals.css", "app/globals.css", "styles/globals.css"],
|
|
50107
50238
|
vite: ["src/index.css", "src/main.css", "src/styles.css", "src/app.css"],
|
|
50108
50239
|
remix: ["app/styles/global.css", "app/globals.css", "app/root.css"],
|
|
50240
|
+
"react-router": ["app/app.css", "app/root.css", "app/styles.css", "app/globals.css"],
|
|
50109
50241
|
unknown: ["src/styles/global.css", "src/index.css", "styles/globals.css"]
|
|
50110
50242
|
};
|
|
50243
|
+
var COMPONENT_PATHS = {
|
|
50244
|
+
astro: { components: "src/components/ui", primitives: "src/lib/primitives" },
|
|
50245
|
+
next: { components: "components/ui", primitives: "lib/primitives" },
|
|
50246
|
+
vite: { components: "src/components/ui", primitives: "src/lib/primitives" },
|
|
50247
|
+
remix: { components: "app/components/ui", primitives: "app/lib/primitives" },
|
|
50248
|
+
"react-router": { components: "app/components/ui", primitives: "app/lib/primitives" },
|
|
50249
|
+
unknown: { components: "components/ui", primitives: "lib/primitives" }
|
|
50250
|
+
};
|
|
50111
50251
|
async function findMainCssFile(cwd, framework) {
|
|
50112
50252
|
const locations = CSS_LOCATIONS[framework] || CSS_LOCATIONS.unknown;
|
|
50113
50253
|
for (const location of locations) {
|
|
50114
|
-
const fullPath =
|
|
50115
|
-
if (
|
|
50254
|
+
const fullPath = join9(cwd, location);
|
|
50255
|
+
if (existsSync3(fullPath)) {
|
|
50116
50256
|
return location;
|
|
50117
50257
|
}
|
|
50118
50258
|
}
|
|
50119
50259
|
return null;
|
|
50120
50260
|
}
|
|
50121
50261
|
async function updateMainCss(cwd, cssPath, themePath) {
|
|
50122
|
-
const fullCssPath =
|
|
50123
|
-
const cssContent = await
|
|
50124
|
-
const cssDir =
|
|
50125
|
-
const themeFullPath =
|
|
50262
|
+
const fullCssPath = join9(cwd, cssPath);
|
|
50263
|
+
const cssContent = await readFile4(fullCssPath, "utf-8");
|
|
50264
|
+
const cssDir = join9(cwd, cssPath, "..");
|
|
50265
|
+
const themeFullPath = join9(cwd, themePath);
|
|
50126
50266
|
const relativeThemePath = relative(cssDir, themeFullPath);
|
|
50127
|
-
if (cssContent.includes(".rafters/output/
|
|
50267
|
+
if (cssContent.includes(".rafters/output/rafters.css")) {
|
|
50128
50268
|
log({ event: "init:css_already_imported", cssPath });
|
|
50129
50269
|
return;
|
|
50130
50270
|
}
|
|
@@ -50146,8 +50286,66 @@ ${cssContent}`;
|
|
|
50146
50286
|
themePath: relativeThemePath
|
|
50147
50287
|
});
|
|
50148
50288
|
}
|
|
50149
|
-
async function
|
|
50289
|
+
async function promptExportFormats(existingConfig) {
|
|
50290
|
+
const choices = EXPORT_CHOICES.map((choice) => ({
|
|
50291
|
+
name: choice.name,
|
|
50292
|
+
value: choice.value,
|
|
50293
|
+
checked: existingConfig ? existingConfig[choice.value] : choice.checked
|
|
50294
|
+
}));
|
|
50295
|
+
const allChoices = [
|
|
50296
|
+
...choices,
|
|
50297
|
+
...FUTURE_EXPORTS.map((choice) => ({
|
|
50298
|
+
name: `${choice.name} (${choice.disabled})`,
|
|
50299
|
+
value: choice.value,
|
|
50300
|
+
checked: false,
|
|
50301
|
+
disabled: true
|
|
50302
|
+
}))
|
|
50303
|
+
];
|
|
50304
|
+
const selections = await checkbox({
|
|
50305
|
+
message: "What would you like to export?",
|
|
50306
|
+
choices: allChoices,
|
|
50307
|
+
required: true
|
|
50308
|
+
});
|
|
50309
|
+
return selectionsToConfig(selections);
|
|
50310
|
+
}
|
|
50311
|
+
async function generateOutputs(cwd, paths, registry2, exports, shadcn) {
|
|
50312
|
+
const outputs = [];
|
|
50313
|
+
if (exports.tailwind) {
|
|
50314
|
+
const tailwindCss = registryToTailwind(registry2, { includeImport: !shadcn });
|
|
50315
|
+
await writeFile3(join9(paths.output, "rafters.css"), tailwindCss);
|
|
50316
|
+
outputs.push("rafters.css");
|
|
50317
|
+
}
|
|
50318
|
+
if (exports.typescript) {
|
|
50319
|
+
const typescriptSrc = registryToTypeScript(registry2, { includeJSDoc: true });
|
|
50320
|
+
await writeFile3(join9(paths.output, "rafters.ts"), typescriptSrc);
|
|
50321
|
+
outputs.push("rafters.ts");
|
|
50322
|
+
}
|
|
50323
|
+
if (exports.dtcg) {
|
|
50324
|
+
const dtcgJson = toDTCG(registry2.list());
|
|
50325
|
+
await writeFile3(join9(paths.output, "rafters.json"), JSON.stringify(dtcgJson, null, 2));
|
|
50326
|
+
outputs.push("rafters.json");
|
|
50327
|
+
}
|
|
50328
|
+
if (exports.compiled) {
|
|
50329
|
+
if (!exports.tailwind) {
|
|
50330
|
+
const tailwindCss = registryToTailwind(registry2, { includeImport: !shadcn });
|
|
50331
|
+
await writeFile3(join9(paths.output, "rafters.css"), tailwindCss);
|
|
50332
|
+
}
|
|
50333
|
+
const inputPath = join9(paths.output, "rafters.css");
|
|
50334
|
+
const outputPath = join9(paths.output, "rafters.compiled.css");
|
|
50335
|
+
log({ event: "init:compiling_css" });
|
|
50336
|
+
await generateCompiledCss(cwd, inputPath, outputPath);
|
|
50337
|
+
outputs.push("rafters.compiled.css");
|
|
50338
|
+
}
|
|
50339
|
+
return outputs;
|
|
50340
|
+
}
|
|
50341
|
+
async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode) {
|
|
50150
50342
|
log({ event: "init:regenerate", cwd });
|
|
50343
|
+
let existingConfig = null;
|
|
50344
|
+
try {
|
|
50345
|
+
const configContent = await readFile4(paths.config, "utf-8");
|
|
50346
|
+
existingConfig = JSON.parse(configContent);
|
|
50347
|
+
} catch {
|
|
50348
|
+
}
|
|
50151
50349
|
const adapter = new NodePersistenceAdapter(cwd);
|
|
50152
50350
|
const namespaces = await adapter.listNamespaces();
|
|
50153
50351
|
if (namespaces.length === 0) {
|
|
@@ -50164,21 +50362,27 @@ async function regenerateFromExisting(cwd, paths, shadcn) {
|
|
|
50164
50362
|
namespaces
|
|
50165
50363
|
});
|
|
50166
50364
|
const registry2 = new TokenRegistry(allTokens);
|
|
50167
|
-
|
|
50168
|
-
|
|
50169
|
-
|
|
50365
|
+
let exports;
|
|
50366
|
+
if (isAgentMode) {
|
|
50367
|
+
exports = existingConfig?.exports ?? DEFAULT_EXPORTS;
|
|
50368
|
+
} else {
|
|
50369
|
+
exports = await promptExportFormats(existingConfig?.exports);
|
|
50370
|
+
}
|
|
50170
50371
|
await mkdir3(paths.output, { recursive: true });
|
|
50171
|
-
await
|
|
50172
|
-
|
|
50173
|
-
|
|
50372
|
+
const outputs = await generateOutputs(cwd, paths, registry2, exports, shadcn);
|
|
50373
|
+
if (existingConfig) {
|
|
50374
|
+
existingConfig.exports = exports;
|
|
50375
|
+
await writeFile3(paths.config, JSON.stringify(existingConfig, null, 2));
|
|
50376
|
+
}
|
|
50174
50377
|
log({
|
|
50175
50378
|
event: "init:complete",
|
|
50176
|
-
outputs
|
|
50379
|
+
outputs,
|
|
50177
50380
|
path: paths.output
|
|
50178
50381
|
});
|
|
50179
50382
|
}
|
|
50180
50383
|
async function init(options) {
|
|
50181
50384
|
setAgentMode(options.agent ?? false);
|
|
50385
|
+
const isAgentMode = options.agent ?? false;
|
|
50182
50386
|
const cwd = process.cwd();
|
|
50183
50387
|
const paths = getRaftersPaths(cwd);
|
|
50184
50388
|
log({ event: "init:start", cwd });
|
|
@@ -50192,21 +50396,21 @@ async function init(options) {
|
|
|
50192
50396
|
if (isTailwindV3(tailwindVersion)) {
|
|
50193
50397
|
throw new Error("Tailwind v3 detected. Rafters requires Tailwind v4.");
|
|
50194
50398
|
}
|
|
50195
|
-
const raftersExists =
|
|
50399
|
+
const raftersExists = existsSync3(paths.root);
|
|
50196
50400
|
if (raftersExists && !options.force) {
|
|
50197
50401
|
throw new Error(
|
|
50198
50402
|
".rafters/ directory already exists. Use --force to regenerate output files from existing config."
|
|
50199
50403
|
);
|
|
50200
50404
|
}
|
|
50201
50405
|
if (raftersExists && options.force) {
|
|
50202
|
-
await regenerateFromExisting(cwd, paths, shadcn);
|
|
50406
|
+
await regenerateFromExisting(cwd, paths, shadcn, isAgentMode);
|
|
50203
50407
|
return;
|
|
50204
50408
|
}
|
|
50205
50409
|
let existingColors = null;
|
|
50206
50410
|
if (shadcn?.tailwind?.css) {
|
|
50207
|
-
const cssPath =
|
|
50411
|
+
const cssPath = join9(cwd, shadcn.tailwind.css);
|
|
50208
50412
|
try {
|
|
50209
|
-
const cssContent = await
|
|
50413
|
+
const cssContent = await readFile4(cssPath, "utf-8");
|
|
50210
50414
|
existingColors = parseCssVariables(cssContent);
|
|
50211
50415
|
const backupPath = await backupCss(cssPath);
|
|
50212
50416
|
log({
|
|
@@ -50222,6 +50426,14 @@ async function init(options) {
|
|
|
50222
50426
|
log({ event: "init:shadcn_css_error", error: String(err) });
|
|
50223
50427
|
}
|
|
50224
50428
|
}
|
|
50429
|
+
let exports;
|
|
50430
|
+
if (isAgentMode) {
|
|
50431
|
+
exports = DEFAULT_EXPORTS;
|
|
50432
|
+
log({ event: "init:exports_default", exports });
|
|
50433
|
+
} else {
|
|
50434
|
+
exports = await promptExportFormats();
|
|
50435
|
+
log({ event: "init:exports_selected", exports });
|
|
50436
|
+
}
|
|
50225
50437
|
const result = buildColorSystem({
|
|
50226
50438
|
exports: {
|
|
50227
50439
|
tailwind: { includeImport: !shadcn },
|
|
@@ -50285,27 +50497,34 @@ async function init(options) {
|
|
|
50285
50497
|
path: paths.tokens,
|
|
50286
50498
|
namespaceCount: tokensByNamespace.size
|
|
50287
50499
|
});
|
|
50288
|
-
const
|
|
50289
|
-
|
|
50290
|
-
|
|
50291
|
-
|
|
50292
|
-
|
|
50293
|
-
|
|
50294
|
-
if (!shadcn) {
|
|
50295
|
-
const mainCssPath = await findMainCssFile(cwd, framework);
|
|
50296
|
-
if (mainCssPath) {
|
|
50297
|
-
await updateMainCss(cwd, mainCssPath, ".rafters/output/theme.css");
|
|
50500
|
+
const outputs = await generateOutputs(cwd, paths, registry2, exports, shadcn);
|
|
50501
|
+
let detectedCssPath = null;
|
|
50502
|
+
if (!shadcn && exports.tailwind) {
|
|
50503
|
+
detectedCssPath = await findMainCssFile(cwd, framework);
|
|
50504
|
+
if (detectedCssPath) {
|
|
50505
|
+
await updateMainCss(cwd, detectedCssPath, ".rafters/output/rafters.css");
|
|
50298
50506
|
} else {
|
|
50299
50507
|
log({
|
|
50300
50508
|
event: "init:css_not_found",
|
|
50301
|
-
message: 'No main CSS file found. Add @import ".rafters/output/
|
|
50509
|
+
message: 'No main CSS file found. Add @import ".rafters/output/rafters.css" manually.',
|
|
50302
50510
|
searchedLocations: CSS_LOCATIONS[framework] || CSS_LOCATIONS.unknown
|
|
50303
50511
|
});
|
|
50304
50512
|
}
|
|
50513
|
+
} else if (shadcn?.tailwind?.css) {
|
|
50514
|
+
detectedCssPath = shadcn.tailwind.css;
|
|
50305
50515
|
}
|
|
50516
|
+
const frameworkPaths = COMPONENT_PATHS[framework] || COMPONENT_PATHS.unknown;
|
|
50517
|
+
const config3 = {
|
|
50518
|
+
framework,
|
|
50519
|
+
componentsPath: frameworkPaths.components,
|
|
50520
|
+
primitivesPath: frameworkPaths.primitives,
|
|
50521
|
+
cssPath: detectedCssPath,
|
|
50522
|
+
exports
|
|
50523
|
+
};
|
|
50524
|
+
await writeFile3(paths.config, JSON.stringify(config3, null, 2));
|
|
50306
50525
|
log({
|
|
50307
50526
|
event: "init:complete",
|
|
50308
|
-
outputs: [
|
|
50527
|
+
outputs: [...outputs, "config.rafters.json"],
|
|
50309
50528
|
path: paths.output
|
|
50310
50529
|
});
|
|
50311
50530
|
}
|
|
@@ -50316,8 +50535,8 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
50316
50535
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
50317
50536
|
|
|
50318
50537
|
// src/mcp/tools.ts
|
|
50319
|
-
import { readdir as readdir3, readFile as
|
|
50320
|
-
import { basename, join as
|
|
50538
|
+
import { readdir as readdir3, readFile as readFile5 } from "fs/promises";
|
|
50539
|
+
import { basename, join as join10 } from "path";
|
|
50321
50540
|
var DESIGN_PATTERNS = {
|
|
50322
50541
|
"destructive-action": {
|
|
50323
50542
|
name: "Destructive Action",
|
|
@@ -50867,7 +51086,7 @@ var RaftersToolHandler = class {
|
|
|
50867
51086
|
* Get path to UI components directory
|
|
50868
51087
|
*/
|
|
50869
51088
|
getComponentsPath() {
|
|
50870
|
-
const monorepoPath =
|
|
51089
|
+
const monorepoPath = join10(this.projectRoot, "packages/ui/src/components/ui");
|
|
50871
51090
|
return monorepoPath;
|
|
50872
51091
|
}
|
|
50873
51092
|
/**
|
|
@@ -50875,9 +51094,9 @@ var RaftersToolHandler = class {
|
|
|
50875
51094
|
*/
|
|
50876
51095
|
async loadComponentMetadata(name2) {
|
|
50877
51096
|
const componentsPath = this.getComponentsPath();
|
|
50878
|
-
const filePath =
|
|
51097
|
+
const filePath = join10(componentsPath, `${name2}.tsx`);
|
|
50879
51098
|
try {
|
|
50880
|
-
const source = await
|
|
51099
|
+
const source = await readFile5(filePath, "utf-8");
|
|
50881
51100
|
const intelligence = parseJSDocIntelligence(source);
|
|
50882
51101
|
const description = parseDescription(source);
|
|
50883
51102
|
const metadata = {
|
|
@@ -51227,22 +51446,22 @@ async function mcp() {
|
|
|
51227
51446
|
}
|
|
51228
51447
|
|
|
51229
51448
|
// src/commands/studio.ts
|
|
51230
|
-
import { existsSync as
|
|
51231
|
-
import { dirname as dirname3, join as
|
|
51449
|
+
import { existsSync as existsSync4 } from "fs";
|
|
51450
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
51232
51451
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
51233
51452
|
import { execa as execa2 } from "execa";
|
|
51234
51453
|
var __dirname2 = dirname3(fileURLToPath3(import.meta.url));
|
|
51235
51454
|
async function studio() {
|
|
51236
51455
|
const cwd = process.cwd();
|
|
51237
51456
|
const paths = getRaftersPaths(cwd);
|
|
51238
|
-
if (!
|
|
51457
|
+
if (!existsSync4(paths.root)) {
|
|
51239
51458
|
console.error('No .rafters/ directory found. Run "rafters init" first.');
|
|
51240
51459
|
process.exit(1);
|
|
51241
51460
|
}
|
|
51242
|
-
const devStudioPath =
|
|
51243
|
-
const prodStudioPath =
|
|
51244
|
-
const studioPath =
|
|
51245
|
-
if (!
|
|
51461
|
+
const devStudioPath = join11(__dirname2, "..", "..", "..", "studio");
|
|
51462
|
+
const prodStudioPath = join11(__dirname2, "..", "node_modules", "@rafters", "studio");
|
|
51463
|
+
const studioPath = existsSync4(devStudioPath) ? devStudioPath : prodStudioPath;
|
|
51464
|
+
if (!existsSync4(studioPath)) {
|
|
51246
51465
|
console.error("Studio package not found. Please reinstall @rafters/cli.");
|
|
51247
51466
|
process.exit(1);
|
|
51248
51467
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rafters",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "CLI for Rafters design system - scaffold tokens and add components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@antfu/ni": "^28.1.0",
|
|
17
|
+
"@inquirer/prompts": "^8.2.0",
|
|
17
18
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
18
19
|
"commander": "^13.0.0",
|
|
19
20
|
"execa": "^9.6.1",
|