@axis-ds/mcp 1.4.6 → 1.4.7

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 +456 -41
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -237,8 +237,8 @@ function validateRegistryIndex(data, where = "index.json") {
237
237
  if (!isValidRegistryName(raw.name)) throw new Error(`${at}: name \uC774 slug \uADDC\uCE59\uC5D0 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
238
238
  if (seen.has(raw.name)) throw new Error(`${at}: name '${raw.name}' \uAC00 \uC911\uBCF5\uC785\uB2C8\uB2E4`);
239
239
  seen.add(raw.name);
240
- const sha256 = optionalString(raw, "sha256", at);
241
- if (sha256 !== void 0 && !/^[0-9a-f]{64}$/.test(sha256)) {
240
+ const sha2562 = optionalString(raw, "sha256", at);
241
+ if (sha2562 !== void 0 && !/^[0-9a-f]{64}$/.test(sha2562)) {
242
242
  throw new Error(`${at}: sha256 \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
243
243
  }
244
244
  return {
@@ -246,7 +246,7 @@ function validateRegistryIndex(data, where = "index.json") {
246
246
  type: requireType(raw, at),
247
247
  title: optionalString(raw, "title", at),
248
248
  description: optionalString(raw, "description", at),
249
- ...sha256 !== void 0 ? { sha256 } : {}
249
+ ...sha2562 !== void 0 ? { sha256: sha2562 } : {}
250
250
  };
251
251
  });
252
252
  return {
@@ -1062,6 +1062,13 @@ function isFile(file) {
1062
1062
  return false;
1063
1063
  }
1064
1064
  }
