rafters 0.0.53 → 0.0.54

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.
Files changed (2) hide show
  1. package/dist/index.js +258 -162
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -863,7 +863,8 @@ async function installRegistryDependencies(items, targetDir, options = {}) {
863
863
  }
864
864
 
865
865
  // src/utils/paths.ts
866
- import { join as join3 } from "path";
866
+ import { realpathSync } from "fs";
867
+ import { isAbsolute, join as join3, relative, resolve } from "path";
867
868
  function getRaftersPaths(projectRoot = process.cwd()) {
868
869
  const root = join3(projectRoot, ".rafters");
869
870
  return {
@@ -874,6 +875,63 @@ function getRaftersPaths(projectRoot = process.cwd()) {
874
875
  importPending: join3(root, "import-pending.json")
875
876
  };
876
877
  }
878
+ var PathEntrySchema = external_exports.union([
879
+ external_exports.string(),
880
+ external_exports.object({ path: external_exports.string(), root: external_exports.literal(true).optional() })
881
+ ]);
882
+ var PathFieldSchema = external_exports.union([external_exports.string(), external_exports.array(PathEntrySchema)]);
883
+ function entryPath(entry) {
884
+ return typeof entry === "string" ? entry : entry.path;
885
+ }
886
+ function entryHasExplicitRoot(entry) {
887
+ return typeof entry === "object" && entry.root === true;
888
+ }
889
+ function tryRealpath(absPath) {
890
+ try {
891
+ return realpathSync(absPath);
892
+ } catch {
893
+ return absPath;
894
+ }
895
+ }
896
+ function isInsideCwd(absPath, cwdReal) {
897
+ const rel = relative(cwdReal, absPath);
898
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
899
+ }
900
+ function resolveRoot(field, cwd, fallback) {
901
+ const cwdReal = tryRealpath(resolve(cwd));
902
+ if (typeof field === "string") {
903
+ return field;
904
+ }
905
+ for (const entry of field) {
906
+ if (entryHasExplicitRoot(entry)) {
907
+ return entryPath(entry);
908
+ }
909
+ }
910
+ for (const entry of field) {
911
+ const p2 = entryPath(entry);
912
+ const abs = isAbsolute(p2) ? p2 : resolve(cwdReal, p2);
913
+ if (isInsideCwd(tryRealpath(abs), cwdReal)) return p2;
914
+ }
915
+ return fallback;
916
+ }
917
+ function resolveReadSet(field, cwd, fallback) {
918
+ const cwdReal = tryRealpath(resolve(cwd));
919
+ const entries = typeof field === "string" ? [field] : field.map(entryPath);
920
+ const root = resolveRoot(field, cwd, fallback ?? entries[0] ?? "");
921
+ const ordered = [root, ...entries.filter((e) => e !== root)];
922
+ const seen = /* @__PURE__ */ new Set();
923
+ const out = [];
924
+ for (const entry of ordered) {
925
+ if (!entry) continue;
926
+ const abs = isAbsolute(entry) ? entry : resolve(cwdReal, entry);
927
+ const real = tryRealpath(abs);
928
+ if (!seen.has(real)) {
929
+ seen.add(real);
930
+ out.push(real);
931
+ }
932
+ }
933
+ return out;
934
+ }
877
935
 
878
936
  // src/commands/add.ts
879
937
  async function isInitialized(cwd) {
@@ -949,50 +1007,45 @@ function isAlreadyInstalled(config2, item) {
949
1007
  }
950
1008
  function trackInstalled(config2, items) {
951
1009
  if (!config2.installed) {
952
- config2.installed = { components: [], primitives: [], composites: [] };
953
- }
954
- if (!config2.installed.composites) {
955
- config2.installed.composites = [];
1010
+ config2.installed = { components: [], primitives: [], composites: [], rules: [] };
956
1011
  }
1012
+ const installed = config2.installed;
1013
+ if (!installed.composites) installed.composites = [];
1014
+ if (!installed.rules) installed.rules = [];
957
1015
  for (const item of items) {
958
- if (item.type === "ui") {
959
- if (!config2.installed.components.includes(item.name)) {
960
- config2.installed.components.push(item.name);
961
- }
962
- } else if (item.type === "composite") {
963
- if (!config2.installed.composites.includes(item.name)) {
964
- config2.installed.composites.push(item.name);
965
- }
966
- } else {
967
- if (!config2.installed.primitives.includes(item.name)) {
968
- config2.installed.primitives.push(item.name);
969
- }
970
- }
1016
+ const bucket = item.type === "ui" ? installed.components : item.type === "composite" ? installed.composites : installed.primitives;
1017
+ if (!bucket.includes(item.name)) bucket.push(item.name);
971
1018
  }
972
- config2.installed.components.sort();
973
- config2.installed.primitives.sort();
974
- config2.installed.composites.sort();
1019
+ installed.components.sort();
1020
+ installed.primitives.sort();
1021
+ installed.composites.sort();
1022
+ installed.rules.sort();
1023
+ }
1024
+ function rootFor(field, cwd, fallback) {
1025
+ return field === void 0 ? fallback : resolveRoot(field, cwd, fallback);
975
1026
  }
976
- function transformPath(registryPath, config2) {
1027
+ function transformPath(registryPath, config2, cwd) {
977
1028
  if (!config2) return registryPath;
978
- if (registryPath.startsWith("components/ui/")) {
979
- return registryPath.replace("components/ui/", `${config2.componentsPath}/`);
980
- }
981
- if (registryPath.startsWith("lib/primitives/")) {
982
- return registryPath.replace("lib/primitives/", `${config2.primitivesPath}/`);
983
- }
984
- if (registryPath.startsWith("composites/")) {
985
- return registryPath.replace("composites/", `${config2.compositesPath}/`);
1029
+ const replacements = [
1030
+ ["components/ui/", config2.componentsPath, "components/ui"],
1031
+ ["lib/primitives/", config2.primitivesPath, "lib/primitives"],
1032
+ ["composites/", config2.compositesPath, "composites"],
1033
+ ["rules/", config2.rulesPath, "rules"]
1034
+ ];
1035
+ for (const [prefix, field, fallback] of replacements) {
1036
+ if (registryPath.startsWith(prefix)) {
1037
+ return registryPath.replace(prefix, `${rootFor(field, cwd, fallback)}/`);
1038
+ }
986
1039
  }
987
1040
  return registryPath;
988
1041
  }
989
1042
  function fileExists(cwd, relativePath) {
990
1043
  return existsSync2(join4(cwd, relativePath));
991
1044
  }
992
- function transformFileContent(content, config2, fileType = "component") {
1045
+ function transformFileContent(content, config2, fileType = "component", cwd = process.cwd()) {
993
1046
  let transformed = content;
994
- const componentsPath = config2?.componentsPath ?? "components/ui";
995
- const primitivesPath = config2?.primitivesPath ?? "lib/primitives";
1047
+ const componentsPath = rootFor(config2?.componentsPath, cwd, "components/ui");
1048
+ const primitivesPath = rootFor(config2?.primitivesPath, cwd, "lib/primitives");
996
1049
  const stripSourceRoot = (p2) => p2.replace(/^(src|app)\//, "");
997
1050
  const aliasComponents = stripSourceRoot(componentsPath);
998
1051
  const aliasPrimitives = stripSourceRoot(primitivesPath);
@@ -1041,7 +1094,7 @@ async function installItem(cwd, item, options, config2) {
1041
1094
  }
1042
1095
  }
1043
1096
  for (const file of filesToInstall) {
1044
- const projectPath2 = transformPath(file.path, config2);
1097
+ const projectPath2 = transformPath(file.path, config2, cwd);
1045
1098
  const targetPath = join4(cwd, projectPath2);
1046
1099
  if (fileExists(cwd, projectPath2)) {
1047
1100
  if (!options.overwrite) {
@@ -1057,7 +1110,7 @@ async function installItem(cwd, item, options, config2) {
1057
1110
  }
1058
1111
  await mkdir(dirname(targetPath), { recursive: true });
1059
1112
  const fileType = item.type === "primitive" ? "primitive" : "component";
1060
- const transformedContent = transformFileContent(file.content, config2, fileType);
1113
+ const transformedContent = transformFileContent(file.content, config2, fileType, cwd);
1061
1114
  await writeFile(targetPath, transformedContent, "utf-8");
1062
1115
  installedFiles.push(projectPath2);
1063
1116
  }
@@ -1242,10 +1295,11 @@ async function add(componentArgs, options) {
1242
1295
  componentsPath: "components/ui",
1243
1296
  primitivesPath: "lib/primitives",
1244
1297
  compositesPath: "composites",
1298
+ rulesPath: "rules",
1245
1299
  cssPath: null,
1246
1300
  shadcn: false,
1247
1301
  exports: DEFAULT_EXPORTS,
1248
- installed: { components: [], primitives: [], composites: [] }
1302
+ installed: { components: [], primitives: [], composites: [], rules: [] }
1249
1303
  };
1250
1304
  trackInstalled(newConfig, installedItems);
1251
1305
  await saveConfig(cwd, newConfig);
@@ -1270,7 +1324,7 @@ async function add(componentArgs, options) {
1270
1324
  // src/commands/import.ts
1271
1325
  import { existsSync as existsSync3 } from "fs";
1272
1326
  import { rename as rename2 } from "fs/promises";
1273
- import { relative as relative2 } from "path";
1327
+ import { relative as relative3 } from "path";
1274
1328
 
1275
1329
  // src/onboard/importers/generic-css.ts
1276
1330
  import { readFile as readFile4 } from "fs/promises";
@@ -2162,13 +2216,13 @@ async function previewOnboard(projectPath2) {
2162
2216
 
2163
2217
  // src/onboard/writer.ts
2164
2218
  import { mkdir as mkdir2, rename, writeFile as writeFile2 } from "fs/promises";
2165
- import { dirname as dirname2, relative } from "path";
2219
+ import { dirname as dirname2, relative as relative2 } from "path";
2166
2220
  function toImportPending(result, projectRoot, now = /* @__PURE__ */ new Date()) {
2167
2221
  if (!result.source) {
2168
2222
  throw new Error("Cannot build ImportPending from a failed onboard result");
2169
2223
  }
2170
2224
  const [primarySource, ...additionalSources] = result.sourcePaths.map(
2171
- (p2) => relative(projectRoot, p2)
2225
+ (p2) => relative2(projectRoot, p2)
2172
2226
  );
2173
2227
  const tokens = result.tokens.map((token) => {
2174
2228
  if (typeof token.value !== "string") {
@@ -2234,7 +2288,7 @@ async function importCommand(options) {
2234
2288
  if (!options.force) {
2235
2289
  log({
2236
2290
  event: "import:pending_exists",
2237
- path: relative2(cwd, paths.importPending),
2291
+ path: relative3(cwd, paths.importPending),
2238
2292
  message: "An import-pending.json already exists. Use --force to overwrite (previous file will be backed up)."
2239
2293
  });
2240
2294
  process.exitCode = 1;
@@ -2244,7 +2298,7 @@ async function importCommand(options) {
2244
2298
  await rename2(paths.importPending, backupPath);
2245
2299
  log({
2246
2300
  event: "import:pending_backed_up",
2247
- backup: relative2(cwd, backupPath)
2301
+ backup: relative3(cwd, backupPath)
2248
2302
  });
2249
2303
  }
2250
2304
  log({ event: "import:scanning" });
@@ -2272,7 +2326,7 @@ async function importCommand(options) {
2272
2326
  await writeImportPending(paths.importPending, doc);
2273
2327
  log({
2274
2328
  event: "import:complete",
2275
- path: relative2(cwd, paths.importPending),
2329
+ path: relative3(cwd, paths.importPending),
2276
2330
  source: result.source,
2277
2331
  confidence: result.confidence,
2278
2332
  tokensCreated: result.stats.tokensCreated,
@@ -2285,7 +2339,7 @@ async function importCommand(options) {
2285
2339
  import { existsSync as existsSync4 } from "fs";
2286
2340
  import { copyFile, mkdir as mkdir4, readFile as readFile8, rm, writeFile as writeFile4 } from "fs/promises";
2287
2341
  import { createRequire } from "module";
2288
- import { join as join10, relative as relative3 } from "path";
2342
+ import { join as join10, relative as relative4 } from "path";
2289
2343
  import { checkbox, confirm, select } from "@inquirer/prompts";
2290
2344
 
2291
2345
  // ../design-tokens/src/dependencies.ts
@@ -7114,8 +7168,8 @@ var require_util = __commonJS({
7114
7168
  }
7115
7169
  function fn() {
7116
7170
  var promiseResolve, promiseReject;
7117
- var promise = new Promise(function(resolve8, reject) {
7118
- promiseResolve = resolve8;
7171
+ var promise = new Promise(function(resolve9, reject) {
7172
+ promiseResolve = resolve9;
7119
7173
  promiseReject = reject;
7120
7174
  });
7121
7175
  var args = [];
@@ -10261,7 +10315,7 @@ var require_path = __commonJS({
10261
10315
  } else if (!path2) {
10262
10316
  continue;
10263
10317
  }
10264
- var result = win32StatPath(path2), device = result.device, isUnc = result.isUnc, isAbsolute = result.isAbsolute, tail = result.tail;
10318
+ var result = win32StatPath(path2), device = result.device, isUnc = result.isUnc, isAbsolute2 = result.isAbsolute, tail = result.tail;
10265
10319
  if (device && resolvedDevice && device.toLowerCase() !== resolvedDevice.toLowerCase()) {
10266
10320
  continue;
10267
10321
  }
@@ -10270,7 +10324,7 @@ var require_path = __commonJS({
10270
10324
  }
10271
10325
  if (!resolvedAbsolute) {
10272
10326
  resolvedTail = tail + "\\" + resolvedTail;
10273
- resolvedAbsolute = isAbsolute;
10327
+ resolvedAbsolute = isAbsolute2;
10274
10328
  }
10275
10329
  if (resolvedDevice && resolvedAbsolute) {
10276
10330
  break;
@@ -10286,9 +10340,9 @@ var require_path = __commonJS({
10286
10340
  return resolvedDevice + (resolvedAbsolute ? "\\" : "") + resolvedTail || ".";
10287
10341
  };
10288
10342
  win323.normalize = function(path2) {
10289
- var result = win32StatPath(path2), device = result.device, isUnc = result.isUnc, isAbsolute = result.isAbsolute, tail = result.tail, trailingSlash = /[\\\/]$/.test(tail);
10290
- tail = normalizeArray(tail.split(/[\\\/]+/), !isAbsolute).join("\\");
10291
- if (!tail && !isAbsolute) {
10343
+ var result = win32StatPath(path2), device = result.device, isUnc = result.isUnc, isAbsolute2 = result.isAbsolute, tail = result.tail, trailingSlash = /[\\\/]$/.test(tail);
10344
+ tail = normalizeArray(tail.split(/[\\\/]+/), !isAbsolute2).join("\\");
10345
+ if (!tail && !isAbsolute2) {
10292
10346
  tail = ".";
10293
10347
  }
10294
10348
  if (tail && trailingSlash) {
@@ -10297,7 +10351,7 @@ var require_path = __commonJS({
10297
10351
  if (isUnc) {
10298
10352
  device = normalizeUNCRoot(device);
10299
10353
  }
10300
- return device + (isAbsolute ? "\\" : "") + tail;
10354
+ return device + (isAbsolute2 ? "\\" : "") + tail;
10301
10355
  };
10302
10356
  win323.isAbsolute = function(path2) {
10303
10357
  return win32StatPath(path2).isAbsolute;
@@ -10445,15 +10499,15 @@ var require_path = __commonJS({
10445
10499
  return (resolvedAbsolute ? "/" : "") + resolvedPath || ".";
10446
10500
  };
10447
10501
  posix3.normalize = function(path2) {
10448
- var isAbsolute = posix3.isAbsolute(path2), trailingSlash = path2 && path2[path2.length - 1] === "/";
10449
- path2 = normalizeArray(path2.split("/"), !isAbsolute).join("/");
10450
- if (!path2 && !isAbsolute) {
10502
+ var isAbsolute2 = posix3.isAbsolute(path2), trailingSlash = path2 && path2[path2.length - 1] === "/";
10503
+ path2 = normalizeArray(path2.split("/"), !isAbsolute2).join("/");
10504
+ if (!path2 && !isAbsolute2) {
10451
10505
  path2 = ".";
10452
10506
  }
10453
10507
  if (path2 && trailingSlash) {
10454
10508
  path2 += "/";
10455
10509
  }
10456
- return (isAbsolute ? "/" : "") + path2;
10510
+ return (isAbsolute2 ? "/" : "") + path2;
10457
10511
  };
10458
10512
  posix3.isAbsolute = function(path2) {
10459
10513
  return path2.charAt(0) === "/";
@@ -11079,7 +11133,7 @@ var require_events = __commonJS({
11079
11133
  return ret;
11080
11134
  }
11081
11135
  function once(emitter, name2) {
11082
- return new Promise(function(resolve8, reject) {
11136
+ return new Promise(function(resolve9, reject) {
11083
11137
  function errorListener(err) {
11084
11138
  emitter.removeListener(name2, resolver);
11085
11139
  reject(err);
@@ -11088,7 +11142,7 @@ var require_events = __commonJS({
11088
11142
  if (typeof emitter.removeListener === "function") {
11089
11143
  emitter.removeListener("error", errorListener);
11090
11144
  }
11091
- resolve8([].slice.call(arguments));
11145
+ resolve9([].slice.call(arguments));
11092
11146
  }
11093
11147
  ;
11094
11148
  eventTargetAgnosticAddListener(emitter, name2, resolver, { once: true });
@@ -11798,11 +11852,11 @@ var require_util3 = __commonJS({
11798
11852
  var queueMicrotask_1 = require_queueMicrotask();
11799
11853
  exports.isWin = process2.platform === "win32";
11800
11854
  function promisify(fs22, fn, getResult = (input) => input) {
11801
- return (...args) => new Promise((resolve8, reject) => {
11855
+ return (...args) => new Promise((resolve9, reject) => {
11802
11856
  fs22[fn].bind(fs22)(...args, (error3, result) => {
11803
11857
  if (error3)
11804
11858
  return reject(error3);
11805
- return resolve8(getResult(result));
11859
+ return resolve9(getResult(result));
11806
11860
  });
11807
11861
  });
11808
11862
  }
@@ -11958,9 +12012,9 @@ var require_util3 = __commonJS({
11958
12012
  }
11959
12013
  function streamToBuffer(stream2) {
11960
12014
  const chunks = [];
11961
- return new Promise((resolve8, reject) => {
12015
+ return new Promise((resolve9, reject) => {
11962
12016
  stream2.on("data", (chunk) => chunks.push(chunk));
11963
- stream2.on("end", () => resolve8(buffer_1.Buffer.concat(chunks)));
12017
+ stream2.on("end", () => resolve9(buffer_1.Buffer.concat(chunks)));
11964
12018
  stream2.on("error", reject);
11965
12019
  });
11966
12020
  }
@@ -12341,11 +12395,11 @@ function __metadata(metadataKey, metadataValue) {
12341
12395
  }
12342
12396
  function __awaiter(thisArg, _arguments, P, generator) {
12343
12397
  function adopt(value2) {
12344
- return value2 instanceof P ? value2 : new P(function(resolve8) {
12345
- resolve8(value2);
12398
+ return value2 instanceof P ? value2 : new P(function(resolve9) {
12399
+ resolve9(value2);
12346
12400
  });
12347
12401
  }
12348
- return new (P || (P = Promise))(function(resolve8, reject) {
12402
+ return new (P || (P = Promise))(function(resolve9, reject) {
12349
12403
  function fulfilled(value2) {
12350
12404
  try {
12351
12405
  step(generator.next(value2));
@@ -12361,7 +12415,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
12361
12415
  }
12362
12416
  }
12363
12417
  function step(result) {
12364
- result.done ? resolve8(result.value) : adopt(result.value).then(fulfilled, rejected);
12418
+ result.done ? resolve9(result.value) : adopt(result.value).then(fulfilled, rejected);
12365
12419
  }
12366
12420
  step((generator = generator.apply(thisArg, _arguments || [])).next());
12367
12421
  });
@@ -12544,14 +12598,14 @@ function __asyncValues(o) {
12544
12598
  }, i);
12545
12599
  function verb(n2) {
12546
12600
  i[n2] = o[n2] && function(v) {
12547
- return new Promise(function(resolve8, reject) {
12548
- v = o[n2](v), settle(resolve8, reject, v.done, v.value);
12601
+ return new Promise(function(resolve9, reject) {
12602
+ v = o[n2](v), settle(resolve9, reject, v.done, v.value);
12549
12603
  });
12550
12604
  };
12551
12605
  }
12552
- function settle(resolve8, reject, d2, v) {
12606
+ function settle(resolve9, reject, d2, v) {
12553
12607
  Promise.resolve(v).then(function(v2) {
12554
- resolve8({ value: v2, done: d2 });
12608
+ resolve9({ value: v2, done: d2 });
12555
12609
  }, reject);
12556
12610
  }
12557
12611
  }
@@ -12969,12 +13023,12 @@ var require_Dir = __commonJS({
12969
13023
  return typeof x === "function";
12970
13024
  }
12971
13025
  promisify(obj, fn) {
12972
- return (...args) => new Promise((resolve8, reject) => {
13026
+ return (...args) => new Promise((resolve9, reject) => {
12973
13027
  if (this.isFunction(obj[fn])) {
12974
13028
  obj[fn].bind(obj)(...args, (error3, result) => {
12975
13029
  if (error3)
12976
13030
  reject(error3);
12977
- resolve8(result);
13031
+ resolve9(result);
12978
13032
  });
12979
13033
  } else {
12980
13034
  reject("Not a function");
@@ -13098,7 +13152,7 @@ var require_volume = __commonJS({
13098
13152
  var Dir_1 = require_Dir();
13099
13153
  var resolveCrossPlatform = pathModule.resolve;
13100
13154
  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;
13101
- var { sep: sep2, relative: relative4, join: join16, dirname: dirname6 } = pathModule.posix ? pathModule.posix : pathModule;
13155
+ var { sep: sep2, relative: relative5, join: join16, dirname: dirname6 } = pathModule.posix ? pathModule.posix : pathModule;
13102
13156
  var kMinPoolSpace = 128;
13103
13157
  var EPERM = "EPERM";
13104
13158
  var ENOENT2 = "ENOENT";
@@ -13113,13 +13167,13 @@ var require_volume = __commonJS({
13113
13167
  var ENOSYS = "ENOSYS";
13114
13168
  var ERR_FS_EISDIR = "ERR_FS_EISDIR";
13115
13169
  var ERR_OUT_OF_RANGE = "ERR_OUT_OF_RANGE";
13116
- var resolve8 = (filename, base = process_1.default.cwd()) => resolveCrossPlatform(base, filename);
13170
+ var resolve9 = (filename, base = process_1.default.cwd()) => resolveCrossPlatform(base, filename);
13117
13171
  if (util_1.isWin) {
13118
- const _resolve = resolve8;
13119
- resolve8 = (filename, base) => (0, util_1.unixify)(_resolve(filename, base));
13172
+ const _resolve = resolve9;
13173
+ resolve9 = (filename, base) => (0, util_1.unixify)(_resolve(filename, base));
13120
13174
  }
13121
13175
  function filenameToSteps(filename, base) {
13122
- const fullPath = resolve8(filename, base);
13176
+ const fullPath = resolve9(filename, base);
13123
13177
  const fullPathSansSlash = fullPath.substring(1);
13124
13178
  if (!fullPathSansSlash)
13125
13179
  return [];
@@ -13441,7 +13495,7 @@ var require_volume = __commonJS({
13441
13495
  if (node.isFile()) {
13442
13496
  let filename = child.getPath();
13443
13497
  if (path2)
13444
- filename = relative4(path2, filename);
13498
+ filename = relative5(path2, filename);
13445
13499
  json2[filename] = asBuffer ? node.getBuffer() : node.getString();
13446
13500
  } else if (node.isDirectory()) {
13447
13501
  this._toJSON(child, json2, path2, asBuffer);
@@ -13449,7 +13503,7 @@ var require_volume = __commonJS({
13449
13503
  }
13450
13504
  let dirPath = link.getPath();
13451
13505
  if (path2)
13452
- dirPath = relative4(path2, dirPath);
13506
+ dirPath = relative5(path2, dirPath);
13453
13507
  if (dirPath && isEmpty) {
13454
13508
  json2[dirPath] = null;
13455
13509
  }
@@ -13480,7 +13534,7 @@ var require_volume = __commonJS({
13480
13534
  fromJSON(json2, cwd = process_1.default.cwd()) {
13481
13535
  for (let filename in json2) {
13482
13536
  const data = json2[filename];
13483
- filename = resolve8(filename, cwd);
13537
+ filename = resolve9(filename, cwd);
13484
13538
  if (typeof data === "string" || data instanceof buffer_1.Buffer) {
13485
13539
  const dir = dirname6(filename);
13486
13540
  this.mkdirpBase(
@@ -14927,7 +14981,7 @@ var require_volume = __commonJS({
14927
14981
  const filepath = link.getPath();
14928
14982
  const node = link.getNode();
14929
14983
  const onNodeChange = () => {
14930
- let filename = relative4(this._filename, filepath);
14984
+ let filename = relative5(this._filename, filepath);
14931
14985
  if (!filename) {
14932
14986
  filename = this._getName();
14933
14987
  }
@@ -14942,7 +14996,7 @@ var require_volume = __commonJS({
14942
14996
  var _a;
14943
14997
  const node = link.getNode();
14944
14998
  const onLinkChildAdd = (l) => {
14945
- this.emit("change", "rename", relative4(this._filename, l.getPath()));
14999
+ this.emit("change", "rename", relative5(this._filename, l.getPath()));
14946
15000
  setTimeout(() => {
14947
15001
  watchLinkNodeChanged(l);
14948
15002
  watchLinkChildrenChanged(l);
@@ -14963,7 +15017,7 @@ var require_volume = __commonJS({
14963
15017
  }
14964
15018
  };
14965
15019
  removeLinkNodeListeners(l);
14966
- this.emit("change", "rename", relative4(this._filename, l.getPath()));
15020
+ this.emit("change", "rename", relative5(this._filename, l.getPath()));
14967
15021
  };
14968
15022
  for (const [name2, childLink] of link.children.entries()) {
14969
15023
  if (childLink && name2 !== "." && name2 !== "..") {
@@ -15430,15 +15484,15 @@ function winResolve(...args) {
15430
15484
  const len = path2.length;
15431
15485
  let rootEnd = 0;
15432
15486
  let device = "";
15433
- let isAbsolute = false;
15487
+ let isAbsolute2 = false;
15434
15488
  const code = path2.charCodeAt(0);
15435
15489
  if (len === 1) {
15436
15490
  if (isPathSeparator(code)) {
15437
15491
  rootEnd = 1;
15438
- isAbsolute = true;
15492
+ isAbsolute2 = true;
15439
15493
  }
15440
15494
  } else if (isPathSeparator(code)) {
15441
- isAbsolute = true;
15495
+ isAbsolute2 = true;
15442
15496
  if (isPathSeparator(path2.charCodeAt(1))) {
15443
15497
  let j = 2;
15444
15498
  let last2 = j;
@@ -15469,7 +15523,7 @@ function winResolve(...args) {
15469
15523
  device = path2.slice(0, 2);
15470
15524
  rootEnd = 2;
15471
15525
  if (len > 2 && isPathSeparator(path2.charCodeAt(2))) {
15472
- isAbsolute = true;
15526
+ isAbsolute2 = true;
15473
15527
  rootEnd = 3;
15474
15528
  }
15475
15529
  }
@@ -15485,8 +15539,8 @@ function winResolve(...args) {
15485
15539
  if (resolvedDevice.length > 0) break;
15486
15540
  } else {
15487
15541
  resolvedTail = `${path2.slice(rootEnd)}\\${resolvedTail}`;
15488
- resolvedAbsolute = isAbsolute;
15489
- if (isAbsolute && resolvedDevice.length > 0) {
15542
+ resolvedAbsolute = isAbsolute2;
15543
+ if (isAbsolute2 && resolvedDevice.length > 0) {
15490
15544
  break;
15491
15545
  }
15492
15546
  }
@@ -15500,13 +15554,13 @@ function winNormalize(path2) {
15500
15554
  if (len === 0) return ".";
15501
15555
  let rootEnd = 0;
15502
15556
  let device;
15503
- let isAbsolute = false;
15557
+ let isAbsolute2 = false;
15504
15558
  const code = path2.charCodeAt(0);
15505
15559
  if (len === 1) {
15506
15560
  return isPosixPathSeparator(code) ? "\\" : path2;
15507
15561
  }
15508
15562
  if (isPathSeparator(code)) {
15509
- isAbsolute = true;
15563
+ isAbsolute2 = true;
15510
15564
  if (isPathSeparator(path2.charCodeAt(1))) {
15511
15565
  let j = 2;
15512
15566
  let last2 = j;
@@ -15540,17 +15594,17 @@ function winNormalize(path2) {
15540
15594
  device = path2.slice(0, 2);
15541
15595
  rootEnd = 2;
15542
15596
  if (len > 2 && isPathSeparator(path2.charCodeAt(2))) {
15543
- isAbsolute = true;
15597
+ isAbsolute2 = true;
15544
15598
  rootEnd = 3;
15545
15599
  }
15546
15600
  }
15547
- let tail = rootEnd < len ? normalizeString(path2.slice(rootEnd), !isAbsolute, "\\", isPathSeparator) : "";
15548
- if (tail.length === 0 && !isAbsolute) tail = ".";
15601
+ let tail = rootEnd < len ? normalizeString(path2.slice(rootEnd), !isAbsolute2, "\\", isPathSeparator) : "";
15602
+ if (tail.length === 0 && !isAbsolute2) tail = ".";
15549
15603
  if (tail.length > 0 && isPathSeparator(path2.charCodeAt(len - 1))) tail += "\\";
15550
15604
  if (device === void 0) {
15551
- return isAbsolute ? `\\${tail}` : tail;
15605
+ return isAbsolute2 ? `\\${tail}` : tail;
15552
15606
  }
15553
- return isAbsolute ? `${device}\\${tail}` : `${device}${tail}`;
15607
+ return isAbsolute2 ? `${device}\\${tail}` : `${device}${tail}`;
15554
15608
  }
15555
15609
  function winIsAbsolute(path2) {
15556
15610
  validateString(path2, "path");
@@ -15962,15 +16016,15 @@ function posResolve(...args) {
15962
16016
  function posNormalize(path2) {
15963
16017
  validateString(path2, "path");
15964
16018
  if (path2.length === 0) return ".";
15965
- const isAbsolute = path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
16019
+ const isAbsolute2 = path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
15966
16020
  const trailingSeparator = path2.charCodeAt(path2.length - 1) === CHAR_FORWARD_SLASH;
15967
- path2 = normalizeString(path2, !isAbsolute, "/", isPosixPathSeparator);
16021
+ path2 = normalizeString(path2, !isAbsolute2, "/", isPosixPathSeparator);
15968
16022
  if (path2.length === 0) {
15969
- if (isAbsolute) return "/";
16023
+ if (isAbsolute2) return "/";
15970
16024
  return trailingSeparator ? "./" : ".";
15971
16025
  }
15972
16026
  if (trailingSeparator) path2 += "/";
15973
- return isAbsolute ? `/${path2}` : path2;
16027
+ return isAbsolute2 ? `/${path2}` : path2;
15974
16028
  }
15975
16029
  function posIsAbsolute(path2) {
15976
16030
  validateString(path2, "path");
@@ -16148,9 +16202,9 @@ function posParse(path2) {
16148
16202
  validateString(path2, "path");
16149
16203
  const ret = { root: "", dir: "", base: "", ext: "", name: "" };
16150
16204
  if (path2.length === 0) return ret;
16151
- const isAbsolute = path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
16205
+ const isAbsolute2 = path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
16152
16206
  let start;
16153
- if (isAbsolute) {
16207
+ if (isAbsolute2) {
16154
16208
  ret.root = "/";
16155
16209
  start = 1;
16156
16210
  } else {
@@ -16183,7 +16237,7 @@ function posParse(path2) {
16183
16237
  }
16184
16238
  }
16185
16239
  if (end !== -1) {
16186
- const start2 = startPart === 0 && isAbsolute ? 1 : startPart;
16240
+ const start2 = startPart === 0 && isAbsolute2 ? 1 : startPart;
16187
16241
  if (startDot === -1 || // We saw a non-dot character immediately before the dot
16188
16242
  preDotState === 0 || // The (right-most) trimmed path component is exactly '..'
16189
16243
  preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
@@ -16195,7 +16249,7 @@ function posParse(path2) {
16195
16249
  }
16196
16250
  }
16197
16251
  if (startPart > 0) ret.dir = path2.slice(0, startPart - 1);
16198
- else if (isAbsolute) ret.dir = "/";
16252
+ else if (isAbsolute2) ret.dir = "/";
16199
16253
  return ret;
16200
16254
  }
16201
16255
  var posSep = "/";
@@ -16244,7 +16298,7 @@ var posix = {
16244
16298
  };
16245
16299
 
16246
16300
  // ../../node_modules/.pnpm/path-unified@0.2.0/node_modules/path-unified/src/posix.js
16247
- var resolve = posResolve;
16301
+ var resolve2 = posResolve;
16248
16302
  var join8 = posJoin;
16249
16303
 
16250
16304
  // ../../node_modules/.pnpm/@isaacs+balanced-match@4.0.1/node_modules/@isaacs/balanced-match/dist/esm/index.js
@@ -19961,10 +20015,10 @@ var Minipass = class extends EventEmitter {
19961
20015
  * Return a void Promise that resolves once the stream ends.
19962
20016
  */
19963
20017
  async promise() {
19964
- return new Promise((resolve8, reject) => {
20018
+ return new Promise((resolve9, reject) => {
19965
20019
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
19966
20020
  this.on("error", (er) => reject(er));
19967
- this.on("end", () => resolve8());
20021
+ this.on("end", () => resolve9());
19968
20022
  });
19969
20023
  }
19970
20024
  /**
@@ -19988,7 +20042,7 @@ var Minipass = class extends EventEmitter {
19988
20042
  return Promise.resolve({ done: false, value: res });
19989
20043
  if (this[EOF])
19990
20044
  return stop();
19991
- let resolve8;
20045
+ let resolve9;
19992
20046
  let reject;
19993
20047
  const onerr = (er) => {
19994
20048
  this.off("data", ondata);
@@ -20002,19 +20056,19 @@ var Minipass = class extends EventEmitter {
20002
20056
  this.off("end", onend);
20003
20057
  this.off(DESTROYED, ondestroy);
20004
20058
  this.pause();
20005
- resolve8({ value: value2, done: !!this[EOF] });
20059
+ resolve9({ value: value2, done: !!this[EOF] });
20006
20060
  };
20007
20061
  const onend = () => {
20008
20062
  this.off("error", onerr);
20009
20063
  this.off("data", ondata);
20010
20064
  this.off(DESTROYED, ondestroy);
20011
20065
  stop();
20012
- resolve8({ done: true, value: void 0 });
20066
+ resolve9({ done: true, value: void 0 });
20013
20067
  };
20014
20068
  const ondestroy = () => onerr(new Error("stream destroyed"));
20015
20069
  return new Promise((res2, rej) => {
20016
20070
  reject = rej;
20017
- resolve8 = res2;
20071
+ resolve9 = res2;
20018
20072
  this.once(DESTROYED, ondestroy);
20019
20073
  this.once("error", onerr);
20020
20074
  this.once("end", onend);
@@ -20111,13 +20165,13 @@ var Minipass = class extends EventEmitter {
20111
20165
  };
20112
20166
 
20113
20167
  // ../../node_modules/.pnpm/path-scurry@2.0.1/node_modules/path-scurry/dist/esm/index.js
20114
- var realpathSync = rps.native;
20168
+ var realpathSync2 = rps.native;
20115
20169
  var defaultFS = {
20116
20170
  lstatSync,
20117
20171
  readdir: readdirCB,
20118
20172
  readdirSync,
20119
20173
  readlinkSync,
20120
- realpathSync,
20174
+ realpathSync: realpathSync2,
20121
20175
  promises: {
20122
20176
  lstat,
20123
20177
  readdir,
@@ -20986,9 +21040,9 @@ var PathBase = class {
20986
21040
  if (this.#asyncReaddirInFlight) {
20987
21041
  await this.#asyncReaddirInFlight;
20988
21042
  } else {
20989
- let resolve8 = () => {
21043
+ let resolve9 = () => {
20990
21044
  };
20991
- this.#asyncReaddirInFlight = new Promise((res) => resolve8 = res);
21045
+ this.#asyncReaddirInFlight = new Promise((res) => resolve9 = res);
20992
21046
  try {
20993
21047
  for (const e of await this.#fs.promises.readdir(fullpath, {
20994
21048
  withFileTypes: true
@@ -21001,7 +21055,7 @@ var PathBase = class {
21001
21055
  children.provisional = 0;
21002
21056
  }
21003
21057
  this.#asyncReaddirInFlight = void 0;
21004
- resolve8();
21058
+ resolve9();
21005
21059
  }
21006
21060
  return children.slice(0, children.provisional);
21007
21061
  }
@@ -22063,10 +22117,10 @@ var Ignore = class {
22063
22117
  ignored(p2) {
22064
22118
  const fullpath = p2.fullpath();
22065
22119
  const fullpaths = `${fullpath}/`;
22066
- const relative4 = p2.relative() || ".";
22067
- const relatives = `${relative4}/`;
22120
+ const relative5 = p2.relative() || ".";
22121
+ const relatives = `${relative5}/`;
22068
22122
  for (const m3 of this.relative) {
22069
- if (m3.match(relative4) || m3.match(relatives))
22123
+ if (m3.match(relative5) || m3.match(relatives))
22070
22124
  return true;
22071
22125
  }
22072
22126
  for (const m3 of this.absolute) {
@@ -22077,9 +22131,9 @@ var Ignore = class {
22077
22131
  }
22078
22132
  childrenIgnored(p2) {
22079
22133
  const fullpath = p2.fullpath() + "/";
22080
- const relative4 = (p2.relative() || ".") + "/";
22134
+ const relative5 = (p2.relative() || ".") + "/";
22081
22135
  for (const m3 of this.relativeChildren) {
22082
- if (m3.match(relative4))
22136
+ if (m3.match(relative5))
22083
22137
  return true;
22084
22138
  }
22085
22139
  for (const m3 of this.absoluteChildren) {
@@ -22899,20 +22953,20 @@ var glob = Object.assign(glob_, {
22899
22953
  glob.glob = glob;
22900
22954
 
22901
22955
  // ../../node_modules/.pnpm/path-unified@0.2.0/node_modules/path-unified/src/win32.js
22902
- var resolve2 = winResolve;
22956
+ var resolve3 = winResolve;
22903
22957
 
22904
22958
  // ../../node_modules/.pnpm/style-dictionary@5.1.1/node_modules/style-dictionary/lib/utils/isNode.js
22905
22959
  var isNode = typeof window === "undefined";
22906
22960
 
22907
22961
  // ../../node_modules/.pnpm/style-dictionary@5.1.1/node_modules/style-dictionary/lib/resolve.js
22908
- var resolve3 = (path2, customVolumeUsed = false) => {
22962
+ var resolve4 = (path2, customVolumeUsed = false) => {
22909
22963
  if (customVolumeUsed) {
22910
22964
  return path2;
22911
22965
  }
22912
22966
  if (isNode && process?.platform === "win32") {
22913
- return resolve2(path2);
22967
+ return resolve3(path2);
22914
22968
  }
22915
- return resolve(path2);
22969
+ return resolve2(path2);
22916
22970
  };
22917
22971
 
22918
22972
  // ../../node_modules/.pnpm/is-plain-obj@4.1.0/node_modules/is-plain-obj/index.js
@@ -24256,7 +24310,7 @@ function toBase64(buffer) {
24256
24310
  if (isNode) {
24257
24311
  return buffer.toString("base64");
24258
24312
  } else {
24259
- return new Promise((resolve8, reject) => {
24313
+ return new Promise((resolve9, reject) => {
24260
24314
  const blob = new Blob([buffer], { type: "application/octet-stream" });
24261
24315
  const reader = new FileReader();
24262
24316
  reader.onloadend = () => {
@@ -24264,7 +24318,7 @@ function toBase64(buffer) {
24264
24318
  /** @type {string } */
24265
24319
  reader.result.split(",")[1]
24266
24320
  );
24267
- resolve8(base64String);
24321
+ resolve9(base64String);
24268
24322
  };
24269
24323
  reader.onerror = reject;
24270
24324
  reader.readAsDataURL(blob);
@@ -24275,7 +24329,7 @@ async function convertToBase64(filePath, vol2 = fs2) {
24275
24329
  if (typeof filePath !== "string") throw new Error("Token filePath name must be a string");
24276
24330
  const body = (
24277
24331
  /** @type {Buffer} */
24278
- vol2.readFileSync(resolve3(filePath, vol2.__custom_fs__))
24332
+ vol2.readFileSync(resolve4(filePath, vol2.__custom_fs__))
24279
24333
  );
24280
24334
  return toBase64(body);
24281
24335
  }
@@ -27877,7 +27931,7 @@ var AESDecryptionStream = class extends TransformStream {
27877
27931
  super({
27878
27932
  start() {
27879
27933
  Object.assign(this, {
27880
- ready: new Promise((resolve8) => this.resolveReady = resolve8),
27934
+ ready: new Promise((resolve9) => this.resolveReady = resolve9),
27881
27935
  password: encodePassword(password2, rawPassword),
27882
27936
  signed,
27883
27937
  strength: encryptionStrength - 1,
@@ -27945,7 +27999,7 @@ var AESEncryptionStream = class extends TransformStream {
27945
27999
  super({
27946
28000
  start() {
27947
28001
  Object.assign(this, {
27948
- ready: new Promise((resolve8) => this.resolveReady = resolve8),
28002
+ ready: new Promise((resolve9) => this.resolveReady = resolve9),
27949
28003
  password: encodePassword(password2, rawPassword),
27950
28004
  strength: encryptionStrength - 1,
27951
28005
  pending: new Uint8Array()
@@ -46295,35 +46349,51 @@ var COMPONENT_PATHS = {
46295
46349
  astro: {
46296
46350
  components: "src/components/ui",
46297
46351
  primitives: "src/lib/primitives",
46298
- composites: "src/composites"
46352
+ composites: "src/composites",
46353
+ rules: "src/rules"
46354
+ },
46355
+ next: {
46356
+ components: "components/ui",
46357
+ primitives: "lib/primitives",
46358
+ composites: "composites",
46359
+ rules: "rules"
46299
46360
  },
46300
- next: { components: "components/ui", primitives: "lib/primitives", composites: "composites" },
46301
46361
  vite: {
46302
46362
  components: "src/components/ui",
46303
46363
  primitives: "src/lib/primitives",
46304
- composites: "src/composites"
46364
+ composites: "src/composites",
46365
+ rules: "src/rules"
46305
46366
  },
46306
46367
  remix: {
46307
46368
  components: "app/components/ui",
46308
46369
  primitives: "app/lib/primitives",
46309
- composites: "app/composites"
46370
+ composites: "app/composites",
46371
+ rules: "app/rules"
46310
46372
  },
46311
46373
  "react-router": {
46312
46374
  components: "app/components/ui",
46313
46375
  primitives: "app/lib/primitives",
46314
- composites: "app/composites"
46376
+ composites: "app/composites",
46377
+ rules: "app/rules"
46315
46378
  },
46316
46379
  wc: {
46317
46380
  components: "src/components/ui",
46318
46381
  primitives: "src/lib/primitives",
46319
- composites: "src/composites"
46382
+ composites: "src/composites",
46383
+ rules: "src/rules"
46320
46384
  },
46321
46385
  vanilla: {
46322
46386
  components: "src/components/ui",
46323
46387
  primitives: "src/lib/primitives",
46324
- composites: "src/composites"
46388
+ composites: "src/composites",
46389
+ rules: "src/rules"
46325
46390
  },
46326
- unknown: { components: "components/ui", primitives: "lib/primitives", composites: "composites" }
46391
+ unknown: {
46392
+ components: "components/ui",
46393
+ primitives: "lib/primitives",
46394
+ composites: "composites",
46395
+ rules: "rules"
46396
+ }
46327
46397
  };
46328
46398
  var FRAMEWORK_PROMPT_LABELS = {
46329
46399
  next: "Next.js",
@@ -46349,7 +46419,7 @@ async function updateMainCss(cwd, cssPath, themePath) {
46349
46419
  const cssContent = await readFile8(fullCssPath, "utf-8");
46350
46420
  const cssDir = join10(cwd, cssPath, "..");
46351
46421
  const themeFullPath = join10(cwd, themePath);
46352
- const relativeThemePath = relative3(cssDir, themeFullPath);
46422
+ const relativeThemePath = relative4(cssDir, themeFullPath);
46353
46423
  if (cssContent.includes(".rafters/output/rafters.css")) {
46354
46424
  log({ event: "init:css_already_imported", cssPath });
46355
46425
  return;
@@ -46495,6 +46565,7 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2, framewor
46495
46565
  existingConfig.componentsPath = frameworkPaths.components;
46496
46566
  existingConfig.primitivesPath = frameworkPaths.primitives;
46497
46567
  existingConfig.compositesPath = frameworkPaths.composites;
46568
+ existingConfig.rulesPath = frameworkPaths.rules;
46498
46569
  }
46499
46570
  const adapter = new NodePersistenceAdapter(cwd);
46500
46571
  const allTokens = await adapter.load();
@@ -46531,10 +46602,11 @@ async function regenerateFromExisting(cwd, paths, shadcn, isAgentMode2, framewor
46531
46602
  componentsPath: frameworkPaths.components,
46532
46603
  primitivesPath: frameworkPaths.primitives,
46533
46604
  compositesPath: frameworkPaths.composites,
46605
+ rulesPath: frameworkPaths.rules,
46534
46606
  cssPath: null,
46535
46607
  shadcn: !!shadcn,
46536
46608
  exports,
46537
- installed: { components: [], primitives: [], composites: [] }
46609
+ installed: { components: [], primitives: [], composites: [], rules: [] }
46538
46610
  };
46539
46611
  await writeFile4(paths.config, JSON.stringify(newConfig, null, 2));
46540
46612
  }
@@ -46558,6 +46630,7 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode2, framework) {
46558
46630
  existingConfig.componentsPath = frameworkPaths.components;
46559
46631
  existingConfig.primitivesPath = frameworkPaths.primitives;
46560
46632
  existingConfig.compositesPath = frameworkPaths.composites;
46633
+ existingConfig.rulesPath = frameworkPaths.rules;
46561
46634
  }
46562
46635
  const adapter = new NodePersistenceAdapter(cwd);
46563
46636
  const existingTokens = await adapter.load();
@@ -46628,10 +46701,11 @@ async function resetToDefaults(cwd, paths, shadcn, isAgentMode2, framework) {
46628
46701
  componentsPath: frameworkPaths.components,
46629
46702
  primitivesPath: frameworkPaths.primitives,
46630
46703
  compositesPath: frameworkPaths.composites,
46704
+ rulesPath: frameworkPaths.rules,
46631
46705
  cssPath: null,
46632
46706
  shadcn: !!shadcn,
46633
46707
  exports,
46634
- installed: { components: [], primitives: [], composites: [] }
46708
+ installed: { components: [], primitives: [], composites: [], rules: [] }
46635
46709
  };
46636
46710
  await writeFile4(paths.config, JSON.stringify(newConfig, null, 2));
46637
46711
  }
@@ -46848,13 +46922,15 @@ async function init(options) {
46848
46922
  componentsPath: frameworkPaths.components,
46849
46923
  primitivesPath: frameworkPaths.primitives,
46850
46924
  compositesPath: frameworkPaths.composites,
46925
+ rulesPath: frameworkPaths.rules,
46851
46926
  cssPath: detectedCssPath,
46852
46927
  shadcn: !!shadcn,
46853
46928
  exports,
46854
46929
  installed: {
46855
46930
  components: [],
46856
46931
  primitives: [],
46857
- composites: []
46932
+ composites: [],
46933
+ rules: []
46858
46934
  }
46859
46935
  };
46860
46936
  await writeFile4(paths.config, JSON.stringify(config2, null, 2));
@@ -46890,7 +46966,7 @@ async function maybeOnboardExisting(cwd, importPendingPath) {
46890
46966
  event: "import:existing_detected",
46891
46967
  source: best.importer,
46892
46968
  confidence: best.confidence,
46893
- sourcePaths: best.sourcePaths.map((p2) => relative3(cwd, p2)).join(", "),
46969
+ sourcePaths: best.sourcePaths.map((p2) => relative4(cwd, p2)).join(", "),
46894
46970
  nextStep: "Run `rafters import` to convert these tokens into pending review."
46895
46971
  });
46896
46972
  return;
@@ -46899,7 +46975,7 @@ async function maybeOnboardExisting(cwd, importPendingPath) {
46899
46975
  event: "import:existing_detected",
46900
46976
  source: best.importer,
46901
46977
  confidence: best.confidence,
46902
- sourcePaths: best.sourcePaths.map((p2) => relative3(cwd, p2)).join(", ")
46978
+ sourcePaths: best.sourcePaths.map((p2) => relative4(cwd, p2)).join(", ")
46903
46979
  });
46904
46980
  let shouldImport;
46905
46981
  try {
@@ -46925,7 +47001,7 @@ async function maybeOnboardExisting(cwd, importPendingPath) {
46925
47001
  await writeImportPending(importPendingPath, doc);
46926
47002
  log({
46927
47003
  event: "import:complete",
46928
- path: relative3(cwd, importPendingPath),
47004
+ path: relative4(cwd, importPendingPath),
46929
47005
  source: result.source,
46930
47006
  confidence: result.confidence,
46931
47007
  tokensCreated: result.stats.tokensCreated,
@@ -46936,7 +47012,7 @@ async function maybeOnboardExisting(cwd, importPendingPath) {
46936
47012
 
46937
47013
  // src/commands/mcp.ts
46938
47014
  import { existsSync as existsSync7 } from "fs";
46939
- import { basename as basename4, join as join14, resolve as resolve6 } from "path";
47015
+ import { basename as basename4, join as join14, resolve as resolve7 } from "path";
46940
47016
 
46941
47017
  // src/mcp/server.ts
46942
47018
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -46944,7 +47020,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
46944
47020
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
46945
47021
 
46946
47022
  // src/mcp/tools.ts
46947
- import { readdir as readdir3 } from "fs/promises";
47023
+ import { readdir as readdir3, readFile as readFile9 } from "fs/promises";
46948
47024
  import { join as join13 } from "path";
46949
47025
 
46950
47026
  // ../composites/src/built-in-rules/email.ts
@@ -47059,13 +47135,13 @@ function search(query) {
47059
47135
 
47060
47136
  // src/utils/workspaces.ts
47061
47137
  import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync, statSync } from "fs";
47062
- import { basename as basename3, dirname as dirname5, join as join12, resolve as resolve5 } from "path";
47138
+ import { basename as basename3, dirname as dirname5, join as join12, resolve as resolve6 } from "path";
47063
47139
 
47064
47140
  // src/utils/discover.ts
47065
47141
  import { existsSync as existsSync5 } from "fs";
47066
- import { dirname as dirname4, join as join11, resolve as resolve4 } from "path";
47142
+ import { dirname as dirname4, join as join11, resolve as resolve5 } from "path";
47067
47143
  function discoverProjectRoot(startDir) {
47068
- let current = resolve4(startDir);
47144
+ let current = resolve5(startDir);
47069
47145
  for (; ; ) {
47070
47146
  const configPath = join11(current, ".rafters", "config.rafters.json");
47071
47147
  if (existsSync5(configPath)) {
@@ -47081,8 +47157,8 @@ function discoverProjectRoot(startDir) {
47081
47157
 
47082
47158
  // src/utils/workspaces.ts
47083
47159
  function findMonorepoRoot(startDir, boundary) {
47084
- let current = resolve5(startDir);
47085
- const stopAt = boundary ? resolve5(boundary) : null;
47160
+ let current = resolve6(startDir);
47161
+ const stopAt = boundary ? resolve6(boundary) : null;
47086
47162
  for (; ; ) {
47087
47163
  const pnpmWorkspace = join12(current, "pnpm-workspace.yaml");
47088
47164
  if (existsSync6(pnpmWorkspace)) {
@@ -47172,7 +47248,7 @@ function discoverWorkspaces(startDir = process.cwd(), options = {}) {
47172
47248
  if (!layout) {
47173
47249
  const single = discoverProjectRoot(startDir);
47174
47250
  if (!single) return [];
47175
- if (options.boundary && !single.startsWith(resolve5(options.boundary))) return [];
47251
+ if (options.boundary && !single.startsWith(resolve6(options.boundary))) return [];
47176
47252
  return [{ name: basename3(single), root: single }];
47177
47253
  }
47178
47254
  const seen = /* @__PURE__ */ new Set();
@@ -47195,7 +47271,7 @@ function discoverWorkspaces(startDir = process.cwd(), options = {}) {
47195
47271
  }
47196
47272
  function pickDefaultWorkspace(workspaces, startDir = process.cwd()) {
47197
47273
  if (workspaces.length === 0) return null;
47198
- const cwd = resolve5(startDir);
47274
+ const cwd = resolve6(startDir);
47199
47275
  const containing = workspaces.find((ws) => cwd === ws.root || cwd.startsWith(`${ws.root}/`));
47200
47276
  if (containing) return containing;
47201
47277
  if (workspaces.length === 1) return workspaces[0] ?? null;
@@ -47384,8 +47460,8 @@ var RaftersToolHandler = class {
47384
47460
  const files = entries.filter((f) => f.endsWith(".composite.json"));
47385
47461
  for (const file of files) {
47386
47462
  try {
47387
- const { readFile: readFile9 } = await import("fs/promises");
47388
- const raw = await readFile9(join13(dir, file), "utf-8");
47463
+ const { readFile: readFile10 } = await import("fs/promises");
47464
+ const raw = await readFile10(join13(dir, file), "utf-8");
47389
47465
  const parsed = JSON.parse(raw);
47390
47466
  const result = CompositeFileSchema.safeParse(parsed);
47391
47467
  if (result.success) {
@@ -47411,11 +47487,31 @@ var RaftersToolHandler = class {
47411
47487
  this.builtInCompositesLoaded = true;
47412
47488
  }
47413
47489
  if (workspace && !this.compositesLoadedFor.has(workspace.root)) {
47414
- const paths = getRaftersPaths(workspace.root);
47415
- await this.loadCompositesFromDir(join13(paths.root, "composites"));
47490
+ for (const dir of await this.compositeReadRoots(workspace.root)) {
47491
+ await this.loadCompositesFromDir(dir);
47492
+ }
47416
47493
  this.compositesLoadedFor.add(workspace.root);
47417
47494
  }
47418
47495
  }
47496
+ /**
47497
+ * Resolve the set of folders to scan for composite manifests in a workspace.
47498
+ * Reads `.rafters/config.rafters.json` and applies the workspace's
47499
+ * `compositesPath` (which may be a string or an array of entries to support
47500
+ * shared packages like `@shingle/shared`). Falls back to `.rafters/composites`
47501
+ * when no config or compositesPath is set.
47502
+ */
47503
+ async compositeReadRoots(workspaceRoot) {
47504
+ const paths = getRaftersPaths(workspaceRoot);
47505
+ let config2 = null;
47506
+ try {
47507
+ config2 = JSON.parse(await readFile9(paths.config, "utf-8"));
47508
+ } catch {
47509
+ }
47510
+ if (!config2?.compositesPath) {
47511
+ return [join13(paths.root, "composites")];
47512
+ }
47513
+ return resolveReadSet(config2.compositesPath, workspaceRoot);
47514
+ }
47419
47515
  async handleComposite(args) {
47420
47516
  const { id, query, category, workspace } = args;
47421
47517
  const resolved = this.resolve(workspace);
@@ -47617,7 +47713,7 @@ async function mcp(options) {
47617
47713
  let workspaces;
47618
47714
  let defaultWorkspace;
47619
47715
  if (options.projectRoot) {
47620
- const explicit = resolve6(options.projectRoot);
47716
+ const explicit = resolve7(options.projectRoot);
47621
47717
  const configPath = join14(explicit, ".rafters", "config.rafters.json");
47622
47718
  if (!existsSync7(configPath)) {
47623
47719
  process.stderr.write(
@@ -47640,7 +47736,7 @@ async function mcp(options) {
47640
47736
 
47641
47737
  // src/commands/studio.ts
47642
47738
  import { existsSync as existsSync8 } from "fs";
47643
- import { resolve as resolve7 } from "path";
47739
+ import { resolve as resolve8 } from "path";
47644
47740
 
47645
47741
  // ../studio/src/api/vite-plugin.ts
47646
47742
  import { writeFile as writeFile5 } from "fs/promises";
@@ -47787,7 +47883,7 @@ function getNamespacePatchSchema(namespace) {
47787
47883
  }
47788
47884
  var MAX_BODY_SIZE = 1024 * 1024;
47789
47885
  function readJsonBody(req) {
47790
- return new Promise((resolve8, reject) => {
47886
+ return new Promise((resolve9, reject) => {
47791
47887
  let body = "";
47792
47888
  let size = 0;
47793
47889
  req.on("data", (chunk) => {
@@ -47800,7 +47896,7 @@ function readJsonBody(req) {
47800
47896
  });
47801
47897
  req.on("end", () => {
47802
47898
  try {
47803
- resolve8(body ? JSON.parse(body) : {});
47899
+ resolve9(body ? JSON.parse(body) : {});
47804
47900
  } catch {
47805
47901
  reject(new Error("Invalid JSON body"));
47806
47902
  }
@@ -48270,7 +48366,7 @@ async function studio() {
48270
48366
  },
48271
48367
  resolve: {
48272
48368
  alias: {
48273
- "@rafters-output": resolve7(cwd, ".rafters", "output")
48369
+ "@rafters-output": resolve8(cwd, ".rafters", "output")
48274
48370
  }
48275
48371
  }
48276
48372
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rafters",
3
- "version": "0.0.53",
3
+ "version": "0.0.54",
4
4
  "description": "CLI for Rafters design system - scaffold tokens and add components",
5
5
  "license": "MIT",
6
6
  "type": "module",