@axis-ds/mcp 1.4.8 → 1.4.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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +30 -24
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -41,7 +41,7 @@ Claude Desktop 또는 기타 MCP 호환 클라이언트에서 설정:
41
41
  - 이름은 레지스트리 이름 그대로입니다. Agentic UI 는 `agentic-` 접두를 붙입니다(예: `agentic-run-progress`). 의존 항목(`utils` · `agentic-a11y-labels`)은 함께 설치됩니다.
42
42
  - `targetDir` 는 이미 있는 프로젝트 루트입니다(상대 경로는 서버의 현재 디렉터리 기준). `axis.config.json` 이 있으면 그 `componentsDir` · `agenticDir` 에, 없으면 `components/ui` · `components/agentic` 에 설치하고 그 사실을 알립니다. 프로젝트 밖으로 나가는 경로는 아무것도 쓰지 않고 실패합니다.
43
43
  - 내용이 다른 기존 파일은 덮어쓰지 않고 건너뛰며 응답 첫머리에 건너뛴 수를 적습니다. `overwrite: true` 일 때만 덮어씁니다.
44
- - 의존성은 설치하지 않고 lockfile 에 맞는 명령(`pnpm add` · `npm install` · `yarn add`)만 안내합니다. lockfile 이 없으면 `package.json` 의 `packageManager` 를 봅니다(1.4.2 부터). `axis.apply_template` 의 「필요한 의존성」 · `axis.list_brands` · `axis.get_brand` 의 설치 안내도 1.4.2 부터 같은 방식으로 `targetDir` 의 매니저를 따릅니다(1.4.1 까지는 `pnpm` 고정).
44
+ - 의존성은 설치하지 않고 lockfile 에 맞는 명령(`pnpm add` · `npm install` · `yarn add`)만 안내합니다. 워크스페이스 루트 `package.json` 에 선언된 의존성은 안내하지 않고, 1.4.8 다음 patch 부터(WI-0095) Yarn Plug'n'Play 에서는 루트에만 선언한 의존성도 앱이 해석하지 못하므로 안내 명령에 넣습니다(CLI `axis add` 와 같음). lockfile 이 없으면 `package.json` 의 `packageManager` 를 봅니다(1.4.2 부터). `axis.apply_template` 의 「필요한 의존성」 · `axis.list_brands` · `axis.get_brand` 의 설치 안내도 1.4.2 부터 같은 방식으로 `targetDir` 의 매니저를 따릅니다(1.4.1 까지는 `pnpm` 고정).
45
45
  - `axis.apply_template` 은 `targetDir` 에 이미 있는 `package.json` · `axis.config.json`(템플릿 루트의 것)을 덮어쓰지 않고 CLI `axis template apply` 와 같은 규칙으로 합칩니다(WI-0088). `packageManager` 등 사용자 필드가 남고, 결과의 파일 목록에 「합치기」로 표시합니다. 파일을 쓰는 도중 실패하면 건드린 파일을 되돌리고 오류로 응답합니다. 템플릿 경로가 `targetDir` 밖(절대 경로 · `..` · 밖을 가리키는 심볼릭 링크 경유)이면 `axis.apply_template` · `axis.diff_template` 은 아무 파일도 쓰거나 읽지 않고 오류로 응답합니다.
46
46
 
47
47
  ## 토큰 도구
package/dist/index.js CHANGED
@@ -1476,9 +1476,6 @@ import { basename, dirname as dirname2, extname, isAbsolute, join as join2, rela
1476
1476
  function declaredRange(baseDir, pkg, name) {
1477
1477
  return declaredDependency(baseDir, pkg, name)?.range;
1478
1478
  }
1479
- function declaredRangeForCheck(baseDir, pkg, name) {
1480
- return declaredDependency(baseDir, pkg, name, void 0, { appOnlyInPnp: true })?.range;
1481
- }
1482
1479
  function isPlainObject2(value) {
1483
1480
  return typeof value === "object" && value !== null && !Array.isArray(value);
1484
1481
  }
@@ -2744,6 +2741,33 @@ function componentsUseAnimation(baseDir, componentsDir) {
2744
2741
  }
2745
2742
  return false;
2746
2743
  }
