@yamada-ui/cli 2.0.0-dev-20250823131710 → 2.0.0-dev-20250824091139

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +847 -234
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
2
  import checkNode from "cli-check-node";
3
- import unhandledError from "cli-handle-unhandled";
4
3
  import { Command } from "commander";
5
4
  import c from "picocolors";
6
5
  import process$1, { env } from "node:process";
@@ -10,7 +9,7 @@ import path from "node:path";
10
9
  import { format, promisify } from "node:util";
11
10
  import os from "node:os";
12
11
  import fs, { existsSync, realpathSync, statSync } from "fs";
13
- import os$1 from "os";
12
+ import os$1, { tmpdir } from "os";
14
13
  import path$1 from "path";
15
14
  import fs$1 from "node:fs";
16
15
  import tty from "node:tty";
@@ -18,24 +17,25 @@ import semverDiff from "semver/functions/diff.js";
18
17
  import semverGt from "semver/functions/gt.js";
19
18
  import semver from "semver";
20
19
  import boxen from "boxen";
21
- import { getObject, isArray, isObject, isString, isUndefined, merge, omitObject } from "@yamada-ui/utils";
22
- import { mkdir, readFile, readdir, writeFile } from "fs/promises";
20
+ import { getObject, isArray, isObject, isString, isUndefined, merge, omitObject, toArray } from "@yamada-ui/utils";
21
+ import { mkdir, mkdtemp, readFile, readdir, writeFile } from "fs/promises";
23
22
  import { Listr } from "listr2";
24
23
  import ora from "ora";
25
24
  import prompts from "prompts";
26
- import { execa } from "execa";
25
+ import { ExecaError, execa } from "execa";
27
26
  import "validate-npm-package-name";
28
27
  import YAML from "yamljs";
29
28
  import { glob } from "glob";
30
29
  import { ESLint } from "eslint";
31
30
  import { format as format$1, resolveConfig, resolveConfigFile } from "prettier";
31
+ import { transform } from "sucrase";
32
32
  import { build } from "esbuild";
33
33
  import nodeEval from "node-eval";
34
34
  import { Script } from "vm";
35
35
  import { HttpsProxyAgent } from "https-proxy-agent";
36
36
  import fetch from "node-fetch";
37
- import { diffLines } from "diff";
38
37
  import { rimraf } from "rimraf";
38
+ import { diffLines } from "diff";
39
39
 
40
40
  //#region rolldown:runtime
41
41
  var __create = Object.create;
@@ -5062,13 +5062,13 @@ var MissingValueError = class extends Error {
5062
5062
  this.key = key;
5063
5063
  }
5064
5064
  };
