@axis-ds/cli 1.7.8 → 1.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -21,20 +21,24 @@ import {
21
21
  findPnpUnpluggedPackages,
22
22
  globalCssSelectionNote,
23
23
  hasDependency,
24
+ installCommandPhrase,
24
25
  isPlainObject,
25
26
  isPnpProject,
26
27
  outsideCssPackageResolution,
28
+ pnpComponentSourceHidden,
27
29
  pnpProjectRoot,
28
30
  pnpRootOnlyDependency,
31
+ pnpUnplugSetupPhrase,
29
32
  projectFileExists,
30
33
  resolveBaseDir,
31
34
  rootDeclarationsAllowed,
32
35
  runScriptCommand,
33
36
  selectGlobalCss,
37
+ tailwindConfigImportResolution,
34
38
  tokensCssResolution,
35
39
  workspaceRootPackage,
36
40
  workspaceRunCommand
37
- } from "./chunk-C2T7NVDG.js";
41
+ } from "./chunk-EAUM5S4O.js";
38
42
  import {
39
43
  V0Client
40
44
  } from "./chunk-2PNCUPCG.js";
@@ -1849,11 +1853,199 @@ import ora3 from "ora";
1849
1853
 
1850
1854
  // src/template/post-install.ts
1851
1855
  import fs6 from "fs-extra";
1852
- import path6 from "path";
1853
1856
  import chalk4 from "chalk";
