@clafoutis/cli 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import * as p2 from '@clack/prompts';
3
3
  import { Command } from 'commander';
4
4
  import fs from 'fs';
5
- import path2 from 'path';
5
+ import path from 'path';
6
6
  import { logger } from '@clafoutis/shared';
7
7
  import { generate } from '@clafoutis/generators/figma';
8
8
  import { generate as generate$1 } from '@clafoutis/generators/tailwind';
@@ -88,6 +88,28 @@ function tokensDirNotFoundError(tokensDir) {
88
88
  );
89
89
  }
90
90
 
91
+ // src/utils/cwd.ts
92
+ function resolveCommandCwd(cwdOverride) {
93
+ const cwd = cwdOverride?.trim() ? cwdOverride : process.cwd();
94
+ return path.resolve(cwd);
95
+ }
96
+ function resolveInCwd(commandCwd, targetPath) {
97
+ return path.isAbsolute(targetPath) ? path.resolve(targetPath) : path.resolve(commandCwd, targetPath);
98
+ }
99
+ function displayPath(commandCwd, absolutePath) {
100
+ const rel = path.relative(commandCwd, absolutePath);
101
+ return rel && !rel.startsWith("..") ? rel : absolutePath;
102
+ }
103
+ function validateCwdOption(cwdOverride) {
104
+ if (cwdOverride !== void 0 && cwdOverride.trim() === "") {
105
+ throw new ClafoutisError(
106
+ "Invalid --cwd value",
107
+ "--cwd cannot be empty",
108
+ "Provide a valid directory path, for example: --cwd ./packages/design-system"
109
+ );
110
+ }
111
+ }
112
+
91
113
  // src/commands/format.ts