2744
+ function animationPluginProblem(baseDir, pkg, name, pnp) {
2745
+ const declared = declaredDependency(baseDir, pkg, name, void 0, { appOnlyInPnp: true });
2746
+ if (declared === void 0) {
2747
+ return pnpRootOnlyDependency(baseDir, pkg, name) !== void 0 ? { name, kind: "pnpRootOnly", why: `${name} \uAC00 ${PNP_ROOT_ONLY_NOTE}` } : { name, kind: "undeclared", why: `${name} \uC120\uC5B8 \uC5C6\uC74C` };
2748
+ }
2749
+ if (!pnp && findInstalledPackage(baseDir, name) === void 0) {
2750
+ return { name, kind: "notInstalled", why: `${name} \uBBF8\uC124\uCE58(\uC120\uC5B8\uB9CC \uC788\uC74C)`, root: declared.source === "root" };
2751
+ }
2752
+ return void 0;
2753
+ }
2754
+ function inspectTailwind4Animation(baseDirInput, pkgInput) {
2755
+ const baseDir = resolveBaseDir(baseDirInput);
2756
+ const pkg = pkgInput ?? readPackageJson(baseDir);
2757
+ const pnp = isPnpProject(baseDir);
2758
+ const selection = selectCheckGlobalCss(baseDir);
2759
+ const note = globalCssSelectionNote(selection);
2760
+ const expanded = selection.path !== void 0 && selection.rel !== void 0 ? expandGlobalCss(baseDir, selection.path, selection.rel, outsideCssDir(selection)) : void 0;
2761
+ const css = expanded !== void 0 ? stripCssComments(expanded.evidence) : "";
2762
+ const twAnimate = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`);
2763
+ const animatePlugin = new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`);
2764
+ const lines = [];
2765
+ if (twAnimate.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND4);
2766
+ if (animatePlugin.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND3);
2767
+ const via = expanded !== void 0 ? cssImportViaNote(viaFiles([evidenceOrigin(expanded, (f) => twAnimate.test(f)), evidenceOrigin(expanded, (f) => animatePlugin.test(f))])) : "";
2768
+ const problems = lines.map((name) => animationPluginProblem(baseDir, pkg, name, pnp)).filter((p) => p !== void 0);
2769
+ return { selection, file: selection.rel, note, via, lines, problems };
2770
+ }
2747
2771
  function checkAnimationPlugin(baseDirInput) {
2748
2772
  const baseDir = resolveBaseDir(baseDirInput);
2749
2773
  const pkg = readPackageJson(baseDir);
@@ -2754,25 +2778,8 @@ function checkAnimationPlugin(baseDirInput) {
2754
2778
  const by = declared ? "@axis-ds/ui-react \uC120\uC5B8" : "componentsDir \uC758 animate-in \uB958 \uD074\uB798\uC2A4";
2755
2779
  const tailwind = detectTailwind(baseDir, pkg);
2756
2780
  const pnp = isPnpProject(baseDir);
2757
- const pluginProblem = (name) => {
2758
- if (declaredRangeForCheck(baseDir, pkg, name) === void 0) {
2759
- return pnpRootOnlyDependency(baseDir, pkg, name) !== void 0 ? `${name} \uAC00 ${PNP_ROOT_ONLY_NOTE}` : `${name} \uC120\uC5B8 \uC5C6\uC74C`;
2760
- }
2761
- if (!pnp && findInstalledPackage(baseDir, name) === void 0) return `${name} \uBBF8\uC124\uCE58(\uC120\uC5B8\uB9CC \uC788\uC74C)`;
2762
- return void 0;
2763
- };
2764
2781
  if (tailwind.major !== void 0 && tailwind.major >= 4) {
2765
- const selection = selectCheckGlobalCss(baseDir);
2766
- const note = globalCssSelectionNote(selection);
2767
- const file = selection.rel;
2768
- const expanded = selection.path !== void 0 && selection.rel !== void 0 ? expandGlobalCss(baseDir, selection.path, selection.rel, outsideCssDir(selection)) : void 0;
2769
- const css = expanded !== void 0 ? stripCssComments(expanded.evidence) : "";
2770
- const twAnimate = new RegExp(`@import\\s+(?:url\\(\\s*)?["']${ANIMATION_PLUGIN_TAILWIND4}["']`);
2771
- const animatePlugin = new RegExp(`@plugin\\s+["']${ANIMATION_PLUGIN_TAILWIND3}["']`);
2772
- const lines = [];
2773
- if (twAnimate.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND4);
2774
- if (animatePlugin.test(css)) lines.push(ANIMATION_PLUGIN_TAILWIND3);
2775
- const via = expanded !== void 0 ? cssImportViaNote(viaFiles([evidenceOrigin(expanded, (f) => twAnimate.test(f)), evidenceOrigin(expanded, (f) => animatePlugin.test(f))])) : "";
2782
+ const { file, note, via, lines, problems } = inspectTailwind4Animation(baseDir, pkg);
2776
2783
  if (lines.length === 0) {
2777
2784
  return {
2778
2785
  name: "animation",
@@ -2780,7 +2787,6 @@ function checkAnimationPlugin(baseDirInput) {
2780
2787
  message: `\uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(${by}): Dialog \xB7 Select \uB4F1\uC758 \uC5F4\uACE0 \uB2EB\uB294 \uC560\uB2C8\uBA54\uC774\uC158\uC774 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 ${ANIMATION_PLUGIN_TAILWIND4} \uC124\uCE58 \uB4A4 @import "${ANIMATION_PLUGIN_TAILWIND4}";${note}`
2781
2788
  };
2782
2789
  }
2783
- const problems = lines.map((name) => ({ name, why: pluginProblem(name) })).filter((x) => x.why !== void 0);
2784
2790
  if (problems.length === 0) return { name: "animation", severity: "pass", message: `${file}\uC5D0 \uC560\uB2C8\uBA54\uC774\uC158 \uD50C\uB7EC\uADF8\uC778\uC774 \uC788\uC2B5\uB2C8\uB2E4${via}${note}` };
2785
2791
  return {
2786
2792
  name: "animation",
@@ -2791,7 +2797,7 @@ function checkAnimationPlugin(baseDirInput) {
2791
2797
  const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync3(join2(baseDir, f)));
2792
2798
  const source = configFile !== void 0 ? stripJsComments(readFileSync4(join2(baseDir, configFile), "utf8")) : "";
2793
2799
  const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
2794
- const pluginReason = pluginProblem(ANIMATION_PLUGIN_TAILWIND3);
2800
+ const pluginReason = animationPluginProblem(baseDir, pkg, ANIMATION_PLUGIN_TAILWIND3, pnp)?.why;
2795
2801
  if (plugins === "found" && pluginReason === void 0) {
2796
2802
  return { name: "animation", severity: "pass", message: `${configFile}\uC758 plugins \uC5D0 ${ANIMATION_PLUGIN_TAILWIND3} \uAC00 \uC788\uC2B5\uB2C8\uB2E4` };
2797
2803
  }
@@ -3305,7 +3311,7 @@ function missingDependencies(root, items) {
3305
3311
  for (const item of items) {
3306
3312
  for (const dep of item.dependencies) {
3307
3313
  const name = dependencyName(dep);
3308
- if (declaredDependency(root, pkg, name, rootPkg) !== void 0) continue;
3314
+ if (declaredDependency(root, pkg, name, rootPkg, { appOnlyInPnp: true }) !== void 0) continue;
3309
3315
  if (name in specs) continue;
3310
3316
  const explicit = dep.length > name.length ? dep.slice(name.length + 1) : void 0;
3311
3317
  specs[name] = explicit ?? ranges[name];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-ds/mcp",
3
- "version": "1.4.8",
3
+ "version": "1.4.9",
4
4
  "type": "module",
5
5
  "description": "AXIS Design System - MCP Server for AI-assisted component discovery",
6
6
  "bin": {