1857
+
1858
+ // ../axis-registry-core/src/template/apply-files.ts
1859
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmdirSync, unlinkSync, writeFileSync } from "fs";
1860
+ import path6 from "path";
1861
+ var TemplatePathError = class extends Error {
1862
+ constructor(relPath, reason) {
1863
+ super(`\uD15C\uD50C\uB9BF \uACBD\uB85C '${relPath}' \uAC00 \uB300\uC0C1 \uB514\uB809\uD130\uB9AC \uBC16\uC744 \uAC00\uB9AC\uCF1C(${reason}) \uC911\uB2E8\uD588\uC2B5\uB2C8\uB2E4. \uC544\uBB34 \uD30C\uC77C\uB3C4 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4`);
1864
+ this.relPath = relPath;
1865
+ this.reason = reason;
1866
+ this.name = "TemplatePathError";
1867
+ }
1868
+ };
1869
+ function realpathOfExisting(p) {
1870
+ const rest = [];
1871
+ let cur = p;
1872
+ for (; ; ) {
1873
+ try {
1874
+ lstatSync(cur);
1875
+ break;
1876
+ } catch {
1877
+ const parent = path6.dirname(cur);
1878
+ if (parent === cur) break;
1879
+ rest.unshift(path6.basename(cur));
1880
+ cur = parent;
1881
+ }
1882
+ }
1883
+ try {
1884
+ return path6.join(realpathSync(cur), ...rest);
1885
+ } catch {
1886
+ return void 0;
1887
+ }
1888
+ }
1889
+ function isInside(root, target) {
1890
+ const rel3 = path6.relative(root, target);
1891
+ return rel3 !== "" && !rel3.startsWith("..") && !path6.isAbsolute(rel3);
1892
+ }
1893
+ function resolveTemplatePath(baseDir, relPath) {
1894
+ if (typeof relPath !== "string" || relPath === "" || relPath.includes("\0")) {
1895
+ throw new TemplatePathError(String(relPath), "\uBE48 \uACBD\uB85C \uB610\uB294 \uC798\uBABB\uB41C \uBB38\uC790");
1896
+ }
1897
+ if (path6.isAbsolute(relPath) || path6.win32.isAbsolute(relPath)) throw new TemplatePathError(relPath, "\uC808\uB300 \uACBD\uB85C");
1898
+ const base = path6.resolve(baseDir);
1899
+ const dest = path6.resolve(base, relPath);
1900
+ if (!isInside(base, dest)) throw new TemplatePathError(relPath, "\uC0C1\uC704 \uB514\uB809\uD130\uB9AC\uB85C \uB098\uAC10");
1901
+ const baseReal = realpathOfExisting(base);
1902
+ const destReal = realpathOfExisting(dest);
1903
+ if (!baseReal || !destReal || !isInside(baseReal, destReal)) {
1904
+ throw new TemplatePathError(relPath, "\uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uAC00 \uB300\uC0C1 \uB514\uB809\uD130\uB9AC \uBC16\uC744 \uAC00\uB9AC\uD0B4");
1905
+ }
1906
+ return dest;
1907
+ }
1908
+ function assertTemplatePaths(baseDir, relPaths) {
1909
+ for (const p of relPaths) resolveTemplatePath(baseDir, p);
1910
+ }
1911
+ var PACKAGE_JSON_MERGED_MAPS = [
1912
+ "scripts",
1913
+ "dependencies",
1914
+ "devDependencies",
1915
+ "peerDependencies",
1916
+ "optionalDependencies"
1917
+ ];
1918
+ function isPlainObject2(v) {
1919
+ return typeof v === "object" && v !== null && !Array.isArray(v);
1920
+ }
1921
+ function parseObject(text) {
1922
+ try {
1923
+ const v = JSON.parse(text);
1924
+ return isPlainObject2(v) ? v : void 0;
1925
+ } catch {
1926
+ return void 0;
1927
+ }
1928
+ }
1929
+ function mergePackageJson(user, template) {
1930
+ const maps = new Set(PACKAGE_JSON_MERGED_MAPS);
1931
+ const out = {};
1932
+ for (const [key, value] of Object.entries(user)) {
1933
+ const tpl = template[key];
1934
+ if (maps.has(key) && isPlainObject2(tpl)) {
1935
+ out[key] = isPlainObject2(value) ? { ...value, ...tpl } : tpl;
1936
+ } else {
1937
+ out[key] = value;
1938
+ }
1939
+ }
1940
+ for (const [key, value] of Object.entries(template)) {
1941
+ if (!(key in out)) out[key] = value;
1942
+ }
1943
+ return out;
1944
+ }
1945
+ function mergeAxisConfigJson(user, template) {
1946
+ return { ...user, ...template };
1947
+ }
1948
+ function detectJsonIndent(text) {
1949
+ const m = /^([ \t]+)\S/m.exec(text);
1950
+ if (!m) return 2;
1951
+ return m[1].startsWith(" ") ? " " : m[1].length;
1952
+ }
1953
+ function serializeLike(before, value) {
1954
+ const crlf = before.includes("\r\n");
1955
+ const trailing = /\r?\n$/.test(before);
1956
+ let text = JSON.stringify(value, null, detectJsonIndent(before));
1957
+ if (trailing) text += "\n";
1958
+ return crlf ? text.replace(/\n/g, "\r\n") : text;
1959
+ }
1960
+ var MERGERS = {
1961
+ "package.json": mergePackageJson,
1962
+ "axis.config.json": mergeAxisConfigJson
1963
+ };
1964
+ function planTemplateFileContent(relPath, templateContent, before) {
1965
+ if (before === void 0) return { action: "created", content: templateContent };
1966
+ const merger = MERGERS[relPath.replace(/^\.\//, "")];
1967
+ if (!merger) return { action: "overwritten", content: templateContent };
1968
+ const user = parseObject(before);
1969
+ const template = parseObject(templateContent);
1970
+ if (!user || !template) {
1971
+ return {
1972
+ action: "overwritten",
1973
+ content: templateContent,
1974
+ note: `\uAE30\uC874 ${relPath} \uC744 JSON \uAC1D\uCCB4\uB85C \uC77D\uC744 \uC218 \uC5C6\uC5B4 \uD15C\uD50C\uB9BF \uB0B4\uC6A9\uC73C\uB85C \uB36E\uC5B4\uC501\uB2C8\uB2E4`
1975
+ };
1976
+ }
1977
+ return { action: "merged", content: serializeLike(before, merger(user, template)) };
1978
+ }
1979
+ function planTemplateFiles(baseDir, files, extraPaths = []) {
1980
+ const dests = files.map((file) => resolveTemplatePath(baseDir, file.path));
1981
+ assertTemplatePaths(baseDir, extraPaths);
1982
+ return files.map((file, i) => {
1983
+ const dest = dests[i];
1984
+ const before = existsSync(dest) ? readFileSync(dest, "utf8") : void 0;
1985
+ return { path: file.path, dest, before, ...planTemplateFileContent(file.path, file.content, before) };
1986
+ });
1987
+ }
1988
+ var TemplateApplyError = class extends Error {
1989
+ constructor(message, restored, unrestored) {
1990
+ super(message);
1991
+ this.restored = restored;
1992
+ this.unrestored = unrestored;
1993
+ this.name = "TemplateApplyError";
1994
+ }
1995
+ };
1996
+ function writeTemplateFiles(plan) {
1997
+ const done = [];
1998
+ const madeDirs = [];
1999
+ try {
2000
+ for (const item of plan) {
2001
+ const dir = path6.dirname(item.dest);
2002
+ if (!existsSync(dir)) {
2003
+ const fresh = [];
2004
+ for (let d = dir; !existsSync(d); d = path6.dirname(d)) fresh.unshift(d);
2005
+ mkdirSync(dir, { recursive: true });
2006
+ madeDirs.push(...fresh);
2007
+ }
2008
+ writeFileSync(item.dest, item.content);
2009
+ done.push(item);
2010
+ }
2011
+ } catch (err) {
2012
+ const restored = [];
2013
+ const unrestored = [];
2014
+ const failed = plan[done.length];
2015
+ const targets = failed ? [...done, failed] : done;
2016
+ for (const item of targets.reverse()) {
2017
+ try {
2018
+ if (item.before === void 0) {
2019
+ if (existsSync(item.dest)) unlinkSync(item.dest);
2020
+ } else {
2021
+ writeFileSync(item.dest, item.before);
2022
+ }
2023
+ restored.push(item.path);
2024
+ } catch {
2025
+ unrestored.push(item.path);
2026
+ }
2027
+ }
2028
+ for (const d of madeDirs.reverse()) {
2029
+ try {
2030
+ if (existsSync(d) && readdirSync(d).length === 0) rmdirSync(d);
2031
+ } catch {
2032
+ }
2033
+ }
2034
+ const reason = err instanceof Error ? err.message : String(err);
2035
+ const tail = unrestored.length > 0 ? ` \uB418\uB3CC\uB9AC\uC9C0 \uBABB\uD55C \uD30C\uC77C: ${unrestored.join(", ")}` : "";
2036
+ throw new TemplateApplyError(
2037
+ `\uD15C\uD50C\uB9BF \uD30C\uC77C\uC744 \uC4F0\uB294 \uB3C4\uC911 \uC2E4\uD328\uD574 \uAC74\uB4DC\uB9B0 \uD30C\uC77C ${restored.length}\uAC1C\uB97C \uC6D0\uB798\uB300\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4(${reason}).${tail}`,
2038
+ restored.reverse(),
2039
+ unrestored
2040
+ );
2041
+ }
2042
+ }
2043
+
2044
+ // src/template/post-install.ts
1854
2045
  async function runPostInstall(patches, baseDir, dryRun = false) {
2046
+ assertTemplatePaths(baseDir, patches.map((p) => p.file));
1855
2047
  for (const patch of patches) {
1856
- const filePath = path6.resolve(baseDir, patch.file);
2048
+ const filePath = resolveTemplatePath(baseDir, patch.file);
1857
2049
  if (dryRun) {
1858
2050
  console.log(chalk4.gray(` [dry-run] patch ${patch.type}: ${patch.file}`));
1859
2051
  continue;
@@ -1940,7 +2132,7 @@ async function readAxisConfig(baseDir) {
1940
2132
  }
1941
2133
 
1942
2134
  // ../axis-registry-core/src/template/tailwind-core.ts
1943
- import { existsSync, lstatSync, readdirSync, readFileSync, realpathSync, statSync } from "fs";
2135
+ import { existsSync as existsSync2, lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, realpathSync as realpathSync2, statSync } from "fs";
1944
2136
  import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "path";
1945
2137
  function declaredRange(baseDir, pkg, name) {
1946
2138
  return declaredDependency(baseDir, pkg, name)?.range;
@@ -1948,7 +2140,7 @@ function declaredRange(baseDir, pkg, name) {
1948
2140
  function declaredRangeForCheck(baseDir, pkg, name) {
1949
2141
  return declaredDependency(baseDir, pkg, name, void 0, { appOnlyInPnp: true })?.range;
1950
2142
  }
1951
- function isPlainObject2(value) {
2143
+ function isPlainObject3(value) {
1952
2144
  return typeof value === "object" && value !== null && !Array.isArray(value);
1953
2145
  }
1954
2146
  var VERSION = String.raw`v?(\d+)(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`;
@@ -2125,10 +2317,10 @@ function regularFile(file) {
2125
2317
  }
2126
2318
  function expandGlobalCss(baseDirInput, entryPath, entryRel, entryCssDir) {
2127
2319
  const baseDir = resolveBaseDir(baseDirInput);
2128
- const entry = readFileSync(entryPath, "utf8");
2320
+ const entry = readFileSync2(entryPath, "utf8");
2129
2321
  let entryReal = entryPath;
2130
2322
  try {
2131
- entryReal = realpathSync(entryPath);
2323
+ entryReal = realpathSync2(entryPath);
2132
2324
  } catch {
2133
2325
  }
2134
2326
  const raws = /* @__PURE__ */ new Map([[entryReal, entry]]);
@@ -2185,7 +2377,7 @@ function walkRelativeCssImports(baseDir, entryReal, raws, limit, includeConditio
2185
2377
  if (target === void 0) continue;
2186
2378
  let real;
2187
2379
  try {
2188
- real = realpathSync(target);
2380
+ real = realpathSync2(target);
2189
2381
  } catch {
2190
2382
  continue;
2191
2383
  }
@@ -2198,7 +2390,7 @@ function walkRelativeCssImports(baseDir, entryReal, raws, limit, includeConditio
2198
2390
  if (rel3 === "" || rel3 === ".." || rel3.startsWith(`..${sep}`) || isAbsolute(rel3)) continue;
2199
2391
  if (!raws.has(real)) {
2200
2392
  try {
2201
- raws.set(real, readFileSync(real, "utf8"));
2393
+ raws.set(real, readFileSync2(real, "utf8"));
2202
2394
  } catch {
2203
2395
  continue;
2204
2396
  }
@@ -2228,10 +2420,10 @@ function findLayoutTokensCssImport(baseDirInput) {
2228
2420
  const baseDir = resolveBaseDir(baseDirInput);
2229
2421
  for (const candidate of ROOT_LAYOUT_FILES) {
2230
2422
  const file = join(baseDir, candidate);
2231
- if (!existsSync(file)) continue;
2423
+ if (!existsSync2(file)) continue;
2232
2424
  let text;
2233
2425
  try {
2234
- text = readFileSync(file, "utf8");
2426
+ text = readFileSync2(file, "utf8");
2235
2427
  } catch {
2236
2428
  continue;
2237
2429
  }
@@ -2273,18 +2465,19 @@ function packageNameOfSpec(spec) {
2273
2465
  function displayRel(baseDir, p) {
2274
2466
  return relative(baseDir, p).split(sep).join("/");
2275
2467
  }
2276
- function packageLineShadowIssue(baseDir, expanded, origin, spec) {
2468
+ function packageLineShadowIssue(baseDir, expanded, origin, spec, opts = {}) {
2277
2469
  const name = packageNameOfSpec(spec);
2278
2470
  const lineDir = dirname(origin.path);
2279
2471
  const others = () => [...new Set(expanded.files.map((f) => dirname(f.path)))].filter((d) => d !== lineDir);
2280
2472
  const r = cssPackageLineResolution(baseDir, lineDir, spec, others);
2281
2473
  const head = `${spec} import \uAC00 \uC788\uC9C0\uB9CC \uADF8 \uC904\uC774 \uC788\uB294 \uD30C\uC77C \uC704\uCE58\uC5D0\uC11C`;
2282
2474
  const label = (pkgDir, version) => `${displayRel(baseDir, pkgDir)}(${version ?? "\uBC84\uC804 \uBAA8\uB984"})`;
2475
+ if (opts.tailwind3 === true && r.kind !== "shadow-not-exported") return void 0;
2283
2476
  switch (r.kind) {
2284
2477
  case "ok":
2285
2478
  return void 0;
2286
2479
  case "shadow-not-exported": {
2287
- const current = r.version !== void 0 && (compareExactVersions(r.version, TAILWIND4_MIN_AXIS_VERSION) ?? -1) >= 0;
2480
+ const current = opts.tailwind3 === true || r.version !== void 0 && (compareExactVersions(r.version, TAILWIND4_MIN_AXIS_VERSION) ?? -1) >= 0;
2288
2481
  const todo = current ? "\uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694" : `${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1\uC73C\uB85C \uB9DE\uCD94\uC138\uC694`;
2289
2482
  return `${head} \uBA3C\uC800 \uC7A1\uD788\uB294 ${label(r.pkgDir, r.version)}\uAC00 ${r.subpath} \uB97C \uB0B4\uBCF4\uB0B4\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uADF8 \uC911\uCCA9 node_modules \uC758 ${name} \uB97C \uC9C0\uC6B0\uAC70\uB098 ${todo}`;
2290
2483
  }
@@ -2327,13 +2520,20 @@ function judgeGlobalsCss(baseDir, selection, candidate, expanded) {
2327
2520
  const origin = evidenceOrigin(expanded, (f) => findTokensCssImport(f) === imported);
2328
2521
  via = cssImportViaNote(viaFiles([origin]));
2329
2522
  const tailwind4 = (detectTailwind(baseDir, pkg).major ?? 0) >= 4;
2330
- const issue = tailwind4 && origin !== void 0 && !isOutsideEntry(origin) ? tokensCssUnresolvedIssue(
2523
+ const inside = origin !== void 0 && !isOutsideEntry(origin);
2524
+ const issue = tailwind4 && inside ? tokensCssUnresolvedIssue(
2331
2525
  baseDir,
2332
2526
  pkg,
2333
2527
  imported,
2334
2528
  void 0,
2335
2529
  () => packageLineShadowIssue(baseDir, expanded, origin, imported)
2336
- ) : tokensCssUnresolvedIssue(baseDir, pkg, imported, origin !== void 0 ? origin.cssDir : outsideCssDir(selection));
2530
+ ) : tokensCssUnresolvedIssue(
2531
+ baseDir,
2532
+ pkg,
2533
+ imported,
2534
+ origin !== void 0 ? origin.cssDir : outsideCssDir(selection),
2535
+ inside ? () => packageLineShadowIssue(baseDir, expanded, origin, imported, { tailwind3: true }) : void 0
2536
+ );
2337
2537
  if (issue !== void 0) unresolved = `${candidate}\uC5D0 ${issue}`;
2338
2538
  else pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
2339
2539
  } else if (AXIS_VARIABLE_DEFINITION.test(stripCssComments(expanded.evidence))) {
@@ -2537,6 +2737,8 @@ function stripJsComments(src) {
2537
2737
  }
2538
2738
  var TOKENS_TAILWIND3_PRESET = "@axis-ds/tokens/tailwind";
2539
2739
  var PRESET_REFERENCE = /(?:\brequire\s*\(\s*|\bimport\s*\(\s*|\bfrom\s*|\bimport\s+)(["'])@axis-ds\/tokens\/tailwind\1/;
2740
+ var PRESET_REQUIRE_REFERENCE = /\brequire\s*\(\s*(["'])@axis-ds\/tokens\/tailwind\1/;
2741
+ var PRESET_IMPORT_REFERENCE = /(?:\bimport\s*\(\s*|\bfrom\s*|\bimport\s+)(["'])@axis-ds\/tokens\/tailwind\1/;
2540
2742
  function hasTokensPresetReference(source) {
2541
2743
  return PRESET_REFERENCE.test(stripJsComments(source));
2542
2744
  }
@@ -2564,7 +2766,7 @@ function hasBareCjsPresetRequire(code) {
2564
2766
  function isCommonJsConfig(file, source) {
2565
2767
  return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
2566
2768
  }
2567
- function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs) {
2769
+ function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs, code) {
2568
2770
  const r = tokensCssResolution(baseDir, pkg, TOKENS_PACKAGE_NAME);
2569
2771
  const head = `${file}\uC5D0 AXIS preset \uCC38\uC870\uAC00 \uC788\uC9C0\uB9CC ${TOKENS_PACKAGE_NAME} \uAC00`;
2570
2772
  if (r.kind === "not-installed") {
@@ -2573,6 +2775,14 @@ function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs) {
2573
2775
  if (r.kind === "pnp-root-only" && !bareCjs) {
2574
2776
  return `${head} ${PNP_ROOT_ONLY_NOTE}(\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8 \uC120\uC5B8 ${r.range}) \u2192 \uC571 package.json \uC5D0 ${TOKENS_PACKAGE_NAME} \uB97C \uC120\uC5B8\uD558\uC138\uC694`;
2575
2777
  }
2778
+ const e = tailwindConfigImportResolution(baseDir, TOKENS_TAILWIND3_PRESET, {
2779
+ require: PRESET_REQUIRE_REFERENCE.test(code),
2780
+ import: PRESET_IMPORT_REFERENCE.test(code)
2781
+ });
2782
+ if (e.kind === "not-exported") {
2783
+ const label = `${displayRel(baseDir, e.pkgDir)}(${e.version ?? "\uBC84\uC804 \uBAA8\uB984"})`;
2784
+ return `${file}\uC5D0 AXIS preset \uCC38\uC870\uAC00 \uC788\uC9C0\uB9CC \uBA3C\uC800 \uC7A1\uD788\uB294 ${label}\uAC00 ${e.subpath} \uB97C \uB0B4\uBCF4\uB0B4\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uADF8 node_modules \uC758 ${TOKENS_PACKAGE_NAME} \uB97C \uC9C0\uC6B0\uAC70\uB098 \uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694`;
2785
+ }
2576
2786
  return void 0;
2577
2787
  }
2578
2788
  function packageVersionGate(baseDirInput, pkg, name, min, options = {}) {
@@ -2604,8 +2814,8 @@ function versionGateLabel(gate) {
2604
2814
  }
2605
2815
  function readPackageJson(baseDir) {
2606
2816
  try {
2607
- const parsed = JSON.parse(readFileSync(join(baseDir, "package.json"), "utf8"));
2608
- return isPlainObject2(parsed) ? parsed : void 0;
2817
+ const parsed = JSON.parse(readFileSync2(join(baseDir, "package.json"), "utf8"));
2818
+ return isPlainObject3(parsed) ? parsed : void 0;
2609
2819
  } catch {
2610
2820
  return void 0;
2611
2821
  }
@@ -2627,7 +2837,8 @@ function tailwind4Issues(input, pkg, versions, baseDir) {
2627
2837
  const r = resolutions.get(name);
2628
2838
  if (r.kind === "undeclared" || r.kind === "app-lockfile") continue;
2629
2839
  if (hasComponentTailwindImport(evidence, name) || hasComponentSource(evidence, name)) continue;
2630
- if (componentCssResolvable(r)) missing.push(name);
2840
+ if (r.kind === "app" && pnpComponentSourceHidden(baseDir, name, r.range)) unresolvedMissing.push(componentCssPnpMissingIssue(name));
2841
+ else if (componentCssResolvable(r)) missing.push(name);
2631
2842
  else unresolvedMissing.push(componentCssMissingIssue(baseDir, name, r));
2632
2843
  }
2633
2844
  if (missing.length > 0) {
@@ -2643,12 +2854,17 @@ function tailwind4Issues(input, pkg, versions, baseDir) {
2643
2854
  }
2644
2855
  for (const name of TAILWIND4_COMPONENT_PACKAGES) {
2645
2856
  if (!hasComponentTailwindImport(evidence, name)) continue;
2646
- const unresolved = componentCssPresentIssue(baseDir, name, resolutions.get(name));
2857
+ const r = resolutions.get(name);
2858
+ const unresolved = componentCssPresentIssue(baseDir, name, r);
2647
2859
  const spec = `${name}/tailwind.css`;
2648
2860
  if (unresolved !== void 0) {
2649
2861
  issues.push(unresolved);
2650
2862
  continue;
2651
2863
  }
2864
+ if (r.kind === "app" && pnpComponentSourceHidden(baseDir, name, r.range)) {
2865
+ issues.push(componentCssPnpPresentIssue(name));
2866
+ continue;
2867
+ }
2652
2868
  const shadow = input.lineIssue === void 0 ? false : input.lineIssue(spec);
2653
2869
  let lineProblem;
2654
2870
  if (shadow !== false) lineProblem = shadow;
@@ -2667,6 +2883,13 @@ function componentInstallPhrase(baseDir, name, range) {
2667
2883
  const g = dependencyInstallGuide(baseDir, name, range);
2668
2884
  return g.kind === "install-at-root" ? `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${g.installCommand}` : g.installCommand;
2669
2885
  }
2886
+ var PNP_ZIP_SOURCE_NOTE = `Plug'n'Play \uC5D0\uC11C @source "./dist" \uAC00 .yarn/cache zip \uC548\uC744 \uAC00\uB9AC\uCF1C \uCEF4\uD3EC\uB10C\uD2B8 \uD074\uB798\uC2A4\uAC00 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`;
2887
+ function componentCssPnpMissingIssue(name) {
2888
+ return `${name} \uC758 tailwind.css \uB294 ${PNP_ZIP_SOURCE_NOTE} \u2192 ${pnpUnplugSetupPhrase(name)} \uB4A4 ${componentTailwindImportLine(name)}`;
2889
+ }
2890
+ function componentCssPnpPresentIssue(name) {
2891
+ return `${name}/tailwind.css import \uAC00 \uC788\uC9C0\uB9CC ${PNP_ZIP_SOURCE_NOTE} \u2192 ${pnpUnplugSetupPhrase(name)} \uD558\uC138\uC694`;
2892
+ }
2670
2893
  function componentCssMissingIssue(baseDir, name, r) {
2671
2894
  const line = componentTailwindImportLine(name);
2672
2895
  switch (r.kind) {
@@ -2763,12 +2986,12 @@ function checkTailwindSetup(baseDirInput) {
2763
2986
  }
2764
2987
  for (const file of TAILWIND_CONFIG_FILES) {
2765
2988
  const path17 = join(baseDir, file);
2766
- if (!existsSync(path17)) continue;
2767
- const content = readFileSync(path17, "utf8");
2989
+ if (!existsSync2(path17)) continue;
2990
+ const content = readFileSync2(path17, "utf8");
2768
2991
  if (hasTokensPresetReference(content)) {
2769
2992
  const code = stripJsComments(content);
2770
2993
  const bareCjs = isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code);
2771
- const unresolved = presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs);
2994
+ const unresolved = presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs, code);
2772
2995
  if (unresolved !== void 0) return { name: "tailwind.config", severity: "warn", message: unresolved };
2773
2996
  if (bareCjs) {
2774
2997
  const gate = packageVersionGate(baseDir, pkg, "@axis-ds/tokens", TOKENS_CJS_PRESET_FIXED_VERSION, { appOnlyInPnp: true });
@@ -2801,8 +3024,8 @@ function checkTailwindSetup(baseDirInput) {
2801
3024
  }
2802
3025
  function readAxisConfigLike(baseDir) {
2803
3026
  try {
2804
- const parsed = JSON.parse(readFileSync(join(baseDir, "axis.config.json"), "utf8"));
2805
- return isPlainObject2(parsed) ? parsed : void 0;
3027
+ const parsed = JSON.parse(readFileSync2(join(baseDir, "axis.config.json"), "utf8"));
3028
+ return isPlainObject3(parsed) ? parsed : void 0;
2806
3029
  } catch {
2807
3030
  return void 0;
2808
3031
  }
@@ -2904,7 +3127,7 @@ function realpathPosix(p) {
2904
3127
  const tail = [];
2905
3128
  for (let i = 0; i < 64; i++) {
2906
3129
  try {
2907
- return [realpathSync(cur), ...tail].join(sep).split(sep).join("/");
3130
+ return [realpathSync2(cur), ...tail].join(sep).split(sep).join("/");
2908
3131
  } catch {
2909
3132
  const parent = dirname(cur);
2910
3133
  if (parent === cur) return void 0;
@@ -2960,15 +3183,15 @@ function relDirOf(baseDir, dir) {
2960
3183
  }
2961
3184
  function realDir(dir) {
2962
3185
  try {
2963
- return realpathSync(dir);
3186
+ return realpathSync2(dir);
2964
3187
  } catch {
2965
3188
  return void 0;
2966
3189
  }
2967
3190
  }
2968
3191
  function packageVersion(dir) {
2969
3192
  try {
2970
- const parsed = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
2971
- return isPlainObject2(parsed) && typeof parsed.version === "string" ? parsed.version : void 0;
3193
+ const parsed = JSON.parse(readFileSync2(join(dir, "package.json"), "utf8"));
3194
+ return isPlainObject3(parsed) && typeof parsed.version === "string" ? parsed.version : void 0;
2972
3195
  } catch {
2973
3196
  return void 0;
2974
3197
  }
@@ -3003,7 +3226,7 @@ function packageContentTarget(baseDir, name, pkg) {
3003
3226
  let dir = dirname(resolve(found.dir, ...name.split("/").map(() => ".."), ".."));
3004
3227
  for (; ; ) {
3005
3228
  const candidate = join(dir, "node_modules", ...name.split("/"));
3006
- const rel3 = existsSync(join(candidate, "package.json")) ? relDirOf(baseDir, candidate) : void 0;
3229
+ const rel3 = existsSync2(join(candidate, "package.json")) ? relDirOf(baseDir, candidate) : void 0;
3007
3230
  if (rel3 !== void 0) {
3008
3231
  const candidateReal = realDir(candidate);
3009
3232
  if (candidateReal === real) alternates.push(`${rel3}/dist/index.js`);
@@ -3080,7 +3303,7 @@ function inspectTailwindContent(baseDirInput) {
3080
3303
  const pkg = readPackageJson(baseDir);
3081
3304
  const tailwind = detectTailwind(baseDir, pkg);
3082
3305
  if (tailwind.major !== void 0 && tailwind.major >= 4) return null;
3083
- const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync(join(baseDir, f)));
3306
+ const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync2(join(baseDir, f)));
3084
3307
  if (configFile === void 0) return null;
3085
3308
  const targets = [];
3086
3309
  const componentsDir = readAxisConfigLike(baseDir)?.componentsDir;
@@ -3094,7 +3317,7 @@ function inspectTailwindContent(baseDirInput) {
3094
3317
  }
3095
3318
  }
3096
3319
  if (targets.length === 0) return null;
3097
- const read = readTailwindContent(readFileSync(join(baseDir, configFile), "utf8"));
3320
+ const read = readTailwindContent(readFileSync2(join(baseDir, configFile), "utf8"));
3098
3321
  const globs = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!"));
3099
3322
  return {
3100
3323
  configFile,
@@ -3162,7 +3385,7 @@ function componentsUseAnimation(baseDir, componentsDir) {
3162
3385
  const [dir, depth] = stack.pop();
3163
3386
  let names;
3164
3387
  try {
3165
- names = readdirSync(dir);
3388
+ names = readdirSync2(dir);
3166
3389
  } catch {
3167
3390
  continue;
3168
3391
  }
@@ -3171,7 +3394,7 @@ function componentsUseAnimation(baseDir, componentsDir) {
3171
3394
  const p = join(dir, name);
3172
3395
  let st;
3173
3396
  try {
3174
- st = lstatSync(p);
3397
+ st = lstatSync2(p);
3175
3398
  } catch {
3176
3399
  continue;
3177
3400
  }
@@ -3179,7 +3402,7 @@ function componentsUseAnimation(baseDir, componentsDir) {
3179
3402
  if (st.isDirectory()) {
3180
3403
  if (name !== "node_modules" && depth < ANIMATION_SCAN_DEPTH_LIMIT) stack.push([p, depth + 1]);
3181
3404
  } else if (st.isFile() && st.size <= ANIMATION_SCAN_FILE_BYTES && /\.(tsx|ts|jsx|js)$/.test(name)) {
3182
- if (/\banimate-(?:in|out)\b/.test(readFileSync(p, "utf8"))) return true;
3405
+ if (/\banimate-(?:in|out)\b/.test(readFileSync2(p, "utf8"))) return true;
3183
3406
  }
3184
3407
  }
3185
3408
  }
@@ -3229,8 +3452,8 @@ function checkAnimationPlugin(baseDirInput) {
3229
3452
  message: `${file}\uC758 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${by}, ${problems.map((x) => x.why).join(" \xB7 ")}): Dialog \xB7 Select \uB4F1\uC758 \uC5F4\uACE0 \uB2EB\uB294 \uC560\uB2C8\uBA54\uC774\uC158\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uACE0 \uBE4C\uB4DC\uAC00 \uC2E4\uD328\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4 \u2192 ${problems.map((x) => x.name).join(" \xB7 ")} \uB97C package.json \uC5D0 \uC120\uC5B8 \xB7 \uC124\uCE58\uD558\uC138\uC694${via}${note}`
3230
3453
  };
3231
3454
  }
3232
- const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync(join(baseDir, f)));
3233
- const source = configFile !== void 0 ? stripJsComments(readFileSync(join(baseDir, configFile), "utf8")) : "";
3455
+ const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync2(join(baseDir, f)));
3456
+ const source = configFile !== void 0 ? stripJsComments(readFileSync2(join(baseDir, configFile), "utf8")) : "";
3234
3457
  const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
3235
3458
  const pluginReason = pluginProblem(ANIMATION_PLUGIN_TAILWIND3);
3236
3459
  if (plugins === "found" && pluginReason === void 0) {
@@ -3318,6 +3541,12 @@ function splitTopLevel(body) {
3318
3541
  }
3319
3542
 
3320
3543
  // src/template/template-apply.ts
3544
+ var ACTION_LABEL = {
3545
+ created: "\uC0DD\uC131",
3546
+ overwritten: "\uB36E\uC5B4\uC4F0\uAE30",
3547
+ merged: "\uD569\uCE58\uAE30"
3548
+ };
3549
+ var MERGED_HINT = "\uAE30\uC874 \uD544\uB4DC\uB97C \uB450\uACE0 \uD15C\uD50C\uB9BF \uD0A4\uB97C \uD569\uCE68";
3321
3550
  function templateDependencyCommands(installCommand, detail) {
3322
3551
  const lines = [];
3323
3552
  const deps = detail.dependencies ?? {};
@@ -3372,18 +3601,21 @@ async function applyTemplate(slug, options) {
3372
3601
  for (const w of await templateApplyWarnings(baseDir, detail)) {
3373
3602
  console.log(chalk5.yellow(`! ${w}`));
3374
3603
  }
3375
- const conflicts = [];
3376
- for (const file of detail.files) {
3377
- const dest = path8.join(baseDir, file.path);
3378
- if (await fs8.pathExists(dest)) {
3379
- conflicts.push(file.path);
3380
- }
3604
+ let plan;
3605
+ try {
3606
+ plan = planTemplateFiles(baseDir, detail.files, (detail.postInstall ?? []).map((p) => p.file));
3607
+ } catch (err) {
3608
+ if (!(err instanceof TemplatePathError)) throw err;
3609
+ console.error(chalk5.red(err.message));
3610
+ process.exitCode = 1;
3611
+ return false;
3381
3612
  }
3613
+ const conflicts = plan.filter((p) => p.action !== "created");
3382
3614
  if (conflicts.length > 0 && !options.yes && !options.dryRun) {
3383
3615
  console.log(chalk5.yellow(`
3384
3616
  \uAE30\uC874 \uD30C\uC77C\uACFC \uCDA9\uB3CC\uD558\uB294 ${conflicts.length}\uAC1C \uD30C\uC77C:`));
3385
3617
  for (const c of conflicts) {
3386
- console.log(chalk5.gray(` - ${c}`));
3618
+ console.log(chalk5.gray(` - ${c.path}${c.action === "merged" ? ` (${MERGED_HINT})` : ""}`));
3387
3619
  }
3388
3620
  const interactive = options.interactive ?? isInteractive();
3389
3621
  if (!interactive) {
@@ -3391,7 +3623,7 @@ async function applyTemplate(slug, options) {
3391
3623
  `\uB36E\uC5B4\uC4F0\uB824\uBA74: axis template apply ${slug} -y`,
3392
3624
  `\uBBF8\uB9AC\uBCF4\uAE30: axis template apply ${slug} --dry-run`
3393
3625
  ]);
3394
- return;
3626
+ return false;
3395
3627
  }
3396
3628
  const { proceed } = await ask(
3397
3629
  {
@@ -3404,16 +3636,16 @@ async function applyTemplate(slug, options) {
3404
3636
  );
3405
3637
  if (!proceed) {
3406
3638
  console.log(chalk5.gray("\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
3407
- return;
3639
+ return false;
3408
3640
  }
3409
3641
  }
3410
3642
  if (options.dryRun) {
3411
3643
  console.log(chalk5.blue("\n[\uBBF8\uB9AC\uBCF4\uAE30] \uC0DD\uC131\uB420 \uD30C\uC77C:"));
3412
- for (const file of detail.files) {
3413
- const dest = path8.join(baseDir, file.path);
3414
- const exists = conflicts.includes(file.path);
3415
- const label = exists ? chalk5.yellow("\uB36E\uC5B4\uC4F0\uAE30") : chalk5.green("\uC0DD\uC131");
3416
- console.log(` ${label} ${dest}`);
3644
+ for (const item of plan) {
3645
+ const text = ACTION_LABEL[item.action];
3646
+ const label = item.action === "created" ? chalk5.green(text) : chalk5.yellow(text);
3647
+ console.log(` ${label} ${item.dest}${item.action === "merged" ? chalk5.gray(` (${MERGED_HINT})`) : ""}`);
3648
+ if (item.note) console.log(chalk5.yellow(` ! ${item.note}`));
3417
3649
  }
3418
3650
  if (detail.postInstall?.length) {
3419
3651
  console.log(chalk5.blue("\n[\uBBF8\uB9AC\uBCF4\uAE30] postInstall \uD328\uCE58:"));
@@ -3421,15 +3653,21 @@ async function applyTemplate(slug, options) {
3421
3653
  console.log(chalk5.gray(` ${p.type}: ${p.file}`));
3422
3654
  }
3423
3655
  }
3424
- return;
3656
+ return false;
3425
3657
  }
3426
3658
  const writeSpinner = ora3("\uD30C\uC77C \uC0DD\uC131 \uC911...").start();
3427
- for (const file of detail.files) {
3428
- const dest = path8.join(baseDir, file.path);
3429
- await fs8.ensureDir(path8.dirname(dest));
3430
- await fs8.writeFile(dest, file.content);
3659
+ try {
3660
+ writeTemplateFiles(plan);
3661
+ } catch (err) {
3662
+ writeSpinner.fail(err.message);
3663
+ process.exitCode = 1;
3664
+ return false;
3431
3665
  }
3432
3666
  writeSpinner.succeed(`${detail.files.length}\uAC1C \uD30C\uC77C \uC0DD\uC131 \uC644\uB8CC`);
3667
+ for (const item of plan) {
3668
+ if (item.action === "merged") console.log(chalk5.gray(` ${item.path}: ${MERGED_HINT}`));
3669
+ if (item.note) console.log(chalk5.yellow(`! ${item.note}`));
3670
+ }
3433
3671
  if (detail.postInstall?.length) {
3434
3672
  console.log(chalk5.blue("\npostInstall \uD328\uCE58 \uC2E4\uD589 \uC911..."));
3435
3673
  await runPostInstall(detail.postInstall, baseDir);
@@ -3443,6 +3681,7 @@ async function applyTemplate(slug, options) {
3443
3681
  }
3444
3682
  console.log(chalk5.green(`
3445
3683
  '${detail.name}' \uD15C\uD50C\uB9BF \uC801\uC6A9 \uC644\uB8CC!`));
3684
+ return true;
3446
3685
  }
3447
3686
  async function initTemplate(slug, options) {
3448
3687
  const interactive = options.interactive ?? isInteractive();
@@ -3528,7 +3767,7 @@ async function initTemplate(slug, options) {
3528
3767
  await fs8.ensureDir(resolved);
3529
3768
  }
3530
3769
  const nextSteps = templateInitNextSteps(resolved);
3531
- await applyTemplate(selectedSlug, { dir: targetDir, yes: true });
3770
+ if (!await applyTemplate(selectedSlug, { dir: targetDir, yes: true })) return;
3532
3771
  const configPath = path8.join(resolved, "axis.config.json");
3533
3772
  if (!await fs8.pathExists(configPath)) {
3534
3773
  const axisConfig = createTemplateConfig(selectedSlug);
@@ -3558,8 +3797,17 @@ async function diffTemplate(slug, options) {
3558
3797
  }
3559
3798
  const baseDir = path9.resolve(options.dir || ".");
3560
3799
  const entries = [];
3561
- for (const file of detail.files) {
3562
- const localPath = path9.join(baseDir, file.path);
3800
+ let localPaths;
3801
+ try {
3802
+ localPaths = detail.files.map((file) => resolveTemplatePath(baseDir, file.path));
3803
+ } catch (err) {
3804
+ if (!(err instanceof TemplatePathError)) throw err;
3805
+ console.error(chalk6.red(err.message));
3806
+ process.exitCode = 1;
3807
+ return;
3808
+ }
3809
+ for (const [i, file] of detail.files.entries()) {
3810
+ const localPath = localPaths[i];
3563
3811
  if (!await fs9.pathExists(localPath)) {
3564
3812
  entries.push({ path: file.path, status: "added" });
3565
3813
  continue;
@@ -3658,7 +3906,7 @@ import chalk7 from "chalk";
3658
3906
 
3659
3907
  // src/theme/brand-core.ts
3660
3908
  import { createHash } from "crypto";
3661
- import { existsSync as existsSync2, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
3909
+ import { existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
3662
3910
  import { createRequire } from "module";
3663
3911
  import { dirname as dirname2, join as join2, relative as relative2, resolve as resolve2, sep as sep2 } from "path";
3664
3912
  import { MessageChannel, Worker, receiveMessageOnPort } from "worker_threads";
@@ -3682,7 +3930,7 @@ var KEY_TOKENS = [
3682
3930
  ];
3683
3931
  var BRAND_ADJUSTMENT_REFERENCE = "WI-0025 PRD \uBD80\uB85D B (docs/workitems/WI-0025-brand-theme/prd.md)";
3684
3932
  function readJsonFile(file) {
3685
- return JSON.parse(readFileSync2(file, "utf8"));
3933
+ return JSON.parse(readFileSync3(file, "utf8"));
3686
3934
  }
3687
3935
  function errorCode(err) {
3688
3936
  return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
@@ -3693,7 +3941,7 @@ function tokensPackageJsonCandidates(baseDir) {
3693
3941
  for (; ; ) {
3694
3942
  const candidate = join2(dir, "node_modules", TOKENS_PACKAGE, "package.json");
3695
3943
  candidates.push(candidate);
3696
- if (existsSync2(candidate)) return { found: candidate, candidates };
3944
+ if (existsSync3(candidate)) return { found: candidate, candidates };
3697
3945
  const parent = dirname2(dir);
3698
3946
  if (parent === dir) return { candidates };
3699
3947
  dir = parent;
@@ -3839,7 +4087,7 @@ function openTokensResolver(baseDir, candidates, pkgJson, pkgText) {
3839
4087
  postChecked = true;
3840
4088
  let after;
3841
4089
  try {
3842
- after = sha256(readFileSync2(pkgJson, "utf8"));
4090
+ after = sha256(readFileSync3(pkgJson, "utf8"));
3843
4091
  } catch {
3844
4092
  after = UNKNOWN;
3845
4093
  }
@@ -3873,13 +4121,13 @@ function readVersion(pkgText) {
3873
4121
  function openTokens(baseDir) {
3874
4122
  const { found: pkgJson, candidates } = tokensPackageJsonCandidates(baseDir);
3875
4123
  if (!pkgJson) return { resolution: { status: "not-installed" } };
3876
- const pkgText = readFileSync2(pkgJson, "utf8");
4124
+ const pkgText = readFileSync3(pkgJson, "utf8");
3877
4125
  let version = readVersion(pkgText);
3878
4126
  const resolver = openTokensResolver(baseDir, candidates, pkgJson, pkgText);
3879
4127
  const finish = (status, indexPath) => {
3880
4128
  if (resolver.raced) {
3881
4129
  try {
3882
- version = readVersion(readFileSync2(pkgJson, "utf8"));
4130
+ version = readVersion(readFileSync3(pkgJson, "utf8"));
3883
4131
  } catch {
3884
4132
  }
3885
4133
  }
@@ -3931,7 +4179,7 @@ var AXIS_CONFIG_FILE_NAME = "axis.config.json";
3931
4179
  function readBrandConfig(baseDir) {
3932
4180
  let parsed;
3933
4181
  try {
3934
- parsed = JSON.parse(readFileSync2(join2(resolve2(baseDir), AXIS_CONFIG_FILE_NAME), "utf8"));
4182
+ parsed = JSON.parse(readFileSync3(join2(resolve2(baseDir), AXIS_CONFIG_FILE_NAME), "utf8"));
3935
4183
  } catch {
3936
4184
  return null;
3937
4185
  }
@@ -4080,13 +4328,13 @@ function findBrandActivation(baseDir) {
4080
4328
  const file = join2(root, candidate);
4081
4329
  if (!isFile(file)) continue;
4082
4330
  layoutFiles.push(candidate);
4083
- const text = stripJsLikeComments(readFileSync2(file, "utf8"));
4331
+ const text = stripJsLikeComments(readFileSync3(file, "utf8"));
4084
4332
  const providerTexts = [];
4085
4333
  for (const m of text.matchAll(/from\s+["']\.\/(providers?)["']/g)) {
4086
4334
  for (const ext of [".tsx", ".jsx", ".ts", ".js"]) {
4087
4335
  const rel3 = `${dirname2(candidate)}/${m[1]}${ext}`;
4088
4336
  const p = join2(root, rel3);
4089
- if (isFile(p)) providerTexts.push({ rel: rel3, text: stripJsLikeComments(readFileSync2(p, "utf8")) });
4337
+ if (isFile(p)) providerTexts.push({ rel: rel3, text: stripJsLikeComments(readFileSync3(p, "utf8")) });
4090
4338
  }
4091
4339
  }
4092
4340
  const all = [text, ...providerTexts.map((x) => x.text)];
@@ -4117,7 +4365,7 @@ function inspectBrandActivation(baseDir) {
4117
4365
  var THEME_PACKAGE = "@axis-ds/theme";
4118
4366
  function readProjectPackageJson(baseDir) {
4119
4367
  try {
4120
- const parsed = JSON.parse(readFileSync2(join2(resolve2(baseDir), "package.json"), "utf8"));
4368
+ const parsed = JSON.parse(readFileSync3(join2(resolve2(baseDir), "package.json"), "utf8"));
4121
4369
  return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : void 0;
4122
4370
  } catch {
4123
4371
  return void 0;
@@ -4146,7 +4394,7 @@ function getBrandWith(tokens, resolver, name) {
4146
4394
  try {
4147
4395
  summary = readSummary(resolver, entry);
4148
4396
  const cssPath = resolver.resolve(summary.importPath);
4149
- parsed = parseBrandCss(readFileSync2(cssPath, "utf8"), name);
4397
+ parsed = parseBrandCss(readFileSync3(cssPath, "utf8"), name);
4150
4398
  } catch (err) {
4151
4399
  if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
4152
4400
  if (resolver.stale && errorCode(err) === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
@@ -4168,7 +4416,7 @@ function getBrandWith(tokens, resolver, name) {
4168
4416
  }
4169
4417
 
4170
4418
  // ../axis-registry-core/src/template/dependencies-core.ts
4171
- import { readFileSync as readFileSync3 } from "fs";
4419
+ import { readFileSync as readFileSync4 } from "fs";
4172
4420
  import { join as join3 } from "path";
4173
4421
  var REQUIRED_DEPENDENCIES = ["tailwindcss"];
4174
4422
  var RECOMMENDED_DEPENDENCIES = ["clsx", "tailwind-merge"];
@@ -4185,7 +4433,7 @@ function checkDependencies(baseDirInput) {
4185
4433
  const baseDir = resolveBaseDir(baseDirInput);
4186
4434
  let pkg;
4187
4435
  try {
4188
- const parsed = JSON.parse(readFileSync3(join3(baseDir, "package.json"), "utf8"));
4436
+ const parsed = JSON.parse(readFileSync4(join3(baseDir, "package.json"), "utf8"));
4189
4437
  if (!isPlainObject(parsed)) throw new Error("not object");
4190
4438
  pkg = parsed;
4191
4439
  } catch (err) {
@@ -4227,11 +4475,15 @@ function checkDependencies(baseDirInput) {
4227
4475
  if (missingRecommended.length > 0) problems.push(`\uAD8C\uC7A5 \uC758\uC874\uC131 \uB204\uB77D: ${missingRecommended.join(", ")}`);
4228
4476
  if (pnpRootRecommended.length > 0) problems.push(`\uAD8C\uC7A5 \uC758\uC874\uC131 ${pnpRootRecommended.join(", ")} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 \uC571 package.json \uC5D0 \uC120\uC5B8\uD558\uC138\uC694`);
4229
4477
  if (pnpRootAxis.length > 0) problems.push(`${pnpRootAxis.join(", ")} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 \uC571 package.json \uC5D0 \uC120\uC5B8\uD558\uC138\uC694`);
4478
+ const installCommand = detectInstallCommand(baseDir);
4230
4479
  if (notInstalledOther.length > 0) {
4231
- problems.push(`\uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 \uC758\uC874\uC131: ${notInstalledOther.join(", ")} \u2192 ${detectInstallCommand(baseDir)}`);
4480
+ const phrase = installCommandPhrase(installCommand, notInstalledOther.some((d) => fromRoot(d)));
4481
+ problems.push(`\uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 \uC758\uC874\uC131: ${notInstalledOther.join(", ")} \u2192 ${phrase}`);
4232
4482
  }
4233
4483
  if (notInstalledRoot.length > 0) {
4234
- problems.push(`\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB3FC \uC788\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4: ${notInstalledRoot.join(", ")} \u2192 ${detectInstallCommand(baseDir)}`);
4484
+ problems.push(
4485
+ `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB3FC \uC788\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4: ${notInstalledRoot.join(", ")} \u2192 ${installCommandPhrase(installCommand, true)}`
4486
+ );
4235
4487
  }
4236
4488
  if (problems.length > 0) {
4237
4489
  return { name: "dependencies", severity: "warn", message: problems.join(" / ") + (rootNote ? ` (${rootNote})` : "") };
@@ -4511,13 +4763,13 @@ import chalk9 from "chalk";
4511
4763
  import path12 from "path";
4512
4764
 
4513
4765
  // src/theme/theme-add.ts
4514
- import { accessSync, constants, existsSync as existsSync3, readFileSync as readFileSync4, realpathSync as realpathSync2, unlinkSync, writeFileSync } from "fs";
4766
+ import { accessSync, constants, existsSync as existsSync4, readFileSync as readFileSync5, realpathSync as realpathSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
4515
4767
  import path11 from "path";
4516
4768
  var TOKENS_DEPENDENCY_RANGE = `^${TOKENS_DEPENDENCY_MIN_VERSION}`;
4517
4769
  var TAILWIND3_BASE_IMPORTS = [`${TOKENS_PACKAGE}/css`, `${TOKENS_PACKAGE}/css/shadcn`];
4518
4770
  var THEME_MIN_VERSION = "1.3.0";
4519
4771
  function readText(file) {
4520
- return existsSync3(file) ? readFileSync4(file, "utf8") : null;
4772
+ return existsSync4(file) ? readFileSync5(file, "utf8") : null;
4521
4773
  }
4522
4774
  function eolOf(text) {
4523
4775
  return text.includes("\r\n") ? "\r\n" : "\n";
@@ -4608,8 +4860,8 @@ function compareVersions(a, b) {
4608
4860
  return 0;
4609
4861
  }
4610
4862
  function realPathInside(baseDir, file) {
4611
- const realBase = realpathSync2(baseDir);
4612
- const realPath = realpathSync2(file);
4863
+ const realBase = realpathSync3(baseDir);
4864
+ const realPath = realpathSync3(file);
4613
4865
  const relPath = path11.relative(realBase, realPath);
4614
4866
  const inside = relPath !== "" && !relPath.startsWith("..") && !path11.isAbsolute(relPath);
4615
4867
  return { inside, realPath };
@@ -4652,7 +4904,7 @@ function planThemeAdd(baseDirInput, brand) {
4652
4904
  }
4653
4905
  plan.tokens = resolveTokens(baseDir);
4654
4906
  if (plan.tokens.status === "ok" && plan.tokens.indexPath) {
4655
- const data = JSON.parse(readFileSync4(plan.tokens.indexPath, "utf8"));
4907
+ const data = JSON.parse(readFileSync5(plan.tokens.indexPath, "utf8"));
4656
4908
  const entries = Array.isArray(data.brands) ? data.brands : [];
4657
4909
  const entry = entries.find((e) => e.name === brand);
4658
4910
  if (!entry) {
@@ -4711,7 +4963,7 @@ function planThemeAdd(baseDirInput, brand) {
4711
4963
  plan.writes = [];
4712
4964
  return plan;
4713
4965
  }
4714
- const before = readFileSync4(location.path, "utf8");
4966
+ const before = readFileSync5(location.path, "utf8");
4715
4967
  const imported = findBrandImports(before);
4716
4968
  const otherBrands = [...new Set(imported.filter((n) => n !== brand))];
4717
4969
  const brandAdded = !imported.includes(brand);
@@ -4747,11 +4999,11 @@ function planThemeAdd(baseDirInput, brand) {
4747
4999
  };
4748
5000
  }
4749
5001
  if (!tailwind4) {
4750
- const configFile2 = TAILWIND_CONFIG_FILES.find((f) => existsSync3(path11.join(baseDir, f)));
5002
+ const configFile2 = TAILWIND_CONFIG_FILES.find((f) => existsSync4(path11.join(baseDir, f)));
4751
5003
  const content = inspectTailwindContent(baseDir);
4752
5004
  plan.tailwindConfig = {
4753
5005
  configFile: configFile2,
4754
- presetMissing: configFile2 === void 0 || !hasTokensPresetReference(readFileSync4(path11.join(baseDir, configFile2), "utf8")),
5006
+ presetMissing: configFile2 === void 0 || !hasTokensPresetReference(readFileSync5(path11.join(baseDir, configFile2), "utf8")),
4755
5007
  contentMissing: content?.targets.filter((t) => !t.covered) ?? [],
4756
5008
  contentUnknown: content !== null && (content.unreadable || content.dynamic)
4757
5009
  };
@@ -4836,15 +5088,15 @@ function applyThemeAdd(plan) {
4836
5088
  const done = [];
4837
5089
  for (const w of plan.writes) {
4838
5090
  try {
4839
- writeFileSync(w.file, w.after);
5091
+ writeFileSync2(w.file, w.after);
4840
5092
  done.push(w);
4841
5093
  } catch (err) {
4842
5094
  const restored = [];
4843
5095
  const restoreFailed = [];
4844
5096
  for (const d of done.reverse()) {
4845
5097
  try {
4846
- if (d.before === null) unlinkSync(d.file);
4847
- else writeFileSync(d.file, d.before);
5098
+ if (d.before === null) unlinkSync2(d.file);
5099
+ else writeFileSync2(d.file, d.before);
4848
5100
  restored.push(d.file);
4849
5101
  } catch {
4850
5102
  restoreFailed.push(d.file);
@@ -4896,6 +5148,10 @@ function installPhrase(g) {
4896
5148
  if (g.kind === "install-at-root") return `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${chalk9.cyan(g.installCommand)}`;
4897
5149
  return chalk9.cyan(g.kind === "install" ? g.installCommand : g.addCommand);
4898
5150
  }
5151
+ function rootInstallPhrase(installCommand) {
5152
+ const phrase = installCommandPhrase(installCommand, true);
5153
+ return phrase === installCommand ? chalk9.cyan(installCommand) : `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${chalk9.cyan(installCommand)}`;
5154
+ }
4899
5155
  function rebuildGuide(g) {
4900
5156
  return `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uBA74 ${chalk9.cyan(workspaceRunCommand(g.installCommand, TOKENS_PACKAGE, "build"))}, \uC544\uB2C8\uBA74 \uC7AC\uC124\uCE58: ${installPhrase(g)}`;
4901
5157
  }
@@ -5109,7 +5365,7 @@ function renderThemeAdd(plan, written) {
5109
5365
  );
5110
5366
  }
5111
5367
  for (const d of css?.deferredComponentImports ?? []) {
5112
- lines.push(chalk9.yellow(` ! ${deferredComponentImportReason(d, plan.installCommand)}`));
5368
+ lines.push(chalk9.yellow(` ! ${deferredComponentImportReason(d, installCommandPhrase(plan.installCommand, true))}`));
5113
5369
  }
5114
5370
  if (css && css.otherBrands.length > 0) {
5115
5371
  lines.push(
@@ -5130,7 +5386,7 @@ function renderThemeAdd(plan, written) {
5130
5386
  lines.push(
5131
5387
  ` ${chalk9.gray("-")} package.json: ${TOKENS_PACKAGE} ${dep.declaredRange} \uAC00 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8\uB3FC \uC788\uC5B4 \uC571 package.json \uC740 \uBC14\uAFB8\uC9C0 \uC54A\uC74C`
5132
5388
  );
5133
- if (plan.tokens.status === "not-installed") lines.push(` \uC124\uCE58: ${chalk9.cyan(plan.installCommand)}`);
5389
+ if (plan.tokens.status === "not-installed") lines.push(` \uC124\uCE58: ${rootInstallPhrase(plan.installCommand)}`);
5134
5390
  else if (plan.tokens.status === "not-built") lines.push(` ${rebuildGuide(tokensGuide)}`);
5135
5391
  } else if (dep?.action === "present") {
5136
5392
  lines.push(` ${chalk9.gray("-")} package.json: ${TOKENS_PACKAGE} ${dep.declaredRange} \uAC00 \uC774\uBBF8 \uC788\uC5B4 \uBC94\uC704\uB97C \uBC14\uAFB8\uC9C0 \uC54A\uC74C`);
@@ -5556,13 +5812,13 @@ async function fetchRegistryJson(url, options = {}) {
5556
5812
  }
5557
5813
 
5558
5814
  // src/init/init.ts
5559
- import { accessSync as accessSync2, constants as constants2, existsSync as existsSync5, lstatSync as lstatSync3, readFileSync as readFileSync5, realpathSync as realpathSync4, statSync as statSync4, writeFileSync as writeFileSync2 } from "fs";
5815
+ import { accessSync as accessSync2, constants as constants2, existsSync as existsSync6, lstatSync as lstatSync4, readFileSync as readFileSync6, realpathSync as realpathSync5, statSync as statSync4, writeFileSync as writeFileSync3 } from "fs";
5560
5816
  import path14 from "path";
5561
5817
  import chalk10 from "chalk";
5562
5818
  import fs12 from "fs-extra";
5563
5819
 
5564
5820
  // ../axis-registry-core/src/add/safe-write.ts
5565
- import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync as realpathSync3, statSync as statSync3 } from "fs";
5821
+ import { constants as fsConstants, existsSync as existsSync5, lstatSync as lstatSync3, realpathSync as realpathSync4, statSync as statSync3 } from "fs";
5566
5822
  import path13 from "path";
5567
5823
  import fs11 from "fs-extra";
5568
5824
  var NEW_FILE_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | (fsConstants.O_NOFOLLOW ?? 0);
@@ -5581,7 +5837,7 @@ function isSameOrInside(parent, child, impl = path13) {
5581
5837
  }
5582
5838
  function nearestExisting(p) {
5583
5839
  let cur = p;
5584
- while (!existsSync4(cur)) {
5840
+ while (!existsSync5(cur)) {
5585
5841
  const up = path13.dirname(cur);
5586
5842
  if (up === cur) return cur;
5587
5843
  cur = up;
@@ -5589,18 +5845,18 @@ function nearestExisting(p) {
5589
5845
  return cur;
5590
5846
  }
5591
5847
  function escapeReason(root, target, options = {}) {
5592
- const realRoot = realpathSync3(root);
5848
+ const realRoot = realpathSync4(root);
5593
5849
  if (!isSameOrInside(path13.resolve(root), path13.resolve(target)) || path13.resolve(target) === path13.resolve(root)) {
5594
5850
  return `\uACBD\uB85C\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4(${target})`;
5595
5851
  }
5596
5852
  const anchor = nearestExisting(path13.dirname(target));
5597
- const realAnchor = realpathSync3(anchor);
5853
+ const realAnchor = realpathSync4(anchor);
5598
5854
  if (!isSameOrInside(realRoot, realAnchor)) {
5599
5855
  return `\uC0C1\uC704 \uB514\uB809\uD130\uB9AC\uC758 \uC2E4\uC81C \uC704\uCE58(${realAnchor})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
5600
5856
  }
5601
5857
  let st = null;
5602
5858
  try {
5603
- st = lstatSync2(target);
5859
+ st = lstatSync3(target);
5604
5860
  } catch {
5605
5861
  st = null;
5606
5862
  }
@@ -5609,7 +5865,7 @@ function escapeReason(root, target, options = {}) {
5609
5865
  const shown = path13.relative(path13.resolve(root), path13.resolve(target)).split(path13.sep).join("/");
5610
5866
  let realTarget;
5611
5867
  try {
5612
- realTarget = realpathSync3(target);
5868
+ realTarget = realpathSync4(target);
5613
5869
  } catch {
5614
5870
  return `\uAE30\uC874 \uD30C\uC77C ${shown} \uC774 \uAE68\uC9C4 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C \uB530\uB77C\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uB9C1\uD06C\uB97C \uC9C0\uC6B0\uAC70\uB098 \uACE0\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694)`;
5615
5871
  }
@@ -5634,7 +5890,7 @@ function escapeReason(root, target, options = {}) {
5634
5890
  }
5635
5891
  function isSymlink(p) {
5636
5892
  try {
5637
- return lstatSync2(p).isSymbolicLink();
5893
+ return lstatSync3(p).isSymbolicLink();
5638
5894
  } catch {
5639
5895
  return false;
5640
5896
  }
@@ -5642,15 +5898,15 @@ function isSymlink(p) {
5642
5898
  function outsideLinkTarget(root, target) {
5643
5899
  if (!isSymlink(target)) return null;
5644
5900
  try {
5645
- const realTarget = realpathSync3(target);
5646
- return isSameOrInside(realpathSync3(root), realTarget) ? null : realTarget;
5901
+ const realTarget = realpathSync4(target);
5902
+ return isSameOrInside(realpathSync4(root), realTarget) ? null : realTarget;
5647
5903
  } catch {
5648
5904
  return null;
5649
5905
  }
5650
5906
  }
5651
5907
  function hardLinkCount(target) {
5652
5908
  try {
5653
- const st = lstatSync2(target);
5909
+ const st = lstatSync3(target);
5654
5910
  return st.isFile() && st.nlink >= 2 ? st.nlink : null;
5655
5911
  } catch {
5656
5912
  return null;
@@ -5660,10 +5916,10 @@ function hardLinkMessage(shownPath, nlink) {
5660
5916
  return `\uAE30\uC874 \uD30C\uC77C ${shownPath} \uC774 \uB2E4\uB978 \uACBD\uB85C\uC640 \uD558\uB4DC\uB9C1\uD06C\uB85C \uC774\uC5B4\uC9C4 \uD30C\uC77C\uC774\uB77C(\uB9C1\uD06C \uC218 ${nlink}) \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB36E\uC5B4\uC4F0\uBA74 \uC774\uC5B4\uC9C4 \uB2E4\uB978 \uACBD\uB85C\uC758 \uB0B4\uC6A9\uB3C4 \uBC14\uB01D\uB2C8\uB2E4. \uD558\uB4DC\uB9C1\uD06C\uB97C \uB04A\uC740(\uD30C\uC77C\uC744 \uBCF5\uC0AC\uD574 \uBC14\uAFBC) \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694`;
5661
5917
  }
5662
5918
  function writtenOutside(root, target) {
5663
- const realRoot = realpathSync3(root);
5919
+ const realRoot = realpathSync4(root);
5664
5920
  let realTarget;
5665
5921
  try {
5666
- realTarget = realpathSync3(target);
5922
+ realTarget = realpathSync4(target);
5667
5923
  } catch {
5668
5924
  return target;
5669
5925
  }
@@ -5709,8 +5965,8 @@ async function overwriteFollowingLinks(target, content) {
5709
5965
  }
5710
5966
  }
5711
5967
  function checkParentInside(root, target) {
5712
- const realRoot = realpathSync3(root);
5713
- const realParent = realpathSync3(path13.dirname(target));
5968
+ const realRoot = realpathSync4(root);
5969
+ const realParent = realpathSync4(path13.dirname(target));
5714
5970
  if (!isSameOrInside(realRoot, realParent)) {
5715
5971
  return `\uBD80\uBAA8 \uB514\uB809\uD130\uB9AC\uC758 \uC2E4\uC81C \uC704\uCE58(${realParent})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
5716
5972
  }
@@ -5827,7 +6083,8 @@ function animationGuideLine(pkg, tailwind4, installCommand, baseDir) {
5827
6083
  if (pnp || findInstalledPackage(baseDir, candidate) !== void 0) return void 0;
5828
6084
  const declaredWhere = declared.source === "root" ? "\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 " : "";
5829
6085
  const setup = !tailwind4 ? `tailwind.config \uC758 plugins \uC5D0 require("${candidate}") \uB97C \uB123\uC73C\uC138\uC694` : candidate === ANIMATION_PLUGIN_TAILWIND4 ? `\uC804\uC5ED CSS \uC5D0 @import "${candidate}"; \uB97C \uB123\uC73C\uC138\uC694` : `\uC804\uC5ED CSS \uC5D0 @plugin "${candidate}"; \uB97C \uB123\uC73C\uC138\uC694`;
5830
- return `\uC560\uB2C8\uBA54\uC774\uC158: ${candidate} \uB294 ${declaredWhere}\uC120\uC5B8\uB3FC \uC788\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. ${installCommand} \uB4A4 ${setup}.`;
6086
+ const install = installCommandPhrase(installCommand, declared.source === "root");
6087
+ return `\uC560\uB2C8\uBA54\uC774\uC158: ${candidate} \uB294 ${declaredWhere}\uC120\uC5B8\uB3FC \uC788\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. ${install} \uB4A4 ${setup}.`;
5831
6088
  }
5832
6089
  } else if (pkg !== void 0 && (hasDependency(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0 || hasDependency(pkg, ANIMATION_PLUGIN_TAILWIND4) !== void 0)) {
5833
6090
  return void 0;
@@ -5844,7 +6101,7 @@ var TAILWIND4_TOKENS_VERSION = TAILWIND4_MIN_AXIS_VERSION;
5844
6101
  var TAILWIND4_CONFLICT_LINE = " ! create-next-app \uAE30\uBCF8 globals.css \uC758 :root \xB7 @theme inline \xB7 @media (prefers-color-scheme: dark) \xB7 body \uBE14\uB85D\uC740 AXIS \uC640 \uAC19\uC740 \uC774\uB984(--background \xB7 --foreground \xB7 --color-background \xB7 --font-sans \xB7 --font-mono)\uC744 \uB2E4\uB978 \uAC12\uC73C\uB85C \uC815\uC758\uD569\uB2C8\uB2E4. \uC774 \uBE14\uB85D\uB4E4\uC744 \uC9C0\uC6B0\uC138\uC694.";
5845
6102
  function readPackageJsonSafe(baseDir) {
5846
6103
  try {
5847
- const text = readFileSync5(path14.join(baseDir, "package.json"), "utf8");
6104
+ const text = readFileSync6(path14.join(baseDir, "package.json"), "utf8");
5848
6105
  const parsed = JSON.parse(text.startsWith(BOM) ? text.slice(1) : text);
5849
6106
  return isPlainObject(parsed) ? parsed : void 0;
5850
6107
  } catch {
@@ -5918,7 +6175,7 @@ function planUtilsDependencies(baseDirInput) {
5918
6175
  addCommand: addCommandFor(installCommand, ranges0)
5919
6176
  };
5920
6177
  const pkgFile = path14.join(baseDir, "package.json");
5921
- if (!existsSync5(pkgFile)) return plan;
6178
+ if (!existsSync6(pkgFile)) return plan;
5922
6179
  const unwritable = (reason) => ({ ...plan, action: "unwritable", reason });
5923
6180
  let where;
5924
6181
  try {
@@ -5929,7 +6186,7 @@ function planUtilsDependencies(baseDirInput) {
5929
6186
  if (!where.inside) return unwritable(`\uC2E4\uC81C \uC704\uCE58(${where.realPath})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`);
5930
6187
  let text;
5931
6188
  try {
5932
- text = readFileSync5(pkgFile, "utf8");
6189
+ text = readFileSync6(pkgFile, "utf8");
5933
6190
  } catch (err) {
5934
6191
  return unwritable(err.message);
5935
6192
  }
@@ -5967,12 +6224,12 @@ function planUtilsDependencies(baseDirInput) {
5967
6224
  const after = bom + formatJsonLike(body, { ...pkg, dependencies: deps });
5968
6225
  return { ...plan, action: "add", write: { file: pkgFile, before: text, after } };
5969
6226
  }
5970
- var defaultWriteFile = (file, data) => writeFileSync2(file, data);
6227
+ var defaultWriteFile = (file, data) => writeFileSync3(file, data);
5971
6228
  function applyUtilsDependencies(baseDirInput, plan, writeFile = defaultWriteFile) {
5972
6229
  const w = plan.write;
5973
6230
  if (plan.action !== "add" || !w) return false;
5974
6231
  const baseDir = path14.resolve(baseDirInput);
5975
- const current = existsSync5(w.file) ? readFileSync5(w.file, "utf8") : null;
6232
+ const current = existsSync6(w.file) ? readFileSync6(w.file, "utf8") : null;
5976
6233
  if (current !== w.before) {
5977
6234
  throw new Error(`${w.file} \uC774 \uACC4\uD68D \uB4A4\uC5D0 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`);
5978
6235
  }
@@ -5988,7 +6245,7 @@ function applyUtilsDependencies(baseDirInput, plan, writeFile = defaultWriteFile
5988
6245
  let restored;
5989
6246
  try {
5990
6247
  writeFile(w.file, w.before);
5991
- if (readFileSync5(w.file, "utf8") !== w.before) throw new Error("\uB418\uB3CC\uB9B0 \uB0B4\uC6A9\uC774 \uC6D0\uB798 \uB0B4\uC6A9\uACFC \uB2E4\uB985\uB2C8\uB2E4");
6248
+ if (readFileSync6(w.file, "utf8") !== w.before) throw new Error("\uB418\uB3CC\uB9B0 \uB0B4\uC6A9\uC774 \uC6D0\uB798 \uB0B4\uC6A9\uACFC \uB2E4\uB985\uB2C8\uB2E4");
5992
6249
  restored = "\uC6D0\uB798 \uB0B4\uC6A9\uC73C\uB85C \uB418\uB3CC\uB838\uC2B5\uB2C8\uB2E4";
5993
6250
  } catch (restoreErr) {
5994
6251
  restored = `\uC6D0\uB798 \uB0B4\uC6A9\uC73C\uB85C \uB418\uB3CC\uB9AC\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${restoreErr.message}). \uD30C\uC77C\uC774 \uC798\uB838\uAC70\uB098 \uBE44\uC5C8\uC744 \uC218 \uC788\uC73C\uB2C8 \uBC84\uC804 \uAD00\uB9AC \uB3C4\uAD6C \uB4F1\uC73C\uB85C \uBCF5\uAD6C\uD558\uC138\uC694`;
@@ -6002,6 +6259,8 @@ function reportDependencies(plan, log) {
6002
6259
  const rootPresent = plan.present.filter((p) => p.source === "root").map((p) => p.name);
6003
6260
  const rootNote = rootPresent.length > 0 ? ` (\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8: ${rootPresent.join(", ")})` : "";
6004
6261
  const basis = ` tailwind-merge \uBC94\uC704 \uAE30\uC900: ${describeTailwindBasis(plan.tailwind)}`;
6262
+ const installPhrase2 = installCommandPhrase(plan.installCommand, rootPresent.length > 0);
6263
+ const installText = installPhrase2 === plan.installCommand ? chalk10.cyan(plan.installCommand) : `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${chalk10.cyan(plan.installCommand)}`;
6005
6264
  const logBasis = () => {
6006
6265
  log(chalk10.gray(basis));
6007
6266
  for (const w of tailwindWarnings(plan.tailwind, plan.installCommand)) log(chalk10.yellow(` ${w}`));
@@ -6011,10 +6270,10 @@ function reportDependencies(plan, log) {
6011
6270
  log(chalk10.green(`\u2713 package.json dependencies \uC5D0 \uCD94\uAC00: ${addedText}`));
6012
6271
  if (plan.present.length > 0) log(chalk10.gray(` \uC774\uBBF8 \uC788\uC74C(\uBC84\uC804 \uC720\uC9C0): ${presentText}${rootNote}`));
6013
6272
  if (plan.added.includes("tailwind-merge")) logBasis();
6014
- log(chalk10.yellow(` \uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${chalk10.cyan(plan.installCommand)}`));
6273
+ log(chalk10.yellow(` \uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${installText}`));
6015
6274
  } else if (plan.action === "present") {
6016
6275
  log(chalk10.green(`\u2713 utils.ts \uC758\uC874\uC131\uC774 package.json \uC5D0 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4(\uBC84\uC804 \uC720\uC9C0): ${presentText}${rootNote}`));
6017
- log(chalk10.yellow(` \uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${chalk10.cyan(plan.installCommand)}`));
6276
+ log(chalk10.yellow(` \uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC124\uCE58: ${installText}`));
6018
6277
  } else if (plan.action === "no-package-json") {
6019
6278
  log(chalk10.yellow("! package.json \uC774 \uC5C6\uC5B4 utils.ts \uC758\uC874\uC131(clsx, tailwind-merge)\uC744 \uCD94\uAC00\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."));
6020
6279
  log(chalk10.yellow(` \uC124\uCE58: ${chalk10.cyan(plan.addCommand)}`));
@@ -6073,7 +6332,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
6073
6332
  const shown = path14.relative(baseDir, utilsPath).split(path14.sep).join("/") || utilsPath;
6074
6333
  let st;
6075
6334
  try {
6076
- st = lstatSync3(utilsPath);
6335
+ st = lstatSync4(utilsPath);
6077
6336
  } catch (e) {
6078
6337
  if (e.code === "ENOENT") return { action: "create" };
6079
6338
  return { action: "reject", reason: `${shown} \uC758 \uC815\uBCF4\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
@@ -6081,13 +6340,13 @@ function planUtilsWrite(baseDirInput, utilsPath) {
6081
6340
  if (st.isSymbolicLink()) {
6082
6341
  let real;
6083
6342
  try {
6084
- real = realpathSync4(utilsPath);
6343
+ real = realpathSync5(utilsPath);
6085
6344
  } catch {
6086
6345
  return { action: "reject", reason: `${shown} \uC774 \uAE68\uC9C4 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB9C1\uD06C\uB97C \uC9C0\uC6B0\uAC70\uB098 \uACE0\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694` };
6087
6346
  }
6088
6347
  let outside = null;
6089
6348
  try {
6090
- outside = isSameOrInside(realpathSync4(baseDir), real) ? null : real;
6349
+ outside = isSameOrInside(realpathSync5(baseDir), real) ? null : real;
6091
6350
  } catch {
6092
6351
  outside = null;
6093
6352
  }
@@ -6101,7 +6360,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
6101
6360
  if (!target.isFile()) return { action: "reject", reason: `${shown} \uB9C1\uD06C \uB300\uC0C1(${real})\uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4` };
6102
6361
  let content2;
6103
6362
  try {
6104
- content2 = readFileSync5(utilsPath, "utf8");
6363
+ content2 = readFileSync6(utilsPath, "utf8");
6105
6364
  } catch (e) {
6106
6365
  return { action: "reject", reason: `${shown} \uB9C1\uD06C \uB300\uC0C1(${real})\uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
6107
6366
  }
@@ -6116,7 +6375,7 @@ function planUtilsWrite(baseDirInput, utilsPath) {
6116
6375
  if (!st.isFile()) return { action: "reject", reason: `${shown} \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2C8\uB77C \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4` };
6117
6376
  let content;
6118
6377
  try {
6119
- content = readFileSync5(utilsPath, "utf8");
6378
+ content = readFileSync6(utilsPath, "utf8");
6120
6379
  } catch (e) {
6121
6380
  return { action: "reject", reason: `\uAE30\uC874 ${shown} \uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
6122
6381
  }
@@ -6328,18 +6587,18 @@ function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL, deps
6328
6587
  import chalk12 from "chalk";
6329
6588
 
6330
6589
  // ../axis-registry-core/src/add/add.ts
6331
- import { existsSync as existsSync7, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
6590
+ import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
6332
6591
  import path16 from "path";
6333
6592
  import fs13 from "fs-extra";
6334
6593
 
6335
6594
  // ../axis-registry-core/src/registry/bundled.ts
6336
- import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
6595
+ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
6337
6596
  import path15 from "path";
6338
6597
  import { fileURLToPath } from "url";
6339
6598
  function findBundledRegistryDir(moduleUrl = import.meta.url) {
6340
6599
  const here = path15.dirname(fileURLToPath(moduleUrl));
6341
6600
  for (const dir of [path15.join(here, "registry"), path15.join(here, "..", "registry")]) {
6342
- if (existsSync6(path15.join(dir, "index.json"))) return dir;
6601
+ if (existsSync7(path15.join(dir, "index.json"))) return dir;
6343
6602
  }
6344
6603
  return null;
6345
6604
  }
@@ -6347,7 +6606,7 @@ function readBundledJson(dir, fileName) {
6347
6606
  const file = path15.join(dir, fileName);
6348
6607
  let text;
6349
6608
  try {
6350
- text = readFileSync6(file, "utf8");
6609
+ text = readFileSync7(file, "utf8");
6351
6610
  } catch {
6352
6611
  throw new Error(`\uB3D9\uBD09 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 ${fileName} \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(${dir})`);
6353
6612
  }
@@ -7062,7 +7321,7 @@ function missingDependencies(root, items) {
7062
7321
  const installCommand = detectInstallCommand(root);
7063
7322
  let pkg;
7064
7323
  try {
7065
- const text = readFileSync7(path16.join(root, "package.json"), "utf8").replace(/^\uFEFF/, "");
7324
+ const text = readFileSync8(path16.join(root, "package.json"), "utf8").replace(/^\uFEFF/, "");
7066
7325
  const parsed = JSON.parse(text);
7067
7326
  pkg = isPlainObject(parsed) ? parsed : void 0;
7068
7327
  } catch {
@@ -7177,12 +7436,12 @@ async function runAdd(cwd, requested, options, ctx) {
7177
7436
  const existing = /* @__PURE__ */ new Map();
7178
7437
  const readErrors = [];
7179
7438
  for (const file of plan.files) {
7180
- if (!existsSync7(file.target)) {
7439
+ if (!existsSync8(file.target)) {
7181
7440
  existing.set(file, null);
7182
7441
  continue;
7183
7442
  }
7184
7443
  try {
7185
- existing.set(file, readFileSync7(file.target, "utf8"));
7444
+ existing.set(file, readFileSync8(file.target, "utf8"));
7186
7445
  } catch (e) {
7187
7446
  readErrors.push(
7188
7447
  `${file.item.name}: \uAE30\uC874 \uD30C\uC77C ${rel2(root, file.target)} \uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${e.code ?? e.message})`