@dsai-io/tools 1.2.5 → 1.3.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/cli/index.js CHANGED
@@ -4566,13 +4566,98 @@ var init_groups = __esm({
4566
4566
  ];
4567
4567
  }
4568
4568
  });
4569
+
4570
+ // src/tokens/style-dictionary/preprocessors/fix-references.ts
4571
+ function fixValue(value, mappings) {
4572
+ if (typeof value !== "string" || !value.startsWith("{")) {
4573
+ return value;
4574
+ }
4575
+ let result = value;
4576
+ for (const mapping of mappings) {
4577
+ result = result.split(mapping[0]).join(mapping[1]);
4578
+ }
4579
+ return result;
4580
+ }
4581
+ function processTokens(obj, mappings) {
4582
+ for (const key of Object.keys(obj)) {
4583
+ const value = obj[key];
4584
+ if (value && typeof value === "object") {
4585
+ const typedValue = value;
4586
+ if ("$value" in typedValue) {
4587
+ typedValue["$value"] = fixValue(typedValue["$value"], mappings);
4588
+ } else if ("value" in typedValue) {
4589
+ typedValue["value"] = fixValue(typedValue["value"], mappings);
4590
+ } else {
4591
+ processTokens(typedValue, mappings);
4592
+ }
4593
+ }
4594
+ }
4595
+ }
4596
+ function createFixReferencesPreprocessor(mappings) {
4597
+ return {
4598
+ name: "fix-references-custom",
4599
+ preprocessor: (dictionary) => {
4600
+ processTokens(dictionary, mappings);
4601
+ return dictionary;
4602
+ }
4603
+ };
4604
+ }
4605
+ var DEFAULT_PATH_MAPPINGS, fixReferences;
4606
+ var init_fix_references = __esm({
4607
+ "src/tokens/style-dictionary/preprocessors/fix-references.ts"() {
4608
+ DEFAULT_PATH_MAPPINGS = [
4609
+ ["{colors.brand.", "{color."],
4610
+ ["{colors.neutral.", "{neutral."],
4611
+ ["{borders.width.", "{border.width."]
4612
+ ];
4613
+ fixReferences = {
4614
+ name: "fix-references",
4615
+ preprocessor: (dictionary) => {
4616
+ processTokens(dictionary, DEFAULT_PATH_MAPPINGS);
4617
+ return dictionary;
4618
+ }
4619
+ };
4620
+ }
4621
+ });
4622
+
4623
+ // src/tokens/style-dictionary/preprocessors/index.ts
4624
+ var preprocessors_exports = {};
4625
+ __export(preprocessors_exports, {
4626
+ builtInPreprocessors: () => builtInPreprocessors,
4627
+ createFixReferencesPreprocessor: () => createFixReferencesPreprocessor,
4628
+ fixReferences: () => fixReferences,
4629
+ registerPreprocessors: () => registerPreprocessors
4630
+ });
4631
+ function registerPreprocessors(sd, customPreprocessors = []) {
4632
+ const allPreprocessors = [...builtInPreprocessors, ...customPreprocessors];
4633
+ for (const preprocessor of allPreprocessors) {
4634
+ sd.registerPreprocessor({
4635
+ name: preprocessor.name,
4636
+ preprocessor: preprocessor.preprocessor
4637
+ });
4638
+ }
4639
+ }
4640
+ var builtInPreprocessors;
4641
+ var init_preprocessors = __esm({
4642
+ "src/tokens/style-dictionary/preprocessors/index.ts"() {
4643
+ init_fix_references();
4644
+ init_fix_references();
4645
+ builtInPreprocessors = [fixReferences];
4646
+ }
4647
+ });
4569
4648
  function generateThemeBuildConfig(options) {
4570
4649
  const { themeDefinition, files, outputDir, config } = options;
4571
4650
  const isDefault = themeDefinition.isDefault;
4572
4651
  const platformsMap = /* @__PURE__ */ new Map();
4573
4652
  const enabledFormats = config.formats;
4574
4653
  for (const format of enabledFormats) {
4575
- const platformConfig = generatePlatformConfig(format, themeDefinition, outputDir, isDefault);
4654
+ const platformConfig = generatePlatformConfig(
4655
+ format,
4656
+ themeDefinition,
4657
+ outputDir,
4658
+ isDefault,
4659
+ config.prefix
4660
+ );
4576
4661
  if (platformConfig) {
4577
4662
  platformsMap.set(format, platformConfig);
4578
4663
  }
@@ -4581,6 +4666,7 @@ function generateThemeBuildConfig(options) {
4581
4666
  return {
4582
4667
  source: files,
4583
4668
  platforms,
4669
+ preprocessors: ["fix-references"],
4584
4670
  // Enable DTCG format support (tokens with $value, $type, etc.)
4585
4671
  usesDtcg: true,
4586
4672
  // Configure logging to not throw on broken references (they'll be logged but build continues)
@@ -4593,7 +4679,7 @@ function generateThemeBuildConfig(options) {
4593
4679
  }
4594
4680
  };
4595
4681
  }
4596
- function generatePlatformConfig(format, themeDefinition, outputDir, isDefault) {
4682
+ function generatePlatformConfig(format, themeDefinition, outputDir, isDefault, prefix) {
4597
4683
  const formatConfig = FORMAT_MAPPING.get(format);
4598
4684
  if (!formatConfig) {
4599
4685
  console.warn(`Unknown format: ${format}`);
@@ -4608,8 +4694,15 @@ function generatePlatformConfig(format, themeDefinition, outputDir, isDefault) {
4608
4694
  destination: outputFile,
4609
4695
  format: sdFormat
4610
4696
  };
4697
+ if (prefix && (format === "css" || format === "scss")) {
4698
+ fileConfig.options = {
4699
+ ...fileConfig.options,
4700
+ prefix
4701
+ };
4702
+ }
4611
4703
  if (format === "css" && !isDefault) {
4612
4704
  fileConfig.options = {
4705
+ ...fileConfig.options,
4613
4706
  selector: themeDefinition.selector
4614
4707
  };
4615
4708
  }
@@ -4722,6 +4815,8 @@ async function runStyleDictionaryBuild(sdConfig, options) {
4722
4815
  registerCustomTransforms(StyleDictionary);
4723
4816
  const { registerTransformGroups: registerTransformGroups2 } = await Promise.resolve().then(() => (init_groups(), groups_exports));
4724
4817
  registerTransformGroups2(StyleDictionary);
4818
+ const { registerPreprocessors: registerPreprocessors2 } = await Promise.resolve().then(() => (init_preprocessors(), preprocessors_exports));
4819
+ registerPreprocessors2(StyleDictionary);
4725
4820
  if (options.verbose) {
4726
4821
  console.warn(` \u{1F527} Style Dictionary platforms:`);
4727
4822
  for (const [platform, config] of Object.entries(sdConfig.platforms)) {
@@ -4915,7 +5010,7 @@ var init_theme_builder = __esm({
4915
5010
  ["ios", { default: "ios/macros", themed: "ios/macros" }]
4916
5011
  ]);
4917
5012
  TRANSFORM_GROUPS = /* @__PURE__ */ new Map([
4918
- ["css", "css"],
5013
+ ["css", "custom/css"],
4919
5014
  ["scss", "scss"],
4920
5015
  ["js", "js-custom"],
4921
5016
  // Use custom transform group for valid JS identifiers
@@ -5154,7 +5249,7 @@ function getPipelinePaths(customPaths) {
5154
5249
  ...customPaths
5155
5250
  };
5156
5251
  }
5157
- function createStepFromName(stepName, tokensPackageDir, figmaExportsDir, tokensDir, paths, sdConfigFile, strict, snapshotService, themesConfig, outputDir, formats = ["css", "scss", "json"], cssOutputDir, postprocessConfig) {
5252
+ function createStepFromName(stepName, tokensPackageDir, figmaExportsDir, tokensDir, paths, sdConfigFile, strict, snapshotService, themesConfig, outputDir, formats = ["css", "scss", "json"], cssOutputDir, postprocessConfig, prefix) {
5158
5253
  const displayName = STEP_DISPLAY_NAMES.get(stepName) ?? `Unknown: ${stepName}`;
5159
5254
  switch (stepName) {
5160
5255
  case "validate":
@@ -5359,6 +5454,7 @@ function createStepFromName(stepName, tokensPackageDir, figmaExportsDir, tokensD
5359
5454
  const result = await buildAllThemes({
5360
5455
  config: {
5361
5456
  formats,
5457
+ prefix,
5362
5458
  themes: {
5363
5459
  definitions: themeDefinitions
5364
5460
  }
@@ -5474,7 +5570,8 @@ function createBuildSteps(tokensDir, _toolsDir, options, pipeline) {
5474
5570
  options.outputDir,
5475
5571
  formats,
5476
5572
  options.cssOutputDir,
5477
- options.postprocessConfig
5573
+ options.postprocessConfig,
5574
+ options.prefix
5478
5575
  );
5479
5576
  if (stepName === "validate" && skipValidate) {
5480
5577
  step.skip = true;
@@ -6859,78 +6956,6 @@ var init_types2 = __esm({
6859
6956
  }
6860
6957
  });
6861
6958
 
6862
- // src/tokens/style-dictionary/preprocessors/fix-references.ts
6863
- function fixValue(value, mappings) {
6864
- if (typeof value !== "string" || !value.startsWith("{")) {
6865
- return value;
6866
- }
6867
- let result = value;
6868
- for (const mapping of mappings) {
6869
- result = result.split(mapping[0]).join(mapping[1]);
6870
- }
6871
- return result;
6872
- }
6873
- function processTokens(obj, mappings) {
6874
- for (const key of Object.keys(obj)) {
6875
- const value = obj[key];
6876
- if (value && typeof value === "object") {
6877
- const typedValue = value;
6878
- if ("$value" in typedValue) {
6879
- typedValue["$value"] = fixValue(typedValue["$value"], mappings);
6880
- } else if ("value" in typedValue) {
6881
- typedValue["value"] = fixValue(typedValue["value"], mappings);
6882
- } else {
6883
- processTokens(typedValue, mappings);
6884
- }
6885
- }
6886
- }
6887
- }
6888
- function createFixReferencesPreprocessor(mappings) {
6889
- return {
6890
- name: "fix-references-custom",
6891
- preprocessor: (dictionary) => {
6892
- processTokens(dictionary, mappings);
6893
- return dictionary;
6894
- }
6895
- };
6896
- }
6897
- var DEFAULT_PATH_MAPPINGS, fixReferences;
6898
- var init_fix_references = __esm({
6899
- "src/tokens/style-dictionary/preprocessors/fix-references.ts"() {
6900
- DEFAULT_PATH_MAPPINGS = [
6901
- ["{colors.brand.", "{color."],
6902
- ["{colors.neutral.", "{neutral."],
6903
- ["{borders.width.", "{border.width."]
6904
- ];
6905
- fixReferences = {
6906
- name: "fix-references",
6907
- preprocessor: (dictionary) => {
6908
- processTokens(dictionary, DEFAULT_PATH_MAPPINGS);
6909
- return dictionary;
6910
- }
6911
- };
6912
- }
6913
- });
6914
-
6915
- // src/tokens/style-dictionary/preprocessors/index.ts
6916
- function registerPreprocessors(sd, customPreprocessors = []) {
6917
- const allPreprocessors = [...builtInPreprocessors, ...customPreprocessors];
6918
- for (const preprocessor of allPreprocessors) {
6919
- sd.registerPreprocessor({
6920
- name: preprocessor.name,
6921
- preprocessor: preprocessor.preprocessor
6922
- });
6923
- }
6924
- }
6925
- var builtInPreprocessors;
6926
- var init_preprocessors = __esm({
6927
- "src/tokens/style-dictionary/preprocessors/index.ts"() {
6928
- init_fix_references();
6929
- init_fix_references();
6930
- builtInPreprocessors = [fixReferences];
6931
- }
6932
- });
6933
-
6934
6959
  // src/tokens/style-dictionary/config.ts
6935
6960
  function createStyleDictionaryConfig(dsaiConfig, options = {}) {
6936
6961
  const {
@@ -8312,7 +8337,7 @@ function transformImports(content, options) {
8312
8337
  const { aliases } = options;
8313
8338
  let result = content;
8314
8339
  result = result.replace(
8315
- /(from\s+['"])(?:\.\.\/)+types(?:\/([^'"]+))?(['"])/g,
8340
+ /(from\s+['"])\.\.\/\.\.\/types(?:\/([^'"]+))?(['"])/g,
8316
8341
  (_match, prefix, subpath, suffix) => {
8317
8342
  if (subpath) {
8318
8343
  return `${prefix}${aliases.importAlias}${aliases.components}/types/${subpath}${suffix}`;
@@ -8320,6 +8345,18 @@ function transformImports(content, options) {
8320
8345
  return `${prefix}${aliases.importAlias}${aliases.components}/types${suffix}`;
8321
8346
  }
8322
8347
  );
8348
+ result = result.replace(
8349
+ /(from\s+['"])\.\.\/\.\.\/hooks\/(\w+)(['"])/g,
8350
+ `$1${aliases.importAlias}${aliases.hooks}/$2$3`
8351
+ );
8352
+ result = result.replace(
8353
+ /(from\s+['"])\.\.\/\.\.\/utils\/(\w+(?:\/\w+)?)(['"])/g,
8354
+ `$1${aliases.importAlias}${aliases.utils}/$2$3`
8355
+ );
8356
+ result = result.replace(
8357
+ /(from\s+['"])\.\.\/\.\.\/utils(['"])/g,
8358
+ `$1${aliases.importAlias}${aliases.utils}$2`
8359
+ );
8323
8360
  result = result.replace(
8324
8361
  /(from\s+['"])\.\.\/(([A-Z]\w+)(\/[^'"]+)?)(['"])/g,
8325
8362
  (_match, prefix, _fullPath, dirName, subPath, suffix) => {
@@ -8330,18 +8367,6 @@ function transformImports(content, options) {
8330
8367
  return `${prefix}${aliases.importAlias}${aliases.ui}/${kebab}${suffix}`;
8331
8368
  }
8332
8369
  );
8333
- result = result.replace(
8334
- /(from\s+['"])(?:\.\.\/)+hooks\/(\w+)(['"])/g,
8335
- `$1${aliases.importAlias}${aliases.hooks}/$2$3`
8336
- );
8337
- result = result.replace(
8338
- /(from\s+['"])(?:\.\.\/)+utils\/(\w+(?:\/\w+)?)(['"])/g,
8339
- `$1${aliases.importAlias}${aliases.utils}/$2$3`
8340
- );
8341
- result = result.replace(
8342
- /(from\s+['"])(?:\.\.\/)+utils(['"])/g,
8343
- `$1${aliases.importAlias}${aliases.utils}$2`
8344
- );
8345
8370
  return result;
8346
8371
  }
8347
8372
  function normalizeExtensions(content, tsx) {
@@ -8397,16 +8422,17 @@ function writeRegistryItems(tree, options) {
8397
8422
  for (const item of tree.items) {
8398
8423
  const targetBaseDir = getTargetDir(item.type, aliases);
8399
8424
  for (const file of item.files) {
8400
- const fileName = basename(file.path);
8401
8425
  let targetPath;
8402
8426
  if (file.target) {
8403
8427
  targetPath = join(projectDir, file.target);
8404
8428
  } else if (item.type === "registry:ui" || item.type === "registry:component") {
8405
- targetPath = join(projectDir, targetBaseDir, item.name, fileName);
8406
- } else if (item.type === "registry:type") {
8429
+ targetPath = join(projectDir, targetBaseDir, item.name, basename(file.path));
8430
+ } else if (item.type === "registry:hook") {
8431
+ targetPath = join(projectDir, targetBaseDir, item.name, basename(file.path));
8432
+ } else if (file.path.includes("/")) {
8407
8433
  targetPath = join(projectDir, targetBaseDir, file.path);
8408
8434
  } else {
8409
- targetPath = join(projectDir, targetBaseDir, fileName);
8435
+ targetPath = join(projectDir, targetBaseDir, basename(file.path));
8410
8436
  }
8411
8437
  if (existsSync(targetPath) && !shouldOverwrite) {
8412
8438
  if (log) log(` Skipped (exists): ${targetPath}`);
@@ -8708,9 +8734,9 @@ function formatCount(count, singular, plural) {
8708
8734
  }
8709
8735
 
8710
8736
  // src/cli/commands/add.ts
8711
- var VALID_TYPES = ["ui", "hook", "util", "lib", "type", "style"];
8737
+ var VALID_TYPES = ["ui", "hook", "util", "lib", "type"];
8712
8738
  function createAddCommand() {
8713
- const cmd = new Command("add").description("Add DSAi items (components, hooks, utils) to your project").argument("[items...]", "Item names to add (e.g., button use-focus-trap cn)").option("--all", "Add all items of the specified type (default: ui)", false).option("--type <type>", "Filter by type: ui, hook, util, lib, type").option("--overwrite", "Overwrite existing files", false).option("--dry-run", "Preview changes without writing files", false).option("--registry <path>", "Path to local registry directory").option("--list", "List all available items", false).action(async (items, opts, cmdObj) => {
8739
+ const cmd = new Command("add").description("Add DSAi items (components, hooks, utils) to your project").argument("[items...]", "Item names to add (e.g., button use-focus-trap cn)").option("--all", "Add all items of the specified type (default: ui)", false).option("--type <type>", "Filter by type: ui, hook, util, type").option("--overwrite", "Overwrite existing files", false).option("--dry-run", "Preview changes without writing files", false).option("--registry <path>", "Path to local registry directory").option("--list", "List all available items", false).action(async (items, opts, cmdObj) => {
8714
8740
  const parentOpts = cmdObj.parent?.opts() ?? {};
8715
8741
  const allOpts = {
8716
8742
  ...parentOpts,
@@ -8760,7 +8786,7 @@ ${colors.bold("Available items:")}
8760
8786
  if (!grouped[type]) grouped[type] = [];
8761
8787
  grouped[type].push(item);
8762
8788
  }
8763
- const displayOrder = ["ui", "hook", "util", "lib", "type", "style"];
8789
+ const displayOrder = ["ui", "hook", "util", "lib", "type"];
8764
8790
  for (const type of displayOrder) {
8765
8791
  const typeItems = grouped[type];
8766
8792
  if (!typeItems || typeItems.length === 0) continue;
@@ -9364,6 +9390,8 @@ async function runTokensBuild(options) {
9364
9390
  pipeline: config.tokens.pipeline,
9365
9391
  // Pass formats from config (default: css, scss, json)
9366
9392
  formats: config.tokens.formats,
9393
+ // Pass CSS custom property prefix from config
9394
+ prefix: config.tokens.prefix,
9367
9395
  // Pass output directory from config
9368
9396
  outputDir: config.tokens.outputDir ? resolve(configDir, config.tokens.outputDir) : resolve(configDir, "dist"),
9369
9397
  // Pass themes config for multi-theme builds
@@ -14059,7 +14087,7 @@ function analyzeImports(files, knownNpmDeps) {
14059
14087
  importPattern.lastIndex = 0;
14060
14088
  while ((m2 = importPattern.exec(file.content)) !== null) {
14061
14089
  const specifier = m2[1] ?? "";
14062
- const typesPattern = /\.\.\/(?:\.\.\/)?types(?:\/.*)?$/;
14090
+ const typesPattern = /^\.\.\/\.\.\/types(?:\/.*)?$/;
14063
14091
  if (typesPattern.test(specifier)) {
14064
14092
  registryDeps.add("dsai-types");
14065
14093
  continue;
@@ -14079,6 +14107,16 @@ function analyzeImports(files, knownNpmDeps) {
14079
14107
  if (regName) registryDeps.add(regName);
14080
14108
  continue;
14081
14109
  }
14110
+ const siblingUtilPattern = /^\.\.\/([a-z][\w-]*)(?:\/.*)?$/;
14111
+ const siblingUtilMatch = siblingUtilPattern.exec(specifier);
14112
+ if (siblingUtilMatch && siblingUtilMatch[1]) {
14113
+ const siblingDir = siblingUtilMatch[1];
14114
+ const regName = UTIL_SUBPATH_TO_REGISTRY[siblingDir];
14115
+ if (regName) {
14116
+ registryDeps.add(regName);
14117
+ continue;
14118
+ }
14119
+ }
14082
14120
  const compPattern = /^\.\.\/(\.\.\/)?(?:components\/)?([A-Z]\w+)(?:\/.*)?$/;
14083
14121
  const compMatch = compPattern.exec(specifier);
14084
14122
  if (compMatch && compMatch[2]) {
@@ -14222,6 +14260,8 @@ function buildTypesItem(reactSrcDir, log) {
14222
14260
  const files = sourceFiles.map((f) => {
14223
14261
  let content = f.content;
14224
14262
  content = content.replace(/export \{[^}]*\} from ['"]\.\.\/utils\/[^'"]+['"];?\n?/g, "");
14263
+ content = content.replace(/export\s+(?!type)\{[^}]*\}\s+from\s+['"]\.\/[^'"]+['"];?\n?/g, "");
14264
+ content = content.replace(/\/\*\*\s*\n\s*\*\s*@deprecated[^*]*\*\/\s*\n/g, "");
14225
14265
  return {
14226
14266
  path: `types/${f.path}`,
14227
14267
  type: "registry:type",
@@ -14364,9 +14404,135 @@ function createRegistryCommand() {
14364
14404
  }
14365
14405
 
14366
14406
  // src/version.ts
14367
- var version = "0.0.1";
14368
-
14369
- // src/cli/create-program.ts
14407
+ var version = "1.3.0";
14408
+
14409
+ // src/cli/commands/info.ts
14410
+ var registry = {
14411
+ package: "@dsai-io/tools",
14412
+ version,
14413
+ description: "Design System AI Toolkit \u2014 build, validate, and manage design tokens and icons.",
14414
+ documentation: "https://github.com/michelve/dsai",
14415
+ cli: {
14416
+ binary: "dsai",
14417
+ globalOptions: [
14418
+ { flag: "-c, --config <path>", description: "Path to config file" },
14419
+ { flag: "--cwd <dir>", description: "Working directory" },
14420
+ { flag: "--debug", description: "Enable debug mode" },
14421
+ { flag: "-q, --quiet", description: "Quiet mode \u2014 minimal output" },
14422
+ { flag: "--dry-run", description: "Dry run \u2014 don't write files" },
14423
+ { flag: "-v, --version", description: "Show version number" },
14424
+ { flag: "-h, --help", description: "Show help" }
14425
+ ],
14426
+ commands: [
14427
+ {
14428
+ name: "add [items...]",
14429
+ description: "Add DSAi items (components, hooks, utils) to your project",
14430
+ options: ["--all", "--type <type>", "--overwrite", "--dry-run", "--list"]
14431
+ },
14432
+ {
14433
+ name: "tokens build",
14434
+ description: "Build design tokens from source collections",
14435
+ options: ["--platforms <list>", "--watch", "--clean", "--theme <name>", "--list-themes"]
14436
+ },
14437
+ {
14438
+ name: "tokens validate",
14439
+ description: "Validate design token files",
14440
+ options: ["--fix", "--strict"]
14441
+ },
14442
+ {
14443
+ name: "tokens transform",
14444
+ description: "Transform Figma exports to Style Dictionary format",
14445
+ options: ["--dry-run", "--default-mode <mode>", "--ignore-modes <list>"]
14446
+ },
14447
+ {
14448
+ name: "tokens sync",
14449
+ description: "Sync tokens flat file",
14450
+ options: ["--format <format>"]
14451
+ },
14452
+ {
14453
+ name: "tokens postprocess",
14454
+ description: "Post-process CSS theme files",
14455
+ options: []
14456
+ },
14457
+ {
14458
+ name: "tokens snapshots list",
14459
+ description: "List all token collection snapshots",
14460
+ options: []
14461
+ },
14462
+ {
14463
+ name: "tokens snapshots info <id>",
14464
+ description: "Show snapshot details",
14465
+ options: []
14466
+ },
14467
+ {
14468
+ name: "tokens snapshots rollback <id>",
14469
+ description: "Rollback to a snapshot",
14470
+ options: ["--dry-run"]
14471
+ },
14472
+ {
14473
+ name: "icons build",
14474
+ description: "Generate icon components from SVG files",
14475
+ options: ["--format <format>", "--no-optimize", "--dry-run"]
14476
+ },
14477
+ {
14478
+ name: "init",
14479
+ description: "Initialize DSAi configuration with interactive prompts",
14480
+ options: ["--yes", "--template <template>", "--force"]
14481
+ },
14482
+ {
14483
+ name: "config",
14484
+ description: "Display resolved configuration",
14485
+ options: ["--json"]
14486
+ },
14487
+ {
14488
+ name: "registry build",
14489
+ description: "Build component registry JSON from source",
14490
+ options: ["--src <path>", "--out <path>", "--verbose"]
14491
+ },
14492
+ {
14493
+ name: "info",
14494
+ description: "Show tool inventory and capabilities",
14495
+ options: ["--json"]
14496
+ }
14497
+ ]
14498
+ }
14499
+ };
14500
+ function printInfo() {
14501
+ const log = (msg) => {
14502
+ console.log(msg);
14503
+ };
14504
+ log("");
14505
+ log(colors.bold(`${registry.package} v${registry.version}`));
14506
+ log(colors.muted(registry.description));
14507
+ log(colors.muted("\u2500".repeat(60)));
14508
+ log("");
14509
+ log(colors.bold("CLI Commands"));
14510
+ log("");
14511
+ for (const cmd of registry.cli.commands) {
14512
+ const opts = cmd.options.length > 0 ? colors.muted(` [${cmd.options.join(", ")}]`) : "";
14513
+ log(` ${colors.command(`dsai ${cmd.name}`)}${opts}`);
14514
+ log(` ${colors.muted(cmd.description)}`);
14515
+ }
14516
+ log("");
14517
+ log(colors.bold("Global Options"));
14518
+ log("");
14519
+ for (const opt of registry.cli.globalOptions) {
14520
+ log(` ${colors.cyan(opt.flag)} ${colors.muted(opt.description)}`);
14521
+ }
14522
+ log("");
14523
+ log(colors.bold("Documentation"));
14524
+ log(` ${colors.path(registry.documentation)}`);
14525
+ log("");
14526
+ }
14527
+ function createInfoCommand() {
14528
+ return new Command("info").description("Show tool inventory and capabilities").option("--json", "Output as JSON for agent consumption", false).action((options) => {
14529
+ if (options.json) {
14530
+ console.log(JSON.stringify(registry, null, 2));
14531
+ } else {
14532
+ printInfo();
14533
+ }
14534
+ });
14535
+ }
14370
14536
  function createProgram() {
14371
14537
  const program2 = new Command().name("dsai").description(
14372
14538
  `${colors.bold("DSAI Tools")} - Design System AI Toolkit
@@ -14433,6 +14599,7 @@ async function run(args = process.argv) {
14433
14599
  program.addCommand(createInitCommand());
14434
14600
  program.addCommand(createConfigCommand());
14435
14601
  program.addCommand(createRegistryCommand());
14602
+ program.addCommand(createInfoCommand());
14436
14603
  setupErrorHandling(program);
14437
14604
  await program.parseAsync(args);
14438
14605
  }