@yamada-ui/cli 2.0.0-dev-20250816072830 → 2.0.0-dev-20250817141319

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 +197 -44
  2. package/package.json +3 -1
package/dist/index.js CHANGED
@@ -23,15 +23,17 @@ import { mkdir, readFile, readdir, writeFile } from "fs/promises";
23
23
  import { Listr } from "listr2";
24
24
  import ora from "ora";
25
25
  import prompts from "prompts";
26
- import { execSync } from "child_process";
26
+ import { execa } from "execa";
27
27
  import "validate-npm-package-name";
28
28
  import YAML from "yamljs";
29
+ import { glob } from "glob";
29
30
  import { format as format$1, resolveConfig, resolveConfigFile } from "prettier";
30
31
  import { build } from "esbuild";
31
32
  import nodeEval from "node-eval";
32
33
  import { Script } from "vm";
33
34
  import { HttpsProxyAgent } from "https-proxy-agent";
34
35
  import fetch from "node-fetch";
36
+ import { diffLines } from "diff";
35
37
  import { rimraf } from "rimraf";
36
38
  import { ESLint } from "eslint";
37
39
 
@@ -5230,8 +5232,10 @@ var dependencies = {
5230
5232
  "cli-check-node": "^1.3.4",
5231
5233
  "cli-handle-unhandled": "^1.1.2",
5232
5234
  "commander": "^14.0.0",
5235
+ "diff": "^8.0.2",
5233
5236
  "esbuild": "^0.25.8",
5234
5237
  "eslint": "^9.32.0",
5238
+ "execa": "9.3.1",
5235
5239
  "glob": "^11.0.3",
5236
5240
  "https-proxy-agent": "^7.0.6",
5237
5241
  "listr2": "^9.0.1",
@@ -5306,13 +5310,37 @@ function timer() {
5306
5310
  const end = () => {
5307
5311
  const end$1 = process.hrtime.bigint();
5308
5312
  const duration = (Number(end$1 - start) / 1e9).toFixed(2);
5309
- console.log("\n", c.green(`Done in ${duration}s`));
5313
+ console.log("");
5314
+ console.log(c.green(`Done in ${duration}s`));
5310
5315
  };
5311
5316
  return {
5312
5317
  end,
5313
5318
  start
5314
5319
  };
5315
5320
  }
5321
+ async function getComponentFiles(componentName, { srcPath }) {
5322
+ const files$1 = {};
5323
+ const [dirPath] = await glob(path$1.join(srcPath, "**", componentName));
5324
+ if (!dirPath) return files$1;
5325
+ const dirents = await readdir(dirPath, { withFileTypes: true });
5326
+ await Promise.all(dirents.map(async (dirent) => {
5327
+ const name$1 = dirent.name;
5328
+ if (dirent.isDirectory()) {
5329
+ const data = await readdir(path$1.join(dirent.parentPath, name$1), { withFileTypes: true });
5330
+ await Promise.all(data.map(async (dirent$1) => {
5331
+ if (dirent$1.isDirectory()) return;
5332
+ const targetPath = path$1.join(dirent$1.parentPath, dirent$1.name);
5333
+ const data$1 = await readFile(targetPath, "utf-8");
5334
+ files$1[`${name$1}/${dirent$1.name}`] = data$1;
5335
+ }));
5336
+ } else {
5337
+ const targetPath = path$1.join(dirent.parentPath, dirent.name);
5338
+ const data = await readFile(targetPath, "utf-8");
5339
+ files$1[name$1] = data;
5340
+ }
5341
+ }));
5342
+ return files$1;
5343
+ }
5316
5344
 
5317
5345
  //#endregion
5318
5346
  //#region src/utils/prettier.ts
@@ -5380,37 +5408,49 @@ function splitVersion(value) {
5380
5408
  function getPackageName(value) {
5381
5409
  return isObject(value) ? `${value.name}@${value.wanted}` : value;
5382
5410
  }
5383
- function packageAddCommand(packageManager, { dev = false, exact = false } = {}) {
5384
- const command = [packageManager];
5385
- if (packageManager === "npm") command.push("install");
5386
- else command.push("add");
5387
- if (dev) if (packageManager === "npm") command.push("--save-dev");
5388
- else command.push("--dev");
5389
- if (exact) command.push("--save-exact");
5390
- return command.join(" ");
5411
+ function packageAddArgs(packageManager, { dev = false, exact = false } = {}) {
5412
+ const args = [];
5413
+ if (packageManager === "npm") args.push("install");
5414
+ else args.push("add");
5415
+ if (dev) if (packageManager === "npm") args.push("--save-dev");
5416
+ else args.push("--dev");
5417
+ if (exact) args.push("--save-exact");
5418
+ return args;
5391
5419
  }
5392
- function packageExecuteCommand(packageManager) {
5420
+ function packageExecuteCommands(packageManager) {
5393
5421
  switch (packageManager) {
5394
- case "npm": return "npx";
5395
- case "pnpm": return "pnpm dlx";
5396
- case "yarn": return "yarn dlx";
5397
- case "bun": return "bunx --bun";
5422
+ case "npm": return {
5423
+ args: [],
5424
+ command: "npx"
5425
+ };
5426
+ case "pnpm": return {
5427
+ args: ["dlx"],
5428
+ command: "pnpm"
5429
+ };
5430
+ case "yarn": return {
5431
+ args: ["dlx"],
5432
+ command: "yarn"
5433
+ };
5434
+ case "bun": return {
5435
+ args: ["--bun"],
5436
+ command: "bunx"
5437
+ };
5398
5438
  }
5399
5439
  }
5400
- function installDependencies(dependencies$1, { cwd: cwd$2, dev, exact = true } = {}) {
5440
+ async function installDependencies(dependencies$1, { cwd: cwd$2, dev, exact = true } = {}) {
5401
5441
  const packageManager = getPackageManager();
5402
5442
  if (dependencies$1?.length) {
5403
- const command = packageAddCommand(packageManager, {
5443
+ const args = packageAddArgs(packageManager, {
5404
5444
  dev,
5405
5445
  exact
5406
5446
  });
5407
- execSync(`${command} ${dependencies$1.join(" ")}`, {
5447
+ await execa(packageManager, [...args, ...dependencies$1], {
5408
5448
  cwd: cwd$2,
5409
- stdio: "ignore"
5449
+ stdout: "ignore"
5410
5450
  });
5411
- } else execSync(`${packageManager} install`, {
5451
+ } else await execa(packageManager, ["install"], {
5412
5452
  cwd: cwd$2,
5413
- stdio: "ignore"
5453
+ stdout: "ignore"
5414
5454
  });
5415
5455
  }
5416
5456
  async function addWorkspace(cwd$2, workspacePath) {
@@ -5502,8 +5542,9 @@ async function getConfig(cwd$2, configPath) {
5502
5542
  };
5503
5543
  } catch {
5504
5544
  const packageManager = getPackageManager();
5505
- const command = packageExecuteCommand(packageManager);
5506
- throw new Error(`No config found. Please run ${c.cyan(`${command} ${package_default.name}@latest init`)}.`);
5545
+ const { args, command } = packageExecuteCommands(packageManager);
5546
+ const prefix = `${command}${args.length ? ` ${args.join(" ")}` : ""}`;
5547
+ throw new Error(`No config found. Please run ${c.cyan(`${prefix} ${package_default.name}@latest init`)}.`);
5507
5548
  }
5508
5549
  }
5509
5550
 
@@ -5630,7 +5671,7 @@ async function getGeneratedNameMap(config$1) {
5630
5671
  }));
5631
5672
  return Object.fromEntries(results);
5632
5673
  }
5633
- function transformTemplate(targetSection, content, { getSection }, generatedNames) {
5674
+ function transformContent(targetSection, content, { getSection }, generatedNames) {
5634
5675
  const matches = content.matchAll(/from\s+["']([^"']+)["']/g);
5635
5676
  matches.forEach((match) => {
5636
5677
  const [searchValue, value] = match;
@@ -5684,11 +5725,11 @@ async function generateSources(dirPath, { section, sources }, config$1, generate
5684
5725
  await Promise.all(sources.map(async ({ name: fileName, content, data, template }) => {
5685
5726
  const targetPath = path$1.resolve(dirPath, fileName);
5686
5727
  if (content) {
5687
- content = transformTemplate(section, content, config$1, generatedNames);
5728
+ content = transformContent(section, content, config$1, generatedNames);
5688
5729
  await writeFileSafe(targetPath, await format$2(content));
5689
5730
  } else if (template && data) await Promise.all(data.map(async ({ name: fileName$1,...rest }) => {
5690
5731
  content = transformTemplateContent(template, rest);
5691
- content = transformTemplate(section, content, config$1, generatedNames);
5732
+ content = transformContent(section, content, config$1, generatedNames);
5692
5733
  await writeFileSafe(path$1.resolve(targetPath, fileName$1), await format$2(content));
5693
5734
  }));
5694
5735
  }));
@@ -5823,18 +5864,18 @@ const add = new Command("add").description("Add a component to your project").ar
5823
5864
  componentNames = await fetchRegistryNames();
5824
5865
  spinner.succeed("Fetched all available components");
5825
5866
  } else {
5826
- spinner.start("Getting generated data");
5867
+ spinner.start("Getting generated components");
5827
5868
  generatedNameMap = await getGeneratedNameMap(config$1);
5828
5869
  const generatedNames = Object.values(generatedNameMap).flat();
5829
5870
  const existsNames = componentNames.filter((name$1) => generatedNames.includes(name$1));
5830
- spinner.succeed("Got generated data");
5871
+ spinner.succeed("Got generated components");
5831
5872
  if (!overwrite && existsNames.length) {
5832
5873
  const colorizedNames = existsNames.map((name$1) => c.yellow(name$1));
5833
5874
  const { overwrite: overwrite$1 } = await prompts({
5834
5875
  type: "confirm",
5835
5876
  name: "overwrite",
5836
5877
  initial: false,
5837
- message: c.reset(`The ${colorizedNames.join(", ")} components already exist. Do you want to overwrite them?`)
5878
+ message: c.reset([`The ${colorizedNames.join(", ")} components already exist.`, "Do you want to overwrite them?"].join(" "))
5838
5879
  });
5839
5880
  if (!overwrite$1) process.exit(0);
5840
5881
  }
@@ -5895,7 +5936,7 @@ const add = new Command("add").description("Add a component to your project").ar
5895
5936
  type: "confirm",
5896
5937
  name: "update",
5897
5938
  initial: true,
5898
- message: c.reset(`The following generated files will be updated: ${colorizedNames.join(", ")}. Do you want to update them?`)
5939
+ message: c.reset([`The following generated files will be updated: ${colorizedNames.join(", ")}.`, "Do you want to update them?"].join(" "))
5899
5940
  });
5900
5941
  if (update) overwrite = update;
5901
5942
  }
@@ -5910,7 +5951,7 @@ const add = new Command("add").description("Add a component to your project").ar
5910
5951
  await Promise.all(dirents.map(async (dirent) => {
5911
5952
  if (dirent.isDirectory()) return;
5912
5953
  const targetPath = path$1.join(dirent.parentPath, dirent.name);
5913
- const content = transformTemplate(section, await readFile(targetPath, "utf-8"), config$1, targetNames);
5954
+ const content = transformContent(section, await readFile(targetPath, "utf-8"), config$1, targetNames);
5914
5955
  await writeFileSafe(targetPath, await format$2(content));
5915
5956
  }));
5916
5957
  task.title = `Updated ${c.cyan(name$1)}`;
@@ -5932,13 +5973,13 @@ const add = new Command("add").description("Add a component to your project").ar
5932
5973
  type: "confirm",
5933
5974
  name: "proceed",
5934
5975
  initial: true,
5935
- message: c.reset(`The following dependencies are not installed: ${colorizedNames.join(", ")}. Do you want to install them?`)
5976
+ message: c.reset([`The following dependencies are not installed: ${colorizedNames.join(", ")}.`, "Do you want to install them?"].join(" "))
5936
5977
  });
5937
5978
  install = proceed;
5938
5979
  }
5939
5980
  if (install) tasks.add({
5940
- task: (_, task) => {
5941
- installDependencies(notInstalledDependencies.map(getPackageName), { cwd: targetPath });
5981
+ task: async (_, task) => {
5982
+ await installDependencies(notInstalledDependencies.map(getPackageName), { cwd: targetPath });
5942
5983
  task.title = "Installed dependencies";
5943
5984
  },
5944
5985
  title: "Installing dependencies"
@@ -5954,17 +5995,125 @@ const add = new Command("add").description("Add a component to your project").ar
5954
5995
 
5955
5996
  //#endregion
5956
5997
  //#region src/commands/diff/index.ts
5957
- const diff = new Command("diff").description("Check for updates against the registry").argument("[component]", "Component to check").option("--cwd <path>", "Current working directory", process.cwd()).option("-c, --config <path>", "Path to the config file", CONFIG_FILE_NAME).action(async function(componentName, { config: configPath, cwd: cwd$2 }) {
5998
+ async function getData(componentNames, config$1) {
5999
+ const data = {};
6000
+ const registries = {};
6001
+ const tasks = new Listr([...componentNames.map((componentName) => ({
6002
+ task: async (_, task) => {
6003
+ data[componentName] = await getComponentFiles(componentName, config$1);
6004
+ task.title = `Got ${c.cyan(componentName)} files`;
6005
+ },
6006
+ title: `Getting ${c.cyan(componentName)} files`
6007
+ })), ...componentNames.map((componentName) => ({
6008
+ task: async (_, task) => {
6009
+ registries[componentName] = await fetchRegistry(componentName);
6010
+ task.title = `Fetched ${c.cyan(componentName)} registry`;
6011
+ },
6012
+ title: `Fetching ${c.cyan(componentName)} registry`
6013
+ }))], { concurrent: true });
6014
+ await tasks.run();
6015
+ return {
6016
+ data,
6017
+ registries
6018
+ };
6019
+ }
6020
+ async function getDiff(generatedNames, data, registries, config$1) {
6021
+ const changes = {};
6022
+ await Promise.all(Object.entries(data).map(async ([name$1, files$1]) => {
6023
+ const registry = registries[name$1];
6024
+ if (!registry) return;
6025
+ await Promise.all(Object.entries(files$1).map(async ([fileName, file$1]) => {
6026
+ const registryFile = registry.sources.find(({ name: name$2 }) => name$2 === fileName);
6027
+ if (!registryFile?.content) return;
6028
+ const content = await format$2(transformContent(registry.section, registryFile.content, config$1, generatedNames));
6029
+ const diff$1 = diffLines(file$1, content);
6030
+ if (diff$1.length < 2) return;
6031
+ changes[name$1] ??= {};
6032
+ changes[name$1][fileName] = diff$1;
6033
+ }));
6034
+ }));
6035
+ return changes;
6036
+ }
6037
+ const diff = new Command("diff").description("Check for updates against the registry").argument("[component]", "Component to check").option("--cwd <path>", "Current working directory", process.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$2, detail = false }) {
5958
6038
  const spinner = ora();
5959
6039
  try {
5960
6040
  const { end } = timer();
6041
+ const packageManager = getPackageManager();
6042
+ const { args, command } = packageExecuteCommands(packageManager);
6043
+ const prefix = `${command}${args.length ? ` ${args.join(" ")}` : ""}`;
6044
+ const addCommand = c.cyan(`${prefix} ${package_default.name}@latest add`);
6045
+ const diffCommand = c.cyan(`${prefix} ${package_default.name}@latest diff`);
5961
6046
  spinner.start("Validating directory");
5962
6047
  await validateDir(cwd$2);
5963
6048
  spinner.succeed("Validated directory");
5964
6049
  spinner.start("Fetching config");
5965
6050
  const config$1 = await getConfig(cwd$2, configPath);
5966
- console.log(config$1);
5967
6051
  spinner.succeed("Fetched config");
6052
+ const componentNames = [];
6053
+ spinner.start("Getting generated components");
6054
+ const generatedNameMap = await getGeneratedNameMap(config$1);
6055
+ const generatedNames = Object.values(generatedNameMap).flat();
6056
+ spinner.succeed("Got generated components");
6057
+ if (componentName) if (generatedNames.includes(componentName)) componentNames.push(componentName);
6058
+ else throw new Error([
6059
+ `No ${c.yellow(componentName)} found in generated components.`,
6060
+ `Please run ${addCommand} ${c.green(componentName)}`,
6061
+ "to add it."
6062
+ ].join(" "));
6063
+ else componentNames.push(...generatedNames);
6064
+ if (!componentNames.length) throw new Error([
6065
+ "No components found.",
6066
+ `Please run ${addCommand} ${c.green("<component>")}`,
6067
+ "to add components."
6068
+ ].join(" "));
6069
+ const { data, registries } = await getData(componentNames, config$1);
6070
+ const changes = await getDiff(generatedNames, data, registries, config$1);
6071
+ const hasChanges = Object.keys(changes).length;
6072
+ console.log("---------------------------------");
6073
+ if (!hasChanges) console.log(c.cyan("No updates found."));
6074
+ else if (componentName) {
6075
+ const diff$1 = changes[componentName];
6076
+ if (!diff$1) return;
6077
+ Object.entries(diff$1).forEach(([fileName, diff$2], index) => {
6078
+ if (!!index) console.log("");
6079
+ console.log(`- ${c.cyan(fileName)}`);
6080
+ console.log("");
6081
+ diff$2.forEach(({ added, removed, value }) => {
6082
+ if (added) return process.stdout.write(c.green(value));
6083
+ else if (removed) return process.stdout.write(c.red(value));
6084
+ else if (detail) return process.stdout.write(value);
6085
+ });
6086
+ });
6087
+ } else {
6088
+ componentNames.forEach((name$1) => {
6089
+ const diff$1 = changes[name$1];
6090
+ if (!diff$1) return;
6091
+ console.log(`- ${name$1}`);
6092
+ Object.entries(diff$1).forEach(([fileName, diff$2]) => {
6093
+ const added = diff$2.reduce((prev, { added: added$1, count }) => {
6094
+ if (added$1) return prev + count;
6095
+ return prev;
6096
+ }, 0);
6097
+ const removed = diff$2.reduce((prev, { count, removed: removed$1 }) => {
6098
+ if (removed$1) return prev + count;
6099
+ return prev;
6100
+ }, 0);
6101
+ console.log(` - ${c.cyan(fileName)} ${c.green(added)} insertions ${c.red(removed)} deletions`);
6102
+ });
6103
+ });
6104
+ console.log("");
6105
+ console.log(boxen([
6106
+ "Run",
6107
+ c.cyan(diffCommand),
6108
+ c.green("<component>"),
6109
+ "to see the changes."
6110
+ ].join(" "), {
6111
+ borderColor: "yellow",
6112
+ borderStyle: "round",
6113
+ padding: 1,
6114
+ textAlignment: "center"
6115
+ }));
6116
+ }
5968
6117
  end();
5969
6118
  } catch (e) {
5970
6119
  if (e instanceof Error) spinner.fail(e.message);
@@ -6045,7 +6194,7 @@ const init = new Command("init").description("Initialize your project and instal
6045
6194
  type: "confirm",
6046
6195
  name: "overwrite",
6047
6196
  initial: false,
6048
- message: c.reset(`The ${c.yellow(outdir)} directory already exists. Do you want to overwrite it?`)
6197
+ message: c.reset([`The ${c.yellow(outdir)} directory already exists.`, "Do you want to overwrite it?"].join(" "))
6049
6198
  });
6050
6199
  if (!overwrite$1) process.exit(0);
6051
6200
  spinner.start("Clearing directory");
@@ -6141,7 +6290,7 @@ const init = new Command("init").description("Initialize your project and instal
6141
6290
  type: "confirm",
6142
6291
  name: "install",
6143
6292
  initial: true,
6144
- message: c.reset(`The following dependencies are not installed: ${colorizedNames.join(", ")}. Do you want to install them?`)
6293
+ message: c.reset([`The following dependencies are not installed: ${colorizedNames.join(", ")}.`, "Do you want to install them?"].join(" "))
6145
6294
  });
6146
6295
  if (install) {
6147
6296
  dependencies$1 = notInstalledDependencies.map(getPackageName);
@@ -6151,21 +6300,25 @@ const init = new Command("init").description("Initialize your project and instal
6151
6300
  }
6152
6301
  if (dependencies$1 || devDependencies$1) {
6153
6302
  spinner.start("Installing dependencies");
6154
- if (dependencies$1) installDependencies(dependencies$1, { cwd: cwd$2 });
6155
- if (devDependencies$1) installDependencies(devDependencies$1, {
6303
+ if (dependencies$1) await installDependencies(dependencies$1, { cwd: cwd$2 });
6304
+ if (devDependencies$1) await installDependencies(devDependencies$1, {
6156
6305
  cwd: cwd$2,
6157
6306
  dev: true
6158
6307
  });
6159
- if (monorepo) installDependencies(["@yamada-ui/react@dev"], { cwd: outdirPath });
6308
+ if (monorepo) await installDependencies(["@yamada-ui/react@dev"], { cwd: outdirPath });
6160
6309
  spinner.succeed("Installed dependencies");
6161
6310
  }
6162
6311
  if (monorepo) {
6163
6312
  const packageManager = getPackageManager();
6164
- const command = packageAddCommand(packageManager);
6165
- console.log(boxen(`Run ${c.cyan(`${command} "${packageName}@workspace:*"`)} in your application.`, {
6313
+ const args = packageAddArgs(packageManager);
6314
+ console.log("");
6315
+ console.log(boxen([
6316
+ "Run",
6317
+ c.cyan(`${packageManager} ${args.join(" ")} "${packageName}@workspace:*"`),
6318
+ "in your application."
6319
+ ].join(" "), {
6166
6320
  borderColor: "yellow",
6167
6321
  borderStyle: "round",
6168
- margin: 1,
6169
6322
  padding: 1,
6170
6323
  textAlignment: "center"
6171
6324
  }));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yamada-ui/cli",
3
3
  "type": "module",
4
- "version": "2.0.0-dev-20250816072830",
4
+ "version": "2.0.0-dev-20250817141319",
5
5
  "description": "The official CLI for Yamada UI projects",
6
6
  "keywords": [
7
7
  "theme",
@@ -41,8 +41,10 @@
41
41
  "cli-check-node": "^1.3.4",
42
42
  "cli-handle-unhandled": "^1.1.2",
43
43
  "commander": "^14.0.0",
44
+ "diff": "^8.0.2",
44
45
  "esbuild": "^0.25.8",
45
46
  "eslint": "^9.32.0",
47
+ "execa": "9.3.1",
46
48
  "glob": "^11.0.3",
47
49
  "https-proxy-agent": "^7.0.6",
48
50
  "listr2": "^9.0.1",