1065
+ function isDirectory(dir) {
1066
+ try {
1067
+ return statSync(dir).isDirectory();
1068
+ } catch {
1069
+ return false;
1070
+ }
1071
+ }
1065
1072
  function selectGlobalCss(baseDir, configured, candidates, options = {}) {
1066
1073
  const result = {};
1067
1074
  if (typeof configured === "string" && configured.trim() !== "") {
@@ -1181,6 +1188,122 @@ function outsideCssPackageResolution(baseDir, cssDir, name, file) {
1181
1188
  if (!usable(findInstalledPackage(baseDir, name))) return "unknown";
1182
1189
  return usable(findInstalledPackage(cssDir, name)) ? "resolved" : "unresolved";
1183
1190
  }
1191
+ var CSS_EXPORT_CONDITIONS = /* @__PURE__ */ new Set(["style", "default"]);
1192
+ function splitPackageSpec(spec) {
1193
+ const parts = spec.split("/");
1194
+ const n = spec.startsWith("@") ? 2 : 1;
1195
+ if (parts.length < n || parts.slice(0, n).some((p) => p === "" || p === "." || p === "..")) return void 0;
1196
+ return { name: parts.slice(0, n).join("/"), rest: parts.slice(n).join("/") };
1197
+ }
1198
+ function resolveExportTarget(value) {
1199
+ if (typeof value === "string") return value;
1200
+ if (Array.isArray(value)) {
1201
+ for (const v of value) {
1202
+ const r = resolveExportTarget(v);
1203
+ if (r !== void 0) return r;
1204
+ }
1205
+ return void 0;
1206
+ }
1207
+ if (isPlainObject(value)) {
1208
+ for (const [key, v] of Object.entries(value)) {
1209
+ if (!CSS_EXPORT_CONDITIONS.has(key)) continue;
1210
+ if (v === null) return void 0;
1211
+ const r = resolveExportTarget(v);
1212
+ if (r !== void 0) return r;
1213
+ }
1214
+ }
1215
+ return void 0;
1216
+ }
1217
+ function cssFileCandidates(p) {
1218
+ return [p, `${p}.css`, path3.join(p, "index.css")];
1219
+ }
1220
+ function exportsTarget(exportsField, subpath) {
1221
+ const map = isPlainObject(exportsField) && Object.keys(exportsField).some((k) => k.startsWith(".")) ? exportsField : { ".": exportsField };
1222
+ if (Object.prototype.hasOwnProperty.call(map, subpath)) {
1223
+ const t = resolveExportTarget(map[subpath]);
1224
+ if (t === void 0) return void 0;
1225
+ return t.includes("*") || !t.startsWith("./") ? "?" : t;
1226
+ }
1227
+ if (Object.keys(map).some((k) => k.includes("*") || k.endsWith("/") && subpath.startsWith(k))) return "?";
1228
+ return void 0;
1229
+ }
1230
+ function resolveCssPackageImport(fromDir, spec) {
1231
+ const parsed = splitPackageSpec(spec);
1232
+ if (parsed === void 0 || parsed.rest === "") return { kind: "unknown" };
1233
+ const subpath = `./${parsed.rest}`;
1234
+ let dir = resolveBaseDir(fromDir);
1235
+ for (; ; ) {
1236
+ const pkgDir = path3.join(dir, "node_modules", ...parsed.name.split("/"));
1237
+ if (isDirectory(pkgDir)) {
1238
+ let manifest;
1239
+ try {
1240
+ const raw = JSON.parse(readFileSync3(path3.join(pkgDir, "package.json"), "utf8"));
1241
+ manifest = isPlainObject(raw) ? raw : void 0;
1242
+ } catch {
1243
+ manifest = void 0;
1244
+ }
1245
+ if (manifest !== void 0 && manifest.exports) {
1246
+ const version = exactVersionOf(manifest.version);
1247
+ const target = exportsTarget(manifest.exports, subpath);
1248
+ if (target === "?") return { kind: "unknown" };
1249
+ if (target === void 0) {
1250
+ return version !== void 0 ? { kind: "not-exported", pkgDir, subpath, version } : { kind: "not-exported", pkgDir, subpath };
1251
+ }
1252
+ const file = cssFileCandidates(path3.join(pkgDir, target)).find(isFile);
1253
+ if (file !== void 0) return { kind: "resolved", pkgDir, file };
1254
+ return version !== void 0 ? { kind: "target-missing", pkgDir, subpath, target, version } : { kind: "target-missing", pkgDir, subpath, target };
1255
+ }
1256
+ const bare = cssFileCandidates(path3.join(pkgDir, parsed.rest)).find(isFile);
1257
+ if (bare !== void 0) return { kind: "resolved", pkgDir, file: bare };
1258
+ }
1259
+ const parent = path3.dirname(dir);
1260
+ if (parent === dir) return { kind: "not-found" };
1261
+ dir = parent;
1262
+ }
1263
+ }
1264
+ function installBase(pkgDir, name) {
1265
+ let base = pkgDir;
1266
+ for (let i = 0; i < name.split("/").length + 1; i++) base = path3.dirname(base);
1267
+ try {
1268
+ return realpathSync(base);
1269
+ } catch {
1270
+ return path3.resolve(base);
1271
+ }
1272
+ }
1273
+ function isAncestorInstall(hit, app, name) {
1274
+ const h = installBase(hit, name);
1275
+ const a = installBase(app, name);
1276
+ return a !== h && a.startsWith(h.endsWith(path3.sep) ? h : h + path3.sep);
1277
+ }
1278
+ function sameRealDir(a, b) {
1279
+ const real = (p) => {
1280
+ try {
1281
+ return realpathSync(p);
1282
+ } catch {
1283
+ return path3.resolve(p);
1284
+ }
1285
+ };
1286
+ return real(a) === real(b);
1287
+ }
1288
+ function cssPackageLineResolution(baseDir, lineDir, spec, otherDirs = []) {
1289
+ if (isPnpProject(baseDir)) return { kind: "ok" };
1290
+ const parsed = splitPackageSpec(spec);
1291
+ if (parsed === void 0) return { kind: "ok" };
1292
+ const r = resolveCssPackageImport(lineDir, spec);
1293
+ if (r.kind === "resolved" || r.kind === "unknown") return { kind: "ok" };
1294
+ const app = findInstalledPackage(baseDir, parsed.name);
1295
+ if (r.kind === "not-exported" || r.kind === "target-missing") {
1296
+ if (app !== void 0 && sameRealDir(app.dir, r.pkgDir)) return { kind: "ok" };
1297
+ if (app !== void 0 && isAncestorInstall(r.pkgDir, app.dir, parsed.name)) return { kind: "ok" };
1298
+ return r.kind === "not-exported" ? { ...r, kind: "shadow-not-exported" } : { ...r, kind: "shadow-target-missing" };
1299
+ }
1300
+ if (app !== void 0) return { kind: "ok" };
1301
+ for (const other of typeof otherDirs === "function" ? otherDirs() : otherDirs) {
1302
+ const o = resolveCssPackageImport(other, spec);
1303
+ if (o.kind === "resolved") return { kind: "not-visible", pkgDir: o.pkgDir, fromDir: resolveBaseDir(other) };
1304
+ }
1305
+ return { kind: "ok" };
1306
+ }
1184
1307
  function findPnpUnpluggedPackages(baseDirInput, name, range) {
1185
1308
  const root = pnpProjectRoot(baseDirInput);
1186
1309
  if (root === void 0) return [];
@@ -1618,12 +1741,12 @@ function outsideCssDir(selection) {
1618
1741
  function outsideCssUnresolvedIssue(spec, name) {
1619
1742
  return `${spec} import \uAC00 \uC788\uC9C0\uB9CC \uC774 \uD30C\uC77C \uC704\uCE58\uC5D0\uC11C ${name} \uB97C \uCC3E\uC9C0 \uBABB\uD574 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC124\uCE58\uBCF8\uC774 \uC571 \uCABD node_modules \uC5D0\uB9CC \uC788\uC74C) \u2192 \uC774 \uD30C\uC77C\uC758 \uC0C1\uC704 node_modules(\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8 \uB4F1)\uC5D0 \uC124\uCE58\uD558\uAC70\uB098 globalCss \uB97C \uC571 \uC548 \uD30C\uC77C\uB85C \uBC14\uAFB8\uC138\uC694`;
1620
1743
  }
1621
- function tokensInstallPhrase(baseDir) {
1622
- const g = dependencyInstallGuide(baseDir, TOKENS_PACKAGE_NAME, `^${TAILWIND4_MIN_AXIS_VERSION}`);
1744
+ function tokensInstallPhrase(baseDir, range = `^${TAILWIND4_MIN_AXIS_VERSION}`) {
1745
+ const g = dependencyInstallGuide(baseDir, TOKENS_PACKAGE_NAME, range);
1623
1746
  if (g.kind === "install-at-root") return `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0\uC11C ${g.installCommand}`;
1624
1747
  return g.kind === "install" ? g.installCommand : g.addCommand;
1625
1748
  }
1626
- function tokensCssUnresolvedIssue(baseDir, pkg, spec, cssDir) {
1749
+ function tokensCssUnresolvedIssue(baseDir, pkg, spec, cssDir, lineIssue) {
1627
1750
  const r = tokensCssResolution(baseDir, pkg, TOKENS_PACKAGE_NAME);
1628
1751
  const head = `${spec} import \uAC00 \uC788\uC9C0\uB9CC`;
1629
1752
  if (r.kind === "pnp-root-only") return `${head} ${TOKENS_PACKAGE_NAME} \uAC00 ${PNP_ROOT_ONLY_NOTE} \u2192 \uC571 package.json \uC5D0 \uC120\uC5B8\uD558\uC138\uC694`;
@@ -1633,7 +1756,41 @@ function tokensCssUnresolvedIssue(baseDir, pkg, spec, cssDir) {
1633
1756
  if (cssDir !== void 0 && outsideCssPackageResolution(baseDir, cssDir, TOKENS_PACKAGE_NAME) === "unresolved") {
1634
1757
  return outsideCssUnresolvedIssue(spec, TOKENS_PACKAGE_NAME);
1635
1758
  }
1636
- return void 0;
1759
+ return lineIssue?.();
1760
+ }
1761
+ function packageNameOfSpec(spec) {
1762
+ const parts = spec.split("/");
1763
+ return parts.slice(0, spec.startsWith("@") ? 2 : 1).join("/");
1764
+ }
1765
+ function displayRel(baseDir, p) {
1766
+ return relative(baseDir, p).split(sep).join("/");
1767
+ }
1768
+ function packageLineShadowIssue(baseDir, expanded, origin, spec) {
1769
+ const name = packageNameOfSpec(spec);
1770
+ const lineDir = dirname2(origin.path);
1771
+ const others = () => [...new Set(expanded.files.map((f) => dirname2(f.path)))].filter((d) => d !== lineDir);
1772
+ const r = cssPackageLineResolution(baseDir, lineDir, spec, others);
1773
+ const head = `${spec} import \uAC00 \uC788\uC9C0\uB9CC \uADF8 \uC904\uC774 \uC788\uB294 \uD30C\uC77C \uC704\uCE58\uC5D0\uC11C`;
1774
+ const label = (pkgDir, version) => `${displayRel(baseDir, pkgDir)}(${version ?? "\uBC84\uC804 \uBAA8\uB984"})`;
1775
+ switch (r.kind) {
1776
+ case "ok":
1777
+ return void 0;
1778
+ case "shadow-not-exported": {
1779
+ const current = r.version !== void 0 && (compareExactVersions(r.version, TAILWIND4_MIN_AXIS_VERSION) ?? -1) >= 0;
1780
+ const todo = current ? "\uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694" : `${TAILWIND4_MIN_AXIS_VERSION} \uC774\uC0C1\uC73C\uB85C \uB9DE\uCD94\uC138\uC694`;
1781
+ 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}`;
1782
+ }
1783
+ case "shadow-target-missing":
1784
+ return `${head} \uBA3C\uC800 \uC7A1\uD788\uB294 ${label(r.pkgDir, r.version)}\uC5D0 \uB0B4\uBCF4\uB0B8 \uD30C\uC77C(${r.target})\uC774 \uC5C6\uC5B4 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uADF8 \uC911\uCCA9 node_modules \uC758 ${name} \uB97C \uC9C0\uC6B0\uAC70\uB098 \uB2E4\uC2DC \uC124\uCE58\uD558\uC138\uC694`;
1785
+ case "not-visible": {
1786
+ const there = expanded.files.find((f) => dirname2(f.path) === r.fromDir);
1787
+ const move = there !== void 0 ? `\uC774 \uC904(${origin.rel})\uC744 ${there.rel} \uB85C \uC62E\uAE30\uC138\uC694` : `\uC774 \uC904(${origin.rel})\uC744 \uADF8 \uC704\uCE58\uC758 CSS \uD30C\uC77C\uB85C \uC62E\uAE30\uC138\uC694`;
1788
+ return `${head} ${name} \uB97C \uCC3E\uC9C0 \uBABB\uD574 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC124\uCE58\uBCF8\uC774 ${displayRel(baseDir, r.pkgDir)} \uC5D0\uB9CC \uC788\uC74C) \u2192 \uC571 \uB610\uB294 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC124\uCE58\uD558\uAC70\uB098 ${move}`;
1789
+ }
1790
+ }
1791
+ }
1792
+ function isOutsideEntry(origin) {
1793
+ return origin.depth === 0 && origin.cssDir !== void 0;
1637
1794
  }
1638
1795
  function checkGlobalsCss(baseDirInput) {
1639
1796
  const baseDir = resolveBaseDir(baseDirInput);
@@ -1661,7 +1818,14 @@ function judgeGlobalsCss(baseDir, selection, candidate, expanded) {
1661
1818
  if (imported !== void 0) {
1662
1819
  const origin = evidenceOrigin(expanded, (f) => findTokensCssImport(f) === imported);
1663
1820
  via = cssImportViaNote(viaFiles([origin]));
1664
- const issue = tokensCssUnresolvedIssue(baseDir, pkg, imported, origin !== void 0 ? origin.cssDir : outsideCssDir(selection));
1821
+ const tailwind4 = (detectTailwind(baseDir, pkg).major ?? 0) >= 4;
1822
+ const issue = tailwind4 && origin !== void 0 && !isOutsideEntry(origin) ? tokensCssUnresolvedIssue(
1823
+ baseDir,
1824
+ pkg,
1825
+ imported,
1826
+ void 0,
1827
+ () => packageLineShadowIssue(baseDir, expanded, origin, imported)
1828
+ ) : tokensCssUnresolvedIssue(baseDir, pkg, imported, origin !== void 0 ? origin.cssDir : outsideCssDir(selection));
1665
1829
  if (issue !== void 0) unresolved = `${candidate}\uC5D0 ${issue}`;
1666
1830
  else pass = `${candidate}\uC5D0 AXIS CSS \uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 (${imported} import)`;
1667
1831
  } else if (AXIS_VARIABLE_DEFINITION.test(stripCssComments(expanded.evidence))) {
@@ -1892,6 +2056,17 @@ function hasBareCjsPresetRequire(code) {
1892
2056
  function isCommonJsConfig(file, source) {
1893
2057
  return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
1894
2058
  }
2059
+ function presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs) {
2060
+ const r = tokensCssResolution(baseDir, pkg, TOKENS_PACKAGE_NAME);
2061
+ const head = `${file}\uC5D0 AXIS preset \uCC38\uC870\uAC00 \uC788\uC9C0\uB9CC ${TOKENS_PACKAGE_NAME} \uAC00`;
2062
+ if (r.kind === "not-installed") {
2063
+ return `${head} \uC124\uCE58\uB418\uC9C0 \uC54A\uC544 \uD574\uC11D\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2192 \uC124\uCE58(${tokensInstallPhrase(baseDir, `^${TOKENS_CJS_PRESET_FIXED_VERSION}`)})`;
2064
+ }
2065
+ if (r.kind === "pnp-root-only" && !bareCjs) {
2066
+ 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`;
2067
+ }
2068
+ return void 0;
2069
+ }
1895
2070
  function packageVersionGate(baseDirInput, pkg, name, min, options = {}) {
1896
2071
  const baseDir = resolveBaseDir(baseDirInput);
1897
2072
  if (!isPnpProject(baseDir)) {
@@ -1961,11 +2136,22 @@ function tailwind4Issues(input, pkg, versions, baseDir) {
1961
2136
  for (const name of TAILWIND4_COMPONENT_PACKAGES) {
1962
2137
  if (!hasComponentTailwindImport(evidence, name)) continue;
1963
2138
  const unresolved = componentCssPresentIssue(baseDir, name, resolutions.get(name));
1964
- const componentDir = cssDirOf(`${name}/tailwind.css`);
1965
- if (unresolved !== void 0) issues.push(unresolved);
1966
- else if (componentDir !== void 0 && outsideCssPackageResolution(baseDir, componentDir, name, "tailwind.css") === "unresolved") {
1967
- issues.push(outsideCssUnresolvedIssue(`${name}/tailwind.css`, name));
1968
- } else if (versions.some((v) => v.name === name)) issues.push(`${name}/tailwind.css import \uAC00 \uC788\uC9C0\uB9CC ${name} \uBC84\uC804 \uD655\uC778\uC774 \uD544\uC694\uD569\uB2C8\uB2E4`);
2139
+ const spec = `${name}/tailwind.css`;
2140
+ if (unresolved !== void 0) {
2141
+ issues.push(unresolved);
2142
+ continue;
2143
+ }
2144
+ const shadow = input.lineIssue === void 0 ? false : input.lineIssue(spec);
2145
+ let lineProblem;
2146
+ if (shadow !== false) lineProblem = shadow;
2147
+ else {
2148
+ const componentDir = cssDirOf(spec);
2149
+ if (componentDir !== void 0 && outsideCssPackageResolution(baseDir, componentDir, name, "tailwind.css") === "unresolved") {
2150
+ lineProblem = outsideCssUnresolvedIssue(spec, name);
2151
+ }
2152
+ }
2153
+ if (lineProblem !== void 0) issues.push(lineProblem);
2154
+ else if (versions.some((v) => v.name === name)) issues.push(`${name}/tailwind.css import \uAC00 \uC788\uC9C0\uB9CC ${name} \uBC84\uC804 \uD655\uC778\uC774 \uD544\uC694\uD569\uB2C8\uB2E4`);
1969
2155
  }
1970
2156
  return issues;
1971
2157
  }
@@ -2033,7 +2219,17 @@ function checkTailwindSetup(baseDirInput) {
2033
2219
  );
2034
2220
  const versions = axisPackagesBelowTailwind4(pkg, baseDir);
2035
2221
  const issues = tailwind4Issues(
2036
- { entry: expanded.entry, evidence: expanded.evidence, cssDirOf: (spec) => packageLineCssDir(expanded, spec) },
2222
+ {
2223
+ entry: expanded.entry,
2224
+ evidence: expanded.evidence,
2225
+ cssDirOf: (spec) => packageLineCssDir(expanded, spec),
2226
+ lineIssue: (spec) => {
2227
+ const line = expanded.packageLines.find((l) => l.spec === spec);
2228
+ const origin = line !== void 0 ? expanded.files.find((f) => f.rel === line.file) : void 0;
2229
+ if (origin === void 0 || isOutsideEntry(origin)) return false;
2230
+ return packageLineShadowIssue(baseDir, expanded, origin, spec);
2231
+ }
2232
+ },
2037
2233
  pkg,
2038
2234
  versions,
2039
2235
  baseDir
@@ -2063,7 +2259,10 @@ function checkTailwindSetup(baseDirInput) {
2063
2259
  const content = readFileSync4(path11, "utf8");
2064
2260
  if (hasTokensPresetReference(content)) {
2065
2261
  const code = stripJsComments(content);
2066
- if (isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code)) {
2262
+ const bareCjs = isCommonJsConfig(file, code) && hasBareCjsPresetRequire(code);
2263
+ const unresolved = presetTokensUnresolvedMessage(baseDir, pkg, file, bareCjs);
2264
+ if (unresolved !== void 0) return { name: "tailwind.config", severity: "warn", message: unresolved };
2265
+ if (bareCjs) {
2067
2266
  const gate = packageVersionGate(baseDir, pkg, "@axis-ds/tokens", TOKENS_CJS_PRESET_FIXED_VERSION, { appOnlyInPnp: true });
2068
2267
  if (gate.status === "unresolved") {
2069
2268
  return {
@@ -5279,9 +5478,11 @@ import fs6 from "fs-extra";
5279
5478
  import path9 from "path";
5280
5479
 
5281
5480
  // src/tools/brand-core.ts
5481
+ import { createHash as createHash2 } from "crypto";
5282
5482
  import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync6 } from "fs";
5283
5483
  import { createRequire } from "module";
5284
5484
  import { dirname as dirname4, join as join4, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
5485
+ import { MessageChannel, Worker, receiveMessageOnPort } from "worker_threads";
5285
5486
  var TOKENS_PACKAGE = "@axis-ds/tokens";
5286
5487
  var MIN_BRAND_TOKENS_VERSION = "1.3.0";
5287
5488
  var TOKENS_DEPENDENCY_MIN_VERSION = "1.6.0";
@@ -5306,13 +5507,15 @@ function readJsonFile(file) {
5306
5507
  function errorCode(err) {
5307
5508
  return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
5308
5509
  }
5309
- function findTokensPackageJson(baseDir) {
5510
+ function tokensPackageJsonCandidates(baseDir) {
5511
+ const candidates = [];
5310
5512
  let dir = resolve3(baseDir);
5311
5513
  for (; ; ) {
5312
5514
  const candidate = join4(dir, "node_modules", TOKENS_PACKAGE, "package.json");
5313
- if (existsSync8(candidate)) return candidate;
5515
+ candidates.push(candidate);
5516
+ if (existsSync8(candidate)) return { found: candidate, candidates };
5314
5517
  const parent = dirname4(dir);
5315
- if (parent === dir) return void 0;
5518
+ if (parent === dir) return { candidates };
5316
5519
  dir = parent;
5317
5520
  }
5318
5521
  }
@@ -5322,18 +5525,195 @@ function projectRequire(baseDir) {
5322
5525
  function tokensSpecifier(subpath) {
5323
5526
  return `${TOKENS_PACKAGE}/${subpath.replace(/^\.\//, "")}`;
5324
5527
  }
5325
- function resolveTokens(baseDir) {
5326
- const pkgJson = findTokensPackageJson(baseDir);
5327
- if (!pkgJson) return { status: "not-installed" };
5328
- const pkg = readJsonFile(pkgJson);
5329
- const version = typeof pkg.version === "string" ? pkg.version : void 0;
5528
+ var nodeSeenStates = /* @__PURE__ */ new Map();
5529
+ var ABSENT = "absent";
5530
+ var UNKNOWN = "unknown";
5531
+ var isolationDisabled = false;
5532
+ var isolatedStats = { workers: 0, resolves: 0, fallbacks: 0 };
5533
+ var ISOLATED_RESOLVE_TIMEOUT_MS = 5e3;
5534
+ var ISOLATED_RESOLVE_SOURCE = `
5535
+ const { workerData } = require("node:worker_threads");
5536
+ const { createRequire } = require("node:module");
5537
+ const { port, signal, from } = workerData;
5538
+ const req = createRequire(from);
5539
+ port.on("message", (spec) => {
5540
+ let reply;
5541
+ try {
5542
+ reply = { path: req.resolve(spec) };
5543
+ } catch (err) {
5544
+ const code = err && typeof err === "object" && "code" in err ? String(err.code) : undefined;
5545
+ reply = { code, message: err && err.message ? String(err.message) : String(err) };
5546
+ }
5547
+ port.postMessage(reply);
5548
+ Atomics.store(signal, 0, 1);
5549
+ Atomics.notify(signal, 0);
5550
+ });
5551
+ `;
5552
+ var IsolationFailure = class extends Error {
5553
+ };
5554
+ function createWorkerResolveSession(from, source, timeoutMs) {
5555
+ const { port1, port2 } = new MessageChannel();
5556
+ const signal = new Int32Array(new SharedArrayBuffer(4));
5557
+ const worker = new Worker(source, {
5558
+ eval: true,
5559
+ workerData: { port: port2, signal, from },
5560
+ transferList: [port2]
5561
+ });
5562
+ worker.on("error", () => {
5563
+ });
5564
+ worker.unref();
5565
+ return {
5566
+ resolve(spec) {
5567
+ Atomics.store(signal, 0, 0);
5568
+ port1.postMessage(spec);
5569
+ const waited = Atomics.wait(signal, 0, 0, timeoutMs);
5570
+ const received = receiveMessageOnPort(port1);
5571
+ if (waited === "timed-out" || !received) throw new IsolationFailure("\uACA9\uB9AC \uD574\uC11D\uC774 \uC751\uB2F5\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
5572
+ const reply = received.message;
5573
+ if (typeof reply.path === "string") return reply.path;
5574
+ throw Object.assign(new Error(reply.message ?? spec), reply.code === void 0 ? {} : { code: reply.code });
5575
+ },
5576
+ close() {
5577
+ port1.close();
5578
+ void worker.terminate();
5579
+ }
5580
+ };
5581
+ }
5582
+ function workerResolveSession(from) {
5583
+ return createWorkerResolveSession(from, ISOLATED_RESOLVE_SOURCE, ISOLATED_RESOLVE_TIMEOUT_MS);
5584
+ }
5585
+ var isolatedFactory = workerResolveSession;
5586
+ function sha256(text) {
5587
+ return createHash2("sha256").update(text).digest("hex");
5588
+ }
5589
+ function openTokensResolver(baseDir, candidates, pkgJson, pkgText) {
5590
+ const nodeRequire = projectRequire(baseDir);
5591
+ const key = sha256(pkgText);
5592
+ const current = candidates.map((c) => c === pkgJson ? key : ABSENT);
5593
+ const changed = candidates.some((c, i) => {
5594
+ const seen = nodeSeenStates.get(c);
5595
+ return seen !== void 0 && seen !== current[i];
5596
+ });
5597
+ let mode = changed ? "isolated" : "node";
5598
+ if (mode === "node") {
5599
+ candidates.forEach((c, i) => {
5600
+ if (!nodeSeenStates.has(c)) nodeSeenStates.set(c, current[i]);
5601
+ });
5602
+ }
5603
+ let session = null;
5604
+ let stale = false;
5605
+ let raced = false;
5606
+ let postChecked = false;
5607
+ const markStale = () => {
5608
+ if (!stale) isolatedStats.fallbacks += 1;
5609
+ stale = true;
5610
+ };
5611
+ const fallBack = () => {
5612
+ markStale();
5613
+ isolationDisabled = true;
5614
+ session?.close();
5615
+ session = null;
5616
+ };
5617
+ const startIsolation = () => {
5618
+ if (isolationDisabled) {
5619
+ markStale();
5620
+ return;
5621
+ }
5622
+ try {
5623
+ session = isolatedFactory(join4(resolve3(baseDir), "package.json"));
5624
+ isolatedStats.workers += 1;
5625
+ } catch {
5626
+ fallBack();
5627
+ }
5628
+ };
5629
+ if (mode === "isolated") startIsolation();
5630
+ const isolatedResolve = (spec) => {
5631
+ if (session) {
5632
+ try {
5633
+ const resolved = session.resolve(spec);
5634
+ isolatedStats.resolves += 1;
5635
+ return resolved;
5636
+ } catch (err) {
5637
+ if (!(err instanceof IsolationFailure)) {
5638
+ isolatedStats.resolves += 1;
5639
+ throw err;
5640
+ }
5641
+ fallBack();
5642
+ }
5643
+ }
5644
+ return nodeRequire.resolve(spec);
5645
+ };
5646
+ return {
5647
+ resolve(spec) {
5648
+ if (mode === "isolated") return isolatedResolve(spec);
5649
+ let resolved;
5650
+ let failure;
5651
+ let failed = false;
5652
+ try {
5653
+ resolved = nodeRequire.resolve(spec);
5654
+ } catch (err) {
5655
+ failed = true;
5656
+ failure = err;
5657
+ }
5658
+ if (!postChecked) {
5659
+ postChecked = true;
5660
+ let after;
5661
+ try {
5662
+ after = sha256(readFileSync8(pkgJson, "utf8"));
5663
+ } catch {
5664
+ after = UNKNOWN;
5665
+ }
5666
+ if (after !== key) {
5667
+ nodeSeenStates.set(pkgJson, UNKNOWN);
5668
+ raced = true;
5669
+ mode = "isolated";
5670
+ startIsolation();
5671
+ return isolatedResolve(spec);
5672
+ }
5673
+ }
5674
+ if (failed) throw failure;
5675
+ return resolved;
5676
+ },
5677
+ get stale() {
5678
+ return stale;
5679
+ },
5680
+ get raced() {
5681
+ return raced;
5682
+ },
5683
+ close() {
5684
+ session?.close();
5685
+ session = null;
5686
+ }
5687
+ };
5688
+ }
5689
+ function readVersion(pkgText) {
5690
+ const pkg = JSON.parse(pkgText);
5691
+ return typeof pkg.version === "string" ? pkg.version : void 0;
5692
+ }
5693
+ function openTokens(baseDir) {
5694
+ const { found: pkgJson, candidates } = tokensPackageJsonCandidates(baseDir);
5695
+ if (!pkgJson) return { resolution: { status: "not-installed" } };
5696
+ const pkgText = readFileSync8(pkgJson, "utf8");
5697
+ let version = readVersion(pkgText);
5698
+ const resolver = openTokensResolver(baseDir, candidates, pkgJson, pkgText);
5699
+ const finish = (status, indexPath) => {
5700
+ if (resolver.raced) {
5701
+ try {
5702
+ version = readVersion(readFileSync8(pkgJson, "utf8"));
5703
+ } catch {
5704
+ }
5705
+ }
5706
+ const resolution = indexPath === void 0 ? { status, version } : { status, version, indexPath };
5707
+ return { resolution: resolver.stale ? { ...resolution, stale: true } : resolution, resolver };
5708
+ };
5330
5709
  try {
5331
- const indexPath = projectRequire(baseDir).resolve(tokensSpecifier("./brands"));
5332
- return { status: "ok", version, indexPath };
5710
+ const indexPath = resolver.resolve(tokensSpecifier("./brands"));
5711
+ return finish("ok", indexPath);
5333
5712
  } catch (err) {
5334
5713
  const code = errorCode(err);
5335
- if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED") return { status: "unsupported", version };
5336
- if (code === "MODULE_NOT_FOUND") return { status: "not-built", version };
5714
+ if (code === "ERR_PACKAGE_PATH_NOT_EXPORTED") return finish("unsupported");
5715
+ if (code === "MODULE_NOT_FOUND") return finish("not-built");
5716
+ resolver.close();
5337
5717
  throw err;
5338
5718
  }
5339
5719
  }
@@ -5402,8 +5782,8 @@ function readBrandIndex(indexPath) {
5402
5782
  }
5403
5783
  return data.brands;
5404
5784
  }
5405
- function readSummary(baseDir, entry) {
5406
- const metaPath = projectRequire(baseDir).resolve(tokensSpecifier(entry.meta));
5785
+ function readSummary(resolver, entry) {
5786
+ const metaPath = resolver.resolve(tokensSpecifier(entry.meta));
5407
5787
  const meta = readJsonFile(metaPath);
5408
5788
  return {
5409
5789
  name: entry.name,
@@ -5414,20 +5794,33 @@ function readSummary(baseDir, entry) {
5414
5794
  };
5415
5795
  }
5416
5796
  function listBrands(baseDir) {
5417
- const tokens = resolveTokens(baseDir);
5418
- if (tokens.status !== "ok" || !tokens.indexPath) {
5797
+ const { resolution: tokens, resolver } = openTokens(baseDir);
5798
+ try {
5799
+ return withStaleOf(resolver, listBrandsWith(tokens, resolver));
5800
+ } finally {
5801
+ resolver?.close();
5802
+ }
5803
+ }
5804
+ function listBrandsWith(tokens, resolver) {
5805
+ if (tokens.status !== "ok" || !tokens.indexPath || !resolver) {
5419
5806
  return { status: tokens.status, version: tokens.version, brands: [] };
5420
5807
  }
5421
5808
  const entries = readBrandIndex(tokens.indexPath);
5422
- let brands;
5423
- try {
5424
- brands = entries.map((entry) => readSummary(baseDir, entry));
5425
- } catch (err) {
5426
- if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brands: [] };
5427
- throw err;
5809
+ const brands = [];
5810
+ for (const entry of entries) {
5811
+ try {
5812
+ brands.push(readSummary(resolver, entry));
5813
+ } catch (err) {
5814
+ if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brands: [] };
5815
+ if (resolver.stale && errorCode(err) === "ERR_PACKAGE_PATH_NOT_EXPORTED") continue;
5816
+ throw err;
5817
+ }
5428
5818
  }
5429
5819
  return { status: "ok", version: tokens.version, brands };
5430
5820
  }
5821
+ function withStaleOf(resolver, result) {
5822
+ return resolver?.stale ? { ...result, stale: true } : result;
5823
+ }
5431
5824
  function stripComments(css) {
5432
5825
  return css.replace(/\/\*[\s\S]*?\*\//g, "");
5433
5826
  }
@@ -5539,8 +5932,15 @@ function readProjectPackageJson(baseDir) {
5539
5932
  }
5540
5933
  }
5541
5934
  function getBrand(baseDir, name) {
5542
- const tokens = resolveTokens(baseDir);
5543
- if (tokens.status !== "ok" || !tokens.indexPath) {
5935
+ const { resolution: tokens, resolver } = openTokens(baseDir);
5936
+ try {
5937
+ return withStaleOf(resolver, getBrandWith(tokens, resolver, name));
5938
+ } finally {
5939
+ resolver?.close();
5940
+ }
5941
+ }
5942
+ function getBrandWith(tokens, resolver, name) {
5943
+ if (tokens.status !== "ok" || !tokens.indexPath || !resolver) {
5544
5944
  return { status: tokens.status, version: tokens.version, brand: null, available: [] };
5545
5945
  }
5546
5946
  const entries = readBrandIndex(tokens.indexPath);
@@ -5552,11 +5952,14 @@ function getBrand(baseDir, name) {
5552
5952
  let summary;
5553
5953
  let parsed;
5554
5954
  try {
5555
- summary = readSummary(baseDir, entry);
5556
- const cssPath = projectRequire(baseDir).resolve(summary.importPath);
5955
+ summary = readSummary(resolver, entry);
5956
+ const cssPath = resolver.resolve(summary.importPath);
5557
5957
  parsed = parseBrandCss(readFileSync8(cssPath, "utf8"), name);
5558
5958
  } catch (err) {
5559
5959
  if (isMissingBuildFile(err)) return { status: "not-built", version: tokens.version, brand: null, available: [] };
5960
+ if (resolver.stale && errorCode(err) === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
5961
+ return { status: "ok", version: tokens.version, brand: null, available: available.filter((n) => n !== name) };
5962
+ }
5560
5963
  throw err;
5561
5964
  }
5562
5965
  return {
@@ -6043,7 +6446,16 @@ function formatTokensStatusGuide(status, version, installCommand = TOKENS_INSTAL
6043
6446
  ].join("\n");
6044
6447
  }
6045
6448
  }
6449
+ var STALE_TOKENS_NOTE = `- \uC8FC\uC758: \uC774 MCP \uC11C\uBC84\uAC00 ${TOKENS_PACKAGE} \uB97C \uCC98\uC74C \uC77D\uC740 \uB4A4 \uB0B4\uC6A9\uC774 \uBC14\uB00C\uC5C8\uB294\uB370 \uC0C8 \uC0C1\uD0DC\uB97C \uB2E4\uC2DC \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC704 \uACB0\uACFC\uB294 \uC774\uC804 \uC124\uCE58 \uAE30\uC900\uC77C \uC218 \uC788\uC73C\uB2C8 MCP \uC11C\uBC84\uB97C \uB2E4\uC2DC \uC2DC\uC791\uD558\uC138\uC694.`;
6450
+ function withStaleNote(text, result) {
6451
+ return result.stale ? `${text}
6452
+
6453
+ ${STALE_TOKENS_NOTE}` : text;
6454
+ }
6046
6455
  function formatListBrandsResult(result, installCommand) {
6456
+ return withStaleNote(listBrandsText(result, installCommand), result);
6457
+ }
6458
+ function listBrandsText(result, installCommand) {
6047
6459
  const lines = ["## AXIS \uBE0C\uB79C\uB4DC\n"];
6048
6460
  if (result.status !== "ok") {
6049
6461
  lines.push(formatTokensStatusGuide(result.status, result.version, installCommand));
@@ -6081,6 +6493,9 @@ function tokenTable(brand) {
6081
6493
  return lines;
6082
6494
  }
6083
6495
  function formatGetBrandResult(result, name, installCommand) {
6496
+ return withStaleNote(getBrandText(result, name, installCommand), result);
6497
+ }
6498
+ function getBrandText(result, name, installCommand) {
6084
6499
  if (result.status !== "ok") {
6085
6500
  return [`## \uBE0C\uB79C\uB4DC: ${name}
6086
6501
  `, formatTokensStatusGuide(result.status, result.version, installCommand)].join("\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-ds/mcp",
3
- "version": "1.4.6",
3
+ "version": "1.4.7",
4
4
  "type": "module",
5
5
  "description": "AXIS Design System - MCP Server for AI-assisted component discovery",
6
6
  "bin": {