92
114
  function loadTokenFiles(dirPath) {
93
115
  const files = [];
@@ -96,7 +118,7 @@ function loadTokenFiles(dirPath) {
96
118
  return;
97
119
  }
98
120
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
99
- const fullPath = path2.join(dir, entry.name);
121
+ const fullPath = path.join(dir, entry.name);
100
122
  const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
101
123
  if (entry.isDirectory()) {
102
124
  walk(fullPath, relativePath);
@@ -120,7 +142,9 @@ function formatJson(content) {
120
142
  return JSON.stringify(parsed, null, 2) + "\n";
121
143
  }
122
144
  function formatCommand(options) {
123
- const tokensDir = options.tokens || "./tokens";
145
+ validateCwdOption(options.cwd);
146
+ const commandCwd = resolveCommandCwd(options.cwd);
147
+ const tokensDir = resolveInCwd(commandCwd, options.tokens || "./tokens");
124
148
  if (!fs.existsSync(tokensDir)) {
125
149
  throw tokensDirNotFoundError(tokensDir);
126
150
  }
@@ -260,8 +284,8 @@ function findUnknownFields(config, schemaProperties, prefix = "") {
260
284
  }
261
285
  return unknown;
262
286
  }
263
- function hasField(config, path6) {
264
- const parts = path6.split(".");
287
+ function hasField(config, path8) {
288
+ const parts = path8.split(".");
265
289
  let current = config;
266
290
  for (const part of parts) {
267
291
  if (current && typeof current === "object" && part in current) {
@@ -590,11 +614,11 @@ function getConsumerGitignore() {
590
614
  `;
591
615
  }
592
616
  var __filename$1 = fileURLToPath(import.meta.url);
593
- var __dirname$1 = path2.dirname(__filename$1);
617
+ var __dirname$1 = path.dirname(__filename$1);
594
618
  function getTokensDir() {
595
- const devPath = path2.resolve(__dirname$1, "tokens");
619
+ const devPath = path.resolve(__dirname$1, "tokens");
596
620
  if (fs.existsSync(devPath)) return devPath;
597
- const distPath = path2.resolve(__dirname$1, "templates", "tokens");
621
+ const distPath = path.resolve(__dirname$1, "templates", "tokens");
598
622
  if (fs.existsSync(distPath)) return distPath;
599
623
  throw new Error(
600
624
  `Starter token templates not found. Searched:
@@ -605,8 +629,8 @@ function getTokensDir() {
605
629
  function walkTokensDir(dir, base = "") {
606
630
  const result = [];
607
631
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
608
- const relPath = base ? path2.join(base, entry.name) : entry.name;
609
- const fullPath = path2.join(dir, entry.name);
632
+ const relPath = base ? path.join(base, entry.name) : entry.name;
633
+ const fullPath = path.join(dir, entry.name);
610
634
  if (entry.isDirectory()) {
611
635
  result.push(...walkTokensDir(fullPath, relPath));
612
636
  } else if (entry.name.endsWith(".json")) {
@@ -632,6 +656,7 @@ on:
632
656
  branches: [main]
633
657
  paths:
634
658
  - 'tokens/**'
659
+ - '.clafoutis/producer.json'
635
660
 
636
661
  jobs:
637
662
  release:
@@ -657,6 +682,18 @@ jobs:
657
682
  - name: Generate tokens
658
683
  run: npx clafoutis generate
659
684
 
685
+ - name: Commit generated build artifacts
686
+ run: |
687
+ if [ -z "$(git status --porcelain build)" ]; then
688
+ echo "No build changes to commit"
689
+ exit 0
690
+ fi
691
+ git config user.name "github-actions[bot]"
692
+ git config user.email "github-actions[bot]@users.noreply.github.com"
693
+ git add build
694
+ git commit -m "chore: update generated build artifacts"
695
+ git push
696
+
660
697
  - name: Get next version
661
698
  id: version
662
699
  run: |
@@ -740,15 +777,17 @@ async function initCommand(options) {
740
777
  "Choose one: --producer for design system repos, --consumer for application repos"
741
778
  );
742
779
  }
780
+ validateCwdOption(options.cwd);
781
+ const commandCwd = resolveCommandCwd(options.cwd);
743
782
  const isInteractive = !options.nonInteractive && process.stdin.isTTY;
744
783
  const isDryRun = options.dryRun ?? false;
745
784
  if (isInteractive) {
746
- await runInteractiveInit(options, isDryRun);
785
+ await runInteractiveInit(options, isDryRun, commandCwd);
747
786
  } else {
748
- await runNonInteractiveInit(options, isDryRun);
787
+ await runNonInteractiveInit(options, isDryRun, commandCwd);
749
788
  }
750
789
  }
751
- async function runInteractiveInit(options, isDryRun) {
790
+ async function runInteractiveInit(options, isDryRun, commandCwd) {
752
791
  showIntro(isDryRun);
753
792
  let mode;
754
793
  if (options.producer) {
@@ -768,13 +807,23 @@ async function runInteractiveInit(options, isDryRun) {
768
807
  if (!answers) {
769
808
  return;
770
809
  }
771
- await createProducerConfig(answers, options.force ?? false, isDryRun);
810
+ await createProducerConfig(
811
+ answers,
812
+ options.force ?? false,
813
+ isDryRun,
814
+ commandCwd
815
+ );
772
816
  } else {
773
817
  const answers = await runConsumerWizard();
774
818
  if (!answers) {
775
819
  return;
776
820
  }
777
- await createConsumerConfig(answers, options.force ?? false, isDryRun);
821
+ await createConsumerConfig(
822
+ answers,
823
+ options.force ?? false,
824
+ isDryRun,
825
+ commandCwd
826
+ );
778
827
  }
779
828
  if (isDryRun) {
780
829
  showOutro("No files were written. Remove --dry-run to apply changes.");
@@ -782,7 +831,7 @@ async function runInteractiveInit(options, isDryRun) {
782
831
  showOutro("Setup complete!");
783
832
  }
784
833
  }
785
- async function runNonInteractiveInit(options, isDryRun) {
834
+ async function runNonInteractiveInit(options, isDryRun, commandCwd) {
786
835
  if (!options.producer && !options.consumer) {
787
836
  throw new ClafoutisError(
788
837
  "Mode required",
@@ -805,7 +854,12 @@ async function runNonInteractiveInit(options, isDryRun) {
805
854
  output: options.output ?? "./build",
806
855
  workflow: options.workflow ?? true
807
856
  };
808
- await createProducerConfig(answers, options.force ?? false, isDryRun);
857
+ await createProducerConfig(
858
+ answers,
859
+ options.force ?? false,
860
+ isDryRun,
861
+ commandCwd
862
+ );
809
863
  } else {
810
864
  const errors = validateConsumerFlags(options);
811
865
  if (errors.length > 0) {
@@ -859,11 +913,16 @@ async function runNonInteractiveInit(options, isDryRun) {
859
913
  repo: options.repo,
860
914
  files
861
915
  };
862
- await createConsumerConfig(answers, options.force ?? false, isDryRun);
916
+ await createConsumerConfig(
917
+ answers,
918
+ options.force ?? false,
919
+ isDryRun,
920
+ commandCwd
921
+ );
863
922
  }
864
923
  }
865
- async function createProducerConfig(answers, force, dryRun) {
866
- const configPath = ".clafoutis/producer.json";
924
+ async function createProducerConfig(answers, force, dryRun, commandCwd) {
925
+ const configPath = resolveInCwd(commandCwd, ".clafoutis/producer.json");
867
926
  if (!force && await fileExists(configPath)) {
868
927
  throw new ClafoutisError(
869
928
  "Configuration already exists",
@@ -896,7 +955,10 @@ async function createProducerConfig(answers, force, dryRun) {
896
955
  ];
897
956
  const starterTokens = getAllStarterTokens();
898
957
  for (const token of starterTokens) {
899
- const tokenPath = path2.join(answers.tokens, token.path);
958
+ const tokenPath = resolveInCwd(
959
+ commandCwd,
960
+ path.join(answers.tokens, token.path)
961
+ );
900
962
  if (!force && await fileExists(tokenPath)) {
901
963
  continue;
902
964
  }
@@ -907,7 +969,7 @@ async function createProducerConfig(answers, force, dryRun) {
907
969
  });
908
970
  }
909
971
  if (answers.workflow) {
910
- const workflowPath = getWorkflowPath();
972
+ const workflowPath = resolveInCwd(commandCwd, getWorkflowPath());
911
973
  if (force || !await fileExists(workflowPath)) {
912
974
  filesToCreate.push({
913
975
  path: workflowPath,
@@ -916,22 +978,23 @@ async function createProducerConfig(answers, force, dryRun) {
916
978
  });
917
979
  }
918
980
  }
919
- if (force || !await fileExists(".gitignore")) {
981
+ const gitignorePath = resolveInCwd(commandCwd, ".gitignore");
982
+ if (force || !await fileExists(gitignorePath)) {
920
983
  filesToCreate.push({
921
- path: ".gitignore",
984
+ path: gitignorePath,
922
985
  content: getProducerGitignore(),
923
986
  description: "Ignore build artifacts and release-assets"
924
987
  });
925
988
  }
926
989
  if (dryRun) {
927
- showDryRunOutput(filesToCreate);
990
+ showDryRunOutput(filesToCreate, commandCwd);
928
991
  } else {
929
- await writeFiles(filesToCreate);
992
+ await writeFiles(filesToCreate, commandCwd);
930
993
  showNextSteps("producer", answers);
931
994
  }
932
995
  }
933
- async function createConsumerConfig(answers, force, dryRun) {
934
- const configPath = ".clafoutis/consumer.json";
996
+ async function createConsumerConfig(answers, force, dryRun, commandCwd) {
997
+ const configPath = resolveInCwd(commandCwd, ".clafoutis/consumer.json");
935
998
  if (!force && await fileExists(configPath)) {
936
999
  throw new ClafoutisError(
937
1000
  "Configuration already exists",
@@ -951,7 +1014,7 @@ async function createConsumerConfig(answers, force, dryRun) {
951
1014
  description: `repo: "${answers.repo}"`
952
1015
  }
953
1016
  ];
954
- const gitignorePath = ".gitignore";
1017
+ const gitignorePath = resolveInCwd(commandCwd, ".gitignore");
955
1018
  const consumerIgnore = getConsumerGitignore();
956
1019
  if (await fileExists(gitignorePath)) {
957
1020
  const existingContent = await fs2.readFile(gitignorePath, "utf-8");
@@ -970,30 +1033,30 @@ async function createConsumerConfig(answers, force, dryRun) {
970
1033
  });
971
1034
  }
972
1035
  if (dryRun) {
973
- showDryRunOutput(filesToCreate);
1036
+ showDryRunOutput(filesToCreate, commandCwd);
974
1037
  } else {
975
- await writeFiles(filesToCreate);
1038
+ await writeFiles(filesToCreate, commandCwd);
976
1039
  showNextSteps("consumer", answers);
977
1040
  }
978
1041
  }
979
- function showDryRunOutput(files) {
1042
+ function showDryRunOutput(files, commandCwd) {
980
1043
  log3.message("");
981
1044
  log3.step("Would create the following files:");
982
1045
  log3.message("");
983
1046
  for (const file of files) {
984
- log3.message(` ${file.path}`);
1047
+ log3.message(` ${displayPath(commandCwd, file.path)}`);
985
1048
  if (file.description) {
986
1049
  log3.message(` \u2514\u2500 ${file.description}`);
987
1050
  }
988
1051
  }
989
1052
  log3.message("");
990
1053
  }
991
- async function writeFiles(files) {
1054
+ async function writeFiles(files, commandCwd) {
992
1055
  for (const file of files) {
993
- const dir = path2.dirname(file.path);
1056
+ const dir = path.dirname(file.path);
994
1057
  await fs2.mkdir(dir, { recursive: true });
995
1058
  await fs2.writeFile(file.path, file.content);
996
- log3.success(`Created ${file.path}`);
1059
+ log3.success(`Created ${displayPath(commandCwd, file.path)}`);
997
1060
  }
998
1061
  }
999
1062
  function showNextSteps(mode, answers) {
@@ -1018,15 +1081,20 @@ function showNextSteps(mode, answers) {
1018
1081
  }
1019
1082
 
1020
1083
  // src/commands/generate.ts
1021
- async function loadPlugin(pluginPath) {
1022
- const absolutePath = path2.resolve(process.cwd(), pluginPath);
1084
+ async function loadPlugin(pluginPath, commandCwd) {
1085
+ const absolutePath = resolveInCwd(commandCwd, pluginPath);
1023
1086
  if (pluginPath.endsWith(".ts")) {
1024
1087
  register();
1025
1088
  }
1026
1089
  return import(pathToFileURL(absolutePath).href);
1027
1090
  }
1028
1091
  async function generateCommand(options) {
1029
- const configPath = options.config || ".clafoutis/producer.json";
1092
+ validateCwdOption(options.cwd);
1093
+ const commandCwd = resolveCommandCwd(options.cwd);
1094
+ const configPath = resolveInCwd(
1095
+ commandCwd,
1096
+ options.config || ".clafoutis/producer.json"
1097
+ );
1030
1098
  let config = await readProducerConfig(configPath);
1031
1099
  if (!config) {
1032
1100
  if (await fileExists(configPath)) {
@@ -1039,7 +1107,7 @@ async function generateCommand(options) {
1039
1107
  if (process.stdin.isTTY) {
1040
1108
  const shouldRunWizard = await offerWizard("producer");
1041
1109
  if (shouldRunWizard) {
1042
- await initCommand({ producer: true });
1110
+ await initCommand({ producer: true, cwd: commandCwd });
1043
1111
  config = await readProducerConfig(configPath);
1044
1112
  if (!config) {
1045
1113
  throw configNotFoundError(configPath, false);
@@ -1065,8 +1133,8 @@ async function generateCommand(options) {
1065
1133
  if (options.output) {
1066
1134
  config.output = options.output;
1067
1135
  }
1068
- const tokensDir = path2.resolve(process.cwd(), config.tokens || "./tokens");
1069
- const outputDir = path2.resolve(process.cwd(), config.output || "./build");
1136
+ const tokensDir = resolveInCwd(commandCwd, config.tokens || "./tokens");
1137
+ const outputDir = resolveInCwd(commandCwd, config.output || "./build");
1070
1138
  if (!await fileExists(tokensDir)) {
1071
1139
  throw tokensDirNotFoundError(tokensDir);
1072
1140
  }
@@ -1092,7 +1160,7 @@ async function generateCommand(options) {
1092
1160
  let generatorModule;
1093
1161
  if (typeof value === "string") {
1094
1162
  try {
1095
- generatorModule = await loadPlugin(value);
1163
+ generatorModule = await loadPlugin(value, commandCwd);
1096
1164
  } catch (err) {
1097
1165
  const errorMessage = err instanceof Error ? err.message : String(err);
1098
1166
  throw pluginLoadError(value, errorMessage);
@@ -1115,7 +1183,7 @@ async function generateCommand(options) {
1115
1183
  }
1116
1184
  const context = {
1117
1185
  tokensDir,
1118
- outputDir: path2.join(outputDir, name),
1186
+ outputDir: path.join(outputDir, name),
1119
1187
  config,
1120
1188
  StyleDictionary
1121
1189
  };
@@ -1139,10 +1207,18 @@ async function generateCommand(options) {
1139
1207
  logger.success("Generation complete");
1140
1208
  }
1141
1209
  var CACHE_DIR = ".clafoutis";
1142
- var CACHE_FILE = `${CACHE_DIR}/cache`;
1143
- async function readCache() {
1210
+ var CACHE_FILE = "cache";
1211
+ function getCachePaths(commandCwd) {
1212
+ const dir = path.resolve(commandCwd, CACHE_DIR);
1213
+ return {
1214
+ dir,
1215
+ file: path.join(dir, CACHE_FILE)
1216
+ };
1217
+ }
1218
+ async function readCache(commandCwd = process.cwd()) {
1219
+ const { file } = getCachePaths(commandCwd);
1144
1220
  try {
1145
- return (await fs2.readFile(CACHE_FILE, "utf-8")).trim();
1221
+ return (await fs2.readFile(file, "utf-8")).trim();
1146
1222
  } catch (err) {
1147
1223
  if (err instanceof Error && err.code === "ENOENT") {
1148
1224
  return null;
@@ -1150,9 +1226,10 @@ async function readCache() {
1150
1226
  throw err;
1151
1227
  }
1152
1228
  }
1153
- async function writeCache(version) {
1154
- await fs2.mkdir(CACHE_DIR, { recursive: true });
1155
- await fs2.writeFile(CACHE_FILE, version);
1229
+ async function writeCache(version, commandCwd = process.cwd()) {
1230
+ const { dir, file } = getCachePaths(commandCwd);
1231
+ await fs2.mkdir(dir, { recursive: true });
1232
+ await fs2.writeFile(file, version);
1156
1233
  }
1157
1234
  async function downloadRelease(config) {
1158
1235
  const token = process.env.CLAFOUTIS_REPO_TOKEN;
@@ -1218,18 +1295,23 @@ async function downloadRelease(config) {
1218
1295
  }
1219
1296
 
1220
1297
  // src/commands/sync.ts
1221
- async function writeOutput(config, files) {
1298
+ async function writeOutput(config, files, commandCwd) {
1222
1299
  for (const [assetName, content] of files) {
1223
1300
  const configPath = config.files[assetName];
1224
1301
  if (!configPath) continue;
1225
- const outputPath = path2.resolve(process.cwd(), configPath);
1226
- await fs2.mkdir(path2.dirname(outputPath), { recursive: true });
1302
+ const outputPath = resolveInCwd(commandCwd, configPath);
1303
+ await fs2.mkdir(path.dirname(outputPath), { recursive: true });
1227
1304
  await fs2.writeFile(outputPath, content);
1228
1305
  logger.success(`Written: ${outputPath}`);
1229
1306
  }
1230
1307
  }
1231
1308
  async function syncCommand(options) {
1232
- const configPath = options.config || ".clafoutis/consumer.json";
1309
+ validateCwdOption(options.cwd);
1310
+ const commandCwd = resolveCommandCwd(options.cwd);
1311
+ const configPath = resolveInCwd(
1312
+ commandCwd,
1313
+ options.config || ".clafoutis/consumer.json"
1314
+ );
1233
1315
  let config = await readConfig(configPath);
1234
1316
  if (!config) {
1235
1317
  if (await fileExists(configPath)) {
@@ -1242,7 +1324,7 @@ async function syncCommand(options) {
1242
1324
  if (process.stdin.isTTY) {
1243
1325
  const shouldRunWizard = await offerWizard("consumer");
1244
1326
  if (shouldRunWizard) {
1245
- await initCommand({ consumer: true });
1327
+ await initCommand({ consumer: true, cwd: commandCwd });
1246
1328
  config = await readConfig(configPath);
1247
1329
  if (!config) {
1248
1330
  throw configNotFoundError(configPath, true);
@@ -1255,7 +1337,7 @@ async function syncCommand(options) {
1255
1337
  }
1256
1338
  }
1257
1339
  validateConsumerConfig(config);
1258
- const cachedVersion = await readCache();
1340
+ const cachedVersion = await readCache(commandCwd);
1259
1341
  const isLatest = config.version === "latest";
1260
1342
  logger.info(`Repo: ${config.repo}`);
1261
1343
  logger.info(`Pinned: ${config.version}`);
@@ -1269,7 +1351,7 @@ async function syncCommand(options) {
1269
1351
  }
1270
1352
  return;
1271
1353
  }
1272
- const resolveOutputPaths = () => Object.values(config.files).map((p5) => path2.resolve(process.cwd(), p5));
1354
+ const resolveOutputPaths = () => Object.values(config.files).map((p5) => resolveInCwd(commandCwd, p5));
1273
1355
  if (!isLatest && !options.force && config.version === cachedVersion) {
1274
1356
  const outputPaths = resolveOutputPaths();
1275
1357
  const existsResults = await Promise.all(
@@ -1294,14 +1376,14 @@ async function syncCommand(options) {
1294
1376
  return;
1295
1377
  }
1296
1378
  }
1297
- await writeOutput(config, files);
1298
- await writeCache(resolvedTag);
1379
+ await writeOutput(config, files, commandCwd);
1380
+ await writeCache(resolvedTag, commandCwd);
1299
1381
  logger.success(`Synced to ${resolvedTag}`);
1300
1382
  if (config.postSync) {
1301
- await runPostSync(config.postSync);
1383
+ await runPostSync(config.postSync, commandCwd);
1302
1384
  }
1303
1385
  }
1304
- async function runPostSync(command) {
1386
+ async function runPostSync(command, commandCwd) {
1305
1387
  logger.info(`Running postSync: ${command}`);
1306
1388
  const isWindows = process.platform === "win32";
1307
1389
  const shell = isWindows ? "cmd.exe" : "/bin/sh";
@@ -1309,7 +1391,8 @@ async function runPostSync(command) {
1309
1391
  return new Promise((resolve, reject) => {
1310
1392
  const child = spawn(shell, shellArgs, {
1311
1393
  stdio: ["inherit", "pipe", "pipe"],
1312
- env: process.env
1394
+ env: process.env,
1395
+ cwd: commandCwd
1313
1396
  });
1314
1397
  let stdout = "";
1315
1398
  let stderr = "";
@@ -1406,23 +1489,23 @@ program.command("generate").description("Generate platform outputs from design t
1406
1489
  "-c, --config <path>",
1407
1490
  "Path to config file",
1408
1491
  ".clafoutis/producer.json"
1409
- ).option("--tailwind", "Generate Tailwind output").option("--figma", "Generate Figma variables").option("-o, --output <dir>", "Output directory", "./build").option("--dry-run", "Preview changes without writing files").action(withErrorHandling(generateCommand));
1492
+ ).option("--tailwind", "Generate Tailwind output").option("--figma", "Generate Figma variables").option("-o, --output <dir>", "Output directory", "./build").option("--cwd <path>", "Run command as if from this directory").option("--dry-run", "Preview changes without writing files").action(withErrorHandling(generateCommand));
1410
1493
  program.command("sync").description("Sync design tokens from GitHub Release (for consumers)").option("-f, --force", "Force sync even if versions match").option(
1411
1494
  "-c, --config <path>",
1412
1495
  "Path to config file",
1413
1496
  ".clafoutis/consumer.json"
1414
- ).option("--dry-run", "Preview changes without writing files").action(withErrorHandling(syncCommand));
1497
+ ).option("--cwd <path>", "Run command as if from this directory").option("--dry-run", "Preview changes without writing files").action(withErrorHandling(syncCommand));
1415
1498
  program.command("init").description("Initialize Clafoutis configuration").option("--producer", "Set up as a design token producer").option("--consumer", "Set up as a design token consumer").option("-r, --repo <repo>", "GitHub repo for consumer mode (org/name)").option("-t, --tokens <path>", "Token directory path (default: ./tokens)").option("-o, --output <path>", "Output directory path (default: ./build)").option(
1416
1499
  "-g, --generators <list>",
1417
1500
  "Comma-separated generators: tailwind, figma"
1418
1501
  ).option("--workflow", "Create GitHub Actions workflow (default: true)").option("--no-workflow", "Skip GitHub Actions workflow").option(
1419
1502
  "--files <mapping>",
1420
1503
  "File mappings for consumer: asset:dest,asset:dest"
1421
- ).option("--force", "Overwrite existing configuration").option("--dry-run", "Preview changes without writing files").option("--non-interactive", "Skip prompts, use defaults or flags").action(withErrorHandling(initCommand));
1504
+ ).option("--force", "Overwrite existing configuration").option("--dry-run", "Preview changes without writing files").option("--non-interactive", "Skip prompts, use defaults or flags").option("--cwd <path>", "Run command as if from this directory").action(withErrorHandling(initCommand));
1422
1505
  program.command("format").description("Format token JSON files for consistent formatting").option("-t, --tokens <path>", "Token directory path", "./tokens").option(
1423
1506
  "--check",
1424
1507
  "Check formatting without modifying files (fails if unformatted)"
1425
- ).option("--dry-run", "Preview changes without writing files").action(withErrorHandling(formatCommand));
1508
+ ).option("--cwd <path>", "Run command as if from this directory").option("--dry-run", "Preview changes without writing files").action(withErrorHandling(formatCommand));
1426
1509
  program.parse();
1427
1510
  //# sourceMappingURL=index.js.map
1428
1511
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/errors.ts","../src/commands/format.ts","../src/cli/validation.ts","../src/cli/wizard.ts","../src/utils/config.ts","../schemas/consumer-config.json","../schemas/producer-config.json","../src/utils/validate.ts","../src/templates/gitignore.ts","../src/templates/tokens.ts","../src/templates/workflow.ts","../src/commands/init.ts","../src/commands/generate.ts","../src/utils/cache.ts","../src/utils/github.ts","../src/commands/sync.ts","../src/index.ts"],"names":["path","p","log","fs","__filename","__dirname","p3","registerTsx","logger","tailwindGenerate","figmaGenerate","p4"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * ANSI color codes for terminal output formatting.\n */\nconst colors = {\n red: (s: string) => `\\x1b[31m${s}\\x1b[0m`,\n cyan: (s: string) => `\\x1b[36m${s}\\x1b[0m`,\n yellow: (s: string) => `\\x1b[33m${s}\\x1b[0m`,\n};\n\n/**\n * Custom error class for Clafoutis CLI errors.\n * Provides structured error messages with actionable suggestions.\n */\nexport class ClafoutisError extends Error {\n constructor(\n public title: string,\n public detail: string,\n public suggestion?: string,\n ) {\n super(`${title}: ${detail}`);\n this.name = \"ClafoutisError\";\n }\n\n /**\n * Formats the error for display in the terminal with colors and structure.\n */\n format(): string {\n let output = `\\n${colors.red(\"Error:\")} ${this.title}\\n`;\n output += `\\n${this.detail}\\n`;\n if (this.suggestion) {\n output += `\\n${colors.cyan(\"Suggestion:\")} ${this.suggestion}\\n`;\n }\n return output;\n }\n}\n\n/**\n * Creates a ClafoutisError for when a configuration file is not found.\n */\nexport function configNotFoundError(\n configPath: string,\n isConsumer: boolean,\n): ClafoutisError {\n return new ClafoutisError(\n \"Configuration not found\",\n `Could not find ${configPath}`,\n `Run: npx clafoutis init --${isConsumer ? \"consumer\" : \"producer\"}`,\n );\n}\n\n/**\n * Creates a ClafoutisError for invalid repository format.\n */\nexport function invalidRepoError(repo: string): ClafoutisError {\n return new ClafoutisError(\n \"Invalid repository format\",\n `\"${repo}\" is not a valid GitHub repository`,\n 'Use format: org/repo (e.g., \"YourOrg/design-system\")',\n );\n}\n\n/**\n * Creates a ClafoutisError for when a GitHub release is not found.\n */\nexport function releaseNotFoundError(\n version: string,\n repo: string,\n): ClafoutisError {\n return new ClafoutisError(\n \"Release not found\",\n `Version ${version} does not exist in ${repo}`,\n `Check available releases: gh release list -R ${repo}`,\n );\n}\n\n/**\n * Creates a ClafoutisError for when GitHub authentication is required.\n */\nexport function authRequiredError(): ClafoutisError {\n return new ClafoutisError(\n \"Authentication required\",\n \"CLAFOUTIS_REPO_TOKEN is required for private repositories\",\n \"Set the environment variable: export CLAFOUTIS_REPO_TOKEN=ghp_xxx\",\n );\n}\n\n/**\n * Creates a ClafoutisError for when a built-in generator is not found.\n */\nexport function generatorNotFoundError(name: string): ClafoutisError {\n return new ClafoutisError(\n \"Generator not found\",\n `Built-in generator \"${name}\" does not exist`,\n \"Available generators: tailwind, figma\",\n );\n}\n\n/**\n * Creates a ClafoutisError for when a plugin fails to load.\n */\nexport function pluginLoadError(\n pluginPath: string,\n errorMessage: string,\n): ClafoutisError {\n return new ClafoutisError(\n \"Plugin load failed\",\n `Could not load generator from ${pluginPath}: ${errorMessage}`,\n 'Ensure the file exports a \"generate\" function',\n );\n}\n\n/**\n * Creates a ClafoutisError for when the tokens directory is missing.\n */\nexport function tokensDirNotFoundError(tokensDir: string): ClafoutisError {\n return new ClafoutisError(\n \"Tokens directory not found\",\n `Directory \"${tokensDir}\" does not exist`,\n \"Create the directory and add token JSON files\",\n );\n}\n\n/**\n * Creates a ClafoutisError for when a config file already exists.\n */\nexport function configExistsError(configPath: string): ClafoutisError {\n return new ClafoutisError(\n \"Configuration already exists\",\n configPath,\n \"Use --force to overwrite the existing configuration\",\n );\n}\n\n/**\n * Creates a ClafoutisError for network/fetch failures.\n */\nexport function networkError(url: string, reason: string): ClafoutisError {\n return new ClafoutisError(\n \"Network error\",\n `Failed to fetch ${url}: ${reason}`,\n \"Check your network connection and ensure the repository is accessible\",\n );\n}\n\n/**\n * Creates a ClafoutisError for invalid CLI flag combinations.\n */\nexport function invalidFlagsError(errors: string[]): ClafoutisError {\n return new ClafoutisError(\n \"Invalid flags\",\n errors.join(\"\\n\"),\n \"Fix the invalid flags and try again\",\n );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { logger } from \"@clafoutis/shared\";\n\nimport { tokensDirNotFoundError } from \"../utils/errors\";\n\ninterface FormatOptions {\n tokens?: string;\n check?: boolean;\n dryRun?: boolean;\n}\n\n/**\n * Recursively loads all JSON token files from a directory.\n */\nfunction loadTokenFiles(\n dirPath: string,\n): Array<{ relativePath: string; fullPath: string; content: string }> {\n const files: Array<{\n relativePath: string;\n fullPath: string;\n content: string;\n }> = [];\n\n function walk(dir: string, prefix: string): void {\n if (!fs.existsSync(dir)) {\n return;\n }\n\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;\n\n if (entry.isDirectory()) {\n walk(fullPath, relativePath);\n } else if (entry.name.endsWith(\".json\")) {\n try {\n const content = fs.readFileSync(fullPath, \"utf-8\");\n files.push({ relativePath, fullPath, content });\n } catch (err) {\n logger.warn(\n `Failed to read ${relativePath}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n }\n }\n\n walk(dirPath, \"\");\n return files;\n}\n\n/**\n * Formats a JSON string to match serializeTokenFile output:\n * JSON.stringify(parsed, null, 2) + \"\\n\"\n *\n * This is the single canonical format used everywhere —\n * Studio's serializeTokenFile and this CLI command produce identical output.\n */\nfunction formatJson(content: string): string {\n const parsed = JSON.parse(content);\n return JSON.stringify(parsed, null, 2) + \"\\n\";\n}\n\n/**\n * Formats token files to ensure consistent JSON formatting.\n */\nexport function formatCommand(options: FormatOptions): void {\n const tokensDir = options.tokens || \"./tokens\";\n\n if (!fs.existsSync(tokensDir)) {\n throw tokensDirNotFoundError(tokensDir);\n }\n\n logger.info(`Formatting token files in ${tokensDir}...`);\n\n const files = loadTokenFiles(tokensDir);\n const fileCount = files.length;\n\n if (fileCount === 0) {\n logger.warn(`No JSON files found in ${tokensDir}`);\n return;\n }\n\n let changedCount = 0;\n const unformattedFiles: string[] = [];\n\n for (const { relativePath, fullPath, content } of files) {\n try {\n const formatted = formatJson(content);\n\n if (content !== formatted) {\n if (options.check) {\n unformattedFiles.push(relativePath);\n changedCount++;\n } else if (options.dryRun) {\n logger.info(`Would format: ${relativePath}`);\n changedCount++;\n } else {\n fs.writeFileSync(fullPath, formatted, \"utf-8\");\n logger.info(`Formatted: ${relativePath}`);\n changedCount++;\n }\n }\n } catch (err) {\n logger.error(\n `Failed to format ${relativePath}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n throw err;\n }\n }\n\n if (options.check) {\n if (changedCount > 0) {\n logger.error(\n `${changedCount} of ${fileCount} files are not formatted correctly:`,\n );\n for (const file of unformattedFiles) {\n logger.error(` - ${file}`);\n }\n logger.info(\n `Run 'npx clafoutis format --tokens ${tokensDir}' to fix formatting.`,\n );\n process.exit(1);\n }\n logger.success(`All ${fileCount} files are correctly formatted`);\n return;\n }\n\n if (options.dryRun) {\n if (changedCount > 0) {\n logger.info(`Would format ${changedCount} of ${fileCount} files`);\n } else {\n logger.info(`All ${fileCount} files are already formatted`);\n }\n return;\n }\n\n if (changedCount > 0) {\n logger.success(`Formatted ${changedCount} of ${fileCount} files`);\n } else {\n logger.success(`All ${fileCount} files are already formatted`);\n }\n}\n","import * as p from \"@clack/prompts\";\nimport { Ajv, type ErrorObject } from \"ajv\";\n\nimport { ClafoutisError } from \"../utils/errors\";\n\n/**\n * Validates a GitHub repository format (org/repo-name).\n * @returns Error message if invalid, undefined if valid.\n */\nexport function validateRepo(value: string | undefined): string | undefined {\n if (!value) {\n return \"Repository is required\";\n }\n if (!/^[\\w-]+\\/[\\w.-]+$/.test(value)) {\n return \"Repository must be in format: org/repo-name\";\n }\n return undefined;\n}\n\n/**\n * Validates a file system path.\n * Paths must start with ./ or / or be exactly \".\"\n * @returns Error message if invalid, undefined if valid.\n */\nexport function validatePath(value: string | undefined): string | undefined {\n if (!value) {\n return \"Path is required\";\n }\n if (!value.startsWith(\"./\") && !value.startsWith(\"/\") && value !== \".\") {\n return 'Path must start with ./ or /, or be \".\"';\n }\n return undefined;\n}\n\n/**\n * Validates that a string value is not empty or whitespace-only.\n * @returns Error message if empty, undefined if valid.\n */\nexport function required(value: string | undefined): string | undefined {\n if (!value || !value.trim()) {\n return \"This field is required\";\n }\n return undefined;\n}\n\nconst DEPRECATED_FIELDS: Record<string, string> = {\n \"generators.css\": 'Use \"generators.tailwind\" instead',\n buildDir: 'Renamed to \"output\"',\n};\n\n/**\n * Validates a config object against its JSON schema and checks for issues.\n * - Throws ClafoutisError if schema validation fails\n * - Logs warnings for unknown fields not defined in the schema\n * - Logs warnings for deprecated fields with migration guidance\n */\nexport function validateConfig(\n config: Record<string, unknown>,\n schema: object,\n configPath: string,\n): void {\n const ajv = new Ajv({ allErrors: true, strict: false });\n const validate = ajv.compile(schema);\n\n if (!validate(config)) {\n const errors = validate.errors\n ?.map((e: ErrorObject) => ` - ${e.instancePath || \"root\"}: ${e.message}`)\n .join(\"\\n\");\n throw new ClafoutisError(\n \"Invalid configuration\",\n `${configPath}:\\n${errors}`,\n 'Check the config against the schema or run \"clafoutis init --force\" to regenerate',\n );\n }\n\n const schemaObj = schema as { properties?: Record<string, unknown> };\n if (schemaObj.properties) {\n const unknownFields = findUnknownFields(config, schemaObj.properties);\n if (unknownFields.length > 0) {\n p.log.warn(\n `Unknown fields in ${configPath}: ${unknownFields.join(\", \")}`,\n );\n p.log.info(\n \"These fields will be ignored. Check for typos or outdated config.\",\n );\n }\n }\n\n for (const [field, message] of Object.entries(DEPRECATED_FIELDS)) {\n if (hasField(config, field)) {\n p.log.warn(`Deprecated field \"${field}\": ${message}`);\n }\n }\n}\n\n/**\n * Recursively finds fields in config that are not defined in the schema.\n * Returns an array of dot-notation paths to unknown fields.\n */\nfunction findUnknownFields(\n config: Record<string, unknown>,\n schemaProperties: Record<string, unknown>,\n prefix = \"\",\n): string[] {\n const unknown: string[] = [];\n\n for (const key of Object.keys(config)) {\n const fullPath = prefix ? `${prefix}.${key}` : key;\n\n if (!(key in schemaProperties)) {\n unknown.push(fullPath);\n } else {\n const value = config[key];\n const schemaProp = schemaProperties[key] as {\n properties?: Record<string, unknown>;\n };\n\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n schemaProp?.properties\n ) {\n unknown.push(\n ...findUnknownFields(\n value as Record<string, unknown>,\n schemaProp.properties,\n fullPath,\n ),\n );\n }\n }\n }\n\n return unknown;\n}\n\n/**\n * Checks if a config object has a field at the given dot-notation path.\n * Example: hasField(config, 'generators.css') checks config.generators.css\n */\nfunction hasField(config: Record<string, unknown>, path: string): boolean {\n const parts = path.split(\".\");\n let current: unknown = config;\n\n for (const part of parts) {\n if (current && typeof current === \"object\" && part in current) {\n current = (current as Record<string, unknown>)[part];\n } else {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Validates CLI flags for producer init command.\n * @returns Array of error messages for invalid flags, empty if all valid.\n */\nexport function validateProducerFlags(options: {\n tokens?: string;\n output?: string;\n generators?: string;\n}): string[] {\n const errors: string[] = [];\n\n if (options.tokens) {\n const tokenError = validatePath(options.tokens);\n if (tokenError) {\n errors.push(`--tokens: ${tokenError}`);\n }\n }\n\n if (options.output) {\n const outputError = validatePath(options.output);\n if (outputError) {\n errors.push(`--output: ${outputError}`);\n }\n }\n\n if (options.generators) {\n const builtInGenerators = [\"tailwind\", \"figma\"];\n const generators = options.generators.split(\",\").map((g) => g.trim());\n for (const gen of generators) {\n // Check if it's a custom generator with path (name:path format)\n const colonIdx = gen.indexOf(\":\");\n if (colonIdx > 0) {\n // Custom generator: validate name and path are non-empty\n const name = gen.slice(0, colonIdx).trim();\n const pluginPath = gen.slice(colonIdx + 1).trim();\n if (!name) {\n errors.push(\n `--generators: Custom generator \"${gen}\" has an empty name`,\n );\n }\n if (!pluginPath) {\n errors.push(\n `--generators: Custom generator \"${name}\" is missing a path`,\n );\n }\n } else if (!builtInGenerators.includes(gen)) {\n // Not a built-in generator and not in name:path format\n errors.push(\n `--generators: Invalid generator \"${gen}\". Built-in options: ${builtInGenerators.join(\", \")}. For custom generators use \"name:./path/to/plugin.js\"`,\n );\n }\n }\n }\n\n return errors;\n}\n\n/**\n * Validates CLI flags for consumer init command.\n * @returns Array of error messages for invalid flags, empty if all valid.\n */\nexport function validateConsumerFlags(options: {\n repo?: string;\n files?: string;\n}): string[] {\n const errors: string[] = [];\n\n if (options.repo) {\n const repoError = validateRepo(options.repo);\n if (repoError) {\n errors.push(`--repo: ${repoError}`);\n }\n }\n\n if (options.files) {\n const mappings = options.files.split(\",\");\n for (const mapping of mappings) {\n if (!mapping.includes(\":\")) {\n errors.push(\n `--files: Invalid format \"${mapping}\". Use format: asset:destination`,\n );\n }\n }\n }\n\n return errors;\n}\n","import * as p from \"@clack/prompts\";\n\nimport { validatePath, validateRepo } from \"./validation\";\n\nexport interface ProducerWizardAnswers {\n generators: string[];\n tokens: string;\n output: string;\n workflow: boolean;\n}\n\nexport interface ConsumerWizardAnswers {\n repo: string;\n files: Record<string, string>;\n}\n\nexport type WizardMode = \"producer\" | \"consumer\";\n\n/**\n * Displays the intro banner for the wizard session.\n * Shows \"(DRY RUN)\" suffix when in dry-run mode.\n */\nexport function showIntro(dryRun = false): void {\n const suffix = dryRun ? \" (DRY RUN)\" : \"\";\n p.intro(`Clafoutis - GitOps Design Token Generator${suffix}`);\n}\n\n/**\n * Displays the outro message after wizard completion.\n */\nexport function showOutro(message: string): void {\n p.outro(message);\n}\n\n/**\n * Prompts user to select between producer and consumer mode.\n * @returns Selected mode, or null if user cancels with Ctrl+C.\n */\nexport async function selectMode(): Promise<WizardMode | null> {\n const mode = await p.select({\n message: \"What would you like to set up?\",\n options: [\n {\n value: \"producer\",\n label: \"Producer\",\n hint: \"I maintain a design system\",\n },\n {\n value: \"consumer\",\n label: \"Consumer\",\n hint: \"I consume tokens from a design system\",\n },\n ],\n });\n\n if (p.isCancel(mode)) {\n return null;\n }\n\n return mode as WizardMode;\n}\n\n/**\n * Runs the interactive wizard for producer setup.\n * Collects: generators to enable, token/output paths, and workflow preference.\n * Exits gracefully if user cancels at any point.\n */\nexport async function runProducerWizard(): Promise<ProducerWizardAnswers | null> {\n const answers = await p.group(\n {\n generators: () =>\n p.multiselect({\n message: \"Which generators would you like to enable?\",\n options: [\n { value: \"tailwind\", label: \"Tailwind CSS\", hint: \"recommended\" },\n { value: \"figma\", label: \"Figma Variables\" },\n ],\n required: true,\n initialValues: [\"tailwind\"],\n }),\n\n tokens: () =>\n p.text({\n message: \"Where are your design tokens located?\",\n placeholder: \"./tokens\",\n initialValue: \"./tokens\",\n validate: validatePath,\n }),\n\n output: () =>\n p.text({\n message: \"Where should generated files be output?\",\n placeholder: \"./build\",\n initialValue: \"./build\",\n validate: validatePath,\n }),\n\n workflow: () =>\n p.confirm({\n message: \"Create GitHub Actions workflow for auto-releases?\",\n initialValue: true,\n }),\n },\n {\n onCancel: () => {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n },\n },\n );\n\n return answers as ProducerWizardAnswers;\n}\n\n/**\n * Runs the interactive wizard for consumer setup.\n * Collects: source repository and file mappings (source -> destination).\n * Exits gracefully if user cancels at any point.\n */\nexport async function runConsumerWizard(): Promise<ConsumerWizardAnswers | null> {\n const repo = await p.text({\n message: \"GitHub repository (org/repo):\",\n placeholder: \"Acme/design-system\",\n validate: validateRepo,\n });\n\n if (p.isCancel(repo)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n const filesInput = await p.text({\n message: \"Which files do you want to sync? (comma-separated)\",\n placeholder: \"tailwind.base.css, tailwind.config.js\",\n initialValue: \"tailwind.base.css, tailwind.config.js\",\n });\n\n if (p.isCancel(filesInput)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n const fileNames = (filesInput as string)\n .split(\",\")\n .map((f) => f.trim())\n .filter(Boolean);\n\n const files: Record<string, string> = {};\n\n for (const fileName of fileNames) {\n const defaultDest = suggestDestination(fileName);\n const dest = await p.text({\n message: `Where should ${fileName} be saved?`,\n placeholder: defaultDest,\n initialValue: defaultDest,\n validate: validatePath,\n });\n\n if (p.isCancel(dest)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n files[fileName] = dest as string;\n }\n\n return {\n repo: repo as string,\n files,\n };\n}\n\n/**\n * Suggests a reasonable destination path based on file extension and name.\n * - tailwind.config files go to project root\n * - CSS/SCSS files go to src/styles/\n * - Other files go to project root\n */\nfunction suggestDestination(fileName: string): string {\n if (fileName.includes(\"tailwind.config\")) {\n return \"./tailwind.config.js\";\n }\n if (fileName.includes(\".css\")) {\n return `./src/styles/${fileName}`;\n }\n if (fileName.includes(\".scss\")) {\n return `./src/styles/${fileName}`;\n }\n return `./${fileName}`;\n}\n\n/**\n * Asks user if they want to run the init wizard when config is missing.\n * Used by generate/sync commands to offer guided setup.\n * @returns true if user wants to run the wizard, false otherwise.\n */\nexport async function offerWizard(\n configType: \"producer\" | \"consumer\",\n): Promise<boolean> {\n p.log.error(`Configuration not found: .clafoutis/${configType}.json`);\n\n const runWizard = await p.confirm({\n message: \"Would you like to create one now?\",\n initialValue: true,\n });\n\n if (p.isCancel(runWizard)) {\n p.cancel(\"Operation cancelled.\");\n process.exit(0);\n }\n\n return runWizard as boolean;\n}\n\n/**\n * Creates a spinner for showing progress during async operations.\n */\nexport function createSpinner(): ReturnType<typeof p.spinner> {\n return p.spinner();\n}\n\n/**\n * Log helpers that use @clack/prompts styling for consistent output.\n */\nexport const log = {\n info: (message: string) => p.log.info(message),\n success: (message: string) => p.log.success(message),\n warn: (message: string) => p.log.warn(message),\n error: (message: string) => p.log.error(message),\n step: (message: string) => p.log.step(message),\n message: (message: string) => p.log.message(message),\n};\n","import fs from \"fs/promises\";\n\nimport type { ClafoutisConfig, ProducerConfig } from \"../types\";\n\n/**\n * Reads and parses a consumer configuration file (.clafoutis.json).\n * Returns null if the file does not exist or cannot be parsed.\n */\nexport async function readConfig(\n configPath: string,\n): Promise<ClafoutisConfig | null> {\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n return JSON.parse(content) as ClafoutisConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Reads and parses a producer configuration file (clafoutis.config.json).\n * Returns null if the file does not exist or cannot be parsed.\n */\nexport async function readProducerConfig(\n configPath: string,\n): Promise<ProducerConfig | null> {\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n return JSON.parse(content) as ProducerConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Checks if a file exists at the given path.\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"required\": [\"repo\", \"version\", \"files\"],\n \"properties\": {\n \"repo\": {\n \"type\": \"string\",\n \"pattern\": \"^[\\\\w.-]+/[\\\\w.-]+$\",\n \"description\": \"GitHub repository in org/name format\"\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^(latest|v\\\\d+\\\\.\\\\d+\\\\.\\\\d+)$\",\n \"description\": \"Release tag (e.g., v1.0.0) or 'latest'\"\n },\n \"files\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"minProperties\": 1,\n \"description\": \"Mapping of release asset names to local file paths\"\n },\n \"postSync\": {\n \"type\": \"string\",\n \"description\": \"Optional command to run after sync\"\n }\n },\n \"additionalProperties\": false\n}\n","{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"required\": [\"tokens\", \"output\", \"generators\"],\n \"properties\": {\n \"tokens\": {\n \"type\": \"string\",\n \"description\": \"Path to tokens directory\"\n },\n \"output\": {\n \"type\": \"string\",\n \"description\": \"Output directory for generated files\"\n },\n \"generators\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [\n { \"type\": \"boolean\" },\n { \"type\": \"string\" }\n ]\n },\n \"description\": \"Generators to run (true for built-in, string path for custom)\"\n }\n },\n \"additionalProperties\": false\n}\n","import consumerSchema from \"../../schemas/consumer-config.json\";\nimport producerSchema from \"../../schemas/producer-config.json\";\nimport { validateConfig } from \"../cli/validation\";\n\n/**\n * Validates a consumer configuration object against the JSON schema.\n * Also warns about unknown or deprecated fields.\n * Throws a ClafoutisError if validation fails.\n */\nexport function validateConsumerConfig(config: unknown): void {\n validateConfig(\n config as Record<string, unknown>,\n consumerSchema,\n \".clafoutis/consumer.json\",\n );\n}\n\n/**\n * Validates a producer configuration object against the JSON schema.\n * Also warns about unknown or deprecated fields.\n * Throws a ClafoutisError if validation fails.\n */\nexport function validateProducerConfig(config: unknown): void {\n validateConfig(\n config as Record<string, unknown>,\n producerSchema,\n \".clafoutis/producer.json\",\n );\n}\n","/**\n * Returns the .gitignore content for producer repos.\n * Ignores build artifacts and CI-generated release assets.\n */\nexport function getProducerGitignore(): string {\n return `# Dependencies\nnode_modules/\n\n# Build output (regenerated by clafoutis generate)\nbuild/\n\n# CI-generated release assets\nrelease-assets/\n`;\n}\n\n/**\n * Returns the .gitignore content for consumer repos.\n * Only ignores the cache file.\n */\nexport function getConsumerGitignore(): string {\n return `# Clafoutis cache\n.clafoutis/cache\n`;\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Resolves the absolute path to the starter token templates directory.\n * Works in both dev (tsx) and built (dist/) contexts.\n */\nfunction getTokensDir(): string {\n // Dev: __dirname is src/templates/, tokens/ is adjacent\n const devPath = path.resolve(__dirname, \"tokens\");\n if (fs.existsSync(devPath)) return devPath;\n\n // Built: __dirname is dist/, templates/tokens/ is a sibling\n const distPath = path.resolve(__dirname, \"templates\", \"tokens\");\n if (fs.existsSync(distPath)) return distPath;\n\n throw new Error(\n `Starter token templates not found. Searched:\\n ${devPath}\\n ${distPath}`,\n );\n}\n\n/**\n * Recursively walks a directory and collects all .json files\n * with their relative paths and raw content.\n */\nfunction walkTokensDir(\n dir: string,\n base = \"\",\n): Array<{ path: string; content: string }> {\n const result: Array<{ path: string; content: string }> = [];\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const relPath = base ? path.join(base, entry.name) : entry.name;\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n result.push(...walkTokensDir(fullPath, relPath));\n } else if (entry.name.endsWith(\".json\")) {\n result.push({\n path: relPath,\n content: fs.readFileSync(fullPath, \"utf-8\"),\n });\n }\n }\n return result;\n}\n\n/**\n * Returns the JSON content for a starter token file.\n * @throws Error if fileName is not found in the templates directory.\n */\nexport function getStarterTokenContent(fileName: string): string {\n const tokensDir = getTokensDir();\n const filePath = path.resolve(tokensDir, fileName);\n\n // Guard against path traversal — filePath must remain inside tokensDir\n const relative = path.relative(tokensDir, filePath);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new Error(`Invalid token file path: ${fileName}`);\n }\n\n if (!fs.existsSync(filePath)) {\n throw new Error(`Unknown starter token file: ${fileName}`);\n }\n return fs.readFileSync(filePath, \"utf-8\");\n}\n\n/**\n * Returns all starter token files with their paths and JSON content.\n * Used during producer init to create the initial token structure.\n */\nexport function getAllStarterTokens(): Array<{\n path: string;\n content: string;\n}> {\n const tokensDir = getTokensDir();\n return walkTokensDir(tokensDir);\n}\n","/**\n * Returns the GitHub Actions workflow YAML for automatic token releases.\n * Triggers on push to main when tokens change, generates outputs, and creates a release.\n */\nexport function getWorkflowTemplate(): string {\n return `name: Design Token Release\n\non:\n push:\n branches: [main]\n paths:\n - 'tokens/**'\n\njobs:\n release:\n runs-on: ubuntu-latest\n permissions:\n contents: write\n\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n\n - uses: actions/setup-node@v4\n with:\n node-version: '22'\n\n - name: Install Clafoutis\n run: npm install -D @clafoutis/cli\n\n - name: Check token file formatting\n run: npx clafoutis format --tokens tokens --check\n\n - name: Generate tokens\n run: npx clafoutis generate\n\n - name: Get next version\n id: version\n run: |\n LATEST=$(git tag -l 'v*' | grep -E '^v[0-9]+\\\\.[0-9]+\\\\.[0-9]+$' | sort -V | tail -n1)\n if [ -z \"$LATEST\" ]; then\n echo \"version=1.0.0\" >> $GITHUB_OUTPUT\n else\n VERSION=\\${LATEST#v}\n IFS='.' read -r MAJOR MINOR PATCH <<< \"$VERSION\"\n PATCH=$((PATCH + 1))\n echo \"version=\\${MAJOR}.\\${MINOR}.\\${PATCH}\" >> $GITHUB_OUTPUT\n fi\n\n - name: Prepare release assets\n run: |\n mkdir -p release-assets\n while IFS= read -r -d '' file; do\n relative=\"\\${file#build/}\"\n flat_name=\"\\${relative//\\\\//.}\"\n target=\"release-assets/$flat_name\"\n if [ -e \"$target\" ]; then\n echo \"::error::Collision detected: '$relative' flattens to '$flat_name' which already exists\"\n exit 1\n fi\n cp \"$file\" \"$target\"\n done < <(find build -type f -print0)\n\n - name: Create Release\n uses: softprops/action-gh-release@v2\n with:\n tag_name: v\\${{ steps.version.outputs.version }}\n name: Design Tokens v\\${{ steps.version.outputs.version }}\n generate_release_notes: true\n files: release-assets/*\n env:\n GITHUB_TOKEN: \\${{ secrets.GITHUB_TOKEN }}\n`;\n}\n\n/**\n * Returns the standard path for the Clafoutis release workflow.\n */\nexport function getWorkflowPath(): string {\n return \".github/workflows/clafoutis-release.yml\";\n}\n","import * as p from \"@clack/prompts\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nimport {\n validateConsumerFlags,\n validateProducerFlags,\n} from \"../cli/validation\";\nimport {\n type ConsumerWizardAnswers,\n log,\n type ProducerWizardAnswers,\n runConsumerWizard,\n runProducerWizard,\n selectMode,\n showIntro,\n showOutro,\n} from \"../cli/wizard\";\nimport {\n getConsumerGitignore,\n getProducerGitignore,\n} from \"../templates/gitignore\";\nimport { getAllStarterTokens } from \"../templates/tokens\";\nimport { getWorkflowPath, getWorkflowTemplate } from \"../templates/workflow\";\nimport { fileExists } from \"../utils/config\";\nimport { ClafoutisError } from \"../utils/errors\";\n\nexport interface InitOptions {\n producer?: boolean;\n consumer?: boolean;\n repo?: string;\n tokens?: string;\n output?: string;\n generators?: string;\n workflow?: boolean;\n files?: string;\n force?: boolean;\n dryRun?: boolean;\n nonInteractive?: boolean;\n}\n\ninterface FileToCreate {\n path: string;\n content: string;\n description?: string;\n}\n\n/**\n * Parses and validates a comma-separated generators string.\n * Each entry can be:\n * - A built-in generator name: \"tailwind\", \"figma\"\n * - A custom generator with path: \"name:./path/to/plugin.js\"\n *\n * @param generatorsString - Comma-separated generators string\n * @returns Array of validated generator entries\n * @throws ClafoutisError if any entries are invalid\n */\nfunction parseGenerators(generatorsString: string): string[] {\n const entries = generatorsString.split(\",\").map((g) => g.trim());\n const invalidEntries: string[] = [];\n\n for (const entry of entries) {\n if (!entry) {\n invalidEntries.push(\"(empty entry - check for extra commas)\");\n continue;\n }\n\n const colonIdx = entry.indexOf(\":\");\n if (colonIdx === 0) {\n invalidEntries.push(`\"${entry}\" (missing generator name before \":\")`);\n } else if (colonIdx > 0) {\n const name = entry.slice(0, colonIdx).trim();\n const pluginPath = entry.slice(colonIdx + 1).trim();\n if (!name) {\n invalidEntries.push(`\"${entry}\" (empty generator name)`);\n }\n if (!pluginPath) {\n invalidEntries.push(`\"${entry}\" (missing path after \":\")`);\n }\n }\n }\n\n if (invalidEntries.length > 0) {\n throw new ClafoutisError(\n \"Invalid generator entries\",\n `The following entries are malformed:\\n - ${invalidEntries.join(\"\\n - \")}`,\n 'Use format \"tailwind,figma\" for built-ins or \"name:./path/to/plugin.js\" for custom generators',\n );\n }\n\n return entries.filter((e) => e.length > 0);\n}\n\n/**\n * Main init command handler.\n * Supports both interactive wizard and non-interactive CLI flag modes.\n * @throws ClafoutisError if both --producer and --consumer flags are set\n */\nexport async function initCommand(options: InitOptions): Promise<void> {\n // Reject ambiguous flag combinations early\n if (options.producer && options.consumer) {\n throw new ClafoutisError(\n \"Conflicting flags\",\n \"Cannot specify both --producer and --consumer\",\n \"Choose one: --producer for design system repos, --consumer for application repos\",\n );\n }\n\n const isInteractive = !options.nonInteractive && process.stdin.isTTY;\n const isDryRun = options.dryRun ?? false;\n\n if (isInteractive) {\n await runInteractiveInit(options, isDryRun);\n } else {\n await runNonInteractiveInit(options, isDryRun);\n }\n}\n\nasync function runInteractiveInit(\n options: InitOptions,\n isDryRun: boolean,\n): Promise<void> {\n showIntro(isDryRun);\n\n let mode: \"producer\" | \"consumer\";\n\n if (options.producer) {\n mode = \"producer\";\n } else if (options.consumer) {\n mode = \"consumer\";\n } else {\n const selectedMode = await selectMode();\n if (!selectedMode) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n mode = selectedMode;\n }\n\n if (mode === \"producer\") {\n const answers = await runProducerWizard();\n if (!answers) {\n return;\n }\n await createProducerConfig(answers, options.force ?? false, isDryRun);\n } else {\n const answers = await runConsumerWizard();\n if (!answers) {\n return;\n }\n await createConsumerConfig(answers, options.force ?? false, isDryRun);\n }\n\n if (isDryRun) {\n showOutro(\"No files were written. Remove --dry-run to apply changes.\");\n } else {\n showOutro(\"Setup complete!\");\n }\n}\n\nasync function runNonInteractiveInit(\n options: InitOptions,\n isDryRun: boolean,\n): Promise<void> {\n if (!options.producer && !options.consumer) {\n throw new ClafoutisError(\n \"Mode required\",\n \"In non-interactive mode, you must specify --producer or --consumer\",\n \"Add --producer or --consumer flag\",\n );\n }\n\n if (options.producer) {\n const errors = validateProducerFlags(options);\n if (errors.length > 0) {\n throw new ClafoutisError(\n \"Invalid flags\",\n errors.join(\"\\n\"),\n \"Fix the invalid flags and try again\",\n );\n }\n\n const answers: ProducerWizardAnswers = {\n generators: options.generators\n ? parseGenerators(options.generators)\n : [\"tailwind\"],\n tokens: options.tokens ?? \"./tokens\",\n output: options.output ?? \"./build\",\n workflow: options.workflow ?? true,\n };\n\n await createProducerConfig(answers, options.force ?? false, isDryRun);\n } else {\n const errors = validateConsumerFlags(options);\n if (errors.length > 0) {\n throw new ClafoutisError(\n \"Invalid flags\",\n errors.join(\"\\n\"),\n \"Fix the invalid flags and try again\",\n );\n }\n\n if (!options.repo) {\n throw new ClafoutisError(\n \"Repository required\",\n \"In non-interactive mode, --repo is required for consumer setup\",\n \"Add --repo=org/repo-name flag\",\n );\n }\n\n const files: Record<string, string> = {};\n if (options.files) {\n for (const mapping of options.files.split(\",\")) {\n const colonIdx = mapping.indexOf(\":\");\n if (colonIdx === -1) {\n throw new ClafoutisError(\n \"Invalid file mapping\",\n `Mapping \"${mapping.trim()}\" is missing a colon separator`,\n 'Use the format \"source:destination\" (e.g., \"tokens.css:./src/styles/tokens.css\")',\n );\n }\n\n const source = mapping.slice(0, colonIdx).trim();\n const dest = mapping.slice(colonIdx + 1).trim();\n\n if (!source) {\n throw new ClafoutisError(\n \"Invalid file mapping\",\n `Mapping \"${mapping.trim()}\" has an empty source`,\n 'Provide a valid asset name before the colon (e.g., \"tokens.css:./path\")',\n );\n }\n\n if (!dest) {\n throw new ClafoutisError(\n \"Invalid file mapping\",\n `Mapping \"${mapping.trim()}\" has an empty destination`,\n 'Provide a valid path after the colon (e.g., \"tokens.css:./path\")',\n );\n }\n\n files[source] = dest;\n }\n } else {\n files[\"tailwind.base.css\"] = \"./src/styles/base.css\";\n files[\"tailwind.config.js\"] = \"./tailwind.config.js\";\n }\n\n const answers: ConsumerWizardAnswers = {\n repo: options.repo,\n files,\n };\n\n await createConsumerConfig(answers, options.force ?? false, isDryRun);\n }\n}\n\nasync function createProducerConfig(\n answers: ProducerWizardAnswers,\n force: boolean,\n dryRun: boolean,\n): Promise<void> {\n const configPath = \".clafoutis/producer.json\";\n\n if (!force && (await fileExists(configPath))) {\n throw new ClafoutisError(\n \"Configuration already exists\",\n configPath,\n \"Use --force to overwrite the existing configuration\",\n );\n }\n\n const generators: Record<string, boolean | string> = {};\n for (const entry of answers.generators) {\n const colonIdx = entry.indexOf(\":\");\n if (colonIdx > 0) {\n const name = entry.slice(0, colonIdx).trim();\n const pluginPath = entry.slice(colonIdx + 1).trim();\n generators[name] = pluginPath;\n } else {\n generators[entry] = true;\n }\n }\n\n const config = {\n tokens: answers.tokens,\n output: answers.output,\n generators,\n };\n\n const filesToCreate: FileToCreate[] = [\n {\n path: configPath,\n content: JSON.stringify(config, null, 2) + \"\\n\",\n description: `tokens: \"${answers.tokens}\", output: \"${answers.output}\"`,\n },\n ];\n\n const starterTokens = getAllStarterTokens();\n for (const token of starterTokens) {\n const tokenPath = path.join(answers.tokens, token.path);\n if (!force && (await fileExists(tokenPath))) {\n continue;\n }\n filesToCreate.push({\n path: tokenPath,\n content: token.content,\n description: \"Starter token template\",\n });\n }\n\n if (answers.workflow) {\n const workflowPath = getWorkflowPath();\n if (force || !(await fileExists(workflowPath))) {\n filesToCreate.push({\n path: workflowPath,\n content: getWorkflowTemplate(),\n description: \"Auto-release workflow on push to main\",\n });\n }\n }\n\n // Add .gitignore for producer repos\n if (force || !(await fileExists(\".gitignore\"))) {\n filesToCreate.push({\n path: \".gitignore\",\n content: getProducerGitignore(),\n description: \"Ignore build artifacts and release-assets\",\n });\n }\n\n if (dryRun) {\n showDryRunOutput(filesToCreate);\n } else {\n await writeFiles(filesToCreate);\n showNextSteps(\"producer\", answers);\n }\n}\n\nasync function createConsumerConfig(\n answers: ConsumerWizardAnswers,\n force: boolean,\n dryRun: boolean,\n): Promise<void> {\n const configPath = \".clafoutis/consumer.json\";\n\n if (!force && (await fileExists(configPath))) {\n throw new ClafoutisError(\n \"Configuration already exists\",\n configPath,\n \"Use --force to overwrite the existing configuration\",\n );\n }\n\n const config = {\n repo: answers.repo,\n version: \"latest\",\n files: answers.files,\n };\n\n const filesToCreate: FileToCreate[] = [\n {\n path: configPath,\n content: JSON.stringify(config, null, 2) + \"\\n\",\n description: `repo: \"${answers.repo}\"`,\n },\n ];\n\n // Add .gitignore entry for consumer repos (append if exists)\n const gitignorePath = \".gitignore\";\n const consumerIgnore = getConsumerGitignore();\n if (await fileExists(gitignorePath)) {\n // Check if cache is already ignored\n const existingContent = await fs.readFile(gitignorePath, \"utf-8\");\n if (!existingContent.includes(\".clafoutis/cache\")) {\n filesToCreate.push({\n path: gitignorePath,\n content: existingContent.trimEnd() + \"\\n\\n\" + consumerIgnore,\n description: \"Append .clafoutis/cache to existing .gitignore\",\n });\n }\n } else {\n filesToCreate.push({\n path: gitignorePath,\n content: consumerIgnore,\n description: \"Ignore .clafoutis/cache\",\n });\n }\n\n if (dryRun) {\n showDryRunOutput(filesToCreate);\n } else {\n await writeFiles(filesToCreate);\n showNextSteps(\"consumer\", answers);\n }\n}\n\nfunction showDryRunOutput(files: FileToCreate[]): void {\n log.message(\"\");\n log.step(\"Would create the following files:\");\n log.message(\"\");\n\n for (const file of files) {\n log.message(` ${file.path}`);\n if (file.description) {\n log.message(` └─ ${file.description}`);\n }\n }\n\n log.message(\"\");\n}\n\nasync function writeFiles(files: FileToCreate[]): Promise<void> {\n for (const file of files) {\n const dir = path.dirname(file.path);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(file.path, file.content);\n log.success(`Created ${file.path}`);\n }\n}\n\nfunction showNextSteps(\n mode: \"producer\" | \"consumer\",\n answers: ProducerWizardAnswers | ConsumerWizardAnswers,\n): void {\n log.message(\"\");\n log.step(\"Next steps:\");\n\n if (mode === \"producer\") {\n const producerAnswers = answers as ProducerWizardAnswers;\n log.message(\n ` 1. Edit ${producerAnswers.tokens}/colors/primitives.json with your design tokens`,\n );\n if (producerAnswers.workflow) {\n log.message(\n \" 2. Push to GitHub - the workflow will generate outputs and create a release automatically\",\n );\n } else {\n log.message(\" 2. Run: npx clafoutis generate\");\n log.message(\" 3. Push to GitHub to share your design system\");\n }\n } else {\n log.message(\" 1. Run: npx clafoutis sync\");\n }\n}\n","import { generate as figmaGenerate } from \"@clafoutis/generators/figma\";\nimport { generate as tailwindGenerate } from \"@clafoutis/generators/tailwind\";\nimport { logger } from \"@clafoutis/shared\";\nimport path from \"path\";\nimport StyleDictionary from \"style-dictionary\";\nimport { register as registerTsx } from \"tsx/esm/api\";\nimport { pathToFileURL } from \"url\";\n\nimport { offerWizard } from \"../cli/wizard\";\nimport type { GeneratorContext, GeneratorPlugin } from \"../types\";\nimport { fileExists, readProducerConfig } from \"../utils/config\";\nimport {\n ClafoutisError,\n configNotFoundError,\n generatorNotFoundError,\n pluginLoadError,\n tokensDirNotFoundError,\n} from \"../utils/errors\";\nimport { validateProducerConfig } from \"../utils/validate\";\nimport { initCommand } from \"./init\";\n\ninterface GenerateOptions {\n config?: string;\n tailwind?: boolean;\n figma?: boolean;\n output?: string;\n dryRun?: boolean;\n}\n\ninterface GeneratorModule {\n generate: GeneratorPlugin;\n}\n\n/**\n * Loads a generator plugin from a file path.\n * Supports both JavaScript and TypeScript files.\n * Resolves relative paths against the current working directory.\n */\nasync function loadPlugin(pluginPath: string): Promise<GeneratorModule> {\n const absolutePath = path.resolve(process.cwd(), pluginPath);\n\n if (pluginPath.endsWith(\".ts\")) {\n registerTsx();\n }\n\n // Dynamic import required here: loads user-provided plugin files by path at runtime\n return import(pathToFileURL(absolutePath).href);\n}\n\n/**\n * Main generate command handler.\n * Reads configuration, validates it, and runs enabled generators.\n */\nexport async function generateCommand(options: GenerateOptions): Promise<void> {\n const configPath = options.config || \".clafoutis/producer.json\";\n\n let config = await readProducerConfig(configPath);\n\n if (!config) {\n if (await fileExists(configPath)) {\n throw new ClafoutisError(\n \"Invalid configuration\",\n `Could not parse ${configPath}`,\n \"Ensure the file contains valid JSON\",\n );\n }\n\n if (process.stdin.isTTY) {\n const shouldRunWizard = await offerWizard(\"producer\");\n if (shouldRunWizard) {\n await initCommand({ producer: true });\n config = await readProducerConfig(configPath);\n if (!config) {\n throw configNotFoundError(configPath, false);\n }\n } else {\n throw configNotFoundError(configPath, false);\n }\n } else {\n throw configNotFoundError(configPath, false);\n }\n }\n\n validateProducerConfig(config);\n\n // Merge CLI flags with existing generators, preserving custom plugins\n if (options.tailwind !== undefined || options.figma !== undefined) {\n config = {\n ...config,\n generators: {\n ...(config.generators || {}),\n ...(options.tailwind !== undefined && { tailwind: options.tailwind }),\n ...(options.figma !== undefined && { figma: options.figma }),\n },\n };\n }\n\n if (options.output) {\n config.output = options.output;\n }\n\n // Resolve paths relative to current working directory (project root)\n const tokensDir = path.resolve(process.cwd(), config.tokens || \"./tokens\");\n const outputDir = path.resolve(process.cwd(), config.output || \"./build\");\n\n if (!(await fileExists(tokensDir))) {\n throw tokensDirNotFoundError(tokensDir);\n }\n\n // Use the same default for both dry-run and actual execution\n const generators = config.generators || { tailwind: true, figma: true };\n\n if (options.dryRun) {\n logger.info(\"[dry-run] Would read tokens from: \" + tokensDir);\n logger.info(\"[dry-run] Would write to: \" + outputDir);\n for (const [name, value] of Object.entries(generators)) {\n if (value !== false) {\n const type = typeof value === \"string\" ? \"custom\" : \"built-in\";\n logger.info(`[dry-run] Would run generator: ${name} (${type})`);\n }\n }\n return;\n }\n\n logger.info(`Tokens: ${tokensDir}`);\n logger.info(`Output: ${outputDir}`);\n\n let hadFailure = false;\n\n for (const [name, value] of Object.entries(generators)) {\n if (value === false) continue;\n\n logger.info(`Running ${name} generator...`);\n\n try {\n let generatorModule: GeneratorModule;\n\n if (typeof value === \"string\") {\n try {\n generatorModule = await loadPlugin(value);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n throw pluginLoadError(value, errorMessage);\n }\n\n if (typeof generatorModule.generate !== \"function\") {\n throw pluginLoadError(\n value,\n 'Module does not export a \"generate\" function',\n );\n }\n } else {\n // Built-in generators from @clafoutis/generators package\n const builtInGenerators: Record<string, GeneratorModule> = {\n tailwind: { generate: () => tailwindGenerate() },\n figma: { generate: () => figmaGenerate() },\n };\n\n if (!builtInGenerators[name]) {\n throw generatorNotFoundError(name);\n }\n\n generatorModule = builtInGenerators[name];\n }\n\n const context: GeneratorContext = {\n tokensDir,\n outputDir: path.join(outputDir, name),\n config,\n StyleDictionary,\n };\n await generatorModule.generate(context);\n\n logger.success(`${name} complete`);\n } catch (err) {\n if (err instanceof ClafoutisError) {\n throw err;\n }\n logger.error(`${name} failed: ${err}`);\n hadFailure = true;\n }\n }\n\n if (hadFailure) {\n throw new ClafoutisError(\n \"Generation failed\",\n \"One or more generators failed\",\n \"Check the error messages above and fix the issues\",\n );\n }\n\n logger.success(\"Generation complete\");\n}\n","import fs from \"fs/promises\";\n\nconst CACHE_DIR = \".clafoutis\";\nconst CACHE_FILE = `${CACHE_DIR}/cache`;\n\n/**\n * Reads the cached version from .clafoutis/cache file.\n * Returns null if the cache file does not exist.\n * Rethrows other errors (permissions, corruption, etc.).\n */\nexport async function readCache(): Promise<string | null> {\n try {\n return (await fs.readFile(CACHE_FILE, \"utf-8\")).trim();\n } catch (err: unknown) {\n if (\n err instanceof Error &&\n (err as NodeJS.ErrnoException).code === \"ENOENT\"\n ) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Writes the current version to the .clafoutis/cache file.\n * Creates the .clafoutis directory if it doesn't exist.\n */\nexport async function writeCache(version: string): Promise<void> {\n await fs.mkdir(CACHE_DIR, { recursive: true });\n await fs.writeFile(CACHE_FILE, version);\n}\n","import { logger } from \"@clafoutis/shared\";\n\nimport type { ClafoutisConfig } from \"../types\";\nimport {\n authRequiredError,\n ClafoutisError,\n releaseNotFoundError,\n} from \"./errors\";\n\ninterface GitHubRelease {\n tag_name: string;\n assets: Array<{\n name: string;\n url: string;\n browser_download_url: string;\n }>;\n}\n\nexport interface DownloadResult {\n files: Map<string, string>;\n resolvedTag: string;\n}\n\n/**\n * Downloads release assets from a GitHub repository.\n * Fetches the release metadata and then downloads each requested file.\n * Handles \"latest\" version by resolving to the actual tag name.\n *\n * @param config - Consumer configuration containing repo, version, and files to download\n * @returns Object containing downloaded files and the resolved tag name\n * @throws ClafoutisError if any requested assets are missing or fail to download\n */\nexport async function downloadRelease(\n config: ClafoutisConfig,\n): Promise<DownloadResult> {\n const token = process.env.CLAFOUTIS_REPO_TOKEN;\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github.v3+json\",\n \"User-Agent\": \"clafoutis-cli\",\n };\n\n if (token) {\n headers[\"Authorization\"] = `token ${token}`;\n }\n\n // Use /releases/latest endpoint for \"latest\", otherwise use /releases/tags/{tag}\n const isLatest = config.version === \"latest\";\n const releaseUrl = isLatest\n ? `https://api.github.com/repos/${config.repo}/releases/latest`\n : `https://api.github.com/repos/${config.repo}/releases/tags/${config.version}`;\n\n const releaseRes = await fetch(releaseUrl, { headers });\n\n if (!releaseRes.ok) {\n if (releaseRes.status === 404) {\n throw releaseNotFoundError(config.version, config.repo);\n } else if (releaseRes.status === 401 || releaseRes.status === 403) {\n throw authRequiredError();\n } else {\n logger.error(`GitHub API error: ${releaseRes.status}`);\n process.exit(1);\n }\n }\n\n const release = (await releaseRes.json()) as GitHubRelease;\n const resolvedTag = release.tag_name;\n\n if (isLatest) {\n logger.info(`Resolved \"latest\" to ${resolvedTag}`);\n }\n const files = new Map<string, string>();\n const missingAssets: string[] = [];\n const failedDownloads: string[] = [];\n\n for (const assetName of Object.keys(config.files)) {\n const asset = release.assets.find((a) => a.name === assetName);\n\n if (!asset) {\n missingAssets.push(assetName);\n continue;\n }\n\n logger.info(`Downloading ${assetName}...`);\n\n const downloadHeaders = { ...headers, Accept: \"application/octet-stream\" };\n const fileRes = await fetch(asset.url, { headers: downloadHeaders });\n\n if (!fileRes.ok) {\n failedDownloads.push(assetName);\n continue;\n }\n\n files.set(assetName, await fileRes.text());\n }\n\n const errors: string[] = [];\n if (missingAssets.length > 0) {\n errors.push(`Assets not found in release: ${missingAssets.join(\", \")}`);\n }\n if (failedDownloads.length > 0) {\n errors.push(`Failed to download: ${failedDownloads.join(\", \")}`);\n }\n\n if (errors.length > 0) {\n const availableAssets = release.assets.map((a) => a.name).join(\", \");\n throw new ClafoutisError(\n \"Download failed\",\n errors.join(\"\\n\"),\n `Available assets in ${resolvedTag}: ${availableAssets || \"none\"}`,\n );\n }\n\n return { files, resolvedTag };\n}\n","import { logger } from \"@clafoutis/shared\";\nimport { spawn } from \"child_process\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nimport { offerWizard } from \"../cli/wizard\";\nimport type { ClafoutisConfig } from \"../types\";\nimport { readCache, writeCache } from \"../utils/cache\";\nimport { fileExists, readConfig } from \"../utils/config\";\nimport { ClafoutisError, configNotFoundError } from \"../utils/errors\";\nimport { downloadRelease } from \"../utils/github\";\nimport { validateConsumerConfig } from \"../utils/validate\";\nimport { initCommand } from \"./init\";\n\ninterface SyncOptions {\n force?: boolean;\n config?: string;\n dryRun?: boolean;\n}\n\n/**\n * Writes downloaded files to the configured output paths.\n */\nasync function writeOutput(\n config: ClafoutisConfig,\n files: Map<string, string>,\n): Promise<void> {\n for (const [assetName, content] of files) {\n const configPath = config.files[assetName];\n if (!configPath) continue;\n\n const outputPath = path.resolve(process.cwd(), configPath);\n\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, content);\n logger.success(`Written: ${outputPath}`);\n }\n}\n\n/**\n * Main sync command handler.\n * Downloads design tokens from a GitHub release and writes them to configured paths.\n */\nexport async function syncCommand(options: SyncOptions): Promise<void> {\n const configPath = options.config || \".clafoutis/consumer.json\";\n\n let config = await readConfig(configPath);\n if (!config) {\n if (await fileExists(configPath)) {\n throw new ClafoutisError(\n \"Invalid configuration\",\n `Could not parse ${configPath}`,\n \"Ensure the file contains valid JSON\",\n );\n }\n\n if (process.stdin.isTTY) {\n const shouldRunWizard = await offerWizard(\"consumer\");\n if (shouldRunWizard) {\n await initCommand({ consumer: true });\n config = await readConfig(configPath);\n if (!config) {\n throw configNotFoundError(configPath, true);\n }\n } else {\n throw configNotFoundError(configPath, true);\n }\n } else {\n throw configNotFoundError(configPath, true);\n }\n }\n\n validateConsumerConfig(config);\n\n const cachedVersion = await readCache();\n const isLatest = config.version === \"latest\";\n\n logger.info(`Repo: ${config.repo}`);\n logger.info(`Pinned: ${config.version}`);\n logger.info(`Cached: ${cachedVersion || \"none\"}`);\n\n if (options.dryRun) {\n logger.info(\n \"[dry-run] Would download from: \" + config.repo + \" \" + config.version,\n );\n for (const [assetName, outputPath] of Object.entries(config.files)) {\n logger.info(`[dry-run] ${assetName} → ${outputPath}`);\n }\n return;\n }\n\n const resolveOutputPaths = () =>\n Object.values(config.files).map((p) => path.resolve(process.cwd(), p));\n\n if (!isLatest && !options.force && config.version === cachedVersion) {\n const outputPaths = resolveOutputPaths();\n const existsResults = await Promise.all(\n outputPaths.map((p) => fileExists(p)),\n );\n const allOutputsExist = existsResults.every((exists) => exists);\n if (allOutputsExist) {\n logger.success(`Already at ${config.version} - no sync needed`);\n return;\n }\n }\n\n logger.warn(`Syncing ${config.version}...`);\n\n const { files, resolvedTag } = await downloadRelease(config);\n\n // For \"latest\", check if we already have this resolved version cached\n if (isLatest && !options.force && resolvedTag === cachedVersion) {\n const outputPaths = resolveOutputPaths();\n const existsResults = await Promise.all(\n outputPaths.map((p) => fileExists(p)),\n );\n const allOutputsExist = existsResults.every((exists) => exists);\n if (allOutputsExist) {\n logger.success(`Already at ${resolvedTag} (latest) - no sync needed`);\n return;\n }\n }\n\n await writeOutput(config, files);\n\n // Cache the resolved tag, not \"latest\"\n await writeCache(resolvedTag);\n\n logger.success(`Synced to ${resolvedTag}`);\n\n if (config.postSync) {\n await runPostSync(config.postSync);\n }\n}\n\n/**\n * Executes the postSync command safely using shell spawn.\n * Awaits completion and handles errors with proper logging of stdout/stderr.\n * Uses the system shell to parse the command string, which is necessary\n * for commands like \"npx prettier --write ./src/styles/base.css\".\n *\n * @param command - The shell command string to execute\n * @throws ClafoutisError if the command fails or exits with non-zero code\n */\nasync function runPostSync(command: string): Promise<void> {\n logger.info(`Running postSync: ${command}`);\n\n // Determine the shell based on platform\n const isWindows = process.platform === \"win32\";\n const shell = isWindows ? \"cmd.exe\" : \"/bin/sh\";\n const shellArgs = isWindows ? [\"/c\", command] : [\"-c\", command];\n\n return new Promise((resolve, reject) => {\n const child = spawn(shell, shellArgs, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n env: process.env,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n\n child.stderr?.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n\n child.on(\"error\", (err: Error) => {\n reject(\n new ClafoutisError(\n \"postSync failed\",\n `Failed to spawn command: ${err.message}`,\n \"Check that the command is valid and executable\",\n ),\n );\n });\n\n child.on(\"close\", (code: number | null) => {\n if (code === 0) {\n if (stdout.trim()) {\n logger.info(stdout.trim());\n }\n logger.success(\"postSync completed\");\n resolve();\n } else {\n const output = [stdout, stderr].filter(Boolean).join(\"\\n\").trim();\n logger.error(`postSync output:\\n${output || \"(no output)\"}`);\n reject(\n new ClafoutisError(\n \"postSync failed\",\n `Command exited with code ${code}`,\n \"Review the command output above and fix any issues\",\n ),\n );\n }\n });\n });\n}\n","import * as p from \"@clack/prompts\";\nimport { Command } from \"commander\";\n\nimport { formatCommand } from \"./commands/format\";\nimport { generateCommand } from \"./commands/generate\";\nimport { initCommand } from \"./commands/init\";\nimport { syncCommand } from \"./commands/sync\";\nimport { ClafoutisError } from \"./utils/errors\";\n\nconst program = new Command();\n\n/**\n * Formats and displays an error using @clack/prompts styling when in TTY,\n * otherwise falls back to plain text formatting.\n */\nfunction displayError(err: ClafoutisError): void {\n if (process.stdin.isTTY) {\n p.log.error(`${err.title}: ${err.detail}`);\n if (err.suggestion) {\n p.log.info(`Suggestion: ${err.suggestion}`);\n }\n } else {\n console.error(err.format());\n }\n}\n\n/**\n * Wraps a command action with error handling for ClafoutisError instances.\n */\nfunction withErrorHandling<T>(\n fn: (options: T) => void | Promise<void>,\n): (options: T) => Promise<void> {\n return async (options: T): Promise<void> => {\n try {\n await fn(options);\n } catch (err) {\n if (err instanceof ClafoutisError) {\n displayError(err);\n process.exit(1);\n }\n throw err;\n }\n };\n}\n\n/**\n * Handles unexpected errors (both sync and async) with consistent formatting.\n */\nfunction handleUnexpectedError(err: unknown): void {\n if (err instanceof ClafoutisError) {\n displayError(err);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n if (process.stdin.isTTY) {\n p.log.error(`Unexpected error: ${message}`);\n p.log.info(\n \"Please report this issue at: https://github.com/Dessert-Labs/clafoutis/issues\",\n );\n } else {\n console.error(`\\nUnexpected error: ${message}\\n`);\n console.error(\n \"Please report this issue at: https://github.com/Dessert-Labs/clafoutis/issues\",\n );\n }\n }\n process.exit(1);\n}\n\nprocess.on(\"uncaughtException\", handleUnexpectedError);\n\nprocess.on(\"unhandledRejection\", (reason: unknown) => {\n handleUnexpectedError(reason);\n});\n\nprogram\n .name(\"clafoutis\")\n .description(\"GitOps powered design system - generate and sync design tokens\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"generate\")\n .description(\"Generate platform outputs from design tokens (for producers)\")\n .option(\n \"-c, --config <path>\",\n \"Path to config file\",\n \".clafoutis/producer.json\",\n )\n .option(\"--tailwind\", \"Generate Tailwind output\")\n .option(\"--figma\", \"Generate Figma variables\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./build\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .action(withErrorHandling(generateCommand));\n\nprogram\n .command(\"sync\")\n .description(\"Sync design tokens from GitHub Release (for consumers)\")\n .option(\"-f, --force\", \"Force sync even if versions match\")\n .option(\n \"-c, --config <path>\",\n \"Path to config file\",\n \".clafoutis/consumer.json\",\n )\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .action(withErrorHandling(syncCommand));\n\nprogram\n .command(\"init\")\n .description(\"Initialize Clafoutis configuration\")\n .option(\"--producer\", \"Set up as a design token producer\")\n .option(\"--consumer\", \"Set up as a design token consumer\")\n .option(\"-r, --repo <repo>\", \"GitHub repo for consumer mode (org/name)\")\n .option(\"-t, --tokens <path>\", \"Token directory path (default: ./tokens)\")\n .option(\"-o, --output <path>\", \"Output directory path (default: ./build)\")\n .option(\n \"-g, --generators <list>\",\n \"Comma-separated generators: tailwind, figma\",\n )\n .option(\"--workflow\", \"Create GitHub Actions workflow (default: true)\")\n .option(\"--no-workflow\", \"Skip GitHub Actions workflow\")\n .option(\n \"--files <mapping>\",\n \"File mappings for consumer: asset:dest,asset:dest\",\n )\n .option(\"--force\", \"Overwrite existing configuration\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .option(\"--non-interactive\", \"Skip prompts, use defaults or flags\")\n .action(withErrorHandling(initCommand));\n\nprogram\n .command(\"format\")\n .description(\"Format token JSON files for consistent formatting\")\n .option(\"-t, --tokens <path>\", \"Token directory path\", \"./tokens\")\n .option(\n \"--check\",\n \"Check formatting without modifying files (fails if unformatted)\",\n )\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .action(withErrorHandling(formatCommand));\n\nprogram.parse();\n"]}
1
+ {"version":3,"sources":["../src/utils/errors.ts","../src/utils/cwd.ts","../src/commands/format.ts","../src/cli/validation.ts","../src/cli/wizard.ts","../src/utils/config.ts","../schemas/consumer-config.json","../schemas/producer-config.json","../src/utils/validate.ts","../src/templates/gitignore.ts","../src/templates/tokens.ts","../src/templates/workflow.ts","../src/commands/init.ts","../src/commands/generate.ts","../src/utils/cache.ts","../src/utils/github.ts","../src/commands/sync.ts","../src/index.ts"],"names":["path","p","log","fs","__filename","__dirname","p3","registerTsx","logger","tailwindGenerate","figmaGenerate","p4"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * ANSI color codes for terminal output formatting.\n */\nconst colors = {\n red: (s: string) => `\\x1b[31m${s}\\x1b[0m`,\n cyan: (s: string) => `\\x1b[36m${s}\\x1b[0m`,\n yellow: (s: string) => `\\x1b[33m${s}\\x1b[0m`,\n};\n\n/**\n * Custom error class for Clafoutis CLI errors.\n * Provides structured error messages with actionable suggestions.\n */\nexport class ClafoutisError extends Error {\n constructor(\n public title: string,\n public detail: string,\n public suggestion?: string,\n ) {\n super(`${title}: ${detail}`);\n this.name = \"ClafoutisError\";\n }\n\n /**\n * Formats the error for display in the terminal with colors and structure.\n */\n format(): string {\n let output = `\\n${colors.red(\"Error:\")} ${this.title}\\n`;\n output += `\\n${this.detail}\\n`;\n if (this.suggestion) {\n output += `\\n${colors.cyan(\"Suggestion:\")} ${this.suggestion}\\n`;\n }\n return output;\n }\n}\n\n/**\n * Creates a ClafoutisError for when a configuration file is not found.\n */\nexport function configNotFoundError(\n configPath: string,\n isConsumer: boolean,\n): ClafoutisError {\n return new ClafoutisError(\n \"Configuration not found\",\n `Could not find ${configPath}`,\n `Run: npx clafoutis init --${isConsumer ? \"consumer\" : \"producer\"}`,\n );\n}\n\n/**\n * Creates a ClafoutisError for invalid repository format.\n */\nexport function invalidRepoError(repo: string): ClafoutisError {\n return new ClafoutisError(\n \"Invalid repository format\",\n `\"${repo}\" is not a valid GitHub repository`,\n 'Use format: org/repo (e.g., \"YourOrg/design-system\")',\n );\n}\n\n/**\n * Creates a ClafoutisError for when a GitHub release is not found.\n */\nexport function releaseNotFoundError(\n version: string,\n repo: string,\n): ClafoutisError {\n return new ClafoutisError(\n \"Release not found\",\n `Version ${version} does not exist in ${repo}`,\n `Check available releases: gh release list -R ${repo}`,\n );\n}\n\n/**\n * Creates a ClafoutisError for when GitHub authentication is required.\n */\nexport function authRequiredError(): ClafoutisError {\n return new ClafoutisError(\n \"Authentication required\",\n \"CLAFOUTIS_REPO_TOKEN is required for private repositories\",\n \"Set the environment variable: export CLAFOUTIS_REPO_TOKEN=ghp_xxx\",\n );\n}\n\n/**\n * Creates a ClafoutisError for when a built-in generator is not found.\n */\nexport function generatorNotFoundError(name: string): ClafoutisError {\n return new ClafoutisError(\n \"Generator not found\",\n `Built-in generator \"${name}\" does not exist`,\n \"Available generators: tailwind, figma\",\n );\n}\n\n/**\n * Creates a ClafoutisError for when a plugin fails to load.\n */\nexport function pluginLoadError(\n pluginPath: string,\n errorMessage: string,\n): ClafoutisError {\n return new ClafoutisError(\n \"Plugin load failed\",\n `Could not load generator from ${pluginPath}: ${errorMessage}`,\n 'Ensure the file exports a \"generate\" function',\n );\n}\n\n/**\n * Creates a ClafoutisError for when the tokens directory is missing.\n */\nexport function tokensDirNotFoundError(tokensDir: string): ClafoutisError {\n return new ClafoutisError(\n \"Tokens directory not found\",\n `Directory \"${tokensDir}\" does not exist`,\n \"Create the directory and add token JSON files\",\n );\n}\n\n/**\n * Creates a ClafoutisError for when a config file already exists.\n */\nexport function configExistsError(configPath: string): ClafoutisError {\n return new ClafoutisError(\n \"Configuration already exists\",\n configPath,\n \"Use --force to overwrite the existing configuration\",\n );\n}\n\n/**\n * Creates a ClafoutisError for network/fetch failures.\n */\nexport function networkError(url: string, reason: string): ClafoutisError {\n return new ClafoutisError(\n \"Network error\",\n `Failed to fetch ${url}: ${reason}`,\n \"Check your network connection and ensure the repository is accessible\",\n );\n}\n\n/**\n * Creates a ClafoutisError for invalid CLI flag combinations.\n */\nexport function invalidFlagsError(errors: string[]): ClafoutisError {\n return new ClafoutisError(\n \"Invalid flags\",\n errors.join(\"\\n\"),\n \"Fix the invalid flags and try again\",\n );\n}\n","import path from \"path\";\n\nimport { ClafoutisError } from \"./errors\";\n\n/**\n * Resolves the effective command working directory.\n * Uses process.cwd() when no --cwd override is provided.\n */\nexport function resolveCommandCwd(cwdOverride?: string): string {\n const cwd = cwdOverride?.trim() ? cwdOverride : process.cwd();\n return path.resolve(cwd);\n}\n\n/**\n * Resolves a path against command cwd when relative.\n */\nexport function resolveInCwd(commandCwd: string, targetPath: string): string {\n return path.isAbsolute(targetPath)\n ? path.resolve(targetPath)\n : path.resolve(commandCwd, targetPath);\n}\n\n/**\n * Converts an absolute path to a cwd-relative display path when possible.\n */\nexport function displayPath(commandCwd: string, absolutePath: string): string {\n const rel = path.relative(commandCwd, absolutePath);\n return rel && !rel.startsWith(\"..\") ? rel : absolutePath;\n}\n\n/**\n * Ensures cwd override is not empty whitespace when provided.\n */\nexport function validateCwdOption(cwdOverride?: string): void {\n if (cwdOverride !== undefined && cwdOverride.trim() === \"\") {\n throw new ClafoutisError(\n \"Invalid --cwd value\",\n \"--cwd cannot be empty\",\n \"Provide a valid directory path, for example: --cwd ./packages/design-system\",\n );\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { logger } from \"@clafoutis/shared\";\n\nimport {\n resolveCommandCwd,\n resolveInCwd,\n validateCwdOption,\n} from \"../utils/cwd\";\nimport { tokensDirNotFoundError } from \"../utils/errors\";\n\ninterface FormatOptions {\n tokens?: string;\n check?: boolean;\n dryRun?: boolean;\n cwd?: string;\n}\n\n/**\n * Recursively loads all JSON token files from a directory.\n */\nfunction loadTokenFiles(\n dirPath: string,\n): Array<{ relativePath: string; fullPath: string; content: string }> {\n const files: Array<{\n relativePath: string;\n fullPath: string;\n content: string;\n }> = [];\n\n function walk(dir: string, prefix: string): void {\n if (!fs.existsSync(dir)) {\n return;\n }\n\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;\n\n if (entry.isDirectory()) {\n walk(fullPath, relativePath);\n } else if (entry.name.endsWith(\".json\")) {\n try {\n const content = fs.readFileSync(fullPath, \"utf-8\");\n files.push({ relativePath, fullPath, content });\n } catch (err) {\n logger.warn(\n `Failed to read ${relativePath}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n }\n }\n\n walk(dirPath, \"\");\n return files;\n}\n\n/**\n * Formats a JSON string to match serializeTokenFile output:\n * JSON.stringify(parsed, null, 2) + \"\\n\"\n *\n * This is the single canonical format used everywhere —\n * Studio's serializeTokenFile and this CLI command produce identical output.\n */\nfunction formatJson(content: string): string {\n const parsed = JSON.parse(content);\n return JSON.stringify(parsed, null, 2) + \"\\n\";\n}\n\n/**\n * Formats token files to ensure consistent JSON formatting.\n */\nexport function formatCommand(options: FormatOptions): void {\n validateCwdOption(options.cwd);\n const commandCwd = resolveCommandCwd(options.cwd);\n const tokensDir = resolveInCwd(commandCwd, options.tokens || \"./tokens\");\n\n if (!fs.existsSync(tokensDir)) {\n throw tokensDirNotFoundError(tokensDir);\n }\n\n logger.info(`Formatting token files in ${tokensDir}...`);\n\n const files = loadTokenFiles(tokensDir);\n const fileCount = files.length;\n\n if (fileCount === 0) {\n logger.warn(`No JSON files found in ${tokensDir}`);\n return;\n }\n\n let changedCount = 0;\n const unformattedFiles: string[] = [];\n\n for (const { relativePath, fullPath, content } of files) {\n try {\n const formatted = formatJson(content);\n\n if (content !== formatted) {\n if (options.check) {\n unformattedFiles.push(relativePath);\n changedCount++;\n } else if (options.dryRun) {\n logger.info(`Would format: ${relativePath}`);\n changedCount++;\n } else {\n fs.writeFileSync(fullPath, formatted, \"utf-8\");\n logger.info(`Formatted: ${relativePath}`);\n changedCount++;\n }\n }\n } catch (err) {\n logger.error(\n `Failed to format ${relativePath}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n throw err;\n }\n }\n\n if (options.check) {\n if (changedCount > 0) {\n logger.error(\n `${changedCount} of ${fileCount} files are not formatted correctly:`,\n );\n for (const file of unformattedFiles) {\n logger.error(` - ${file}`);\n }\n logger.info(\n `Run 'npx clafoutis format --tokens ${tokensDir}' to fix formatting.`,\n );\n process.exit(1);\n }\n logger.success(`All ${fileCount} files are correctly formatted`);\n return;\n }\n\n if (options.dryRun) {\n if (changedCount > 0) {\n logger.info(`Would format ${changedCount} of ${fileCount} files`);\n } else {\n logger.info(`All ${fileCount} files are already formatted`);\n }\n return;\n }\n\n if (changedCount > 0) {\n logger.success(`Formatted ${changedCount} of ${fileCount} files`);\n } else {\n logger.success(`All ${fileCount} files are already formatted`);\n }\n}\n","import * as p from \"@clack/prompts\";\nimport { Ajv, type ErrorObject } from \"ajv\";\n\nimport { ClafoutisError } from \"../utils/errors\";\n\n/**\n * Validates a GitHub repository format (org/repo-name).\n * @returns Error message if invalid, undefined if valid.\n */\nexport function validateRepo(value: string | undefined): string | undefined {\n if (!value) {\n return \"Repository is required\";\n }\n if (!/^[\\w-]+\\/[\\w.-]+$/.test(value)) {\n return \"Repository must be in format: org/repo-name\";\n }\n return undefined;\n}\n\n/**\n * Validates a file system path.\n * Paths must start with ./ or / or be exactly \".\"\n * @returns Error message if invalid, undefined if valid.\n */\nexport function validatePath(value: string | undefined): string | undefined {\n if (!value) {\n return \"Path is required\";\n }\n if (!value.startsWith(\"./\") && !value.startsWith(\"/\") && value !== \".\") {\n return 'Path must start with ./ or /, or be \".\"';\n }\n return undefined;\n}\n\n/**\n * Validates that a string value is not empty or whitespace-only.\n * @returns Error message if empty, undefined if valid.\n */\nexport function required(value: string | undefined): string | undefined {\n if (!value || !value.trim()) {\n return \"This field is required\";\n }\n return undefined;\n}\n\nconst DEPRECATED_FIELDS: Record<string, string> = {\n \"generators.css\": 'Use \"generators.tailwind\" instead',\n buildDir: 'Renamed to \"output\"',\n};\n\n/**\n * Validates a config object against its JSON schema and checks for issues.\n * - Throws ClafoutisError if schema validation fails\n * - Logs warnings for unknown fields not defined in the schema\n * - Logs warnings for deprecated fields with migration guidance\n */\nexport function validateConfig(\n config: Record<string, unknown>,\n schema: object,\n configPath: string,\n): void {\n const ajv = new Ajv({ allErrors: true, strict: false });\n const validate = ajv.compile(schema);\n\n if (!validate(config)) {\n const errors = validate.errors\n ?.map((e: ErrorObject) => ` - ${e.instancePath || \"root\"}: ${e.message}`)\n .join(\"\\n\");\n throw new ClafoutisError(\n \"Invalid configuration\",\n `${configPath}:\\n${errors}`,\n 'Check the config against the schema or run \"clafoutis init --force\" to regenerate',\n );\n }\n\n const schemaObj = schema as { properties?: Record<string, unknown> };\n if (schemaObj.properties) {\n const unknownFields = findUnknownFields(config, schemaObj.properties);\n if (unknownFields.length > 0) {\n p.log.warn(\n `Unknown fields in ${configPath}: ${unknownFields.join(\", \")}`,\n );\n p.log.info(\n \"These fields will be ignored. Check for typos or outdated config.\",\n );\n }\n }\n\n for (const [field, message] of Object.entries(DEPRECATED_FIELDS)) {\n if (hasField(config, field)) {\n p.log.warn(`Deprecated field \"${field}\": ${message}`);\n }\n }\n}\n\n/**\n * Recursively finds fields in config that are not defined in the schema.\n * Returns an array of dot-notation paths to unknown fields.\n */\nfunction findUnknownFields(\n config: Record<string, unknown>,\n schemaProperties: Record<string, unknown>,\n prefix = \"\",\n): string[] {\n const unknown: string[] = [];\n\n for (const key of Object.keys(config)) {\n const fullPath = prefix ? `${prefix}.${key}` : key;\n\n if (!(key in schemaProperties)) {\n unknown.push(fullPath);\n } else {\n const value = config[key];\n const schemaProp = schemaProperties[key] as {\n properties?: Record<string, unknown>;\n };\n\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n schemaProp?.properties\n ) {\n unknown.push(\n ...findUnknownFields(\n value as Record<string, unknown>,\n schemaProp.properties,\n fullPath,\n ),\n );\n }\n }\n }\n\n return unknown;\n}\n\n/**\n * Checks if a config object has a field at the given dot-notation path.\n * Example: hasField(config, 'generators.css') checks config.generators.css\n */\nfunction hasField(config: Record<string, unknown>, path: string): boolean {\n const parts = path.split(\".\");\n let current: unknown = config;\n\n for (const part of parts) {\n if (current && typeof current === \"object\" && part in current) {\n current = (current as Record<string, unknown>)[part];\n } else {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Validates CLI flags for producer init command.\n * @returns Array of error messages for invalid flags, empty if all valid.\n */\nexport function validateProducerFlags(options: {\n tokens?: string;\n output?: string;\n generators?: string;\n}): string[] {\n const errors: string[] = [];\n\n if (options.tokens) {\n const tokenError = validatePath(options.tokens);\n if (tokenError) {\n errors.push(`--tokens: ${tokenError}`);\n }\n }\n\n if (options.output) {\n const outputError = validatePath(options.output);\n if (outputError) {\n errors.push(`--output: ${outputError}`);\n }\n }\n\n if (options.generators) {\n const builtInGenerators = [\"tailwind\", \"figma\"];\n const generators = options.generators.split(\",\").map((g) => g.trim());\n for (const gen of generators) {\n // Check if it's a custom generator with path (name:path format)\n const colonIdx = gen.indexOf(\":\");\n if (colonIdx > 0) {\n // Custom generator: validate name and path are non-empty\n const name = gen.slice(0, colonIdx).trim();\n const pluginPath = gen.slice(colonIdx + 1).trim();\n if (!name) {\n errors.push(\n `--generators: Custom generator \"${gen}\" has an empty name`,\n );\n }\n if (!pluginPath) {\n errors.push(\n `--generators: Custom generator \"${name}\" is missing a path`,\n );\n }\n } else if (!builtInGenerators.includes(gen)) {\n // Not a built-in generator and not in name:path format\n errors.push(\n `--generators: Invalid generator \"${gen}\". Built-in options: ${builtInGenerators.join(\", \")}. For custom generators use \"name:./path/to/plugin.js\"`,\n );\n }\n }\n }\n\n return errors;\n}\n\n/**\n * Validates CLI flags for consumer init command.\n * @returns Array of error messages for invalid flags, empty if all valid.\n */\nexport function validateConsumerFlags(options: {\n repo?: string;\n files?: string;\n}): string[] {\n const errors: string[] = [];\n\n if (options.repo) {\n const repoError = validateRepo(options.repo);\n if (repoError) {\n errors.push(`--repo: ${repoError}`);\n }\n }\n\n if (options.files) {\n const mappings = options.files.split(\",\");\n for (const mapping of mappings) {\n if (!mapping.includes(\":\")) {\n errors.push(\n `--files: Invalid format \"${mapping}\". Use format: asset:destination`,\n );\n }\n }\n }\n\n return errors;\n}\n","import * as p from \"@clack/prompts\";\n\nimport { validatePath, validateRepo } from \"./validation\";\n\nexport interface ProducerWizardAnswers {\n generators: string[];\n tokens: string;\n output: string;\n workflow: boolean;\n}\n\nexport interface ConsumerWizardAnswers {\n repo: string;\n files: Record<string, string>;\n}\n\nexport type WizardMode = \"producer\" | \"consumer\";\n\n/**\n * Displays the intro banner for the wizard session.\n * Shows \"(DRY RUN)\" suffix when in dry-run mode.\n */\nexport function showIntro(dryRun = false): void {\n const suffix = dryRun ? \" (DRY RUN)\" : \"\";\n p.intro(`Clafoutis - GitOps Design Token Generator${suffix}`);\n}\n\n/**\n * Displays the outro message after wizard completion.\n */\nexport function showOutro(message: string): void {\n p.outro(message);\n}\n\n/**\n * Prompts user to select between producer and consumer mode.\n * @returns Selected mode, or null if user cancels with Ctrl+C.\n */\nexport async function selectMode(): Promise<WizardMode | null> {\n const mode = await p.select({\n message: \"What would you like to set up?\",\n options: [\n {\n value: \"producer\",\n label: \"Producer\",\n hint: \"I maintain a design system\",\n },\n {\n value: \"consumer\",\n label: \"Consumer\",\n hint: \"I consume tokens from a design system\",\n },\n ],\n });\n\n if (p.isCancel(mode)) {\n return null;\n }\n\n return mode as WizardMode;\n}\n\n/**\n * Runs the interactive wizard for producer setup.\n * Collects: generators to enable, token/output paths, and workflow preference.\n * Exits gracefully if user cancels at any point.\n */\nexport async function runProducerWizard(): Promise<ProducerWizardAnswers | null> {\n const answers = await p.group(\n {\n generators: () =>\n p.multiselect({\n message: \"Which generators would you like to enable?\",\n options: [\n { value: \"tailwind\", label: \"Tailwind CSS\", hint: \"recommended\" },\n { value: \"figma\", label: \"Figma Variables\" },\n ],\n required: true,\n initialValues: [\"tailwind\"],\n }),\n\n tokens: () =>\n p.text({\n message: \"Where are your design tokens located?\",\n placeholder: \"./tokens\",\n initialValue: \"./tokens\",\n validate: validatePath,\n }),\n\n output: () =>\n p.text({\n message: \"Where should generated files be output?\",\n placeholder: \"./build\",\n initialValue: \"./build\",\n validate: validatePath,\n }),\n\n workflow: () =>\n p.confirm({\n message: \"Create GitHub Actions workflow for auto-releases?\",\n initialValue: true,\n }),\n },\n {\n onCancel: () => {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n },\n },\n );\n\n return answers as ProducerWizardAnswers;\n}\n\n/**\n * Runs the interactive wizard for consumer setup.\n * Collects: source repository and file mappings (source -> destination).\n * Exits gracefully if user cancels at any point.\n */\nexport async function runConsumerWizard(): Promise<ConsumerWizardAnswers | null> {\n const repo = await p.text({\n message: \"GitHub repository (org/repo):\",\n placeholder: \"Acme/design-system\",\n validate: validateRepo,\n });\n\n if (p.isCancel(repo)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n const filesInput = await p.text({\n message: \"Which files do you want to sync? (comma-separated)\",\n placeholder: \"tailwind.base.css, tailwind.config.js\",\n initialValue: \"tailwind.base.css, tailwind.config.js\",\n });\n\n if (p.isCancel(filesInput)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n const fileNames = (filesInput as string)\n .split(\",\")\n .map((f) => f.trim())\n .filter(Boolean);\n\n const files: Record<string, string> = {};\n\n for (const fileName of fileNames) {\n const defaultDest = suggestDestination(fileName);\n const dest = await p.text({\n message: `Where should ${fileName} be saved?`,\n placeholder: defaultDest,\n initialValue: defaultDest,\n validate: validatePath,\n });\n\n if (p.isCancel(dest)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n files[fileName] = dest as string;\n }\n\n return {\n repo: repo as string,\n files,\n };\n}\n\n/**\n * Suggests a reasonable destination path based on file extension and name.\n * - tailwind.config files go to project root\n * - CSS/SCSS files go to src/styles/\n * - Other files go to project root\n */\nfunction suggestDestination(fileName: string): string {\n if (fileName.includes(\"tailwind.config\")) {\n return \"./tailwind.config.js\";\n }\n if (fileName.includes(\".css\")) {\n return `./src/styles/${fileName}`;\n }\n if (fileName.includes(\".scss\")) {\n return `./src/styles/${fileName}`;\n }\n return `./${fileName}`;\n}\n\n/**\n * Asks user if they want to run the init wizard when config is missing.\n * Used by generate/sync commands to offer guided setup.\n * @returns true if user wants to run the wizard, false otherwise.\n */\nexport async function offerWizard(\n configType: \"producer\" | \"consumer\",\n): Promise<boolean> {\n p.log.error(`Configuration not found: .clafoutis/${configType}.json`);\n\n const runWizard = await p.confirm({\n message: \"Would you like to create one now?\",\n initialValue: true,\n });\n\n if (p.isCancel(runWizard)) {\n p.cancel(\"Operation cancelled.\");\n process.exit(0);\n }\n\n return runWizard as boolean;\n}\n\n/**\n * Creates a spinner for showing progress during async operations.\n */\nexport function createSpinner(): ReturnType<typeof p.spinner> {\n return p.spinner();\n}\n\n/**\n * Log helpers that use @clack/prompts styling for consistent output.\n */\nexport const log = {\n info: (message: string) => p.log.info(message),\n success: (message: string) => p.log.success(message),\n warn: (message: string) => p.log.warn(message),\n error: (message: string) => p.log.error(message),\n step: (message: string) => p.log.step(message),\n message: (message: string) => p.log.message(message),\n};\n","import fs from \"fs/promises\";\n\nimport type { ClafoutisConfig, ProducerConfig } from \"../types\";\n\n/**\n * Reads and parses a consumer configuration file (.clafoutis.json).\n * Returns null if the file does not exist or cannot be parsed.\n */\nexport async function readConfig(\n configPath: string,\n): Promise<ClafoutisConfig | null> {\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n return JSON.parse(content) as ClafoutisConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Reads and parses a producer configuration file (clafoutis.config.json).\n * Returns null if the file does not exist or cannot be parsed.\n */\nexport async function readProducerConfig(\n configPath: string,\n): Promise<ProducerConfig | null> {\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n return JSON.parse(content) as ProducerConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Checks if a file exists at the given path.\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"required\": [\"repo\", \"version\", \"files\"],\n \"properties\": {\n \"repo\": {\n \"type\": \"string\",\n \"pattern\": \"^[\\\\w.-]+/[\\\\w.-]+$\",\n \"description\": \"GitHub repository in org/name format\"\n },\n \"version\": {\n \"type\": \"string\",\n \"pattern\": \"^(latest|v\\\\d+\\\\.\\\\d+\\\\.\\\\d+)$\",\n \"description\": \"Release tag (e.g., v1.0.0) or 'latest'\"\n },\n \"files\": {\n \"type\": \"object\",\n \"additionalProperties\": { \"type\": \"string\" },\n \"minProperties\": 1,\n \"description\": \"Mapping of release asset names to local file paths\"\n },\n \"postSync\": {\n \"type\": \"string\",\n \"description\": \"Optional command to run after sync\"\n }\n },\n \"additionalProperties\": false\n}\n","{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"required\": [\"tokens\", \"output\", \"generators\"],\n \"properties\": {\n \"tokens\": {\n \"type\": \"string\",\n \"description\": \"Path to tokens directory\"\n },\n \"output\": {\n \"type\": \"string\",\n \"description\": \"Output directory for generated files\"\n },\n \"generators\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"oneOf\": [\n { \"type\": \"boolean\" },\n { \"type\": \"string\" }\n ]\n },\n \"description\": \"Generators to run (true for built-in, string path for custom)\"\n }\n },\n \"additionalProperties\": false\n}\n","import consumerSchema from \"../../schemas/consumer-config.json\";\nimport producerSchema from \"../../schemas/producer-config.json\";\nimport { validateConfig } from \"../cli/validation\";\n\n/**\n * Validates a consumer configuration object against the JSON schema.\n * Also warns about unknown or deprecated fields.\n * Throws a ClafoutisError if validation fails.\n */\nexport function validateConsumerConfig(config: unknown): void {\n validateConfig(\n config as Record<string, unknown>,\n consumerSchema,\n \".clafoutis/consumer.json\",\n );\n}\n\n/**\n * Validates a producer configuration object against the JSON schema.\n * Also warns about unknown or deprecated fields.\n * Throws a ClafoutisError if validation fails.\n */\nexport function validateProducerConfig(config: unknown): void {\n validateConfig(\n config as Record<string, unknown>,\n producerSchema,\n \".clafoutis/producer.json\",\n );\n}\n","/**\n * Returns the .gitignore content for producer repos.\n * Ignores build artifacts and CI-generated release assets.\n */\nexport function getProducerGitignore(): string {\n return `# Dependencies\nnode_modules/\n\n# Build output (regenerated by clafoutis generate)\nbuild/\n\n# CI-generated release assets\nrelease-assets/\n`;\n}\n\n/**\n * Returns the .gitignore content for consumer repos.\n * Only ignores the cache file.\n */\nexport function getConsumerGitignore(): string {\n return `# Clafoutis cache\n.clafoutis/cache\n`;\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Resolves the absolute path to the starter token templates directory.\n * Works in both dev (tsx) and built (dist/) contexts.\n */\nfunction getTokensDir(): string {\n // Dev: __dirname is src/templates/, tokens/ is adjacent\n const devPath = path.resolve(__dirname, \"tokens\");\n if (fs.existsSync(devPath)) return devPath;\n\n // Built: __dirname is dist/, templates/tokens/ is a sibling\n const distPath = path.resolve(__dirname, \"templates\", \"tokens\");\n if (fs.existsSync(distPath)) return distPath;\n\n throw new Error(\n `Starter token templates not found. Searched:\\n ${devPath}\\n ${distPath}`,\n );\n}\n\n/**\n * Recursively walks a directory and collects all .json files\n * with their relative paths and raw content.\n */\nfunction walkTokensDir(\n dir: string,\n base = \"\",\n): Array<{ path: string; content: string }> {\n const result: Array<{ path: string; content: string }> = [];\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const relPath = base ? path.join(base, entry.name) : entry.name;\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n result.push(...walkTokensDir(fullPath, relPath));\n } else if (entry.name.endsWith(\".json\")) {\n result.push({\n path: relPath,\n content: fs.readFileSync(fullPath, \"utf-8\"),\n });\n }\n }\n return result;\n}\n\n/**\n * Returns the JSON content for a starter token file.\n * @throws Error if fileName is not found in the templates directory.\n */\nexport function getStarterTokenContent(fileName: string): string {\n const tokensDir = getTokensDir();\n const filePath = path.resolve(tokensDir, fileName);\n\n // Guard against path traversal — filePath must remain inside tokensDir\n const relative = path.relative(tokensDir, filePath);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new Error(`Invalid token file path: ${fileName}`);\n }\n\n if (!fs.existsSync(filePath)) {\n throw new Error(`Unknown starter token file: ${fileName}`);\n }\n return fs.readFileSync(filePath, \"utf-8\");\n}\n\n/**\n * Returns all starter token files with their paths and JSON content.\n * Used during producer init to create the initial token structure.\n */\nexport function getAllStarterTokens(): Array<{\n path: string;\n content: string;\n}> {\n const tokensDir = getTokensDir();\n return walkTokensDir(tokensDir);\n}\n","/**\n * Returns the GitHub Actions workflow YAML for automatic token releases.\n * Triggers on push to main when tokens change, generates outputs,\n * commits build artifacts back to the repo, and creates a release.\n */\nexport function getWorkflowTemplate(): string {\n return `name: Design Token Release\n\non:\n push:\n branches: [main]\n paths:\n - 'tokens/**'\n - '.clafoutis/producer.json'\n\njobs:\n release:\n runs-on: ubuntu-latest\n permissions:\n contents: write\n\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n\n - uses: actions/setup-node@v4\n with:\n node-version: '22'\n\n - name: Install Clafoutis\n run: npm install -D @clafoutis/cli\n\n - name: Check token file formatting\n run: npx clafoutis format --tokens tokens --check\n\n - name: Generate tokens\n run: npx clafoutis generate\n\n - name: Commit generated build artifacts\n run: |\n if [ -z \"$(git status --porcelain build)\" ]; then\n echo \"No build changes to commit\"\n exit 0\n fi\n git config user.name \"github-actions[bot]\"\n git config user.email \"github-actions[bot]@users.noreply.github.com\"\n git add build\n git commit -m \"chore: update generated build artifacts\"\n git push\n\n - name: Get next version\n id: version\n run: |\n LATEST=$(git tag -l 'v*' | grep -E '^v[0-9]+\\\\.[0-9]+\\\\.[0-9]+$' | sort -V | tail -n1)\n if [ -z \"$LATEST\" ]; then\n echo \"version=1.0.0\" >> $GITHUB_OUTPUT\n else\n VERSION=\\${LATEST#v}\n IFS='.' read -r MAJOR MINOR PATCH <<< \"$VERSION\"\n PATCH=$((PATCH + 1))\n echo \"version=\\${MAJOR}.\\${MINOR}.\\${PATCH}\" >> $GITHUB_OUTPUT\n fi\n\n - name: Prepare release assets\n run: |\n mkdir -p release-assets\n while IFS= read -r -d '' file; do\n relative=\"\\${file#build/}\"\n flat_name=\"\\${relative//\\\\//.}\"\n target=\"release-assets/$flat_name\"\n if [ -e \"$target\" ]; then\n echo \"::error::Collision detected: '$relative' flattens to '$flat_name' which already exists\"\n exit 1\n fi\n cp \"$file\" \"$target\"\n done < <(find build -type f -print0)\n\n - name: Create Release\n uses: softprops/action-gh-release@v2\n with:\n tag_name: v\\${{ steps.version.outputs.version }}\n name: Design Tokens v\\${{ steps.version.outputs.version }}\n generate_release_notes: true\n files: release-assets/*\n env:\n GITHUB_TOKEN: \\${{ secrets.GITHUB_TOKEN }}\n`;\n}\n\n/**\n * Returns the standard path for the Clafoutis release workflow.\n */\nexport function getWorkflowPath(): string {\n return \".github/workflows/clafoutis-release.yml\";\n}\n","import * as p from \"@clack/prompts\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nimport {\n validateConsumerFlags,\n validateProducerFlags,\n} from \"../cli/validation\";\nimport {\n type ConsumerWizardAnswers,\n log,\n type ProducerWizardAnswers,\n runConsumerWizard,\n runProducerWizard,\n selectMode,\n showIntro,\n showOutro,\n} from \"../cli/wizard\";\nimport {\n getConsumerGitignore,\n getProducerGitignore,\n} from \"../templates/gitignore\";\nimport { getAllStarterTokens } from \"../templates/tokens\";\nimport { getWorkflowPath, getWorkflowTemplate } from \"../templates/workflow\";\nimport { fileExists } from \"../utils/config\";\nimport {\n displayPath,\n resolveCommandCwd,\n resolveInCwd,\n validateCwdOption,\n} from \"../utils/cwd\";\nimport { ClafoutisError } from \"../utils/errors\";\n\nexport interface InitOptions {\n producer?: boolean;\n consumer?: boolean;\n repo?: string;\n tokens?: string;\n output?: string;\n generators?: string;\n workflow?: boolean;\n files?: string;\n force?: boolean;\n dryRun?: boolean;\n nonInteractive?: boolean;\n cwd?: string;\n}\n\ninterface FileToCreate {\n path: string;\n content: string;\n description?: string;\n}\n\n/**\n * Parses and validates a comma-separated generators string.\n * Each entry can be:\n * - A built-in generator name: \"tailwind\", \"figma\"\n * - A custom generator with path: \"name:./path/to/plugin.js\"\n *\n * @param generatorsString - Comma-separated generators string\n * @returns Array of validated generator entries\n * @throws ClafoutisError if any entries are invalid\n */\nfunction parseGenerators(generatorsString: string): string[] {\n const entries = generatorsString.split(\",\").map((g) => g.trim());\n const invalidEntries: string[] = [];\n\n for (const entry of entries) {\n if (!entry) {\n invalidEntries.push(\"(empty entry - check for extra commas)\");\n continue;\n }\n\n const colonIdx = entry.indexOf(\":\");\n if (colonIdx === 0) {\n invalidEntries.push(`\"${entry}\" (missing generator name before \":\")`);\n } else if (colonIdx > 0) {\n const name = entry.slice(0, colonIdx).trim();\n const pluginPath = entry.slice(colonIdx + 1).trim();\n if (!name) {\n invalidEntries.push(`\"${entry}\" (empty generator name)`);\n }\n if (!pluginPath) {\n invalidEntries.push(`\"${entry}\" (missing path after \":\")`);\n }\n }\n }\n\n if (invalidEntries.length > 0) {\n throw new ClafoutisError(\n \"Invalid generator entries\",\n `The following entries are malformed:\\n - ${invalidEntries.join(\"\\n - \")}`,\n 'Use format \"tailwind,figma\" for built-ins or \"name:./path/to/plugin.js\" for custom generators',\n );\n }\n\n return entries.filter((e) => e.length > 0);\n}\n\n/**\n * Main init command handler.\n * Supports both interactive wizard and non-interactive CLI flag modes.\n * @throws ClafoutisError if both --producer and --consumer flags are set\n */\nexport async function initCommand(options: InitOptions): Promise<void> {\n // Reject ambiguous flag combinations early\n if (options.producer && options.consumer) {\n throw new ClafoutisError(\n \"Conflicting flags\",\n \"Cannot specify both --producer and --consumer\",\n \"Choose one: --producer for design system repos, --consumer for application repos\",\n );\n }\n\n validateCwdOption(options.cwd);\n const commandCwd = resolveCommandCwd(options.cwd);\n\n const isInteractive = !options.nonInteractive && process.stdin.isTTY;\n const isDryRun = options.dryRun ?? false;\n\n if (isInteractive) {\n await runInteractiveInit(options, isDryRun, commandCwd);\n } else {\n await runNonInteractiveInit(options, isDryRun, commandCwd);\n }\n}\n\nasync function runInteractiveInit(\n options: InitOptions,\n isDryRun: boolean,\n commandCwd: string,\n): Promise<void> {\n showIntro(isDryRun);\n\n let mode: \"producer\" | \"consumer\";\n\n if (options.producer) {\n mode = \"producer\";\n } else if (options.consumer) {\n mode = \"consumer\";\n } else {\n const selectedMode = await selectMode();\n if (!selectedMode) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n mode = selectedMode;\n }\n\n if (mode === \"producer\") {\n const answers = await runProducerWizard();\n if (!answers) {\n return;\n }\n await createProducerConfig(\n answers,\n options.force ?? false,\n isDryRun,\n commandCwd,\n );\n } else {\n const answers = await runConsumerWizard();\n if (!answers) {\n return;\n }\n await createConsumerConfig(\n answers,\n options.force ?? false,\n isDryRun,\n commandCwd,\n );\n }\n\n if (isDryRun) {\n showOutro(\"No files were written. Remove --dry-run to apply changes.\");\n } else {\n showOutro(\"Setup complete!\");\n }\n}\n\nasync function runNonInteractiveInit(\n options: InitOptions,\n isDryRun: boolean,\n commandCwd: string,\n): Promise<void> {\n if (!options.producer && !options.consumer) {\n throw new ClafoutisError(\n \"Mode required\",\n \"In non-interactive mode, you must specify --producer or --consumer\",\n \"Add --producer or --consumer flag\",\n );\n }\n\n if (options.producer) {\n const errors = validateProducerFlags(options);\n if (errors.length > 0) {\n throw new ClafoutisError(\n \"Invalid flags\",\n errors.join(\"\\n\"),\n \"Fix the invalid flags and try again\",\n );\n }\n\n const answers: ProducerWizardAnswers = {\n generators: options.generators\n ? parseGenerators(options.generators)\n : [\"tailwind\"],\n tokens: options.tokens ?? \"./tokens\",\n output: options.output ?? \"./build\",\n workflow: options.workflow ?? true,\n };\n\n await createProducerConfig(\n answers,\n options.force ?? false,\n isDryRun,\n commandCwd,\n );\n } else {\n const errors = validateConsumerFlags(options);\n if (errors.length > 0) {\n throw new ClafoutisError(\n \"Invalid flags\",\n errors.join(\"\\n\"),\n \"Fix the invalid flags and try again\",\n );\n }\n\n if (!options.repo) {\n throw new ClafoutisError(\n \"Repository required\",\n \"In non-interactive mode, --repo is required for consumer setup\",\n \"Add --repo=org/repo-name flag\",\n );\n }\n\n const files: Record<string, string> = {};\n if (options.files) {\n for (const mapping of options.files.split(\",\")) {\n const colonIdx = mapping.indexOf(\":\");\n if (colonIdx === -1) {\n throw new ClafoutisError(\n \"Invalid file mapping\",\n `Mapping \"${mapping.trim()}\" is missing a colon separator`,\n 'Use the format \"source:destination\" (e.g., \"tokens.css:./src/styles/tokens.css\")',\n );\n }\n\n const source = mapping.slice(0, colonIdx).trim();\n const dest = mapping.slice(colonIdx + 1).trim();\n\n if (!source) {\n throw new ClafoutisError(\n \"Invalid file mapping\",\n `Mapping \"${mapping.trim()}\" has an empty source`,\n 'Provide a valid asset name before the colon (e.g., \"tokens.css:./path\")',\n );\n }\n\n if (!dest) {\n throw new ClafoutisError(\n \"Invalid file mapping\",\n `Mapping \"${mapping.trim()}\" has an empty destination`,\n 'Provide a valid path after the colon (e.g., \"tokens.css:./path\")',\n );\n }\n\n files[source] = dest;\n }\n } else {\n files[\"tailwind.base.css\"] = \"./src/styles/base.css\";\n files[\"tailwind.config.js\"] = \"./tailwind.config.js\";\n }\n\n const answers: ConsumerWizardAnswers = {\n repo: options.repo,\n files,\n };\n\n await createConsumerConfig(\n answers,\n options.force ?? false,\n isDryRun,\n commandCwd,\n );\n }\n}\n\nasync function createProducerConfig(\n answers: ProducerWizardAnswers,\n force: boolean,\n dryRun: boolean,\n commandCwd: string,\n): Promise<void> {\n const configPath = resolveInCwd(commandCwd, \".clafoutis/producer.json\");\n\n if (!force && (await fileExists(configPath))) {\n throw new ClafoutisError(\n \"Configuration already exists\",\n configPath,\n \"Use --force to overwrite the existing configuration\",\n );\n }\n\n const generators: Record<string, boolean | string> = {};\n for (const entry of answers.generators) {\n const colonIdx = entry.indexOf(\":\");\n if (colonIdx > 0) {\n const name = entry.slice(0, colonIdx).trim();\n const pluginPath = entry.slice(colonIdx + 1).trim();\n generators[name] = pluginPath;\n } else {\n generators[entry] = true;\n }\n }\n\n const config = {\n tokens: answers.tokens,\n output: answers.output,\n generators,\n };\n\n const filesToCreate: FileToCreate[] = [\n {\n path: configPath,\n content: JSON.stringify(config, null, 2) + \"\\n\",\n description: `tokens: \"${answers.tokens}\", output: \"${answers.output}\"`,\n },\n ];\n\n const starterTokens = getAllStarterTokens();\n for (const token of starterTokens) {\n const tokenPath = resolveInCwd(\n commandCwd,\n path.join(answers.tokens, token.path),\n );\n if (!force && (await fileExists(tokenPath))) {\n continue;\n }\n filesToCreate.push({\n path: tokenPath,\n content: token.content,\n description: \"Starter token template\",\n });\n }\n\n if (answers.workflow) {\n const workflowPath = resolveInCwd(commandCwd, getWorkflowPath());\n if (force || !(await fileExists(workflowPath))) {\n filesToCreate.push({\n path: workflowPath,\n content: getWorkflowTemplate(),\n description: \"Auto-release workflow on push to main\",\n });\n }\n }\n\n // Add .gitignore for producer repos\n const gitignorePath = resolveInCwd(commandCwd, \".gitignore\");\n if (force || !(await fileExists(gitignorePath))) {\n filesToCreate.push({\n path: gitignorePath,\n content: getProducerGitignore(),\n description: \"Ignore build artifacts and release-assets\",\n });\n }\n\n if (dryRun) {\n showDryRunOutput(filesToCreate, commandCwd);\n } else {\n await writeFiles(filesToCreate, commandCwd);\n showNextSteps(\"producer\", answers);\n }\n}\n\nasync function createConsumerConfig(\n answers: ConsumerWizardAnswers,\n force: boolean,\n dryRun: boolean,\n commandCwd: string,\n): Promise<void> {\n const configPath = resolveInCwd(commandCwd, \".clafoutis/consumer.json\");\n\n if (!force && (await fileExists(configPath))) {\n throw new ClafoutisError(\n \"Configuration already exists\",\n configPath,\n \"Use --force to overwrite the existing configuration\",\n );\n }\n\n const config = {\n repo: answers.repo,\n version: \"latest\",\n files: answers.files,\n };\n\n const filesToCreate: FileToCreate[] = [\n {\n path: configPath,\n content: JSON.stringify(config, null, 2) + \"\\n\",\n description: `repo: \"${answers.repo}\"`,\n },\n ];\n\n // Add .gitignore entry for consumer repos (append if exists)\n const gitignorePath = resolveInCwd(commandCwd, \".gitignore\");\n const consumerIgnore = getConsumerGitignore();\n if (await fileExists(gitignorePath)) {\n // Check if cache is already ignored\n const existingContent = await fs.readFile(gitignorePath, \"utf-8\");\n if (!existingContent.includes(\".clafoutis/cache\")) {\n filesToCreate.push({\n path: gitignorePath,\n content: existingContent.trimEnd() + \"\\n\\n\" + consumerIgnore,\n description: \"Append .clafoutis/cache to existing .gitignore\",\n });\n }\n } else {\n filesToCreate.push({\n path: gitignorePath,\n content: consumerIgnore,\n description: \"Ignore .clafoutis/cache\",\n });\n }\n\n if (dryRun) {\n showDryRunOutput(filesToCreate, commandCwd);\n } else {\n await writeFiles(filesToCreate, commandCwd);\n showNextSteps(\"consumer\", answers);\n }\n}\n\nfunction showDryRunOutput(files: FileToCreate[], commandCwd: string): void {\n log.message(\"\");\n log.step(\"Would create the following files:\");\n log.message(\"\");\n\n for (const file of files) {\n log.message(` ${displayPath(commandCwd, file.path)}`);\n if (file.description) {\n log.message(` └─ ${file.description}`);\n }\n }\n\n log.message(\"\");\n}\n\nasync function writeFiles(\n files: FileToCreate[],\n commandCwd: string,\n): Promise<void> {\n for (const file of files) {\n const dir = path.dirname(file.path);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(file.path, file.content);\n log.success(`Created ${displayPath(commandCwd, file.path)}`);\n }\n}\n\nfunction showNextSteps(\n mode: \"producer\" | \"consumer\",\n answers: ProducerWizardAnswers | ConsumerWizardAnswers,\n): void {\n log.message(\"\");\n log.step(\"Next steps:\");\n\n if (mode === \"producer\") {\n const producerAnswers = answers as ProducerWizardAnswers;\n log.message(\n ` 1. Edit ${producerAnswers.tokens}/colors/primitives.json with your design tokens`,\n );\n if (producerAnswers.workflow) {\n log.message(\n \" 2. Push to GitHub - the workflow will generate outputs and create a release automatically\",\n );\n } else {\n log.message(\" 2. Run: npx clafoutis generate\");\n log.message(\" 3. Push to GitHub to share your design system\");\n }\n } else {\n log.message(\" 1. Run: npx clafoutis sync\");\n }\n}\n","import { generate as figmaGenerate } from \"@clafoutis/generators/figma\";\nimport { generate as tailwindGenerate } from \"@clafoutis/generators/tailwind\";\nimport { logger } from \"@clafoutis/shared\";\nimport path from \"path\";\nimport StyleDictionary from \"style-dictionary\";\nimport { register as registerTsx } from \"tsx/esm/api\";\nimport { pathToFileURL } from \"url\";\n\nimport { offerWizard } from \"../cli/wizard\";\nimport type { GeneratorContext, GeneratorPlugin } from \"../types\";\nimport { fileExists, readProducerConfig } from \"../utils/config\";\nimport {\n resolveCommandCwd,\n resolveInCwd,\n validateCwdOption,\n} from \"../utils/cwd\";\nimport {\n ClafoutisError,\n configNotFoundError,\n generatorNotFoundError,\n pluginLoadError,\n tokensDirNotFoundError,\n} from \"../utils/errors\";\nimport { validateProducerConfig } from \"../utils/validate\";\nimport { initCommand } from \"./init\";\n\ninterface GenerateOptions {\n config?: string;\n tailwind?: boolean;\n figma?: boolean;\n output?: string;\n dryRun?: boolean;\n cwd?: string;\n}\n\ninterface GeneratorModule {\n generate: GeneratorPlugin;\n}\n\n/**\n * Loads a generator plugin from a file path.\n * Supports both JavaScript and TypeScript files.\n * Resolves relative paths against the current working directory.\n */\nasync function loadPlugin(\n pluginPath: string,\n commandCwd: string,\n): Promise<GeneratorModule> {\n const absolutePath = resolveInCwd(commandCwd, pluginPath);\n\n if (pluginPath.endsWith(\".ts\")) {\n registerTsx();\n }\n\n // Dynamic import required here: loads user-provided plugin files by path at runtime\n return import(pathToFileURL(absolutePath).href);\n}\n\n/**\n * Main generate command handler.\n * Reads configuration, validates it, and runs enabled generators.\n */\nexport async function generateCommand(options: GenerateOptions): Promise<void> {\n validateCwdOption(options.cwd);\n const commandCwd = resolveCommandCwd(options.cwd);\n const configPath = resolveInCwd(\n commandCwd,\n options.config || \".clafoutis/producer.json\",\n );\n\n let config = await readProducerConfig(configPath);\n\n if (!config) {\n if (await fileExists(configPath)) {\n throw new ClafoutisError(\n \"Invalid configuration\",\n `Could not parse ${configPath}`,\n \"Ensure the file contains valid JSON\",\n );\n }\n\n if (process.stdin.isTTY) {\n const shouldRunWizard = await offerWizard(\"producer\");\n if (shouldRunWizard) {\n await initCommand({ producer: true, cwd: commandCwd });\n config = await readProducerConfig(configPath);\n if (!config) {\n throw configNotFoundError(configPath, false);\n }\n } else {\n throw configNotFoundError(configPath, false);\n }\n } else {\n throw configNotFoundError(configPath, false);\n }\n }\n\n validateProducerConfig(config);\n\n // Merge CLI flags with existing generators, preserving custom plugins\n if (options.tailwind !== undefined || options.figma !== undefined) {\n config = {\n ...config,\n generators: {\n ...(config.generators || {}),\n ...(options.tailwind !== undefined && { tailwind: options.tailwind }),\n ...(options.figma !== undefined && { figma: options.figma }),\n },\n };\n }\n\n if (options.output) {\n config.output = options.output;\n }\n\n // Resolve paths relative to current working directory (project root)\n const tokensDir = resolveInCwd(commandCwd, config.tokens || \"./tokens\");\n const outputDir = resolveInCwd(commandCwd, config.output || \"./build\");\n\n if (!(await fileExists(tokensDir))) {\n throw tokensDirNotFoundError(tokensDir);\n }\n\n // Use the same default for both dry-run and actual execution\n const generators = config.generators || { tailwind: true, figma: true };\n\n if (options.dryRun) {\n logger.info(\"[dry-run] Would read tokens from: \" + tokensDir);\n logger.info(\"[dry-run] Would write to: \" + outputDir);\n for (const [name, value] of Object.entries(generators)) {\n if (value !== false) {\n const type = typeof value === \"string\" ? \"custom\" : \"built-in\";\n logger.info(`[dry-run] Would run generator: ${name} (${type})`);\n }\n }\n return;\n }\n\n logger.info(`Tokens: ${tokensDir}`);\n logger.info(`Output: ${outputDir}`);\n\n let hadFailure = false;\n\n for (const [name, value] of Object.entries(generators)) {\n if (value === false) continue;\n\n logger.info(`Running ${name} generator...`);\n\n try {\n let generatorModule: GeneratorModule;\n\n if (typeof value === \"string\") {\n try {\n generatorModule = await loadPlugin(value, commandCwd);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n throw pluginLoadError(value, errorMessage);\n }\n\n if (typeof generatorModule.generate !== \"function\") {\n throw pluginLoadError(\n value,\n 'Module does not export a \"generate\" function',\n );\n }\n } else {\n // Built-in generators from @clafoutis/generators package\n const builtInGenerators: Record<string, GeneratorModule> = {\n tailwind: { generate: () => tailwindGenerate() },\n figma: { generate: () => figmaGenerate() },\n };\n\n if (!builtInGenerators[name]) {\n throw generatorNotFoundError(name);\n }\n\n generatorModule = builtInGenerators[name];\n }\n\n const context: GeneratorContext = {\n tokensDir,\n outputDir: path.join(outputDir, name),\n config,\n StyleDictionary,\n };\n await generatorModule.generate(context);\n\n logger.success(`${name} complete`);\n } catch (err) {\n if (err instanceof ClafoutisError) {\n throw err;\n }\n logger.error(`${name} failed: ${err}`);\n hadFailure = true;\n }\n }\n\n if (hadFailure) {\n throw new ClafoutisError(\n \"Generation failed\",\n \"One or more generators failed\",\n \"Check the error messages above and fix the issues\",\n );\n }\n\n logger.success(\"Generation complete\");\n}\n","import fs from \"fs/promises\";\nimport path from \"path\";\n\nconst CACHE_DIR = \".clafoutis\";\nconst CACHE_FILE = \"cache\";\n\nfunction getCachePaths(commandCwd: string): { dir: string; file: string } {\n const dir = path.resolve(commandCwd, CACHE_DIR);\n return {\n dir,\n file: path.join(dir, CACHE_FILE),\n };\n}\n\n/**\n * Reads the cached version from .clafoutis/cache file.\n * Returns null if the cache file does not exist.\n * Rethrows other errors (permissions, corruption, etc.).\n */\nexport async function readCache(\n commandCwd = process.cwd(),\n): Promise<string | null> {\n const { file } = getCachePaths(commandCwd);\n try {\n return (await fs.readFile(file, \"utf-8\")).trim();\n } catch (err: unknown) {\n if (\n err instanceof Error &&\n (err as NodeJS.ErrnoException).code === \"ENOENT\"\n ) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Writes the current version to the .clafoutis/cache file.\n * Creates the .clafoutis directory if it doesn't exist.\n */\nexport async function writeCache(\n version: string,\n commandCwd = process.cwd(),\n): Promise<void> {\n const { dir, file } = getCachePaths(commandCwd);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(file, version);\n}\n","import { logger } from \"@clafoutis/shared\";\n\nimport type { ClafoutisConfig } from \"../types\";\nimport {\n authRequiredError,\n ClafoutisError,\n releaseNotFoundError,\n} from \"./errors\";\n\ninterface GitHubRelease {\n tag_name: string;\n assets: Array<{\n name: string;\n url: string;\n browser_download_url: string;\n }>;\n}\n\nexport interface DownloadResult {\n files: Map<string, string>;\n resolvedTag: string;\n}\n\n/**\n * Downloads release assets from a GitHub repository.\n * Fetches the release metadata and then downloads each requested file.\n * Handles \"latest\" version by resolving to the actual tag name.\n *\n * @param config - Consumer configuration containing repo, version, and files to download\n * @returns Object containing downloaded files and the resolved tag name\n * @throws ClafoutisError if any requested assets are missing or fail to download\n */\nexport async function downloadRelease(\n config: ClafoutisConfig,\n): Promise<DownloadResult> {\n const token = process.env.CLAFOUTIS_REPO_TOKEN;\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github.v3+json\",\n \"User-Agent\": \"clafoutis-cli\",\n };\n\n if (token) {\n headers[\"Authorization\"] = `token ${token}`;\n }\n\n // Use /releases/latest endpoint for \"latest\", otherwise use /releases/tags/{tag}\n const isLatest = config.version === \"latest\";\n const releaseUrl = isLatest\n ? `https://api.github.com/repos/${config.repo}/releases/latest`\n : `https://api.github.com/repos/${config.repo}/releases/tags/${config.version}`;\n\n const releaseRes = await fetch(releaseUrl, { headers });\n\n if (!releaseRes.ok) {\n if (releaseRes.status === 404) {\n throw releaseNotFoundError(config.version, config.repo);\n } else if (releaseRes.status === 401 || releaseRes.status === 403) {\n throw authRequiredError();\n } else {\n logger.error(`GitHub API error: ${releaseRes.status}`);\n process.exit(1);\n }\n }\n\n const release = (await releaseRes.json()) as GitHubRelease;\n const resolvedTag = release.tag_name;\n\n if (isLatest) {\n logger.info(`Resolved \"latest\" to ${resolvedTag}`);\n }\n const files = new Map<string, string>();\n const missingAssets: string[] = [];\n const failedDownloads: string[] = [];\n\n for (const assetName of Object.keys(config.files)) {\n const asset = release.assets.find((a) => a.name === assetName);\n\n if (!asset) {\n missingAssets.push(assetName);\n continue;\n }\n\n logger.info(`Downloading ${assetName}...`);\n\n const downloadHeaders = { ...headers, Accept: \"application/octet-stream\" };\n const fileRes = await fetch(asset.url, { headers: downloadHeaders });\n\n if (!fileRes.ok) {\n failedDownloads.push(assetName);\n continue;\n }\n\n files.set(assetName, await fileRes.text());\n }\n\n const errors: string[] = [];\n if (missingAssets.length > 0) {\n errors.push(`Assets not found in release: ${missingAssets.join(\", \")}`);\n }\n if (failedDownloads.length > 0) {\n errors.push(`Failed to download: ${failedDownloads.join(\", \")}`);\n }\n\n if (errors.length > 0) {\n const availableAssets = release.assets.map((a) => a.name).join(\", \");\n throw new ClafoutisError(\n \"Download failed\",\n errors.join(\"\\n\"),\n `Available assets in ${resolvedTag}: ${availableAssets || \"none\"}`,\n );\n }\n\n return { files, resolvedTag };\n}\n","import { logger } from \"@clafoutis/shared\";\nimport { spawn } from \"child_process\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nimport { offerWizard } from \"../cli/wizard\";\nimport type { ClafoutisConfig } from \"../types\";\nimport { readCache, writeCache } from \"../utils/cache\";\nimport { fileExists, readConfig } from \"../utils/config\";\nimport {\n resolveCommandCwd,\n resolveInCwd,\n validateCwdOption,\n} from \"../utils/cwd\";\nimport { ClafoutisError, configNotFoundError } from \"../utils/errors\";\nimport { downloadRelease } from \"../utils/github\";\nimport { validateConsumerConfig } from \"../utils/validate\";\nimport { initCommand } from \"./init\";\n\ninterface SyncOptions {\n force?: boolean;\n config?: string;\n dryRun?: boolean;\n cwd?: string;\n}\n\n/**\n * Writes downloaded files to the configured output paths.\n */\nasync function writeOutput(\n config: ClafoutisConfig,\n files: Map<string, string>,\n commandCwd: string,\n): Promise<void> {\n for (const [assetName, content] of files) {\n const configPath = config.files[assetName];\n if (!configPath) continue;\n\n const outputPath = resolveInCwd(commandCwd, configPath);\n\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, content);\n logger.success(`Written: ${outputPath}`);\n }\n}\n\n/**\n * Main sync command handler.\n * Downloads design tokens from a GitHub release and writes them to configured paths.\n */\nexport async function syncCommand(options: SyncOptions): Promise<void> {\n validateCwdOption(options.cwd);\n const commandCwd = resolveCommandCwd(options.cwd);\n const configPath = resolveInCwd(\n commandCwd,\n options.config || \".clafoutis/consumer.json\",\n );\n\n let config = await readConfig(configPath);\n if (!config) {\n if (await fileExists(configPath)) {\n throw new ClafoutisError(\n \"Invalid configuration\",\n `Could not parse ${configPath}`,\n \"Ensure the file contains valid JSON\",\n );\n }\n\n if (process.stdin.isTTY) {\n const shouldRunWizard = await offerWizard(\"consumer\");\n if (shouldRunWizard) {\n await initCommand({ consumer: true, cwd: commandCwd });\n config = await readConfig(configPath);\n if (!config) {\n throw configNotFoundError(configPath, true);\n }\n } else {\n throw configNotFoundError(configPath, true);\n }\n } else {\n throw configNotFoundError(configPath, true);\n }\n }\n\n validateConsumerConfig(config);\n\n const cachedVersion = await readCache(commandCwd);\n const isLatest = config.version === \"latest\";\n\n logger.info(`Repo: ${config.repo}`);\n logger.info(`Pinned: ${config.version}`);\n logger.info(`Cached: ${cachedVersion || \"none\"}`);\n\n if (options.dryRun) {\n logger.info(\n \"[dry-run] Would download from: \" + config.repo + \" \" + config.version,\n );\n for (const [assetName, outputPath] of Object.entries(config.files)) {\n logger.info(`[dry-run] ${assetName} → ${outputPath}`);\n }\n return;\n }\n\n const resolveOutputPaths = () =>\n Object.values(config.files).map((p) => resolveInCwd(commandCwd, p));\n\n if (!isLatest && !options.force && config.version === cachedVersion) {\n const outputPaths = resolveOutputPaths();\n const existsResults = await Promise.all(\n outputPaths.map((p) => fileExists(p)),\n );\n const allOutputsExist = existsResults.every((exists) => exists);\n if (allOutputsExist) {\n logger.success(`Already at ${config.version} - no sync needed`);\n return;\n }\n }\n\n logger.warn(`Syncing ${config.version}...`);\n\n const { files, resolvedTag } = await downloadRelease(config);\n\n // For \"latest\", check if we already have this resolved version cached\n if (isLatest && !options.force && resolvedTag === cachedVersion) {\n const outputPaths = resolveOutputPaths();\n const existsResults = await Promise.all(\n outputPaths.map((p) => fileExists(p)),\n );\n const allOutputsExist = existsResults.every((exists) => exists);\n if (allOutputsExist) {\n logger.success(`Already at ${resolvedTag} (latest) - no sync needed`);\n return;\n }\n }\n\n await writeOutput(config, files, commandCwd);\n\n // Cache the resolved tag, not \"latest\"\n await writeCache(resolvedTag, commandCwd);\n\n logger.success(`Synced to ${resolvedTag}`);\n\n if (config.postSync) {\n await runPostSync(config.postSync, commandCwd);\n }\n}\n\n/**\n * Executes the postSync command safely using shell spawn.\n * Awaits completion and handles errors with proper logging of stdout/stderr.\n * Uses the system shell to parse the command string, which is necessary\n * for commands like \"npx prettier --write ./src/styles/base.css\".\n *\n * @param command - The shell command string to execute\n * @throws ClafoutisError if the command fails or exits with non-zero code\n */\nasync function runPostSync(command: string, commandCwd: string): Promise<void> {\n logger.info(`Running postSync: ${command}`);\n\n // Determine the shell based on platform\n const isWindows = process.platform === \"win32\";\n const shell = isWindows ? \"cmd.exe\" : \"/bin/sh\";\n const shellArgs = isWindows ? [\"/c\", command] : [\"-c\", command];\n\n return new Promise((resolve, reject) => {\n const child = spawn(shell, shellArgs, {\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n env: process.env,\n cwd: commandCwd,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n\n child.stderr?.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n\n child.on(\"error\", (err: Error) => {\n reject(\n new ClafoutisError(\n \"postSync failed\",\n `Failed to spawn command: ${err.message}`,\n \"Check that the command is valid and executable\",\n ),\n );\n });\n\n child.on(\"close\", (code: number | null) => {\n if (code === 0) {\n if (stdout.trim()) {\n logger.info(stdout.trim());\n }\n logger.success(\"postSync completed\");\n resolve();\n } else {\n const output = [stdout, stderr].filter(Boolean).join(\"\\n\").trim();\n logger.error(`postSync output:\\n${output || \"(no output)\"}`);\n reject(\n new ClafoutisError(\n \"postSync failed\",\n `Command exited with code ${code}`,\n \"Review the command output above and fix any issues\",\n ),\n );\n }\n });\n });\n}\n","import * as p from \"@clack/prompts\";\nimport { Command } from \"commander\";\n\nimport { formatCommand } from \"./commands/format\";\nimport { generateCommand } from \"./commands/generate\";\nimport { initCommand } from \"./commands/init\";\nimport { syncCommand } from \"./commands/sync\";\nimport { ClafoutisError } from \"./utils/errors\";\n\nconst program = new Command();\n\n/**\n * Formats and displays an error using @clack/prompts styling when in TTY,\n * otherwise falls back to plain text formatting.\n */\nfunction displayError(err: ClafoutisError): void {\n if (process.stdin.isTTY) {\n p.log.error(`${err.title}: ${err.detail}`);\n if (err.suggestion) {\n p.log.info(`Suggestion: ${err.suggestion}`);\n }\n } else {\n console.error(err.format());\n }\n}\n\n/**\n * Wraps a command action with error handling for ClafoutisError instances.\n */\nfunction withErrorHandling<T>(\n fn: (options: T) => void | Promise<void>,\n): (options: T) => Promise<void> {\n return async (options: T): Promise<void> => {\n try {\n await fn(options);\n } catch (err) {\n if (err instanceof ClafoutisError) {\n displayError(err);\n process.exit(1);\n }\n throw err;\n }\n };\n}\n\n/**\n * Handles unexpected errors (both sync and async) with consistent formatting.\n */\nfunction handleUnexpectedError(err: unknown): void {\n if (err instanceof ClafoutisError) {\n displayError(err);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n if (process.stdin.isTTY) {\n p.log.error(`Unexpected error: ${message}`);\n p.log.info(\n \"Please report this issue at: https://github.com/Dessert-Labs/clafoutis/issues\",\n );\n } else {\n console.error(`\\nUnexpected error: ${message}\\n`);\n console.error(\n \"Please report this issue at: https://github.com/Dessert-Labs/clafoutis/issues\",\n );\n }\n }\n process.exit(1);\n}\n\nprocess.on(\"uncaughtException\", handleUnexpectedError);\n\nprocess.on(\"unhandledRejection\", (reason: unknown) => {\n handleUnexpectedError(reason);\n});\n\nprogram\n .name(\"clafoutis\")\n .description(\"GitOps powered design system - generate and sync design tokens\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"generate\")\n .description(\"Generate platform outputs from design tokens (for producers)\")\n .option(\n \"-c, --config <path>\",\n \"Path to config file\",\n \".clafoutis/producer.json\",\n )\n .option(\"--tailwind\", \"Generate Tailwind output\")\n .option(\"--figma\", \"Generate Figma variables\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./build\")\n .option(\"--cwd <path>\", \"Run command as if from this directory\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .action(withErrorHandling(generateCommand));\n\nprogram\n .command(\"sync\")\n .description(\"Sync design tokens from GitHub Release (for consumers)\")\n .option(\"-f, --force\", \"Force sync even if versions match\")\n .option(\n \"-c, --config <path>\",\n \"Path to config file\",\n \".clafoutis/consumer.json\",\n )\n .option(\"--cwd <path>\", \"Run command as if from this directory\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .action(withErrorHandling(syncCommand));\n\nprogram\n .command(\"init\")\n .description(\"Initialize Clafoutis configuration\")\n .option(\"--producer\", \"Set up as a design token producer\")\n .option(\"--consumer\", \"Set up as a design token consumer\")\n .option(\"-r, --repo <repo>\", \"GitHub repo for consumer mode (org/name)\")\n .option(\"-t, --tokens <path>\", \"Token directory path (default: ./tokens)\")\n .option(\"-o, --output <path>\", \"Output directory path (default: ./build)\")\n .option(\n \"-g, --generators <list>\",\n \"Comma-separated generators: tailwind, figma\",\n )\n .option(\"--workflow\", \"Create GitHub Actions workflow (default: true)\")\n .option(\"--no-workflow\", \"Skip GitHub Actions workflow\")\n .option(\n \"--files <mapping>\",\n \"File mappings for consumer: asset:dest,asset:dest\",\n )\n .option(\"--force\", \"Overwrite existing configuration\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .option(\"--non-interactive\", \"Skip prompts, use defaults or flags\")\n .option(\"--cwd <path>\", \"Run command as if from this directory\")\n .action(withErrorHandling(initCommand));\n\nprogram\n .command(\"format\")\n .description(\"Format token JSON files for consistent formatting\")\n .option(\"-t, --tokens <path>\", \"Token directory path\", \"./tokens\")\n .option(\n \"--check\",\n \"Check formatting without modifying files (fails if unformatted)\",\n )\n .option(\"--cwd <path>\", \"Run command as if from this directory\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .action(withErrorHandling(formatCommand));\n\nprogram.parse();\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clafoutis/cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "GitOps powered design system CLI - generate and sync design tokens",
5
5
  "author": "Dessert Labs",
6
6
  "license": "BUSL-1.1",