rafters 0.0.9 → 0.0.13

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/index.js CHANGED
@@ -12563,23 +12563,23 @@ var RegistryFileSchema = external_exports.object({
12563
12563
  devDependencies: external_exports.array(external_exports.string()).default([])
12564
12564
  // e.g., ["vitest"] - from @devDependencies JSDoc
12565
12565
  });
12566
- var RegistryItemTypeSchema = external_exports.enum([
12567
- "registry:ui",
12568
- "registry:primitive",
12569
- "registry:composite"
12570
- ]);
12566
+ var RegistryItemTypeSchema = external_exports.enum(["ui", "primitive", "composite"]);
12571
12567
  var RegistryItemSchema = external_exports.object({
12572
12568
  name: external_exports.string(),
12573
12569
  type: RegistryItemTypeSchema,
12574
12570
  description: external_exports.string().optional(),
12575
12571
  primitives: external_exports.array(external_exports.string()),
12576
- files: external_exports.array(RegistryFileSchema)
12572
+ files: external_exports.array(RegistryFileSchema),
12573
+ rules: external_exports.array(external_exports.string()).default([]),
12574
+ composites: external_exports.array(external_exports.string()).default([])
12577
12575
  });
12578
12576
  var RegistryIndexSchema = external_exports.object({
12579
12577
  name: external_exports.string(),
12580
12578
  homepage: external_exports.string(),
12581
12579
  components: external_exports.array(external_exports.string()),
12582
- primitives: external_exports.array(external_exports.string())
12580
+ primitives: external_exports.array(external_exports.string()),
12581
+ composites: external_exports.array(external_exports.string()).default([]),
12582
+ rules: external_exports.array(external_exports.string()).default([])
12583
12583
  });
12584
12584
 
12585
12585
  // src/registry/client.ts
@@ -12650,6 +12650,30 @@ var RegistryClient = class {
12650
12650
  this.cache.set(cacheKey, item);
12651
12651
  return item;
12652
12652
  }
12653
+ /**
12654
+ * Fetch a composite by name
12655
+ */
12656
+ async fetchComposite(name2) {
12657
+ const cacheKey = `composite:${name2}`;
12658
+ const cached2 = this.cache.get(cacheKey);
12659
+ if (cached2) {
12660
+ return cached2;
12661
+ }
12662
+ const url2 = `${this.baseUrl}/registry/composites/${name2}.json`;
12663
+ const response = await fetch(url2);
12664
+ if (response.status === 404) {
12665
+ throw new Error(`Composite "${name2}" not found`);
12666
+ }
12667
+ if (!response.ok) {
12668
+ throw new Error(
12669
+ `Failed to fetch composite "${name2}": ${response.status} ${response.statusText}`
12670
+ );
12671
+ }
12672
+ const data = await response.json();
12673
+ const item = RegistryItemSchema.parse(data);
12674
+ this.cache.set(cacheKey, item);
12675
+ return item;
12676
+ }
12653
12677
  /**
12654
12678
  * Fetch a registry item (component or primitive) by name
12655
12679
  * Tries component first, then primitive
@@ -12675,6 +12699,13 @@ var RegistryClient = class {
12675
12699
  const index = await this.fetchIndex();
12676
12700
  return index.components.map((name2) => ({ name: name2 }));
12677
12701
  }
12702
+ /**
12703
+ * List all available composites
12704
+ */
12705
+ async listComposites() {
12706
+ const index = await this.fetchIndex();
12707
+ return index.composites.map((name2) => ({ name: name2 }));
12708
+ }
12678
12709
  /**
12679
12710
  * Check if a component exists in the registry
12680
12711
  */
@@ -13199,25 +13230,40 @@ async function saveConfig(cwd, config3) {
13199
13230
  }
13200
13231
  function getInstalledNames(config3) {
13201
13232
  if (!config3?.installed) return [];
13202
- const names2 = /* @__PURE__ */ new Set([...config3.installed.components, ...config3.installed.primitives]);
13233
+ const names2 = /* @__PURE__ */ new Set([
13234
+ ...config3.installed.components,
13235
+ ...config3.installed.primitives,
13236
+ ...config3.installed.composites ?? []
13237
+ ]);
13203
13238
  return [...names2].sort();
13204
13239
  }