5065
- function pupa(template, data, { ignoreMissing = false, transform = ({ value }) => value } = {}) {
5065
+ function pupa(template, data, { ignoreMissing = false, transform: transform$1 = ({ value }) => value } = {}) {
5066
5066
  if (typeof template !== "string") throw new TypeError(`Expected a \`string\` in the first argument, got \`${typeof template}\``);
5067
5067
  if (typeof data !== "object") throw new TypeError(`Expected an \`object\` or \`Array\` in the second argument, got \`${typeof data}\``);
5068
5068
  const replace = (placeholder, key) => {
5069
5069
  let value = data;
5070
5070
  for (const property of key.split(".")) value = value ? value[property] : void 0;
5071
- const transformedValue = transform({
5071
+ const transformedValue = transform$1({
5072
5072
  value,
5073
5073
  key
5074
5074
  });
@@ -5230,7 +5230,6 @@ var dependencies = {
5230
5230
  "@yamada-ui/utils": "workspace:*",
5231
5231
  "boxen": "^8.0.1",
5232
5232
  "cli-check-node": "^1.3.4",
5233
- "cli-handle-unhandled": "^1.1.2",
5234
5233
  "commander": "^14.0.0",
5235
5234
  "diff": "^8.0.2",
5236
5235
  "esbuild": "^0.25.8",
@@ -5247,6 +5246,7 @@ var dependencies = {
5247
5246
  "prompts": "^2.4.2",
5248
5247
  "rimraf": "^6.0.1",
5249
5248
  "semver": "^7.7.2",
5249
+ "sucrase": "^3.35.0",
5250
5250
  "validate-npm-package-name": "^6.0.2",
5251
5251
  "yamljs": "^0.3.0"
5252
5252
  };
@@ -5283,7 +5283,7 @@ var package_default = {
5283
5283
 
5284
5284
  //#endregion
5285
5285
  //#region src/utils/lint.ts
5286
- async function lint(content, { cwd: cwd$3, enabled = true, filePath } = {}) {
5286
+ async function lintText(content, { cwd: cwd$3, enabled = true, filePath } = {}) {
5287
5287
  if (!enabled) return content;
5288
5288
  try {
5289
5289
  const eslint = new ESLint({
@@ -5297,10 +5297,21 @@ async function lint(content, { cwd: cwd$3, enabled = true, filePath } = {}) {
5297
5297
  return content;
5298
5298
  }
5299
5299
  }
5300
+ async function lintFiles(patterns, { cwd: cwd$3, enabled = true } = {}) {
5301
+ if (!enabled) return;
5302
+ try {
5303
+ const eslint = new ESLint({
5304
+ cwd: cwd$3,
5305
+ fix: true
5306
+ });
5307
+ const results = await eslint.lintFiles(patterns);
5308
+ await ESLint.outputFixes(results);
5309
+ } catch {}
5310
+ }
5300
5311
 
5301
5312
  //#endregion
5302
5313
  //#region src/utils/prettier.ts
5303
- async function format$2(content, { configPath, enabled = true,...options } = {}) {
5314
+ async function formatText(content, { configPath, enabled = true,...options } = {}) {
5304
5315
  if (!enabled) return content;
5305
5316
  try {
5306
5317
  configPath ??= await resolveConfigFile();
@@ -5314,6 +5325,15 @@ async function format$2(content, { configPath, enabled = true,...options } = {})
5314
5325
  return content;
5315
5326
  }
5316
5327
  }
5328
+ async function formatFiles(patterns, { enabled = true,...options } = {}) {
5329
+ if (!enabled) return;
5330
+ patterns = toArray(patterns);
5331
+ await Promise.all(patterns.map(async (pattern) => {
5332
+ let content = await readFile(pattern, "utf-8");
5333
+ content = await formatText(content, options);
5334
+ await writeFile(pattern, content, "utf-8");
5335
+ }));
5336
+ }
5317
5337
 
5318
5338
  //#endregion
5319
5339
  //#region src/utils/fs.ts
@@ -5326,13 +5346,13 @@ async function isWriteable(directory) {
5326
5346
  return false;
5327
5347
  }
5328
5348
  }
5329
- async function writeFile$1(path$9, content, { format: formatConfig, lint: lintConfig,...rest } = {}) {
5330
- content = await lint(content, {
5331
- cwd: rest.cwd ?? cwd,
5332
- ...lintConfig
5349
+ async function writeFile$1(path$9, content, options = {}) {
5350
+ await writeFile(path$9, content, options.encoding ?? "utf-8");
5351
+ await lintFiles(path$9, {
5352
+ cwd: options.cwd ?? cwd,
5353
+ ...options.lint
5333
5354
  });
5334
- content = await format$2(content, formatConfig);
5335
- await writeFile(path$9, content, rest.encoding ?? "utf-8");
5355
+ await formatFiles(path$9, options.format);
5336
5356
  }
5337
5357
  async function writeFileSafe(path$9, content, options) {
5338
5358
  if (path$9.includes("/")) {
@@ -5343,9 +5363,9 @@ async function writeFileSafe(path$9, content, options) {
5343
5363
  }
5344
5364
  async function validateDir(path$9) {
5345
5365
  const writeable = await isWriteable(path$9);
5346
- if (!writeable) throw new Error(`The path ${path$9} does not writeable. Please check the permissions.`);
5347
- if (!existsSync(path$9)) throw new Error(`The path ${path$9} does not exist. Please try again.`);
5348
- if (!statSync(path$9).isDirectory()) throw new Error(`The path ${path$9} is not a directory. Please try again.`);
5366
+ if (!writeable) throw new Error(`The path ${c.yellow(path$9)} does not writeable. Please check the permissions.`);
5367
+ if (!existsSync(path$9)) throw new Error(`The path ${c.yellow(path$9)} does not exist. Please try again.`);
5368
+ if (!statSync(path$9).isDirectory()) throw new Error(`The path ${c.yellow(path$9)} is not a directory. Please try again.`);
5349
5369
  return true;
5350
5370
  }
5351
5371
  function timer() {
@@ -5361,28 +5381,31 @@ function timer() {
5361
5381
  start
5362
5382
  };
5363
5383
  }
5364
- async function getComponentFiles(componentName, { srcPath }) {
5384
+ async function getFiles(pattern) {
5365
5385
  const files$1 = {};
5366
- const [dirPath] = await glob(path$1.join(srcPath, "**", componentName));
5367
- if (!dirPath) return files$1;
5386
+ const [dirPath] = await glob(pattern);
5368
5387
  const dirents = await readdir(dirPath, { withFileTypes: true });
5369
5388
  await Promise.all(dirents.map(async (dirent) => {
5370
5389
  const name$1 = dirent.name;
5371
5390
  if (dirent.isDirectory()) {
5372
- const data = await readdir(path$1.join(dirent.parentPath, name$1), { withFileTypes: true });
5373
- await Promise.all(data.map(async (dirent$1) => {
5391
+ const dirents$1 = await readdir(path$1.join(dirent.parentPath, name$1), { withFileTypes: true });
5392
+ await Promise.all(dirents$1.map(async (dirent$1) => {
5374
5393
  if (dirent$1.isDirectory()) return;
5394
+ if (dirent$1.name === REGISTRY_FILE_NAME) return;
5375
5395
  const targetPath = path$1.join(dirent$1.parentPath, dirent$1.name);
5376
- const data$1 = await readFile(targetPath, "utf-8");
5377
- files$1[`${name$1}/${dirent$1.name}`] = data$1;
5396
+ const data = await readFile(targetPath, "utf-8");
5397
+ files$1[`${name$1}/${dirent$1.name}`] = data;
5378
5398
  }));
5379
- } else {
5399
+ } else if (name$1 !== REGISTRY_FILE_NAME) {
5380
5400
  const targetPath = path$1.join(dirent.parentPath, dirent.name);
5381
5401
  const data = await readFile(targetPath, "utf-8");
5382
5402
  files$1[name$1] = data;
5383
5403
  }
5384
5404
  }));
5385
- return files$1;
5405
+ return {
5406
+ dirPath,
5407
+ files: files$1
5408
+ };
5386
5409
  }
5387
5410
 
5388
5411
  //#endregion
@@ -5404,7 +5427,6 @@ async function getPackageJson(cwd$3) {
5404
5427
  }
5405
5428
  function getVersion({ dependencies: dependencies$1, devDependencies: devDependencies$1 }, nameWithVersion) {
5406
5429
  const [name$1, version$1] = splitVersion(nameWithVersion);
5407
- if (!name$1) return;
5408
5430
  let currentVersion;
5409
5431
  if (isObject(dependencies$1) && name$1 in dependencies$1) currentVersion = dependencies$1[name$1];
5410
5432
  else if (isObject(devDependencies$1) && name$1 in devDependencies$1) currentVersion = devDependencies$1[name$1];
@@ -5433,6 +5455,9 @@ function splitVersion(value) {
5433
5455
  } else return value.split("@");
5434
5456
  }
5435
5457
  function getPackageName(value) {
5458
+ return splitVersion(value)[0];
5459
+ }
5460
+ function getPackageNameWithVersion(value) {
5436
5461
  return isObject(value) ? `${value.name}@${value.wanted}` : value;
5437
5462
  }
5438
5463
  function packageAddArgs(packageManager, { dev = false, exact = false } = {}) {
@@ -5480,6 +5505,16 @@ async function installDependencies(dependencies$1, { cwd: cwd$3, dev, exact = tr
5480
5505
  stdout: "ignore"
5481
5506
  });
5482
5507
  }
5508
+ async function uninstallDependencies(dependencies$1, { cwd: cwd$3 } = {}) {
5509
+ const packageManager = getPackageManager();
5510
+ if (dependencies$1.length) {
5511
+ const command = packageManager === "npm" ? "uninstall" : "remove";
5512
+ await execa(packageManager, [command, ...dependencies$1], {
5513
+ cwd: cwd$3,
5514
+ stdout: "ignore"
5515
+ });
5516
+ }
5517
+ }
5483
5518
  async function addWorkspace(cwd$3, workspacePath, config$1) {
5484
5519
  const packageManager = getPackageManager();
5485
5520
  switch (packageManager) {
@@ -5513,14 +5548,40 @@ async function addWorkspace(cwd$3, workspacePath, config$1) {
5513
5548
  }
5514
5549
  }
5515
5550
 
5551
+ //#endregion
5552
+ //#region src/utils/typescript.ts
5553
+ function transformExtension(value, jsx) {
5554
+ if (!jsx) return value;
5555
+ const extension = value.split(".").at(-1);
5556
+ if (extension === "tsx") return value.replace(/\.tsx$/, ".jsx");
5557
+ if (extension === "ts") return value.replace(/\.ts$/, ".js");
5558
+ return value;
5559
+ }
5560
+ function isTsx(value) {
5561
+ return value.endsWith(".tsx");
5562
+ }
5563
+ function isJsx(value) {
5564
+ return value.endsWith(".jsx");
5565
+ }
5566
+ function transformTsxToJsx(content) {
5567
+ return transform(content, {
5568
+ jsxRuntime: "preserve",
5569
+ transforms: ["jsx", "typescript"]
5570
+ }).code;
5571
+ }
5572
+ function transformTsToJs(content) {
5573
+ return transform(content, { transforms: ["typescript"] }).code;
5574
+ }
5575
+
5516
5576
  //#endregion
5517
5577
  //#region src/utils/config.ts
5518
- async function getConfig(cwd$3, configPath, { format: format$3, lint: lint$1 } = {}) {
5578
+ async function getConfig(cwd$3, configPath, { format: format$2, jsx, lint } = {}) {
5519
5579
  try {
5520
- const data = await readFile(path$1.resolve(cwd$3, configPath), "utf8");
5580
+ const data = await readFile(path$1.resolve(cwd$3, configPath), "utf-8");
5521
5581
  const userConfig = JSON.parse(data);
5522
- if (!isUndefined(format$3)) userConfig.format = { enabled: format$3 };
5523
- if (!isUndefined(lint$1)) userConfig.lint = { enabled: lint$1 };
5582
+ if (!isUndefined(format$2)) userConfig.format = { enabled: format$2 };
5583
+ if (!isUndefined(lint)) userConfig.lint = { enabled: lint };
5584
+ if (!isUndefined(jsx)) userConfig.jsx = jsx;
5524
5585
  const rootPath = path$1.resolve(cwd$3, userConfig.path ?? (userConfig.monorepo ? DEFAULT_PATH.monorepo : DEFAULT_PATH.polyrepo));
5525
5586
  const src = existsSync(path$1.resolve(rootPath, "src"));
5526
5587
  const srcPath = src ? path$1.resolve(rootPath, "src") : rootPath;
@@ -5529,9 +5590,13 @@ async function getConfig(cwd$3, configPath, { format: format$3, lint: lint$1 } =
5529
5590
  const replacedSection = path$9.replace(/(\.\.\/|\.\/)/g, "").replace(/(^\/|\/$)/g, "");
5530
5591
  return [section, replacedSection];
5531
5592
  }));
5532
- userConfig.lint ??= {};
5533
- userConfig.lint.filePath ??= path$1.resolve(srcPath, "index.ts");
5534
- function getSectionAbsolutePath(section) {
5593
+ const indexPath = path$1.resolve(srcPath, transformExtension("index.ts", userConfig.jsx));
5594
+ const registryPath = path$1.resolve(srcPath, REGISTRY_FILE_NAME);
5595
+ if (userConfig.theme?.path) userConfig.theme.path = path$1.resolve(cwd$3, userConfig.theme.path);
5596
+ function isSection(section) {
5597
+ return SECTION_NAMES.includes(section);
5598
+ }
5599
+ function getSectionResolvedPath(section) {
5535
5600
  return path$1.resolve(srcPath, userConfig[section]?.path ?? DEFAULT_PATH[section]);
5536
5601
  }
5537
5602
  function getSectionPath(section) {
@@ -5546,8 +5611,8 @@ async function getConfig(cwd$3, configPath, { format: format$3, lint: lint$1 } =
5546
5611
  const section = value;
5547
5612
  return {
5548
5613
  ...userConfig[section],
5549
- absolutePath: getSectionAbsolutePath(section),
5550
5614
  path: getSectionPath(section),
5615
+ resolvedPath: getSectionResolvedPath(section),
5551
5616
  section
5552
5617
  };
5553
5618
  } else {
@@ -5556,8 +5621,8 @@ async function getConfig(cwd$3, configPath, { format: format$3, lint: lint$1 } =
5556
5621
  const section = result;
5557
5622
  return {
5558
5623
  ...userConfig[section],
5559
- absolutePath: getSectionAbsolutePath(section),
5560
5624
  path: getSectionPath(section),
5625
+ resolvedPath: getSectionResolvedPath(section),
5561
5626
  section
5562
5627
  };
5563
5628
  }
@@ -5567,8 +5632,11 @@ async function getConfig(cwd$3, configPath, { format: format$3, lint: lint$1 } =
5567
5632
  src,
5568
5633
  cwd: cwd$3,
5569
5634
  getSection,
5570
- getSectionAbsolutePath,
5571
5635
  getSectionPath,
5636
+ getSectionResolvedPath,
5637
+ indexPath,
5638
+ isSection,
5639
+ registryPath,
5572
5640
  rootPath,
5573
5641
  srcPath
5574
5642
  };
@@ -5576,7 +5644,7 @@ async function getConfig(cwd$3, configPath, { format: format$3, lint: lint$1 } =
5576
5644
  const packageManager = getPackageManager();
5577
5645
  const { args, command } = packageExecuteCommands(packageManager);
5578
5646
  const prefix = `${command}${args.length ? ` ${args.join(" ")}` : ""}`;
5579
- throw new Error(`No config found. Please run ${c.cyan(`${prefix} ${package_default.name}@latest init`)}.`);
5647
+ throw new Error(`No ${c.yellow("config")} found. Please run ${c.cyan(`${prefix} ${package_default.name}@latest init`)}.`);
5580
5648
  }
5581
5649
  }
5582
5650
 
@@ -5671,7 +5739,7 @@ async function fetchRegistries(names, config$1, { cache: cache$1 = true, depende
5671
5739
  results[name$1] = await results[name$1];
5672
5740
  const { dependencies: dependencies$1, dependents, section } = results[name$1];
5673
5741
  const target = [];
5674
- if (section === "root" || section === "theme") return;
5742
+ if (!config$1.isSection(section)) return;
5675
5743
  withDependencies = withDependencies && (config$1[section]?.dependents ?? true);
5676
5744
  withDependents = withDependents && (config$1[section]?.dependencies ?? false);
5677
5745
  if (withDependencies && dependents) {
@@ -5691,10 +5759,13 @@ async function fetchRegistries(names, config$1, { cache: cache$1 = true, depende
5691
5759
  await fetch$1(names);
5692
5760
  return results;
5693
5761
  }
5762
+ async function fetchLocaleRegistry(path$9) {
5763
+ return JSON.parse(await readFile(path$9, "utf-8"));
5764
+ }
5694
5765
  async function getGeneratedNameMap(config$1) {
5695
5766
  const results = await Promise.all(SECTION_NAMES.map(async (section) => {
5696
5767
  try {
5697
- const sectionPath = config$1.getSectionAbsolutePath(section);
5768
+ const sectionPath = config$1.getSectionResolvedPath(section);
5698
5769
  const dirents = await readdir(sectionPath, { withFileTypes: true });
5699
5770
  return [section, dirents.filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)];
5700
5771
  } catch {
@@ -5746,6 +5817,18 @@ function transformContent(targetSection, content, { getSection }, generatedNames
5746
5817
  });
5747
5818
  return content;
5748
5819
  }
5820
+ async function transformContentWithFormatAndLint(filePath, section, content, config$1, generatedNames) {
5821
+ const { cwd: cwd$3, format: format$2, jsx, lint } = config$1;
5822
+ content = transformContent(section, content, config$1, generatedNames);
5823
+ if (jsx) content = isJsx(filePath) ? transformTsxToJsx(content) : transformTsToJs(content);
5824
+ content = await lintText(content, {
5825
+ ...lint,
5826
+ cwd: cwd$3,
5827
+ filePath
5828
+ });
5829
+ content = await formatText(content, format$2);
5830
+ return content;
5831
+ }
5749
5832
  function transformTemplateContent(template, data) {
5750
5833
  let content = template;
5751
5834
  Object.entries(data).forEach(([key, value]) => {
@@ -5753,20 +5836,7 @@ function transformTemplateContent(template, data) {
5753
5836
  });
5754
5837
  return content;
5755
5838
  }
5756
- async function generateSources(dirPath, { section, sources }, config$1, generatedNames = []) {
5757
- await Promise.all(sources.map(async ({ name: fileName, content, data, template }) => {
5758
- const targetPath = path$1.resolve(dirPath, fileName);
5759
- if (content) {
5760
- content = transformContent(section, content, config$1, generatedNames);
5761
- await writeFileSafe(targetPath, content, config$1);
5762
- } else if (template && data) await Promise.all(data.map(async ({ name: fileName$1,...rest }) => {
5763
- content = transformTemplateContent(template, rest);
5764
- content = transformContent(section, content, config$1, generatedNames);
5765
- await writeFileSafe(path$1.resolve(targetPath, fileName$1), content, config$1);
5766
- }));
5767
- }));
5768
- }
5769
- function replaceIndex(generatedNames, content, { getSection }) {
5839
+ function transformIndex(generatedNames, content, { getSection }) {
5770
5840
  const matches = content.matchAll(/from\s+["']([^"']+)["']/g);
5771
5841
  matches.forEach((match) => {
5772
5842
  const [searchValue, value] = match;
@@ -5791,10 +5861,42 @@ function replaceIndex(generatedNames, content, { getSection }) {
5791
5861
  });
5792
5862
  return content;
5793
5863
  }
5864
+ async function transformIndexWithFormatAndLint(content, config$1, generatedNames) {
5865
+ const { cwd: cwd$3, format: format$2, indexPath, jsx, lint } = config$1;
5866
+ content = transformIndex(generatedNames, content, config$1);
5867
+ if (jsx) content = transformTsToJs(content);
5868
+ content = await lintText(content, {
5869
+ ...lint,
5870
+ cwd: cwd$3,
5871
+ filePath: indexPath
5872
+ });
5873
+ content = await formatText(content, format$2);
5874
+ return content;
5875
+ }
5876
+ async function generateSource(dirPath, section, { name: fileName, content, data, template }, config$1, generatedNames = []) {
5877
+ fileName = transformExtension(fileName, config$1.jsx);
5878
+ const targetPath = path$1.resolve(dirPath, fileName);
5879
+ if (content) {
5880
+ content = transformContent(section, content, config$1, generatedNames);
5881
+ if (config$1.jsx) content = isJsx(fileName) ? transformTsxToJsx(content) : transformTsToJs(content);
5882
+ await writeFileSafe(targetPath, content, config$1);
5883
+ } else if (template && data) await Promise.all(data.map(async ({ name: fileName$1,...rest }) => {
5884
+ fileName$1 = transformExtension(fileName$1, config$1.jsx);
5885
+ let content$1 = transformTemplateContent(template, rest);
5886
+ content$1 = transformContent(section, content$1, config$1, generatedNames);
5887
+ if (config$1.jsx) content$1 = isJsx(fileName$1) ? transformTsxToJsx(content$1) : transformTsToJs(content$1);
5888
+ await writeFileSafe(path$1.resolve(targetPath, fileName$1), content$1, config$1);
5889
+ }));
5890
+ }
5891
+ async function generateSources(dirPath, registry, config$1, generatedNames = []) {
5892
+ await Promise.all([...registry.sources.map((source) => generateSource(dirPath, registry.section, source, config$1, generatedNames)), writeFileSafe(path$1.resolve(dirPath, REGISTRY_FILE_NAME), JSON.stringify(registry), merge(config$1, { format: { parser: "json" } }))]);
5893
+ }
5794
5894
 
5795
5895
  //#endregion
5796
5896
  //#region src/constant.ts
5797
5897
  const CONFIG_FILE_NAME = "ui.json";
5898
+ const REGISTRY_FILE_NAME = "registry.json";
5899
+ const THEME_PATH = "./theme";
5798
5900
  const DEFAULT_PACKAGE_NAME = "@workspaces/ui";
5799
5901
  const REGISTRY_URL = "https://v2.yamada-ui.com/registry/v2";
5800
5902
  const DEFAULT_PATH = {
@@ -5821,14 +5923,22 @@ const DEFAULT_PACKAGE_JSON = {
5821
5923
  type: "module",
5822
5924
  private: true,
5823
5925
  scripts: {},
5824
- exports: {
5926
+ dependencies: Object.fromEntries(REQUIRED_DEPENDENCIES.map((dependency) => splitVersion(dependency))),
5927
+ devDependencies: Object.fromEntries(REQUIRED_DEV_DEPENDENCIES.map((dependency) => splitVersion(dependency)))
5928
+ };
5929
+ const DEFAULT_PACKAGE_JSON_EXPORTS = {
5930
+ TSX: {
5825
5931
  ".": "./src/index.ts",
5826
5932
  "./components/*": "./src/components/*/index.ts",
5827
5933
  "./hooks/*": "./src/hooks/*/index.ts",
5828
5934
  "./providers/*": "./src/providers/*/index.ts"
5829
5935
  },
5830
- dependencies: Object.fromEntries(REQUIRED_DEPENDENCIES.map((dependency) => splitVersion(dependency))),
5831
- devDependencies: Object.fromEntries(REQUIRED_DEV_DEPENDENCIES.map((dependency) => splitVersion(dependency)))
5936
+ JSX: {
5937
+ ".": "./src/index.js",
5938
+ "./components/*": "./src/components/*/index.js",
5939
+ "./hooks/*": "./src/hooks/*/index.js",
5940
+ "./providers/*": "./src/providers/*/index.js"
5941
+ }
5832
5942
  };
5833
5943
  const TSCONFIG_JSON = {
5834
5944
  compilerOptions: {
@@ -5863,23 +5973,22 @@ const TSCONFIG_JSON = {
5863
5973
 
5864
5974
  //#endregion
5865
5975
  //#region src/commands/add/index.ts
5866
- const add = new Command("add").description("Add a component to your project").argument("[components...]", "Components to add").option("--cwd <path>", "Current working directory", cwd).option("-c, --config <path>", "Path to the config file", CONFIG_FILE_NAME).option("-o, --overwrite", "overwrite existing files.", false).option("-i, --install", "Install dependencies", false).option("-f, --format", "Format the output files.", false).option("-l, --lint", "Lint the output files.", false).action(async function(componentNames, { config: configPath, cwd: cwd$3, format: format$3, install, lint: lint$1, overwrite }) {
5976
+ const add = new Command("add").description("add a component to your project").argument("[components...]", "components to add").option("--cwd <path>", "current working directory", cwd).option("-c, --config <path>", "path to the config file", CONFIG_FILE_NAME).option("-o, --overwrite", "overwrite existing files.", false).option("-i, --install", "install dependencies", false).option("-s, --sequential", "run tasks sequentially.", false).option("-f, --format", "format the output files.").option("-l, --lint", "lint the output files.").action(async function(componentNames, { config: configPath, cwd: cwd$3, format: format$2, install, lint, overwrite, sequential }) {
5867
5977
  const spinner = ora();
5868
5978
  try {
5869
5979
  const { end } = timer();
5870
- const all = !componentNames.length;
5871
5980
  spinner.start("Validating directory");
5872
5981
  await validateDir(cwd$3);
5873
5982
  spinner.succeed("Validated directory");
5874
5983
  spinner.start("Fetching config");
5875
5984
  const config$1 = await getConfig(cwd$3, configPath, {
5876
- format: format$3,
5877
- lint: lint$1
5985
+ format: format$2,
5986
+ lint
5878
5987
  });
5879
5988
  spinner.succeed("Fetched config");
5880
5989
  let generatedNameMap;
5881
5990
  const omittedGeneratedNames = [];
5882
- if (all) {
5991
+ if (!componentNames.length) {
5883
5992
  const { proceed } = await prompts({
5884
5993
  type: "confirm",
5885
5994
  name: "proceed",
@@ -5919,8 +6028,8 @@ const add = new Command("add").description("Add a component to your project").ar
5919
6028
  }
5920
6029
  spinner.start("Fetching registries");
5921
6030
  const registries = await fetchRegistries(componentNames, config$1, {
5922
- dependencies: !all,
5923
- dependents: !all,
6031
+ dependencies: !!componentNames.length,
6032
+ dependents: !!componentNames.length,
5924
6033
  omit: omittedGeneratedNames
5925
6034
  });
5926
6035
  const registryNames = Object.keys(registries);
@@ -5931,10 +6040,20 @@ const add = new Command("add").description("Add a component to your project").ar
5931
6040
  ...dependents?.providers ?? []
5932
6041
  ]).flat().filter((dependent) => omittedGeneratedNames.includes(dependent)))];
5933
6042
  spinner.succeed("Fetched registries");
6043
+ if (componentNames.length !== registryNames.length) {
6044
+ const colorizedNames = registryNames.map((name$1) => c.yellow(name$1));
6045
+ const { proceed } = await prompts({
6046
+ type: "confirm",
6047
+ name: "proceed",
6048
+ initial: true,
6049
+ message: c.reset(`The following components will be added: ${colorizedNames.join(", ")}. Do you want to add them?`)
6050
+ });
6051
+ if (!proceed) process.exit(0);
6052
+ }
5934
6053
  const targetNames = [...new Set([...omittedGeneratedNames, ...registryNames])];
5935
6054
  const tasks = new Listr(Object.entries(registries).map(([name$1, registry]) => {
5936
- if (registry.section === "root" || registry.section === "theme") return;
5937
- const sectionPath = config$1.getSectionAbsolutePath(registry.section);
6055
+ if (!config$1.isSection(registry.section)) return;
6056
+ const sectionPath = config$1.getSectionResolvedPath(registry.section);
5938
6057
  const dirPath = path$1.join(sectionPath, name$1);
5939
6058
  return {
5940
6059
  task: async (_, task) => {
@@ -5943,50 +6062,43 @@ const add = new Command("add").description("Add a component to your project").ar
5943
6062
  },
5944
6063
  title: `Generating ${c.cyan(name$1)}`
5945
6064
  };
5946
- }).filter((task) => !isUndefined(task)), { concurrent: true });
5947
- if (existsSync(path$1.resolve(config$1.srcPath, "index.ts"))) tasks.add({
5948
- task: async (_, task) => {
5949
- const targetPath = path$1.resolve(config$1.srcPath, "index.ts");
5950
- const content = replaceIndex(targetNames, await readFile(targetPath, "utf-8"), config$1);
5951
- await writeFileSafe(targetPath, content, config$1);
5952
- task.title = `Updated ${c.cyan("index.ts")}`;
5953
- },
5954
- title: `Updating ${c.cyan("index.ts")}`
5955
- });
5956
- else tasks.add({
5957
- task: async (_, task) => {
5958
- const { sources } = await fetchRegistry("index");
5959
- const targetPath = path$1.resolve(config$1.srcPath, "index.ts");
5960
- const content = replaceIndex(targetNames, sources[0].content, config$1);
5961
- await writeFileSafe(targetPath, content, config$1);
5962
- task.title = `Generated ${c.cyan("index.ts")}`;
5963
- },
5964
- title: `Generating ${c.cyan("index.ts")}`
5965
- });
6065
+ }).filter((task) => !isUndefined(task)), { concurrent: !sequential });
5966
6066
  if (affectedNames.length && generatedNameMap) {
5967
6067
  if (!overwrite) {
5968
6068
  const colorizedNames = affectedNames.map((name$1) => c.yellow(name$1));
5969
- const { update } = await prompts({
6069
+ const { update: update$1 } = await prompts({
5970
6070
  type: "confirm",
5971
6071
  name: "update",
5972
6072
  initial: true,
5973
6073
  message: c.reset([`The following generated files will be updated: ${colorizedNames.join(", ")}.`, "Do you want to update them?"].join(" "))
5974
6074
  });
5975
- if (update) overwrite = update;
6075
+ if (update$1) overwrite = update$1;
5976
6076
  }
5977
6077
  if (overwrite) Object.entries(generatedNameMap).forEach(([section, names]) => {
5978
6078
  names.forEach((name$1) => {
5979
6079
  if (!affectedNames.includes(name$1)) return;
5980
6080
  tasks.add({
5981
6081
  task: async (_, task) => {
5982
- const sectionPath = config$1.getSectionAbsolutePath(section);
6082
+ const sectionPath = config$1.getSectionResolvedPath(section);
5983
6083
  const dirPath = path$1.join(sectionPath, name$1);
5984
6084
  const dirents = await readdir(dirPath, { withFileTypes: true });
5985
6085
  await Promise.all(dirents.map(async (dirent) => {
5986
- if (dirent.isDirectory()) return;
5987
- const targetPath = path$1.join(dirent.parentPath, dirent.name);
5988
- const content = transformContent(section, await readFile(targetPath, "utf-8"), config$1, targetNames);
5989
- await writeFileSafe(targetPath, content, config$1);
6086
+ if (dirent.isDirectory()) {
6087
+ const dirents$1 = await readdir(path$1.join(dirent.parentPath, name$1), { withFileTypes: true });
6088
+ await Promise.all(dirents$1.map(async (dirent$1) => {
6089
+ if (dirent$1.isDirectory()) return;
6090
+ if (dirent$1.name === REGISTRY_FILE_NAME) return;
6091
+ const targetPath = path$1.join(dirent$1.parentPath, dirent$1.name);
6092
+ let content = await readFile(targetPath, "utf-8");
6093
+ content = transformContent(section, content, config$1, targetNames);
6094
+ await writeFileSafe(targetPath, content, config$1);
6095
+ }));
6096
+ } else if (dirent.name !== REGISTRY_FILE_NAME) {
6097
+ const targetPath = path$1.join(dirent.parentPath, dirent.name);
6098
+ let content = await readFile(targetPath, "utf-8");
6099
+ content = transformContent(section, content, config$1, targetNames);
6100
+ await writeFileSafe(targetPath, content, config$1);
6101
+ }
5990
6102
  }));
5991
6103
  task.title = `Updated ${c.cyan(name$1)}`;
5992
6104
  },
@@ -5995,6 +6107,26 @@ const add = new Command("add").description("Add a component to your project").ar
5995
6107
  });
5996
6108
  });
5997
6109
  }
6110
+ const indexFileName = transformExtension("index.ts", config$1.jsx);
6111
+ if (existsSync(config$1.indexPath)) tasks.add({
6112
+ task: async (_, task) => {
6113
+ let content = await readFile(config$1.indexPath, "utf-8");
6114
+ content = transformIndex(targetNames, content, config$1);
6115
+ await writeFileSafe(config$1.indexPath, content, config$1);
6116
+ task.title = `Updated ${c.cyan(indexFileName)}`;
6117
+ },
6118
+ title: `Updating ${c.cyan(indexFileName)}`
6119
+ });
6120
+ else tasks.add({
6121
+ task: async (_, task) => {
6122
+ const { sources: [source] } = await fetchRegistry("index");
6123
+ let content = transformIndex(targetNames, source.content, config$1);
6124
+ if (config$1.jsx) content = transformTsToJs(content);
6125
+ await writeFileSafe(config$1.indexPath, content, config$1);
6126
+ task.title = `Generated ${c.cyan(indexFileName)}`;
6127
+ },
6128
+ title: `Generating ${c.cyan(indexFileName)}`
6129
+ });
5998
6130
  if (dependencies$1.length) {
5999
6131
  const targetPath = config$1.monorepo ? config$1.rootPath : cwd$3;
6000
6132
  spinner.start(`Checking ${c.cyan("package.json")} dependencies`);
@@ -6013,7 +6145,7 @@ const add = new Command("add").description("Add a component to your project").ar
6013
6145
  }
6014
6146
  if (install) tasks.add({
6015
6147
  task: async (_, task) => {
6016
- await installDependencies(notInstalledDependencies.map(getPackageName), { cwd: targetPath });
6148
+ await installDependencies(notInstalledDependencies.map(getPackageNameWithVersion), { cwd: targetPath });
6017
6149
  task.title = "Installed dependencies";
6018
6150
  },
6019
6151
  title: "Installing dependencies"
@@ -6028,125 +6160,464 @@ const add = new Command("add").description("Add a component to your project").ar
6028
6160
  });
6029
6161
 
6030
6162
  //#endregion
6031
- //#region src/commands/diff/index.ts
6032
- async function getData(componentNames, config$1) {
6033
- const data = {};
6034
- const registries = {};
6035
- const tasks = new Listr([...componentNames.map((componentName) => ({
6163
+ //#region src/commands/update/print-conflicts.ts
6164
+ function printConflicts(conflictMap, config$1) {
6165
+ Object.entries(conflictMap).forEach(([name$1, files$1]) => {
6166
+ if (name$1 === "index") console.log(`- ${c.yellow(transformExtension("index.ts", config$1.jsx))}: ${config$1.indexPath.replace(`${config$1.cwd}/`, "")}`);
6167
+ else {
6168
+ console.log(`- ${name$1}`);
6169
+ Object.entries(files$1).forEach(([fileName, path$9]) => {
6170
+ console.log(` - ${c.yellow(fileName)}: ${path$9.replace(`${config$1.cwd}/`, "")}`);
6171
+ });
6172
+ }
6173
+ });
6174
+ }
6175
+
6176
+ //#endregion
6177
+ //#region src/commands/diff/get-diff.ts
6178
+ function getDirPath(section, name$1, config$1) {
6179
+ return config$1.isSection(section) ? path$1.join(config$1.getSectionResolvedPath(section), name$1) : section === "theme" ? config$1.theme.path : config$1.srcPath;
6180
+ }
6181
+ async function getDiff(generatedNames, { locale, remote }, config$1, concurrent = true) {
6182
+ const changeMap = {};
6183
+ const dependencyMap = {
6184
+ add: [],
6185
+ remove: [],
6186
+ update: []
6187
+ };
6188
+ const tasks = new Listr(Object.entries(remote).map(([componentName, { dependencies: dependencies$1, section, sources }]) => ({
6189
+ task: async (_, task) => {
6190
+ const localeRegistry = locale[componentName];
6191
+ if (componentName === "index") {
6192
+ const [source] = sources;
6193
+ const fileName = transformExtension(source.name, config$1.jsx);
6194
+ const [remote$1, locale$1] = await Promise.all([transformIndexWithFormatAndLint(source.content, config$1, generatedNames), transformIndexWithFormatAndLint(localeRegistry.sources[0].content, config$1, generatedNames)]);
6195
+ const diff$1 = diffLines(locale$1, remote$1);
6196
+ if (diff$1.length < 2) return;
6197
+ changeMap[componentName] ??= {};
6198
+ changeMap[componentName][fileName] = {
6199
+ diff: diff$1,
6200
+ locale: locale$1,
6201
+ remote: remote$1
6202
+ };
6203
+ } else {
6204
+ const dirPath = getDirPath(section, componentName, config$1);
6205
+ if (dependencies$1 || localeRegistry.dependencies) {
6206
+ const remoteDependencies = dependencies$1?.externals ?? [];
6207
+ const localeDependencies = localeRegistry.dependencies?.externals ?? [];
6208
+ const remotePackageNames = remoteDependencies.map(getPackageName);
6209
+ const localePackageNames = localeDependencies.map(getPackageName);
6210
+ const add$1 = remotePackageNames.filter((name$1) => !localePackageNames.includes(name$1));
6211
+ const remove = localePackageNames.filter((name$1) => !remotePackageNames.includes(name$1));
6212
+ const update$1 = localeDependencies.map((name$1) => {
6213
+ const [packageName, current] = splitVersion(name$1);
6214
+ const remoteDependency = remoteDependencies.find((name$2) => getPackageName(name$2) === packageName);
6215
+ if (!remoteDependency) return;
6216
+ const [, wanted] = splitVersion(remoteDependency);
6217
+ if (current === wanted) return;
6218
+ return {
6219
+ name: packageName,
6220
+ current,
6221
+ wanted
6222
+ };
6223
+ }).filter((data) => !isUndefined(data));
6224
+ dependencyMap.add.push(...add$1);
6225
+ dependencyMap.remove.push(...remove);
6226
+ dependencyMap.update.push(...update$1);
6227
+ }
6228
+ await Promise.all(sources.map(async ({ name: name$1, content, data, template }) => {
6229
+ const source = localeRegistry.sources.find((source$1) => source$1.name === name$1);
6230
+ name$1 = transformExtension(name$1, config$1.jsx);
6231
+ const targetPath = path$1.join(dirPath, name$1);
6232
+ if (content) if (source) {
6233
+ const [remote$1, locale$1] = await Promise.all([transformContentWithFormatAndLint(targetPath, section, content, config$1, generatedNames), transformContentWithFormatAndLint(targetPath, section, source.content, config$1, generatedNames)]);
6234
+ const diff$1 = diffLines(locale$1, remote$1);
6235
+ if (diff$1.length < 2) return;
6236
+ changeMap[componentName] ??= {};
6237
+ changeMap[componentName][name$1] = {
6238
+ diff: diff$1,
6239
+ locale: locale$1,
6240
+ remote: remote$1
6241
+ };
6242
+ } else {
6243
+ let remote$1 = transformContent(section, content, config$1, generatedNames);
6244
+ if (config$1.jsx) remote$1 = isJsx(name$1) ? transformTsxToJsx(remote$1) : transformTsToJs(remote$1);
6245
+ const diff$1 = [{
6246
+ added: true,
6247
+ count: remote$1.length,
6248
+ removed: false,
6249
+ value: remote$1
6250
+ }];
6251
+ changeMap[componentName] ??= {};
6252
+ changeMap[componentName][name$1] = {
6253
+ diff: diff$1,
6254
+ remote: remote$1
6255
+ };
6256
+ }
6257
+ else if (template && data) await Promise.all(data.map(async ({ name: fileName,...remoteRest }) => {
6258
+ const localeData = source?.data?.find(({ name: name$2 }) => name$2 === fileName);
6259
+ fileName = transformExtension(fileName, config$1.jsx);
6260
+ if (localeData) {
6261
+ if (template === source?.template) return;
6262
+ const { name: _name,...localeRest } = localeData;
6263
+ const [remote$1, locale$1] = await Promise.all([transformContentWithFormatAndLint(path$1.join(targetPath, fileName), section, transformTemplateContent(template, remoteRest), config$1, generatedNames), transformContentWithFormatAndLint(path$1.join(targetPath, fileName), section, transformTemplateContent(source.template, localeRest), config$1, generatedNames)]);
6264
+ const diff$1 = diffLines(locale$1, remote$1);
6265
+ if (diff$1.length < 2) return;
6266
+ changeMap[componentName] ??= {};
6267
+ changeMap[componentName][`${name$1}/${fileName}`] = {
6268
+ diff: diff$1,
6269
+ locale: locale$1,
6270
+ remote: remote$1
6271
+ };
6272
+ } else {
6273
+ let remote$1 = transformContent(section, transformTemplateContent(template, remoteRest), config$1, generatedNames);
6274
+ if (config$1.jsx) remote$1 = isJsx(fileName) ? transformTsxToJsx(remote$1) : transformTsToJs(remote$1);
6275
+ const diff$1 = [{
6276
+ added: true,
6277
+ count: remote$1.length,
6278
+ removed: false,
6279
+ value: remote$1
6280
+ }];
6281
+ changeMap[componentName] ??= {};
6282
+ changeMap[componentName][`${name$1}/${fileName}`] = {
6283
+ diff: diff$1,
6284
+ remote: remote$1
6285
+ };
6286
+ }
6287
+ }));
6288
+ }));
6289
+ const removeSources = localeRegistry.sources.filter(({ name: name$1 }) => !sources.some((source) => source.name === name$1));
6290
+ removeSources.forEach(({ name: name$1, content, data, template }) => {
6291
+ if (content) {
6292
+ let locale$1 = transformContent(section, content, config$1, generatedNames);
6293
+ if (config$1.jsx) locale$1 = isJsx(name$1) ? transformTsxToJsx(locale$1) : transformTsToJs(locale$1);
6294
+ const diff$1 = [{
6295
+ added: false,
6296
+ count: locale$1.length,
6297
+ removed: true,
6298
+ value: locale$1
6299
+ }];
6300
+ changeMap[componentName] ??= {};
6301
+ changeMap[componentName][name$1] = {
6302
+ diff: diff$1,
6303
+ locale: locale$1
6304
+ };
6305
+ } else if (template && data) data.forEach(({ name: fileName,...remoteRest }) => {
6306
+ let locale$1 = transformContent(section, transformTemplateContent(template, remoteRest), config$1, generatedNames);
6307
+ if (config$1.jsx) locale$1 = isJsx(fileName) ? transformTsxToJsx(locale$1) : transformTsToJs(locale$1);
6308
+ const diff$1 = [{
6309
+ added: true,
6310
+ count: locale$1.length,
6311
+ removed: false,
6312
+ value: locale$1
6313
+ }];
6314
+ changeMap[componentName] ??= {};
6315
+ changeMap[componentName][`${name$1}/${fileName}`] = {
6316
+ diff: diff$1,
6317
+ locale: locale$1
6318
+ };
6319
+ });
6320
+ });
6321
+ }
6322
+ task.title = `Checked ${c.cyan(componentName)}`;
6323
+ },
6324
+ title: `Checking ${c.cyan(componentName)}`
6325
+ })), { concurrent });
6326
+ await tasks.run();
6327
+ return {
6328
+ changeMap,
6329
+ dependencyMap
6330
+ };
6331
+ }
6332
+
6333
+ //#endregion
6334
+ //#region src/commands/update/update-files.ts
6335
+ async function mergeContent(remotePath, localePath, currentPath, fallback) {
6336
+ let content = "";
6337
+ let conflict = false;
6338
+ try {
6339
+ const { stdout } = await execa("diff3", [
6340
+ "-m",
6341
+ remotePath,
6342
+ localePath,
6343
+ currentPath
6344
+ ]);
6345
+ content = stdout;
6346
+ } catch (e) {
6347
+ if (e instanceof ExecaError) if (e.stdout) {
6348
+ conflict = true;
6349
+ content = e.stdout;
6350
+ } else content = fallback;
6351
+ }
6352
+ content = content.replaceAll(remotePath, "remote");
6353
+ content = content.replaceAll(localePath, "locale");
6354
+ content = content.replaceAll(currentPath, "current");
6355
+ content = content.replace(/\|\|\|\|\|\|\|[\s\S]*?=======/g, "=======");
6356
+ return {
6357
+ conflict,
6358
+ content
6359
+ };
6360
+ }
6361
+ async function updateFiles(changeMap, { add: add$1, remove, update: update$1 }, { remote }, config$1, { concurrent = true, install = false } = {}) {
6362
+ const conflictMap = {};
6363
+ const disabledFormatAndLint = {
6364
+ format: { enabled: false },
6365
+ lint: { enabled: false }
6366
+ };
6367
+ const tasks = new Listr(Object.entries(changeMap).map(([componentName, changes]) => ({
6368
+ task: async (_, task) => {
6369
+ const tempDirPath = await mkdtemp(path$1.join(tmpdir(), `yamada-ui-${componentName}-`));
6370
+ const registry = remote[componentName];
6371
+ const dirPath = getDirPath(registry.section, componentName, config$1);
6372
+ try {
6373
+ if (componentName === "index") {
6374
+ const name$1 = config$1.indexPath.split("/").at(-1);
6375
+ const data = changes[name$1];
6376
+ if (!("locale" in data && "remote" in data)) return;
6377
+ const remotePath = path$1.join(tempDirPath, `remote-${name$1}`);
6378
+ const localePath = path$1.join(tempDirPath, `locale-${name$1}`);
6379
+ await Promise.all([writeFileSafe(remotePath, data.remote, disabledFormatAndLint), writeFileSafe(localePath, data.locale, disabledFormatAndLint)]);
6380
+ const { conflict, content: mergedContent } = await mergeContent(remotePath, localePath, config$1.indexPath, data.remote);
6381
+ await writeFileSafe(config$1.indexPath, mergedContent, conflict ? merge(config$1, disabledFormatAndLint) : config$1);
6382
+ if (conflict) {
6383
+ conflictMap[componentName] ??= {};
6384
+ conflictMap[componentName][name$1] = config$1.indexPath;
6385
+ }
6386
+ } else await Promise.all(Object.entries(changes).map(async ([name$1, { ...data }]) => {
6387
+ const currentPath = path$1.join(dirPath, name$1);
6388
+ if ("locale" in data && "remote" in data) {
6389
+ const remotePath = path$1.join(tempDirPath, `remote-${name$1}`);
6390
+ const localePath = path$1.join(tempDirPath, `locale-${name$1}`);
6391
+ await Promise.all([writeFileSafe(remotePath, data.remote, disabledFormatAndLint), writeFileSafe(localePath, data.locale, disabledFormatAndLint)]);
6392
+ const { conflict, content: mergedContent } = await mergeContent(remotePath, localePath, currentPath, data.remote);
6393
+ await writeFileSafe(currentPath, mergedContent, conflict ? merge(config$1, disabledFormatAndLint) : config$1);
6394
+ if (conflict) {
6395
+ conflictMap[componentName] ??= {};
6396
+ conflictMap[componentName][name$1] = currentPath;
6397
+ }
6398
+ } else if ("remote" in data) await writeFileSafe(currentPath, data.remote, config$1);
6399
+ else await rimraf(currentPath);
6400
+ }));
6401
+ await writeFileSafe(path$1.resolve(dirPath, REGISTRY_FILE_NAME), JSON.stringify(registry), merge(config$1, { format: { parser: "json" } }));
6402
+ } catch {} finally {
6403
+ await rimraf(tempDirPath);
6404
+ }
6405
+ task.title = `Changed ${c.cyan(componentName)}`;
6406
+ },
6407
+ title: `Changing ${c.cyan(componentName)}`
6408
+ })), { concurrent });
6409
+ await tasks.run();
6410
+ if (!install && (add$1.length || remove.length || update$1.length)) {
6411
+ const { install: install$1 } = await prompts({
6412
+ type: "confirm",
6413
+ name: "install",
6414
+ initial: true,
6415
+ message: c.reset("There are dependency updates. Do you want to install them?")
6416
+ });
6417
+ if (!install$1) return conflictMap;
6418
+ }
6419
+ const cwd$3 = config$1.monorepo ? config$1.rootPath : config$1.cwd;
6420
+ remove.push(...update$1.map(({ name: name$1 }) => name$1));
6421
+ add$1.push(...update$1.map(getPackageNameWithVersion));
6422
+ if (remove.length) await uninstallDependencies(remove.map(getPackageName), { cwd: cwd$3 });
6423
+ if (add$1.length) await installDependencies(add$1, { cwd: cwd$3 });
6424
+ return conflictMap;
6425
+ }
6426
+
6427
+ //#endregion
6428
+ //#region src/commands/diff/get-registries-and-files.ts
6429
+ async function getRegistriesAndFiles(componentNames, config$1, { concurrent = true, index = false, theme: theme$1 = false } = {}) {
6430
+ const fileMap = {};
6431
+ const registryMap = {
6432
+ locale: {},
6433
+ remote: {}
6434
+ };
6435
+ const tasks = new Listr([], { concurrent });
6436
+ if (index) tasks.add([{
6437
+ task: async (_, task) => {
6438
+ const indexFileName = transformExtension("index.ts", config$1.jsx);
6439
+ fileMap.index = { [indexFileName]: await readFile(config$1.indexPath, "utf-8") };
6440
+ registryMap.locale.index = await fetchLocaleRegistry(config$1.registryPath);
6441
+ task.title = `Got ${c.cyan("index")} file`;
6442
+ },
6443
+ title: `Getting ${c.cyan("index")} file`
6444
+ }, {
6445
+ task: async (_, task) => {
6446
+ registryMap.remote.index = await fetchRegistry("index");
6447
+ task.title = `Fetched ${c.cyan("index")} registry`;
6448
+ },
6449
+ title: `Fetching ${c.cyan("index")} registry`
6450
+ }]);
6451
+ if (theme$1) tasks.add([{
6036
6452
  task: async (_, task) => {
6037
- data[componentName] = await getComponentFiles(componentName, config$1);
6453
+ if (!config$1.theme?.path) return;
6454
+ const { dirPath, files: files$1 } = await getFiles(config$1.theme.path);
6455
+ fileMap.theme = files$1;
6456
+ registryMap.locale.theme = await fetchLocaleRegistry(path$1.join(dirPath, REGISTRY_FILE_NAME));
6457
+ task.title = `Got ${c.cyan("theme")} files`;
6458
+ },
6459
+ title: `Getting ${c.cyan("theme")} files`
6460
+ }, {
6461
+ task: async (_, task) => {
6462
+ registryMap.remote.theme = await fetchRegistry("theme");
6463
+ task.title = `Fetched ${c.cyan("theme")} registry`;
6464
+ },
6465
+ title: `Fetching ${c.cyan("theme")} registry`
6466
+ }]);
6467
+ tasks.add(componentNames.map((componentName) => [{
6468
+ task: async (_, task) => {
6469
+ const { dirPath, files: files$1 } = await getFiles(path$1.join(config$1.srcPath, "**", componentName));
6470
+ fileMap[componentName] = files$1;
6471
+ registryMap.locale[componentName] = await fetchLocaleRegistry(path$1.join(dirPath, REGISTRY_FILE_NAME));
6038
6472
  task.title = `Got ${c.cyan(componentName)} files`;
6039
6473
  },
6040
6474
  title: `Getting ${c.cyan(componentName)} files`
6041
- })), ...componentNames.map((componentName) => ({
6475
+ }, {
6042
6476
  task: async (_, task) => {
6043
- registries[componentName] = await fetchRegistry(componentName);
6477
+ registryMap.remote[componentName] = await fetchRegistry(componentName);
6044
6478
  task.title = `Fetched ${c.cyan(componentName)} registry`;
6045
6479
  },
6046
6480
  title: `Fetching ${c.cyan(componentName)} registry`
6047
- }))], { concurrent: true });
6481
+ }]).flat());
6048
6482
  await tasks.run();
6049
6483
  return {
6050
- data,
6051
- registries
6484
+ fileMap,
6485
+ registryMap
6052
6486
  };
6053
6487
  }
6054
- async function getDiff(generatedNames, data, registries, config$1) {
6055
- const changes = {};
6056
- await Promise.all(Object.entries(data).map(async ([name$1, files$1]) => {
6057
- const registry = registries[name$1];
6058
- if (!registry) return;
6059
- await Promise.all(Object.entries(files$1).map(async ([fileName, file$1]) => {
6060
- const registryFile = registry.sources.find(({ name: name$2 }) => name$2 === fileName);
6061
- if (!registryFile?.content) return;
6062
- const content = await format$2(transformContent(registry.section, registryFile.content, config$1, generatedNames));
6063
- const diff$1 = diffLines(file$1, content);
6064
- if (diff$1.length < 2) return;
6065
- changes[name$1] ??= {};
6066
- changes[name$1][fileName] = diff$1;
6067
- }));
6068
- }));
6069
- return changes;
6488
+
6489
+ //#endregion
6490
+ //#region src/commands/diff/print-diff.ts
6491
+ function printDiff(changes, detail = false) {
6492
+ if (!changes) return;
6493
+ Object.entries(changes).forEach(([fileName, { diff: diff$1 }]) => {
6494
+ console.log(`- ${c.cyan(fileName)}`);
6495
+ console.log("");
6496
+ diff$1.forEach(({ added, removed, value }) => {
6497
+ if (added) return process.stdout.write(c.green(value));
6498
+ else if (removed) return process.stdout.write(c.red(value));
6499
+ else if (detail) return process.stdout.write(value);
6500
+ });
6501
+ });
6502
+ }
6503
+ function printDiffFiles(name$1, changes) {
6504
+ if (!changes) return;
6505
+ console.log(`- ${name$1}`);
6506
+ Object.entries(changes).forEach(([fileName, { diff: diff$1 }]) => {
6507
+ printDiffFile(fileName, diff$1, " ");
6508
+ });
6509
+ }
6510
+ function printDiffFile(name$1, diff$1 = [], space = "") {
6511
+ const added = diff$1.reduce((prev, { added: added$1, count }) => {
6512
+ if (added$1) return prev + count;
6513
+ return prev;
6514
+ }, 0);
6515
+ const removed = diff$1.reduce((prev, { count, removed: removed$1 }) => {
6516
+ if (removed$1) return prev + count;
6517
+ return prev;
6518
+ }, 0);
6519
+ if (!added && !removed) return;
6520
+ const result = [`${space}- ${c.cyan(name$1)}`];
6521
+ if (added) result.push(`${c.green(added)} insertions`);
6522
+ if (removed) result.push(`${c.red(removed)} deletions`);
6523
+ console.log(result.join(" "));
6070
6524
  }
6071
- const diff = new Command("diff").description("Check for updates against the registry").argument("[component]", "Component to check").option("--cwd <path>", "Current working directory", cwd).option("-c, --config <path>", "Path to the config file", CONFIG_FILE_NAME).option("-d, --detail", "Show detailed changes", false).action(async function(componentName, { config: configPath, cwd: cwd$3, detail = false }) {
6525
+ function printDiffDependencies({ add: add$1, remove, update: update$1 }) {
6526
+ console.log("- dependencies");
6527
+ if (add$1.length) add$1.forEach((name$1) => {
6528
+ console.log(` - ${c.green(getPackageName(name$1))}`);
6529
+ });
6530
+ if (remove.length) remove.forEach((name$1) => {
6531
+ console.log(` - ${c.red(getPackageName(name$1))}`);
6532
+ });
6533
+ if (update$1.length) update$1.forEach(({ name: name$1, current, wanted }) => {
6534
+ console.log(` - ${name$1}@${c.red(current)}->${c.green(wanted)}`);
6535
+ });
6536
+ }
6537
+
6538
+ //#endregion
6539
+ //#region src/commands/diff/index.ts
6540
+ const diff = new Command("diff").description("check for updates against the registry").argument("[component]", "component to check").option("--cwd <path>", "current working directory", cwd).option("-c, --config <path>", "path to the config file", CONFIG_FILE_NAME).option("-s, --sequential", "run tasks sequentially.", false).option("-d, --detail", "show detailed changes", false).action(async function(targetName, { config: configPath, cwd: cwd$3, detail, sequential }) {
6072
6541
  const spinner = ora();
6073
6542
  try {
6074
6543
  const { end } = timer();
6075
6544
  const packageManager = getPackageManager();
6076
6545
  const { args, command } = packageExecuteCommands(packageManager);
6077
6546
  const prefix = `${command}${args.length ? ` ${args.join(" ")}` : ""}`;
6078
- const addCommand = c.cyan(`${prefix} ${package_default.name}@latest add`);
6079
- const diffCommand = c.cyan(`${prefix} ${package_default.name}@latest diff`);
6547
+ const getCommand = (command$1) => c.cyan(`${prefix} ${package_default.name}@latest ${command$1}`);
6080
6548
  spinner.start("Validating directory");
6081
6549
  await validateDir(cwd$3);
6082
6550
  spinner.succeed("Validated directory");
6083
6551
  spinner.start("Fetching config");
6084
6552
  const config$1 = await getConfig(cwd$3, configPath);
6085
6553
  spinner.succeed("Fetched config");
6086
- const componentNames = [];
6087
6554
  spinner.start("Getting generated components");
6555
+ const componentNames = [];
6088
6556
  const generatedNameMap = await getGeneratedNameMap(config$1);
6089
6557
  const generatedNames = Object.values(generatedNameMap).flat();
6558
+ const existsTheme = !!config$1.theme?.path && existsSync(config$1.theme.path);
6559
+ let index = targetName === "index";
6560
+ let theme$1 = targetName === "theme";
6090
6561
  spinner.succeed("Got generated components");
6091
- if (componentName) if (generatedNames.includes(componentName)) componentNames.push(componentName);
6562
+ if (theme$1 && !existsTheme) throw new Error([
6563
+ `No ${c.yellow("theme")} found.`,
6564
+ `Please run ${getCommand("theme")}`,
6565
+ "to generate it."
6566
+ ].join(" "));
6567
+ if (!index && !theme$1) if (targetName) if (generatedNames.includes(targetName)) componentNames.push(targetName);
6092
6568
  else throw new Error([
6093
- `No ${c.yellow(componentName)} found in generated components.`,
6094
- `Please run ${addCommand} ${c.green(componentName)}`,
6569
+ `No ${c.yellow(targetName)} found in generated components.`,
6570
+ `Please run ${getCommand("add")} ${c.green(targetName)}`,
6095
6571
  "to add it."
6096
6572
  ].join(" "));
6097
- else componentNames.push(...generatedNames);
6098
- if (!componentNames.length) throw new Error([
6573
+ else {
6574
+ componentNames.push(...generatedNames);
6575
+ index = true;
6576
+ if (existsTheme) theme$1 = true;
6577
+ }
6578
+ if (!index && !theme$1 && !componentNames.length) throw new Error([
6099
6579
  "No components found.",
6100
- `Please run ${addCommand} ${c.green("<component>")}`,
6580
+ `Please run ${getCommand("add")} ${c.green("<component>")}`,
6101
6581
  "to add components."
6102
6582
  ].join(" "));
6103
- const { data, registries } = await getData(componentNames, config$1);
6104
- const changes = await getDiff(generatedNames, data, registries, config$1);
6105
- const hasChanges = Object.keys(changes).length;
6583
+ const { registryMap } = await getRegistriesAndFiles(componentNames, config$1, {
6584
+ concurrent: !sequential,
6585
+ index,
6586
+ theme: theme$1
6587
+ });
6588
+ const { changeMap, dependencyMap } = await getDiff(generatedNames, registryMap, config$1, !sequential);
6589
+ const hasChanges = !!Object.keys(changeMap).length;
6590
+ const hasDependencyChanges = !!dependencyMap.add.length || !!dependencyMap.remove.length || !!dependencyMap.update.length;
6106
6591
  console.log("---------------------------------");
6107
- if (!hasChanges) console.log(c.cyan("No updates found."));
6108
- else if (componentName) {
6109
- const diff$1 = changes[componentName];
6110
- if (!diff$1) return;
6111
- Object.entries(diff$1).forEach(([fileName, diff$2], index) => {
6112
- if (!!index) console.log("");
6113
- console.log(`- ${c.cyan(fileName)}`);
6114
- console.log("");
6115
- diff$2.forEach(({ added, removed, value }) => {
6116
- if (added) return process.stdout.write(c.green(value));
6117
- else if (removed) return process.stdout.write(c.red(value));
6118
- else if (detail) return process.stdout.write(value);
6119
- });
6120
- });
6121
- } else {
6122
- componentNames.forEach((name$1) => {
6123
- const diff$1 = changes[name$1];
6124
- if (!diff$1) return;
6125
- console.log(`- ${name$1}`);
6126
- Object.entries(diff$1).forEach(([fileName, diff$2]) => {
6127
- const added = diff$2.reduce((prev, { added: added$1, count }) => {
6128
- if (added$1) return prev + count;
6129
- return prev;
6130
- }, 0);
6131
- const removed = diff$2.reduce((prev, { count, removed: removed$1 }) => {
6132
- if (removed$1) return prev + count;
6133
- return prev;
6134
- }, 0);
6135
- console.log(` - ${c.cyan(fileName)} ${c.green(added)} insertions ${c.red(removed)} deletions`);
6592
+ if (!hasChanges && !hasDependencyChanges) console.log(c.cyan("No updates found."));
6593
+ else {
6594
+ if (targetName) printDiff(changeMap[targetName], detail);
6595
+ else {
6596
+ if (index && changeMap.index) {
6597
+ const indexFileName = transformExtension("index.ts", config$1.jsx);
6598
+ printDiffFile(indexFileName, changeMap.index[indexFileName]?.diff);
6599
+ }
6600
+ if (theme$1 && changeMap.theme) printDiffFiles("theme", changeMap.theme);
6601
+ componentNames.forEach((name$1) => {
6602
+ printDiffFiles(name$1, changeMap[name$1]);
6136
6603
  });
6604
+ }
6605
+ if (hasDependencyChanges) printDiffDependencies(dependencyMap);
6606
+ console.log("---------------------------------");
6607
+ const { update: update$1 } = await prompts({
6608
+ type: "confirm",
6609
+ name: "update",
6610
+ initial: true,
6611
+ message: c.reset("Do you want to update the files?")
6137
6612
  });
6138
- console.log("");
6139
- console.log(boxen([
6140
- "Run",
6141
- c.cyan(diffCommand),
6142
- c.green("<component>"),
6143
- "to see the changes."
6144
- ].join(" "), {
6145
- borderColor: "yellow",
6146
- borderStyle: "round",
6147
- padding: 1,
6148
- textAlignment: "center"
6149
- }));
6613
+ if (update$1) {
6614
+ const conflictMap = await updateFiles(changeMap, dependencyMap, registryMap, config$1, { concurrent: !sequential });
6615
+ if (Object.keys(conflictMap).length) {
6616
+ console.log("---------------------------------");
6617
+ spinner.warn("There are conflicts. Please check the following files:");
6618
+ printConflicts(conflictMap, config$1);
6619
+ }
6620
+ }
6150
6621
  }
6151
6622
  end();
6152
6623
  } catch (e) {
@@ -6157,17 +6628,18 @@ const diff = new Command("diff").description("Check for updates against the regi
6157
6628
 
6158
6629
  //#endregion
6159
6630
  //#region src/commands/init/index.ts
6160
- const init = new Command("init").description("Initialize your project and install dependencies").option("--cwd <path>", "Current working directory", cwd).option("-c, --config <path>", "Path to the config file", CONFIG_FILE_NAME).option("-o, --overwrite", "Overwrite existing files.", false).action(async function({ config: configPath, cwd: cwd$3, overwrite }) {
6631
+ const init = new Command("init").description("initialize your project and install dependencies").option("--cwd <path>", "current working directory", cwd).option("-c, --config <path>", "path to the config file", CONFIG_FILE_NAME).option("-o, --overwrite", "overwrite existing files.", false).option("-j, --jsx", "use jsx instead of tsx", false).action(async function({ config: configPath, cwd: cwd$3, jsx, overwrite }) {
6161
6632
  const spinner = ora();
6162
6633
  try {
6163
6634
  const { end } = timer();
6164
6635
  await validateDir(cwd$3);
6636
+ const indexFileName = transformExtension("index.ts", jsx);
6165
6637
  const configFileName = configPath.includes("/") ? configPath.split("/").at(-1) : configPath;
6166
6638
  const config$1 = { ...DEFAULT_CONFIG };
6167
6639
  configPath = path$1.resolve(cwd$3, configPath);
6168
6640
  let dependencies$1;
6169
6641
  let devDependencies$1;
6170
- let { src = true, format: format$3 = true, lint: lint$1 = true, monorepo = true, outdir = "", packageName = "" } = await prompts([
6642
+ let { src = true, format: format$2 = true, lint = true, monorepo = true, outdir = "", packageName = "" } = await prompts([
6171
6643
  {
6172
6644
  type: "toggle",
6173
6645
  name: "monorepo",
@@ -6217,10 +6689,11 @@ const init = new Command("init").description("Initialize your project and instal
6217
6689
  outdir ||= monorepo ? DEFAULT_PATH.monorepo : DEFAULT_PATH.polyrepo;
6218
6690
  packageName = packageName.replace(/\x17/g, "").trim();
6219
6691
  packageName ||= DEFAULT_PACKAGE_NAME;
6220
- config$1.monorepo = monorepo;
6692
+ if (monorepo) config$1.monorepo = monorepo;
6693
+ if (jsx) config$1.jsx = jsx;
6221
6694
  config$1.path = outdir;
6222
- config$1.format = { enabled: format$3 };
6223
- config$1.lint = { enabled: lint$1 };
6695
+ config$1.format = { enabled: format$2 };
6696
+ config$1.lint = { enabled: lint };
6224
6697
  const { generate } = await prompts({
6225
6698
  type: "confirm",
6226
6699
  name: "generate",
@@ -6267,7 +6740,8 @@ const init = new Command("init").description("Initialize your project and instal
6267
6740
  const targetPath = path$1.resolve(outdirPath, "package.json");
6268
6741
  const content = JSON.stringify({
6269
6742
  name: packageName,
6270
- ...DEFAULT_PACKAGE_JSON
6743
+ ...DEFAULT_PACKAGE_JSON,
6744
+ exports: DEFAULT_PACKAGE_JSON_EXPORTS[jsx ? "JSX" : "TSX"]
6271
6745
  });
6272
6746
  await writeFileSafe(targetPath, content, merge(config$1, { format: { parser: "json" } }));
6273
6747
  task.title = `Generated ${c.cyan("package.json")}`;
@@ -6276,22 +6750,14 @@ const init = new Command("init").description("Initialize your project and instal
6276
6750
  },
6277
6751
  {
6278
6752
  task: async (_, task) => {
6279
- const targetPath = path$1.resolve(outdirPath, "tsconfig.json");
6280
- const content = JSON.stringify({ ...TSCONFIG_JSON });
6281
- await writeFileSafe(targetPath, content, merge(config$1, { format: { parser: "json" } }));
6282
- task.title = `Generated ${c.cyan("tsconfig.json")}`;
6283
- },
6284
- title: `Generating ${c.cyan("tsconfig.json")}`
6285
- },
6286
- {
6287
- task: async (_, task) => {
6288
- const targetPath = path$1.resolve(outdirPath, src ? "src" : "", "index.ts");
6289
- const { sources } = await fetchRegistry("index");
6290
- const content = sources[0].content;
6291
- await writeFileSafe(targetPath, content, config$1);
6292
- task.title = `Generated ${c.cyan("index.ts")}`;
6753
+ const targetPath = path$1.resolve(outdirPath, src ? "src" : "");
6754
+ const registry = await fetchRegistry("index");
6755
+ let content = registry.sources[0].content;
6756
+ if (jsx) content = transformTsToJs(content);
6757
+ await Promise.all([writeFileSafe(path$1.join(targetPath, indexFileName), content, config$1), writeFileSafe(path$1.join(targetPath, REGISTRY_FILE_NAME), JSON.stringify(registry), merge(config$1, { format: { parser: "json" } }))]);
6758
+ task.title = `Generated ${c.cyan(indexFileName)}`;
6293
6759
  },
6294
- title: `Generating ${c.cyan("index.ts")}`
6760
+ title: `Generating ${c.cyan(indexFileName)}`
6295
6761
  },
6296
6762
  {
6297
6763
  task: async (_, task) => {
@@ -6304,6 +6770,15 @@ const init = new Command("init").description("Initialize your project and instal
6304
6770
  title: "Adding workspace"
6305
6771
  }
6306
6772
  ], { concurrent: true });
6773
+ if (!jsx) tasks.add({
6774
+ task: async (_, task) => {
6775
+ const targetPath = path$1.resolve(outdirPath, "tsconfig.json");
6776
+ const content = JSON.stringify({ ...TSCONFIG_JSON });
6777
+ await writeFileSafe(targetPath, content, merge(config$1, { format: { parser: "json" } }));
6778
+ task.title = `Generated ${c.cyan("tsconfig.json")}`;
6779
+ },
6780
+ title: `Generating ${c.cyan("tsconfig.json")}`
6781
+ });
6307
6782
  await tasks.run();
6308
6783
  const { install } = await prompts({
6309
6784
  type: "confirm",
@@ -6325,13 +6800,13 @@ const init = new Command("init").description("Initialize your project and instal
6325
6800
  title: `Checking ${c.cyan("package.json")} dependencies`
6326
6801
  }, {
6327
6802
  task: async (_, task) => {
6328
- const { sources } = await fetchRegistry("index");
6329
- const targetPath = path$1.resolve(outdirPath, "index.ts");
6330
- const content = sources[0].content;
6331
- await writeFileSafe(targetPath, content, config$1);
6332
- task.title = `Generated ${c.cyan("index.ts")}`;
6803
+ const registry = await fetchRegistry("index");
6804
+ let content = registry.sources[0].content;
6805
+ if (jsx) content = transformTsToJs(content);
6806
+ await Promise.all([writeFileSafe(path$1.resolve(outdirPath, indexFileName), content, config$1), writeFileSafe(path$1.resolve(outdirPath, REGISTRY_FILE_NAME), JSON.stringify(registry), merge(config$1, { format: { parser: "json" } }))]);
6807
+ task.title = `Generated ${c.cyan(indexFileName)}`;
6333
6808
  },
6334
- title: `Generating ${c.cyan("index.ts")}`
6809
+ title: `Generating ${c.cyan(indexFileName)}`
6335
6810
  }], { concurrent: true });
6336
6811
  await tasks.run();
6337
6812
  if (notInstalledDependencies.length || notInstalledDevDependencies.length) {
@@ -6343,8 +6818,8 @@ const init = new Command("init").description("Initialize your project and instal
6343
6818
  message: c.reset([`The following dependencies are not installed: ${colorizedNames.join(", ")}.`, "Do you want to install them?"].join(" "))
6344
6819
  });
6345
6820
  if (install) {
6346
- dependencies$1 = notInstalledDependencies.map(getPackageName);
6347
- devDependencies$1 = notInstalledDevDependencies.map(getPackageName);
6821
+ dependencies$1 = notInstalledDependencies.map(getPackageNameWithVersion);
6822
+ devDependencies$1 = notInstalledDevDependencies.map(getPackageNameWithVersion);
6348
6823
  }
6349
6824
  }
6350
6825
  }
@@ -6380,6 +6855,70 @@ const init = new Command("init").description("Initialize your project and instal
6380
6855
  }
6381
6856
  });
6382
6857
 
6858
+ //#endregion
6859
+ //#region src/commands/theme/index.ts
6860
+ const theme = new Command("theme").description("generate theme to your project").argument("[path]", "path to the theme directory").option("--cwd <path>", "current working directory", cwd).option("-c, --config <path>", "path to the config file", CONFIG_FILE_NAME).option("-o, --overwrite", "overwrite existing directory.", false).option("-j, --js", "use js instead of ts").option("-f, --format", "format the output files.").option("-l, --lint", "lint the output files.").action(async function(themePath, { config: configPath, cwd: cwd$3, format: format$2, js, lint, overwrite }) {
6861
+ const spinner = ora();
6862
+ try {
6863
+ const { end } = timer();
6864
+ spinner.start("Validating directory");
6865
+ await validateDir(cwd$3);
6866
+ spinner.succeed("Validated directory");
6867
+ spinner.start("Fetching config");
6868
+ const config$1 = await getConfig(cwd$3, configPath, {
6869
+ format: format$2,
6870
+ jsx: js,
6871
+ lint
6872
+ });
6873
+ const resolvedPath = themePath ? path$1.resolve(cwd$3, themePath) : config$1.theme?.path ?? path$1.resolve(cwd$3, THEME_PATH);
6874
+ spinner.succeed("Fetched config");
6875
+ if (!overwrite && existsSync(resolvedPath)) {
6876
+ const { overwrite: overwrite$1 } = await prompts({
6877
+ type: "confirm",
6878
+ name: "overwrite",
6879
+ initial: false,
6880
+ message: c.reset(`The directory already exists. Do you want to overwrite it?`)
6881
+ });
6882
+ if (!overwrite$1) process.exit(0);
6883
+ spinner.start("Clearing directory");
6884
+ await rimraf(resolvedPath);
6885
+ spinner.succeed("Cleared directory");
6886
+ }
6887
+ spinner.start("Fetching registry");
6888
+ const registry = await fetchRegistry("theme");
6889
+ spinner.succeed("Fetched registry");
6890
+ const tasks = new Listr([{
6891
+ task: async (_, task) => {
6892
+ await Promise.all([...registry.sources.map(async ({ name: name$1, content }) => {
6893
+ if (!content) return;
6894
+ name$1 = transformExtension(name$1, config$1.jsx);
6895
+ const targetPath = path$1.resolve(resolvedPath, name$1);
6896
+ if (config$1.jsx) content = isTsx(name$1) ? transformTsxToJsx(content) : transformTsToJs(content);
6897
+ await writeFileSafe(targetPath, content, config$1);
6898
+ }), writeFileSafe(path$1.resolve(resolvedPath, REGISTRY_FILE_NAME), JSON.stringify(registry), merge(config$1, { format: { parser: "json" } }))]);
6899
+ task.title = `Generated theme`;
6900
+ },
6901
+ title: `Generating theme`
6902
+ }, {
6903
+ task: async (_, task) => {
6904
+ const targetPath = path$1.resolve(cwd$3, configPath);
6905
+ const data = await readFile(targetPath, "utf-8");
6906
+ const userConfig = JSON.parse(data);
6907
+ userConfig.theme ??= {};
6908
+ userConfig.theme.path ??= themePath ?? THEME_PATH;
6909
+ await writeFileSafe(targetPath, JSON.stringify(userConfig), merge(config$1, { format: { parser: "json" } }));
6910
+ task.title = `Updated config`;
6911
+ },
6912
+ title: `Updating config`
6913
+ }], { concurrent: true });
6914
+ await tasks.run();
6915
+ end();
6916
+ } catch (e) {
6917
+ if (e instanceof Error) spinner.fail(e.message);
6918
+ else spinner.fail("An unknown error occurred");
6919
+ }
6920
+ });
6921
+
6383
6922
  //#endregion
6384
6923
  //#region src/commands/tokens/config.ts
6385
6924
  const config = [
@@ -6441,9 +6980,9 @@ function isTone(value) {
6441
6980
  function print(unions) {
6442
6981
  return Object.entries(unions).sort(([a], [b]) => a.localeCompare(b)).map(([key, union]) => `${key}: ${!union.length ? "never" : union.map((value) => `"${value}"`).join(" | ")};`).join("\n");
6443
6982
  }
6444
- function extractColorSchemes(theme, colorTokens = []) {
6983
+ function extractColorSchemes(theme$1, colorTokens = []) {
6445
6984
  colorTokens.push("colorScheme.contrast", "colorScheme.fg", "colorScheme.subtle", "colorScheme.muted", "colorScheme.emphasized", "colorScheme.ghost", "colorScheme.solid", "colorScheme.outline");
6446
- const { colors, semanticTokens } = theme;
6985
+ const { colors, semanticTokens } = theme$1;
6447
6986
  const colorSchemes = [];
6448
6987
  Object.entries(colors ?? {}).forEach(([key, value]) => {
6449
6988
  if (!isTone(value)) return;
@@ -6467,8 +7006,8 @@ function extractColorSchemes(theme, colorTokens = []) {
6467
7006
  });
6468
7007
  return { colorSchemes };
6469
7008
  }
6470
- function extractThemeSchemes(theme) {
6471
- const { themeSchemes } = theme;
7009
+ function extractThemeSchemes(theme$1) {
7010
+ const { themeSchemes } = theme$1;
6472
7011
  return Object.keys(themeSchemes ?? {});
6473
7012
  }
6474
7013
  function extractPaths(target, { maxDepth = Infinity, replaceKey = (key) => key, shouldProcess = () => true } = {}) {
@@ -6488,10 +7027,10 @@ function extractKeys(obj, key) {
6488
7027
  if (!isObject(property)) return [];
6489
7028
  return Object.keys(property);
6490
7029
  }
6491
- function generateThemeTokens(theme, { internal = false, theme: { responsive = false } = {} }) {
7030
+ function generateThemeTokens(theme$1, { internal = false, theme: { responsive = false } = {} }) {
6492
7031
  let shouldProcess = () => true;
6493
- if (responsive && isObject(theme.breakpoints)) {
6494
- const keys = ["base", ...Object.keys(theme.breakpoints)];
7032
+ if (responsive && isObject(theme$1.breakpoints)) {
7033
+ const keys = ["base", ...Object.keys(theme$1.breakpoints)];
6495
7034
  const isResponsive = (obj) => {
6496
7035
  const providedKeys = Object.keys(obj);
6497
7036
  if (!providedKeys.length) return false;
@@ -6501,15 +7040,15 @@ function generateThemeTokens(theme, { internal = false, theme: { responsive = fa
6501
7040
  shouldProcess = (obj) => !isResponsive(obj);
6502
7041
  }
6503
7042
  const tokens$1 = config.reduce((prev, { key, flatMap = (value) => value, maxDepth, replaceKey, shouldProcess: additionalShouldProcess = () => true }) => {
6504
- const target = getObject(theme, key);
7043
+ const target = getObject(theme$1, key);
6505
7044
  prev[key] = [];
6506
7045
  if (isObject(target) || isArray(target)) prev[key] = extractPaths(target, {
6507
7046
  maxDepth,
6508
7047
  replaceKey,
6509
7048
  shouldProcess: (obj) => shouldProcess(obj) && additionalShouldProcess(obj)
6510
7049
  }).flatMap(flatMap);
6511
- if (isObject(theme.semanticTokens)) {
6512
- const target$1 = getObject(theme.semanticTokens, key);
7050
+ if (isObject(theme$1.semanticTokens)) {
7051
+ const target$1 = getObject(theme$1.semanticTokens, key);
6513
7052
  const semanticKeys = extractPaths(target$1, {
6514
7053
  maxDepth,
6515
7054
  replaceKey,
@@ -6519,16 +7058,16 @@ function generateThemeTokens(theme, { internal = false, theme: { responsive = fa
6519
7058
  }
6520
7059
  return prev;
6521
7060
  }, {});
6522
- const textStyles = extractKeys(theme, "styles.textStyles");
6523
- const layerStyles = extractKeys(theme, "styles.layerStyles");
6524
- const apply = extractPaths(omitObject(theme.styles ?? {}, [
7061
+ const textStyles = extractKeys(theme$1, "styles.textStyles");
7062
+ const layerStyles = extractKeys(theme$1, "styles.layerStyles");
7063
+ const apply = extractPaths(omitObject(theme$1.styles ?? {}, [
6525
7064
  "globalStyle",
6526
7065
  "layerStyles",
6527
7066
  "resetStyle",
6528
7067
  "textStyles"
6529
7068
  ]), { maxDepth: 2 });
6530
- const { colorSchemes } = extractColorSchemes(theme, tokens$1.colors);
6531
- const themeSchemes = extractThemeSchemes(theme);
7069
+ const { colorSchemes } = extractColorSchemes(theme$1, tokens$1.colors);
7070
+ const themeSchemes = extractThemeSchemes(theme$1);
6532
7071
  if (internal) return [
6533
7072
  `import type { UsageThemeTokens } from "./system"`,
6534
7073
  ``,
@@ -6562,15 +7101,15 @@ function generateThemeTokens(theme, { internal = false, theme: { responsive = fa
6562
7101
  }
6563
7102
  async function getTheme(path$9, cwd$3) {
6564
7103
  const { dependencies: dependencies$1, mod } = await getModule(path$9, cwd$3);
6565
- const theme = mod?.default ?? mod?.theme ?? mod?.customTheme ?? mod?.defaultTheme ?? {};
7104
+ const theme$1 = mod?.default ?? mod?.theme ?? mod?.customTheme ?? mod?.defaultTheme ?? {};
6566
7105
  const config$1 = mod?.config ?? mod?.customConfig ?? mod?.defaultConfig ?? {};
6567
7106
  return {
6568
7107
  config: config$1,
6569
7108
  dependencies: dependencies$1,
6570
- theme
7109
+ theme: theme$1
6571
7110
  };
6572
7111
  }
6573
- const tokens = new Command("tokens").description("Generate theme typings").argument("<path>", "Path to the theme file").option("--cwd <path>", "Current working directory", cwd).option("-c, --config <path>", "Path to the config file", CONFIG_FILE_NAME).option("-o, --out <path>", `Output path`).option("-f, --format", "Format the output file").option("-l, --lint", "Lint the output file").option("--internal", "Generate internal tokens", false).action(async function(inputPath, { config: configPath, cwd: cwd$3, format: format$3, internal, lint: lint$1, out: outPath }) {
7112
+ const tokens = new Command("tokens").description("generate theme typings").argument("[path]", "path to the theme file").option("--cwd <path>", "current working directory", cwd).option("-c, --config <path>", "path to the config file", CONFIG_FILE_NAME).option("-o, --out <path>", `output path`).option("-f, --format", "format the output file").option("-l, --lint", "lint the output file").option("--internal", "generate internal tokens", false).action(async function(inputPath, { config: configPath, cwd: cwd$3, format: format$2, internal, lint, out: outPath }) {
6574
7113
  const spinner = ora();
6575
7114
  try {
6576
7115
  const { end } = timer();
@@ -6581,11 +7120,13 @@ const tokens = new Command("tokens").description("Generate theme typings").argum
6581
7120
  if (!internal) {
6582
7121
  spinner.start("Fetching config");
6583
7122
  config$1 = await getConfig(cwd$3, configPath, {
6584
- format: format$3,
6585
- lint: lint$1
7123
+ format: format$2,
7124
+ lint
6586
7125
  });
7126
+ if (config$1.theme?.path) inputPath ??= path$1.resolve(cwd$3, config$1.theme.path, "index.ts");
6587
7127
  spinner.succeed("Fetched config");
6588
7128
  }
7129
+ if (!inputPath) throw new Error("No input path provided");
6589
7130
  spinner.start(`Getting theme`);
6590
7131
  cwd$3 = path$1.resolve(cwd$3);
6591
7132
  inputPath = path$1.resolve(cwd$3, inputPath);
@@ -6594,18 +7135,18 @@ const tokens = new Command("tokens").description("Generate theme typings").argum
6594
7135
  const dirPath = inputPath.split("/").slice(0, -1).join("/");
6595
7136
  outPath = path$1.join(dirPath, "index.types.ts");
6596
7137
  } else outPath = path$1.join(cwd$3, "index.types.ts");
6597
- const { config: themeConfig, theme } = await getTheme(inputPath, cwd$3);
7138
+ const { config: themeConfig, theme: theme$1 } = await getTheme(inputPath, cwd$3);
6598
7139
  spinner.succeed(`Got theme`);
6599
7140
  spinner.start(`Generating theme typings`);
6600
- const content = generateThemeTokens(theme, {
7141
+ const content = generateThemeTokens(theme$1, {
6601
7142
  ...themeConfig,
6602
7143
  internal
6603
7144
  });
6604
7145
  await writeFileSafe(outPath, content, config$1 ? merge(config$1, { lint: { filePath: inputPath } }) : {
6605
7146
  cwd: cwd$3,
6606
- format: { enabled: format$3 },
7147
+ format: { enabled: format$2 },
6607
7148
  lint: {
6608
- enabled: lint$1,
7149
+ enabled: lint,
6609
7150
  filePath: inputPath
6610
7151
  }
6611
7152
  });
@@ -6617,11 +7158,81 @@ const tokens = new Command("tokens").description("Generate theme typings").argum
6617
7158
  }
6618
7159
  });
6619
7160
 
7161
+ //#endregion
7162
+ //#region src/commands/update/index.ts
7163
+ const update = new Command("update").description("update components in your project").argument("[components...]", "components to update").option("--cwd <path>", "current working directory", cwd).option("-c, --config <path>", "path to the config file", CONFIG_FILE_NAME).option("-i, --install", "install dependencies", false).option("-s, --sequential", "run tasks sequentially.", false).option("-f, --format", "format the output files.").option("-l, --lint", "lint the output files.").action(async function(targetNames, { config: configPath, cwd: cwd$3, format: format$2, install, lint, sequential }) {
7164
+ const spinner = ora();
7165
+ try {
7166
+ const { end } = timer();
7167
+ const packageManager = getPackageManager();
7168
+ const { args, command } = packageExecuteCommands(packageManager);
7169
+ const prefix = `${command}${args.length ? ` ${args.join(" ")}` : ""}`;
7170
+ const getCommand = (command$1) => c.cyan(`${prefix} ${package_default.name}@latest ${command$1}`);
7171
+ spinner.start("Validating directory");
7172
+ await validateDir(cwd$3);
7173
+ spinner.succeed("Validated directory");
7174
+ spinner.start("Fetching config");
7175
+ const config$1 = await getConfig(cwd$3, configPath, {
7176
+ format: format$2,
7177
+ lint
7178
+ });
7179
+ spinner.succeed("Fetched config");
7180
+ spinner.start("Getting generated components");
7181
+ const all = !targetNames.length;
7182
+ const index = all || targetNames.includes("index");
7183
+ const theme$1 = all || targetNames.includes("theme");
7184
+ const existsTheme = !!config$1.theme?.path && existsSync(config$1.theme.path);
7185
+ if (theme$1 && !existsTheme) throw new Error([
7186
+ `No ${c.yellow("theme")} found.`,
7187
+ `Please run ${getCommand("theme")}`,
7188
+ "to generate it."
7189
+ ].join(" "));
7190
+ const omittedTargetNames = targetNames.filter((name$1) => !["index", "theme"].includes(name$1));
7191
+ const componentNames = [];
7192
+ const generatedNameMap = await getGeneratedNameMap(config$1);
7193
+ const generatedNames = Object.values(generatedNameMap).flat();
7194
+ spinner.succeed("Got generated components");
7195
+ if (omittedTargetNames.length) {
7196
+ const notFoundNames = omittedTargetNames.filter((name$1) => !generatedNames.includes(name$1));
7197
+ if (notFoundNames.length) throw new Error([
7198
+ `No ${notFoundNames.map((name$1) => c.yellow(name$1)).join(", ")} found in generated components.`,
7199
+ `Please run ${getCommand("add")} ${notFoundNames.map((name$1) => c.green(name$1)).join(", ")}`,
7200
+ "to add it."
7201
+ ].join(" "));
7202
+ else componentNames.push(...omittedTargetNames);
7203
+ } else if (all || !index && !theme$1) componentNames.push(...generatedNames);
7204
+ const { registryMap } = await getRegistriesAndFiles(componentNames, config$1, {
7205
+ concurrent: !sequential,
7206
+ index,
7207
+ theme: theme$1
7208
+ });
7209
+ const { changeMap, dependencyMap } = await getDiff(generatedNames, registryMap, config$1, !sequential);
7210
+ const hasChanges = !!Object.keys(changeMap).length;
7211
+ const hasDependencyChanges = !!dependencyMap.add.length || !!dependencyMap.remove.length || !!dependencyMap.update.length;
7212
+ console.log("---------------------------------");
7213
+ if (!hasChanges && !hasDependencyChanges) console.log(c.cyan("No updates found."));
7214
+ else {
7215
+ const conflictMap = await updateFiles(changeMap, dependencyMap, registryMap, config$1, {
7216
+ concurrent: !sequential,
7217
+ install
7218
+ });
7219
+ if (Object.keys(conflictMap).length) {
7220
+ console.log("---------------------------------");
7221
+ spinner.warn("There are conflicts. Please check the following files:");
7222
+ printConflicts(conflictMap, config$1);
7223
+ }
7224
+ }
7225
+ end();
7226
+ } catch (e) {
7227
+ if (e instanceof Error) spinner.fail(e.message);
7228
+ else spinner.fail("An unknown error occurred");
7229
+ }
7230
+ });
7231
+
6620
7232
  //#endregion
6621
7233
  //#region src/index.ts
6622
- async function run() {
7234
+ function run() {
6623
7235
  checkNode("22");
6624
- await unhandledError();
6625
7236
  updateNotifier({
6626
7237
  pkg: package_default,
6627
7238
  shouldNotifyInNpmScript: true,
@@ -6629,10 +7240,12 @@ async function run() {
6629
7240
  }).notify({ isGlobal: true });
6630
7241
  console.log(`\n${c.bold(c.green("Yamada UI CLI"))} v${package_default.version} ${c.dim("by Yamada UI")}`);
6631
7242
  console.log(`${c.dim(package_default.description)}\n`);
6632
- const program = new Command("Yamada UI CLI").version(package_default.version, "-v, --version", "Display the version number").usage(`${c.green("<command>")} [options]`);
7243
+ const program = new Command("Yamada UI CLI").version(package_default.version, "-v, --version", "display the version number").usage(`${c.green("<command>")} [options]`);
6633
7244
  program.addCommand(init);
6634
7245
  program.addCommand(add);
7246
+ program.addCommand(update);
6635
7247
  program.addCommand(diff);
7248
+ program.addCommand(theme);
6636
7249
  program.addCommand(tokens);
6637
7250
  program.parse();
6638
7251
  }