13240
+ var FOLDER_NAMES = /* @__PURE__ */ new Set(["composites"]);
13205
13241
  function isAlreadyInstalled(config3, item) {
13206
13242
  if (!config3?.installed) return false;
13207
- if (item.type === "registry:ui") {
13243
+ if (item.type === "ui") {
13208
13244
  return config3.installed.components.includes(item.name);
13209
13245
  }
13246
+ if (item.type === "composite") {
13247
+ return (config3.installed.composites ?? []).includes(item.name);
13248
+ }
13210
13249
  return config3.installed.primitives.includes(item.name);
13211
13250
  }
13212
13251
  function trackInstalled(config3, items) {
13213
13252
  if (!config3.installed) {
13214
- config3.installed = { components: [], primitives: [] };
13253
+ config3.installed = { components: [], primitives: [], composites: [] };
13254
+ }
13255
+ if (!config3.installed.composites) {
13256
+ config3.installed.composites = [];
13215
13257
  }
13216
13258
  for (const item of items) {
13217
- if (item.type === "registry:ui") {
13259
+ if (item.type === "ui") {
13218
13260
  if (!config3.installed.components.includes(item.name)) {
13219
13261
  config3.installed.components.push(item.name);
13220
13262
  }
13263
+ } else if (item.type === "composite") {
13264
+ if (!config3.installed.composites.includes(item.name)) {
13265
+ config3.installed.composites.push(item.name);
13266
+ }
13221
13267
  } else {
13222
13268
  if (!config3.installed.primitives.includes(item.name)) {
13223
13269
  config3.installed.primitives.push(item.name);
@@ -13226,6 +13272,7 @@ function trackInstalled(config3, items) {
13226
13272
  }
13227
13273
  config3.installed.components.sort();
13228
13274
  config3.installed.primitives.sort();
13275
+ config3.installed.composites.sort();
13229
13276
  }
13230
13277
  function transformPath(registryPath, config3) {
13231
13278
  if (!config3) return registryPath;
@@ -13235,12 +13282,15 @@ function transformPath(registryPath, config3) {
13235
13282
  if (registryPath.startsWith("lib/primitives/")) {
13236
13283
  return registryPath.replace("lib/primitives/", `${config3.primitivesPath}/`);
13237
13284
  }
13285
+ if (registryPath.startsWith("composites/")) {
13286
+ return registryPath.replace("composites/", `${config3.compositesPath}/`);
13287
+ }
13238
13288
  return registryPath;
13239
13289
  }
13240
13290
  function fileExists(cwd, relativePath) {
13241
13291
  return existsSync(join3(cwd, relativePath));
13242
13292
  }
13243
- function transformFileContent(content, config3) {
13293
+ function transformFileContent(content, config3, fileType = "component") {
13244
13294
  let transformed = content;
13245
13295
  const componentsPath = config3?.componentsPath ?? "components/ui";
13246
13296
  const primitivesPath = config3?.primitivesPath ?? "lib/primitives";
@@ -13252,10 +13302,8 @@ function transformFileContent(content, config3) {
13252
13302
  /from\s+['"]\.\.\/primitives\/([^'"]+)['"]/g,
13253
13303
  `from '@/${primitivesPath}/$1'`
13254
13304
  );
13255
- transformed = transformed.replace(
13256
- /from\s+['"]\.\/([^'"]+)['"]/g,
13257
- `from '@/${componentsPath}/$1'`
13258
- );
13305
+ const siblingPath = fileType === "primitive" ? primitivesPath : componentsPath;
13306
+ transformed = transformed.replace(/from\s+['"]\.\/([^'"]+)['"]/g, `from '@/${siblingPath}/$1'`);
13259
13307
  const libPath = dirname(primitivesPath);
13260
13308
  transformed = transformed.replace(
13261
13309
  /from\s+['"]\.\.\/lib\/([^'"]+)['"]/g,
@@ -13292,7 +13340,8 @@ async function installItem(cwd, item, options, config3) {
13292
13340
  }
13293
13341
  }
13294
13342
  await mkdir(dirname(targetPath), { recursive: true });
13295
- const transformedContent = transformFileContent(file2.content, config3);
13343
+ const fileType = item.type === "primitive" ? "primitive" : "component";
13344
+ const transformedContent = transformFileContent(file2.content, config3, fileType);
13296
13345
  await writeFile(targetPath, transformedContent, "utf-8");
13297
13346
  installedFiles.push(projectPath);
13298
13347
  }
@@ -13306,15 +13355,32 @@ async function add(componentArgs, options) {
13306
13355
  setAgentMode(options.agent ?? false);
13307
13356
  let components = componentArgs;
13308
13357
  const client = new RegistryClient(options.registryUrl);
13358
+ let folder;
13359
+ const firstArg = components[0];
13360
+ if (firstArg && FOLDER_NAMES.has(firstArg)) {
13361
+ folder = firstArg;
13362
+ components = components.slice(1);
13363
+ }
13309
13364
  if (options.list) {
13310
13365
  const availableComponents = await client.listComponents();
13366
+ const availableComposites = await client.listComposites();
13311
13367
  if (options.agent) {
13312
- log({ event: "add:list", components: availableComponents });
13368
+ log({
13369
+ event: "add:list",
13370
+ components: availableComponents,
13371
+ composites: availableComposites
13372
+ });
13313
13373
  } else {
13314
13374
  console.log("Available components:\n");
13315
13375
  for (const comp of availableComponents) {
13316
13376
  console.log(` ${comp.name} ${comp.description ?? ""}`);
13317
13377
  }
13378
+ if (availableComposites.length > 0) {
13379
+ console.log("\nAvailable composites:\n");
13380
+ for (const comp of availableComposites) {
13381
+ console.log(` ${comp.name} ${comp.description ?? ""}`);
13382
+ }
13383
+ }
13318
13384
  }
13319
13385
  return;
13320
13386
  }
@@ -13357,15 +13423,23 @@ async function add(componentArgs, options) {
13357
13423
  });
13358
13424
  const allItems = [];
13359
13425
  const seen = /* @__PURE__ */ new Set();
13360
- for (const componentName of components) {
13426
+ for (const itemName of components) {
13361
13427
  try {
13362
- const items = await client.resolveDependencies(componentName, seen);
13363
- allItems.push(...items);
13428
+ if (folder === "composites") {
13429
+ if (!seen.has(itemName)) {
13430
+ const item = await client.fetchComposite(itemName);
13431
+ seen.add(itemName);
13432
+ allItems.push(item);
13433
+ }
13434
+ } else {
13435
+ const items = await client.resolveDependencies(itemName, seen);
13436
+ allItems.push(...items);
13437
+ }
13364
13438
  } catch (err) {
13365
13439
  if (err instanceof Error) {
13366
13440
  error46(err.message);
13367
13441
  } else {
13368
- error46(`Failed to fetch component "${componentName}"`);
13442
+ error46(`Failed to fetch "${itemName}"`);
13369
13443
  }
13370
13444
  process.exitCode = 1;
13371
13445
  return;
@@ -13443,10 +13517,11 @@ async function add(componentArgs, options) {
13443
13517
  framework: "unknown",
13444
13518
  componentsPath: "components/ui",
13445
13519
  primitivesPath: "lib/primitives",
13520
+ compositesPath: "composites",
13446
13521
  cssPath: null,
13447
13522
  shadcn: false,
13448
13523
  exports: DEFAULT_EXPORTS,
13449
- installed: { components: [], primitives: [] }
13524
+ installed: { components: [], primitives: [], composites: [] }
13450
13525
  };
13451
13526
  trackInstalled(newConfig, installedItems);
13452
13527
  await saveConfig(cwd, newConfig);
@@ -13469,7 +13544,7 @@ async function add(componentArgs, options) {
13469
13544
  }
13470
13545
 
13471
13546
  // src/commands/init.ts
13472
- import { existsSync as existsSync2 } from "fs";
13547
+ import { existsSync as existsSync3 } from "fs";
13473
13548
  import { copyFile, mkdir as mkdir3, readFile as readFile5, rm, writeFile as writeFile3 } from "fs/promises";
13474
13549
  import { createRequire } from "module";
13475
13550
  import { join as join9, relative } from "path";
@@ -14397,6 +14472,42 @@ function buildExtensions(token) {
14397
14472
  if (token.customPropertyOnly) {
14398
14473
  extensions.customPropertyOnly = token.customPropertyOnly;
14399
14474
  }
14475
+ if (token.userOverride) {
14476
+ extensions.userOverride = token.userOverride;
14477
+ }
14478
+ if (token.computedValue !== void 0) {
14479
+ extensions.computedValue = convertValue({ ...token, value: token.computedValue });
14480
+ }
14481
+ if (token.generationRule) {
14482
+ extensions.generationRule = token.generationRule;
14483
+ }
14484
+ if (token.pairedWith && token.pairedWith.length > 0) {
14485
+ extensions.pairedWith = token.pairedWith;
14486
+ }
14487
+ if (token.conflictsWith && token.conflictsWith.length > 0) {
14488
+ extensions.conflictsWith = token.conflictsWith;
14489
+ }
14490
+ if (token.applicableComponents && token.applicableComponents.length > 0) {
14491
+ extensions.applicableComponents = token.applicableComponents;
14492
+ }
14493
+ if (token.requiredForComponents && token.requiredForComponents.length > 0) {
14494
+ extensions.requiredForComponents = token.requiredForComponents;
14495
+ }
14496
+ if (token.trustLevel) {
14497
+ extensions.trustLevel = token.trustLevel;
14498
+ }
14499
+ if (token.cognitiveLoad !== void 0) {
14500
+ extensions.cognitiveLoad = token.cognitiveLoad;
14501
+ }
14502
+ if (token.consequence) {
14503
+ extensions.consequence = token.consequence;
14504
+ }
14505
+ if (token.accessibilityLevel) {
14506
+ extensions.accessibilityLevel = token.accessibilityLevel;
14507
+ }
14508
+ if (token.appliesWhen && token.appliesWhen.length > 0) {
14509
+ extensions.appliesWhen = token.appliesWhen;
14510
+ }
14400
14511
  return Object.keys(extensions).length > 0 ? { rafters: extensions } : {};
14401
14512
  }
14402
14513
  function tokenToDTCG(token) {
@@ -24603,7 +24714,7 @@ var require_volume = __commonJS({
24603
24714
  var Dir_1 = require_Dir();
24604
24715
  var resolveCrossPlatform = pathModule.resolve;
24605
24716
  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;
24606
- var { sep: sep2, relative: relative2, join: join12, dirname: dirname4 } = pathModule.posix ? pathModule.posix : pathModule;
24717
+ var { sep: sep2, relative: relative3, join: join12, dirname: dirname4 } = pathModule.posix ? pathModule.posix : pathModule;
24607
24718
  var kMinPoolSpace = 128;
24608
24719
  var EPERM = "EPERM";
24609
24720
  var ENOENT2 = "ENOENT";
@@ -24946,7 +25057,7 @@ var require_volume = __commonJS({
24946
25057
  if (node.isFile()) {
24947
25058
  let filename = child.getPath();
24948
25059
  if (path2)
24949
- filename = relative2(path2, filename);
25060
+ filename = relative3(path2, filename);
24950
25061
  json3[filename] = asBuffer ? node.getBuffer() : node.getString();
24951
25062
  } else if (node.isDirectory()) {
24952
25063
  this._toJSON(child, json3, path2, asBuffer);
@@ -24954,7 +25065,7 @@ var require_volume = __commonJS({
24954
25065
  }
24955
25066
  let dirPath = link.getPath();
24956
25067
  if (path2)
24957
- dirPath = relative2(path2, dirPath);
25068
+ dirPath = relative3(path2, dirPath);
24958
25069
  if (dirPath && isEmpty) {
24959
25070
  json3[dirPath] = null;
24960
25071
  }
@@ -26432,7 +26543,7 @@ var require_volume = __commonJS({
26432
26543
  const filepath = link.getPath();
26433
26544
  const node = link.getNode();
26434
26545
  const onNodeChange = () => {
26435
- let filename = relative2(this._filename, filepath);
26546
+ let filename = relative3(this._filename, filepath);
26436
26547
  if (!filename) {
26437
26548
  filename = this._getName();
26438
26549
  }
@@ -26447,7 +26558,7 @@ var require_volume = __commonJS({
26447
26558
  var _a;
26448
26559
  const node = link.getNode();
26449
26560
  const onLinkChildAdd = (l) => {
26450
- this.emit("change", "rename", relative2(this._filename, l.getPath()));
26561
+ this.emit("change", "rename", relative3(this._filename, l.getPath()));
26451
26562
  setTimeout(() => {
26452
26563
  watchLinkNodeChanged(l);
26453
26564
  watchLinkChildrenChanged(l);
@@ -26468,7 +26579,7 @@ var require_volume = __commonJS({
26468
26579
  }
26469
26580
  };
26470
26581
  removeLinkNodeListeners(l);
26471
- this.emit("change", "rename", relative2(this._filename, l.getPath()));
26582
+ this.emit("change", "rename", relative3(this._filename, l.getPath()));
26472
26583
  };
26473
26584
  for (const [name2, childLink] of link.children.entries()) {
26474
26585
  if (childLink && name2 !== "." && name2 !== "..") {
@@ -33568,10 +33679,10 @@ var Ignore = class {
33568
33679
  ignored(p) {
33569
33680
  const fullpath = p.fullpath();
33570
33681
  const fullpaths = `${fullpath}/`;
33571
- const relative2 = p.relative() || ".";
33572
- const relatives = `${relative2}/`;
33682
+ const relative3 = p.relative() || ".";
33683
+ const relatives = `${relative3}/`;
33573
33684
  for (const m of this.relative) {
33574
- if (m.match(relative2) || m.match(relatives))
33685
+ if (m.match(relative3) || m.match(relatives))
33575
33686
  return true;
33576
33687
  }
33577
33688
  for (const m of this.absolute) {
@@ -33582,9 +33693,9 @@ var Ignore = class {
33582
33693
  }
33583
33694
  childrenIgnored(p) {
33584
33695
  const fullpath = p.fullpath() + "/";
33585
- const relative2 = (p.relative() || ".") + "/";
33696
+ const relative3 = (p.relative() || ".") + "/";
33586
33697
  for (const m of this.relativeChildren) {
33587
- if (m.match(relative2))
33698
+ if (m.match(relative3))
33588
33699
  return true;
33589
33700
  }
33590
33701
  for (const m of this.absoluteChildren) {
@@ -46517,6 +46628,9 @@ function getSemanticMappingsFromTokens(semanticTokens) {
46517
46628
  function tokenValueToCSS(token) {
46518
46629
  const { value: value2 } = token;
46519
46630
  if (typeof value2 === "string") {
46631
+ if (value2.startsWith("{") || value2.startsWith("[")) {
46632
+ return null;
46633
+ }
46520
46634
  return value2;
46521
46635
  }
46522
46636
  if (typeof value2 === "object" && value2 !== null) {
@@ -46642,6 +46756,7 @@ function generateThemeBlock(groups) {
46642
46756
  if (groups.color.length > 0) {
46643
46757
  for (const token of groups.color) {
46644
46758
  const value2 = tokenValueToCSS(token);
46759
+ if (value2 === null) continue;
46645
46760
  lines.push(` --color-${token.name}: ${value2};`);
46646
46761
  }
46647
46762
  lines.push("");
@@ -46649,6 +46764,7 @@ function generateThemeBlock(groups) {
46649
46764
  if (groups.spacing.length > 0) {
46650
46765
  for (const token of groups.spacing) {
46651
46766
  const value2 = tokenValueToCSS(token);
46767
+ if (value2 === null) continue;
46652
46768
  lines.push(` --spacing-${token.name}: ${value2};`);
46653
46769
  }
46654
46770
  lines.push("");
@@ -46656,6 +46772,7 @@ function generateThemeBlock(groups) {
46656
46772
  if (groups.typography.length > 0) {
46657
46773
  for (const token of groups.typography) {
46658
46774
  const value2 = tokenValueToCSS(token);
46775
+ if (value2 === null) continue;
46659
46776
  lines.push(` --${token.name}: ${value2};`);
46660
46777
  if (token.lineHeight) {
46661
46778
  lines.push(` --${token.name}--line-height: ${token.lineHeight};`);
@@ -46666,6 +46783,7 @@ function generateThemeBlock(groups) {
46666
46783
  if (groups.radius.length > 0) {
46667
46784
  for (const token of groups.radius) {
46668
46785
  const value2 = tokenValueToCSS(token);
46786
+ if (value2 === null) continue;
46669
46787
  lines.push(` --radius-${token.name}: ${value2};`);
46670
46788
  }
46671
46789
  lines.push("");
@@ -46673,6 +46791,7 @@ function generateThemeBlock(groups) {
46673
46791
  if (groups.shadow.length > 0) {
46674
46792
  for (const token of groups.shadow) {
46675
46793
  const value2 = tokenValueToCSS(token);
46794
+ if (value2 === null) continue;
46676
46795
  lines.push(` --shadow-${token.name}: ${value2};`);
46677
46796
  }
46678
46797
  lines.push("");
@@ -46680,6 +46799,7 @@ function generateThemeBlock(groups) {
46680
46799
  if (groups.depth.length > 0) {
46681
46800
  for (const token of groups.depth) {
46682
46801
  const value2 = tokenValueToCSS(token);
46802
+ if (value2 === null) continue;
46683
46803
  lines.push(` --${token.name}: ${value2};`);
46684
46804
  }
46685
46805
  lines.push("");
@@ -46687,6 +46807,7 @@ function generateThemeBlock(groups) {
46687
46807
  if (groups.motion.length > 0) {
46688
46808
  for (const token of groups.motion) {
46689
46809
  const value2 = tokenValueToCSS(token);
46810
+ if (value2 === null) continue;
46690
46811
  lines.push(` --${token.name}: ${value2};`);
46691
46812
  }
46692
46813
  lines.push("");
@@ -46694,6 +46815,7 @@ function generateThemeBlock(groups) {
46694
46815
  if (groups.breakpoint.length > 0) {
46695
46816
  for (const token of groups.breakpoint) {
46696
46817
  const value2 = tokenValueToCSS(token);
46818
+ if (value2 === null) continue;
46697
46819
  lines.push(` --${token.name}: ${value2};`);
46698
46820
  }
46699
46821
  lines.push("");
@@ -46701,6 +46823,7 @@ function generateThemeBlock(groups) {
46701
46823
  if (groups.elevation.length > 0) {
46702
46824
  for (const token of groups.elevation) {
46703
46825
  const value2 = tokenValueToCSS(token);
46826
+ if (value2 === null) continue;
46704
46827
  lines.push(` --${token.name}: ${value2};`);
46705
46828
  }
46706
46829
  lines.push("");
@@ -46708,6 +46831,7 @@ function generateThemeBlock(groups) {
46708
46831
  if (groups.focus.length > 0) {
46709
46832
  for (const token of groups.focus) {
46710
46833
  const value2 = tokenValueToCSS(token);
46834
+ if (value2 === null) continue;
46711
46835
  lines.push(` --${token.name}: ${value2};`);
46712
46836
  }
46713
46837
  lines.push("");
@@ -46715,6 +46839,7 @@ function generateThemeBlock(groups) {
46715
46839
  if (groups.other.length > 0) {
46716
46840
  for (const token of groups.other) {
46717
46841
  const value2 = tokenValueToCSS(token);
46842
+ if (value2 === null) continue;
46718
46843
  lines.push(` --${token.name}: ${value2};`);
46719
46844
  }
46720
46845
  lines.push("");
@@ -46896,6 +47021,9 @@ async function registryToCompiled(registry2, options = {}) {
46896
47021
  function tokenValueToTS(token) {
46897
47022
  const { value: value2 } = token;
46898
47023
  if (typeof value2 === "string") {
47024
+ if (value2.startsWith("{") || value2.startsWith("[")) {
47025
+ return value2;
47026
+ }
46899
47027
  return escapeStringValue(value2);
46900
47028
  }
46901
47029
  if (typeof value2 === "object" && value2 !== null) {
@@ -47524,7 +47652,7 @@ function extractPrimitiveDependencies(source) {
47524
47652
  const pkg = match2[1];
47525
47653
  if (pkg && (pkg.includes("/primitives/") || pkg.includes("../primitives/"))) {
47526
47654
  const primitiveName = pkg.split("/").pop()?.replace(/\.(ts|tsx)$/, "");
47527
- if (primitiveName && !primitives.includes(primitiveName) && primitiveName !== "types") {
47655
+ if (primitiveName && !primitives.includes(primitiveName)) {
47528
47656
  primitives.push(primitiveName);
47529
47657
  }
47530
47658
  }
@@ -47547,7 +47675,13 @@ function extractJSDocDependencies(source) {
47547
47675
  if (!field) continue;
47548
47676
  const value2 = getTagValue(tag).trim();
47549
47677
  if (value2) {
47550
- result[field].push(...value2.split(/\s+/).filter(Boolean));
47678
+ const tokens = value2.split(/\s+/).filter(Boolean);
47679
+ const validTokens = [];
47680
+ for (const token of tokens) {
47681
+ if (token.startsWith("(")) break;
47682
+ validTokens.push(token);
47683
+ }
47684
+ result[field].push(...validTokens);
47551
47685
  }
47552
47686
  }
47553
47687
  }
@@ -50782,8 +50916,15 @@ var RuleContextSchema = external_exports.object({
50782
50916
  });
50783
50917
 
50784
50918
  // src/utils/detect.ts
50919
+ import { existsSync as existsSync2 } from "fs";
50785
50920
  import { readFile as readFile4 } from "fs/promises";
50786
50921
  import { join as join8 } from "path";
50922
+ var CONFIG_FILE_FRAMEWORKS = [
50923
+ { files: ["astro.config.mjs", "astro.config.ts", "astro.config.js"], framework: "astro" },
50924
+ { files: ["next.config.mjs", "next.config.ts", "next.config.js"], framework: "next" },
50925
+ { files: ["remix.config.js", "remix.config.ts"], framework: "remix" },
50926
+ { files: ["vite.config.ts", "vite.config.js", "vite.config.mjs"], framework: "vite" }
50927
+ ];
50787
50928
  async function detectFramework(cwd) {
50788
50929
  try {
50789
50930
  const content = await readFile4(join8(cwd, "package.json"), "utf-8");
@@ -50805,10 +50946,19 @@ async function detectFramework(cwd) {
50805
50946
  if (deps.vite) {
50806
50947
  return "vite";
50807
50948
  }
50808
- return "unknown";
50809
50949
  } catch {
50810
- return "unknown";
50811
50950
  }
50951
+ return detectFrameworkFromConfigFiles(cwd);
50952
+ }
50953
+ function detectFrameworkFromConfigFiles(cwd) {
50954
+ for (const { files, framework } of CONFIG_FILE_FRAMEWORKS) {
50955
+ for (const file2 of files) {
50956
+ if (existsSync2(join8(cwd, file2))) {
50957
+ return framework;
50958
+ }
50959
+ }
50960
+ }
50961
+ return "unknown";
50812
50962
  }
50813
50963
  async function detectTailwindVersion(cwd) {
50814
50964
  try {
@@ -50910,18 +51060,34 @@ var CSS_LOCATIONS = {
50910
51060
  unknown: ["src/styles/global.css", "src/index.css", "styles/globals.css"]
50911
51061
  };
50912
51062
  var COMPONENT_PATHS = {
50913
- astro: { components: "src/components/ui", primitives: "src/lib/primitives" },
50914
- next: { components: "components/ui", primitives: "lib/primitives" },
50915
- vite: { components: "src/components/ui", primitives: "src/lib/primitives" },
50916
- remix: { components: "app/components/ui", primitives: "app/lib/primitives" },
50917
- "react-router": { components: "app/components/ui", primitives: "app/lib/primitives" },
50918
- unknown: { components: "components/ui", primitives: "lib/primitives" }
51063
+ astro: {
51064
+ components: "src/components/ui",
51065
+ primitives: "src/lib/primitives",
51066
+ composites: "src/composites"
51067
+ },
51068
+ next: { components: "components/ui", primitives: "lib/primitives", composites: "composites" },
51069
+ vite: {
51070
+ components: "src/components/ui",
51071
+ primitives: "src/lib/primitives",
51072
+ composites: "src/composites"
51073
+ },
51074
+ remix: {
51075
+ components: "app/components/ui",
51076
+ primitives: "app/lib/primitives",
51077
+ composites: "app/composites"
51078
+ },
51079
+ "react-router": {
51080
+ components: "app/components/ui",
51081
+ primitives: "app/lib/primitives",
51082
+ composites: "app/composites"
51083
+ },
51084
+ unknown: { components: "components/ui", primitives: "lib/primitives", composites: "composites" }
50919
51085
  };
50920
51086
  async function findMainCssFile(cwd, framework) {
50921
51087
  const locations = CSS_LOCATIONS[framework] || CSS_LOCATIONS.unknown;
50922
51088
  for (const location of locations) {
50923
51089
  const fullPath = join9(cwd, location);
50924
- if (existsSync2(fullPath)) {
51090
+ if (existsSync3(fullPath)) {
50925
51091
  return location;
50926
51092
  }
50927
51093
  }
@@ -51043,7 +51209,7 @@ async function generateOutputs(cwd, paths, registry2, exports, shadcn) {
51043
51209
  }
51044
51210
  return outputs;
51045
51211
  }
51046
- async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2) {
51212
+ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2, framework) {
51047
51213
  log({ event: "init:regenerate", cwd });
51048
51214
  let existingConfig = null;
51049
51215
  try {
@@ -51051,6 +51217,13 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2) {
51051
51217
  existingConfig = JSON.parse(configContent);
51052
51218
  } catch {
51053
51219
  }
51220
+ if (framework !== "unknown" && existingConfig) {
51221
+ const frameworkPaths = COMPONENT_PATHS[framework] || COMPONENT_PATHS.unknown;
51222
+ existingConfig.framework = framework;
51223
+ existingConfig.componentsPath = frameworkPaths.components;
51224
+ existingConfig.primitivesPath = frameworkPaths.primitives;
51225
+ existingConfig.compositesPath = frameworkPaths.composites;
51226
+ }
51054
51227
  const adapter = new NodePersistenceAdapter(cwd);
51055
51228
  const allTokens = await adapter.load();
51056
51229
  if (allTokens.length === 0) {
@@ -51086,7 +51259,7 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2) {
51086
51259
  path: paths.output
51087
51260
  });
51088
51261
  }
51089
- async function resetToDefaults(cwd, paths, shadcn, isAgentMode2) {
51262
+ async function resetToDefaults(cwd, paths, shadcn, isAgentMode2, framework) {
51090
51263
  log({ event: "init:reset", cwd });
51091
51264
  let existingConfig = null;
51092
51265
  try {
@@ -51094,6 +51267,13 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode2) {
51094
51267
  existingConfig = JSON.parse(configContent);
51095
51268
  } catch {
51096
51269
  }
51270
+ if (framework !== "unknown" && existingConfig) {
51271
+ const frameworkPaths = COMPONENT_PATHS[framework] || COMPONENT_PATHS.unknown;
51272
+ existingConfig.framework = framework;
51273
+ existingConfig.componentsPath = frameworkPaths.components;
51274
+ existingConfig.primitivesPath = frameworkPaths.primitives;
51275
+ existingConfig.compositesPath = frameworkPaths.composites;
51276
+ }
51097
51277
  const adapter = new NodePersistenceAdapter(cwd);
51098
51278
  const existingTokens = await adapter.load();
51099
51279
  const overriddenTokens = existingTokens.filter((t2) => t2.userOverride);
@@ -51179,12 +51359,12 @@ async function init(options) {
51179
51359
  if (isTailwindV3(tailwindVersion)) {
51180
51360
  throw new Error("Tailwind v3 detected. Rafters requires Tailwind v4.");
51181
51361
  }
51182
- const raftersExists = existsSync2(paths.root);
51362
+ const raftersExists = existsSync3(paths.root);
51183
51363
  if (options.reset && !raftersExists) {
51184
51364
  throw new Error("Nothing to reset. No .rafters/ directory found.");
51185
51365
  }
51186
51366
  if (raftersExists && options.reset) {
51187
- await resetToDefaults(cwd, paths, shadcn, isAgentMode2);
51367
+ await resetToDefaults(cwd, paths, shadcn, isAgentMode2, framework);
51188
51368
  return;
51189
51369
  }
51190
51370
  if (raftersExists && !options.rebuild) {
@@ -51193,7 +51373,7 @@ async function init(options) {
51193
51373
  );
51194
51374
  }
51195
51375
  if (raftersExists && options.rebuild) {
51196
- await regenerateFromExisting(cwd, paths, shadcn, isAgentMode2);
51376
+ await regenerateFromExisting(cwd, paths, shadcn, isAgentMode2, framework);
51197
51377
  return;
51198
51378
  }
51199
51379
  let existingColors = null;
@@ -51304,12 +51484,14 @@ async function init(options) {
51304
51484
  framework,
51305
51485
  componentsPath: frameworkPaths.components,
51306
51486
  primitivesPath: frameworkPaths.primitives,
51487
+ compositesPath: frameworkPaths.composites,
51307
51488
  cssPath: detectedCssPath,
51308
51489
  shadcn: !!shadcn,
51309
51490
  exports,
51310
51491
  installed: {
51311
51492
  components: [],
51312
- primitives: []
51493
+ primitives: [],
51494
+ composites: []
51313
51495
  }
51314
51496
  };
51315
51497
  await writeFile3(paths.config, JSON.stringify(config3, null, 2));
@@ -51326,9 +51508,9 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
51326
51508
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
51327
51509
 
51328
51510
  // src/mcp/tools.ts
51329
- import { existsSync as existsSync3 } from "fs";
51511
+ import { existsSync as existsSync4 } from "fs";
51330
51512
  import { readdir as readdir3, readFile as readFile6 } from "fs/promises";
51331
- import { basename, join as join10 } from "path";
51513
+ import { basename, join as join10, relative as relative2 } from "path";
51332
51514
 
51333
51515
  // src/mcp/cognitive-load.ts
51334
51516
  var BUDGET_TIERS = {
@@ -52746,16 +52928,30 @@ var RaftersToolHandler = class {
52746
52928
  return { sizes: {}, weights: [] };
52747
52929
  }
52748
52930
  }
52931
+ /**
52932
+ * Load and cache the project's Rafters config from .rafters/config.rafters.json.
52933
+ * Returns null when no config exists or when it cannot be parsed.
52934
+ */
52935
+ async loadConfig() {
52936
+ try {
52937
+ const paths = getRaftersPaths(this.projectRoot);
52938
+ if (!existsSync4(paths.config)) {
52939
+ return null;
52940
+ }
52941
+ const content = await readFile6(paths.config, "utf-8");
52942
+ return JSON.parse(content);
52943
+ } catch {
52944
+ return null;
52945
+ }
52946
+ }
52749
52947
  /**
52750
52948
  * Extract compact component vocabulary
52751
52949
  */
52752
52950
  async getComponentVocabulary() {
52753
52951
  let installed = [];
52754
52952
  try {
52755
- const paths = getRaftersPaths(this.projectRoot);
52756
- if (existsSync3(paths.config)) {
52757
- const content = await readFile6(paths.config, "utf-8");
52758
- const config3 = JSON.parse(content);
52953
+ const config3 = await this.loadConfig();
52954
+ if (config3) {
52759
52955
  installed = config3.installed?.components ?? [];
52760
52956
  }
52761
52957
  } catch {
@@ -52807,17 +53003,22 @@ var RaftersToolHandler = class {
52807
53003
  }
52808
53004
  // ==================== Tool 3: Component ====================
52809
53005
  /**
52810
- * Get path to UI components directory
53006
+ * Get path to UI components directory.
53007
+ * Reads componentsPath from .rafters/config.rafters.json when available,
53008
+ * falls back to the monorepo layout for local development.
52811
53009
  */
52812
- getComponentsPath() {
52813
- const monorepoPath = join10(this.projectRoot, "packages/ui/src/components/ui");
52814
- return monorepoPath;
53010
+ async getComponentsPath() {
53011
+ const config3 = await this.loadConfig();
53012
+ if (config3?.componentsPath) {
53013
+ return join10(this.projectRoot, config3.componentsPath);
53014
+ }
53015
+ return join10(this.projectRoot, "packages/ui/src/components/ui");
52815
53016
  }
52816
53017
  /**
52817
53018
  * Load component metadata from source file
52818
53019
  */
52819
53020
  async loadComponentMetadata(name2) {
52820
- const componentsPath = this.getComponentsPath();
53021
+ const componentsPath = await this.getComponentsPath();
52821
53022
  const filePath = join10(componentsPath, `${name2}.tsx`);
52822
53023
  try {
52823
53024
  const source = await readFile6(filePath, "utf-8");
@@ -52836,7 +53037,7 @@ var RaftersToolHandler = class {
52836
53037
  sizes: extractSizes(source),
52837
53038
  dependencies: extractDependencies(source),
52838
53039
  primitives: extractPrimitiveDependencies(source),
52839
- filePath: `packages/ui/src/components/ui/${name2}.tsx`
53040
+ filePath: relative2(this.projectRoot, join10(componentsPath, `${name2}.tsx`))
52840
53041
  };
52841
53042
  if (hasAnyDeps(jsDocDeps)) {
52842
53043
  metadata.jsDocDependencies = jsDocDeps;
@@ -52928,7 +53129,7 @@ var RaftersToolHandler = class {
52928
53129
  try {
52929
53130
  const metadata = await this.loadComponentMetadata(name2);
52930
53131
  if (!metadata) {
52931
- const componentsPath = this.getComponentsPath();
53132
+ const componentsPath = await this.getComponentsPath();
52932
53133
  let available = [];
52933
53134
  try {
52934
53135
  const files = await readdir3(componentsPath);
@@ -53291,7 +53492,7 @@ async function mcp() {
53291
53492
  }
53292
53493
 
53293
53494
  // src/commands/studio.ts
53294
- import { existsSync as existsSync4 } from "fs";
53495
+ import { existsSync as existsSync5 } from "fs";
53295
53496
  import { dirname as dirname3, join as join11 } from "path";
53296
53497
  import { fileURLToPath as fileURLToPath3 } from "url";
53297
53498
  import { execa as execa2 } from "execa";
@@ -53299,14 +53500,14 @@ var __dirname2 = dirname3(fileURLToPath3(import.meta.url));
53299
53500
  async function studio() {
53300
53501
  const cwd = process.cwd();
53301
53502
  const paths = getRaftersPaths(cwd);
53302
- if (!existsSync4(paths.root)) {
53503
+ if (!existsSync5(paths.root)) {
53303
53504
  console.error('No .rafters/ directory found. Run "rafters init" first.');
53304
53505
  process.exit(1);
53305
53506
  }
53306
53507
  const devStudioPath = join11(__dirname2, "..", "..", "..", "studio");
53307
53508
  const prodStudioPath = join11(__dirname2, "..", "node_modules", "@rafters", "studio");
53308
- const studioPath = existsSync4(devStudioPath) ? devStudioPath : prodStudioPath;
53309
- if (!existsSync4(studioPath)) {
53509
+ const studioPath = existsSync5(devStudioPath) ? devStudioPath : prodStudioPath;
53510
+ if (!existsSync5(studioPath)) {
53310
53511
  console.error("Studio package not found. Please reinstall @rafters/cli.");
53311
53512
  process.exit(1);
53312
53513
  }
@@ -22,9 +22,9 @@ type RegistryFile = z.infer<typeof RegistryFileSchema>;
22
22
  * Item type in registry
23
23
  */
24
24
  declare const RegistryItemTypeSchema: z.ZodEnum<{
25
- "registry:ui": "registry:ui";
26
- "registry:primitive": "registry:primitive";
27
- "registry:composite": "registry:composite";
25
+ ui: "ui";
26
+ primitive: "primitive";
27
+ composite: "composite";
28
28
  }>;
29
29
  type RegistryItemType = z.infer<typeof RegistryItemTypeSchema>;
30
30
  /**
@@ -33,9 +33,9 @@ type RegistryItemType = z.infer<typeof RegistryItemTypeSchema>;
33
33
  declare const RegistryItemSchema: z.ZodObject<{
34
34
  name: z.ZodString;
35
35
  type: z.ZodEnum<{
36
- "registry:ui": "registry:ui";
37
- "registry:primitive": "registry:primitive";
38
- "registry:composite": "registry:composite";
36
+ ui: "ui";
37
+ primitive: "primitive";
38
+ composite: "composite";
39
39
  }>;
40
40
  description: z.ZodOptional<z.ZodString>;
41
41
  primitives: z.ZodArray<z.ZodString>;
@@ -45,6 +45,8 @@ declare const RegistryItemSchema: z.ZodObject<{
45
45
  dependencies: z.ZodArray<z.ZodString>;
46
46
  devDependencies: z.ZodDefault<z.ZodArray<z.ZodString>>;
47
47
  }, z.core.$strip>>;
48
+ rules: z.ZodDefault<z.ZodArray<z.ZodString>>;
49
+ composites: z.ZodDefault<z.ZodArray<z.ZodString>>;
48
50
  }, z.core.$strip>;
49
51
  type RegistryItem = z.infer<typeof RegistryItemSchema>;
50
52
  /**
@@ -55,6 +57,8 @@ declare const RegistryIndexSchema: z.ZodObject<{
55
57
  homepage: z.ZodString;
56
58
  components: z.ZodArray<z.ZodString>;
57
59
  primitives: z.ZodArray<z.ZodString>;
60
+ composites: z.ZodDefault<z.ZodArray<z.ZodString>>;
61
+ rules: z.ZodDefault<z.ZodArray<z.ZodString>>;
58
62
  }, z.core.$strip>;
59
63
  type RegistryIndex = z.infer<typeof RegistryIndexSchema>;
60
64
 
@@ -8,23 +8,23 @@ var RegistryFileSchema = z.object({
8
8
  devDependencies: z.array(z.string()).default([])
9
9
  // e.g., ["vitest"] - from @devDependencies JSDoc
10
10
  });
11
- var RegistryItemTypeSchema = z.enum([
12
- "registry:ui",
13
- "registry:primitive",
14
- "registry:composite"
15
- ]);
11
+ var RegistryItemTypeSchema = z.enum(["ui", "primitive", "composite"]);
16
12
  var RegistryItemSchema = z.object({
17
13
  name: z.string(),
18
14
  type: RegistryItemTypeSchema,
19
15
  description: z.string().optional(),
20
16
  primitives: z.array(z.string()),
21
- files: z.array(RegistryFileSchema)
17
+ files: z.array(RegistryFileSchema),
18
+ rules: z.array(z.string()).default([]),
19
+ composites: z.array(z.string()).default([])
22
20
  });
23
21
  var RegistryIndexSchema = z.object({
24
22
  name: z.string(),
25
23
  homepage: z.string(),
26
24
  components: z.array(z.string()),
27
- primitives: z.array(z.string())
25
+ primitives: z.array(z.string()),
26
+ composites: z.array(z.string()).default([]),
27
+ rules: z.array(z.string()).default([])
28
28
  });
29
29
  export {
30
30
  RegistryFileSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rafters",
3
- "version": "0.0.9",
3
+ "version": "0.0.13",
4
4
  "description": "CLI for Rafters design system - scaffold tokens and add components",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,6 +48,11 @@
48
48
  "vitest": "catalog:",
49
49
  "zocker": "catalog:"
50
50
  },
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/ezmode-games/rafters.git",
54
+ "directory": "packages/cli"
55
+ },
51
56
  "publishConfig": {
52
57
  "access": "public"
53
58
  }