@axis-ds/cli 1.4.0 → 1.5.0
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/README.md +24 -3
- package/dist/index.js +1536 -250
- package/dist/registry/agentic-a11y-labels.json +16 -0
- package/dist/registry/agentic-agent-avatar.json +19 -0
- package/dist/registry/agentic-approval-card.json +19 -0
- package/dist/registry/agentic-attachment-card.json +19 -0
- package/dist/registry/agentic-code-block.json +18 -0
- package/dist/registry/agentic-context-panel.json +18 -0
- package/dist/registry/agentic-diff-viewer.json +19 -0
- package/dist/registry/agentic-feedback-buttons.json +19 -0
- package/dist/registry/agentic-message-bubble.json +19 -0
- package/dist/registry/agentic-plan-card.json +19 -0
- package/dist/registry/agentic-recovery-banner.json +18 -0
- package/dist/registry/agentic-run-progress.json +19 -0
- package/dist/registry/agentic-source-panel.json +19 -0
- package/dist/registry/agentic-step-timeline.json +19 -0
- package/dist/registry/agentic-streaming-text.json +18 -0
- package/dist/registry/agentic-surface-renderer.json +18 -0
- package/dist/registry/agentic-thinking-indicator.json +18 -0
- package/dist/registry/agentic-token-usage-indicator.json +18 -0
- package/dist/registry/agentic-tool-call-card.json +19 -0
- package/dist/registry/badge.json +20 -0
- package/dist/registry/button.json +21 -0
- package/dist/registry/card.json +18 -0
- package/dist/registry/dialog.json +20 -0
- package/dist/registry/index.json +217 -0
- package/dist/registry/input.json +18 -0
- package/dist/registry/label.json +21 -0
- package/dist/registry/registry.json +218 -0
- package/dist/registry/select.json +20 -0
- package/dist/registry/separator.json +20 -0
- package/dist/registry/tabs.json +20 -0
- package/dist/registry/toast.json +21 -0
- package/dist/registry/utils.json +19 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -15,12 +15,8 @@ import {
|
|
|
15
15
|
|
|
16
16
|
// src/index.ts
|
|
17
17
|
import { Command } from "commander";
|
|
18
|
-
import
|
|
19
|
-
import ora6 from "ora";
|
|
20
|
-
import fs11 from "fs-extra";
|
|
21
|
-
import path12 from "path";
|
|
18
|
+
import chalk12 from "chalk";
|
|
22
19
|
import { createRequire as createRequire2 } from "module";
|
|
23
|
-
import prompts3 from "prompts";
|
|
24
20
|
|
|
25
21
|
// src/library/base-collector.ts
|
|
26
22
|
import crypto from "crypto";
|
|
@@ -484,11 +480,11 @@ var ShadcnCollector = class extends BaseCollector {
|
|
|
484
480
|
/**
|
|
485
481
|
* 파일 타입 추론
|
|
486
482
|
*/
|
|
487
|
-
getFileType(
|
|
488
|
-
if (
|
|
489
|
-
if (
|
|
490
|
-
if (
|
|
491
|
-
if (
|
|
483
|
+
getFileType(path16) {
|
|
484
|
+
if (path16.includes("hook") || path16.startsWith("use")) return "hook";
|
|
485
|
+
if (path16.includes("util") || path16.includes("lib")) return "util";
|
|
486
|
+
if (path16.endsWith(".css")) return "style";
|
|
487
|
+
if (path16.endsWith(".d.ts") || path16.includes("types")) return "type";
|
|
492
488
|
return "component";
|
|
493
489
|
}
|
|
494
490
|
};
|
|
@@ -1505,7 +1501,7 @@ import ora5 from "ora";
|
|
|
1505
1501
|
|
|
1506
1502
|
// src/template/template-apply.ts
|
|
1507
1503
|
import fs7 from "fs-extra";
|
|
1508
|
-
import
|
|
1504
|
+
import path7 from "path";
|
|
1509
1505
|
import chalk4 from "chalk";
|
|
1510
1506
|
import ora3 from "ora";
|
|
1511
1507
|
import prompts from "prompts";
|
|
@@ -1574,12 +1570,14 @@ function deepMerge(target, source) {
|
|
|
1574
1570
|
|
|
1575
1571
|
// src/config/axis-config.ts
|
|
1576
1572
|
import fs6 from "fs-extra";
|
|
1573
|
+
import path6 from "path";
|
|
1577
1574
|
var AXIS_CONFIG_SCHEMA_URL = "https://axis.minu.best/schema.json";
|
|
1578
1575
|
var AXIS_CONFIG_FILE = "axis.config.json";
|
|
1579
1576
|
function createInitConfig(answers, registry) {
|
|
1580
1577
|
return {
|
|
1581
1578
|
$schema: AXIS_CONFIG_SCHEMA_URL,
|
|
1582
1579
|
componentsDir: answers.componentsDir,
|
|
1580
|
+
...answers.agenticDir !== void 0 ? { agenticDir: answers.agenticDir } : {},
|
|
1583
1581
|
...answers.tailwindConfig !== void 0 ? { tailwindConfig: answers.tailwindConfig } : {},
|
|
1584
1582
|
globalCss: answers.globalCss,
|
|
1585
1583
|
registry
|
|
@@ -1594,6 +1592,11 @@ function createTemplateConfig(template) {
|
|
|
1594
1592
|
globalCss: "./globals.css"
|
|
1595
1593
|
};
|
|
1596
1594
|
}
|
|
1595
|
+
async function readAxisConfig(baseDir) {
|
|
1596
|
+
const configPath = path6.join(baseDir, AXIS_CONFIG_FILE);
|
|
1597
|
+
if (!await fs6.pathExists(configPath)) return null;
|
|
1598
|
+
return await fs6.readJSON(configPath);
|
|
1599
|
+
}
|
|
1597
1600
|
|
|
1598
1601
|
// src/template/template-apply.ts
|
|
1599
1602
|
async function applyTemplate(slug, options) {
|
|
@@ -1606,10 +1609,10 @@ async function applyTemplate(slug, options) {
|
|
|
1606
1609
|
spinner.fail(err.message);
|
|
1607
1610
|
process.exit(1);
|
|
1608
1611
|
}
|
|
1609
|
-
const baseDir =
|
|
1612
|
+
const baseDir = path7.resolve(options.dir || ".");
|
|
1610
1613
|
const conflicts = [];
|
|
1611
1614
|
for (const file of detail.files) {
|
|
1612
|
-
const dest =
|
|
1615
|
+
const dest = path7.join(baseDir, file.path);
|
|
1613
1616
|
if (await fs7.pathExists(dest)) {
|
|
1614
1617
|
conflicts.push(file.path);
|
|
1615
1618
|
}
|
|
@@ -1634,7 +1637,7 @@ async function applyTemplate(slug, options) {
|
|
|
1634
1637
|
if (options.dryRun) {
|
|
1635
1638
|
console.log(chalk4.blue("\n[\uBBF8\uB9AC\uBCF4\uAE30] \uC0DD\uC131\uB420 \uD30C\uC77C:"));
|
|
1636
1639
|
for (const file of detail.files) {
|
|
1637
|
-
const dest =
|
|
1640
|
+
const dest = path7.join(baseDir, file.path);
|
|
1638
1641
|
const exists = conflicts.includes(file.path);
|
|
1639
1642
|
const label = exists ? chalk4.yellow("\uB36E\uC5B4\uC4F0\uAE30") : chalk4.green("\uC0DD\uC131");
|
|
1640
1643
|
console.log(` ${label} ${dest}`);
|
|
@@ -1649,8 +1652,8 @@ async function applyTemplate(slug, options) {
|
|
|
1649
1652
|
}
|
|
1650
1653
|
const writeSpinner = ora3("\uD30C\uC77C \uC0DD\uC131 \uC911...").start();
|
|
1651
1654
|
for (const file of detail.files) {
|
|
1652
|
-
const dest =
|
|
1653
|
-
await fs7.ensureDir(
|
|
1655
|
+
const dest = path7.join(baseDir, file.path);
|
|
1656
|
+
await fs7.ensureDir(path7.dirname(dest));
|
|
1654
1657
|
await fs7.writeFile(dest, file.content);
|
|
1655
1658
|
}
|
|
1656
1659
|
writeSpinner.succeed(`${detail.files.length}\uAC1C \uD30C\uC77C \uC0DD\uC131 \uC644\uB8CC`);
|
|
@@ -1711,7 +1714,7 @@ async function initTemplate(slug, options) {
|
|
|
1711
1714
|
}
|
|
1712
1715
|
targetDir = dir;
|
|
1713
1716
|
}
|
|
1714
|
-
const resolved =
|
|
1717
|
+
const resolved = path7.resolve(targetDir);
|
|
1715
1718
|
if (await fs7.pathExists(resolved)) {
|
|
1716
1719
|
const entries = await fs7.readdir(resolved);
|
|
1717
1720
|
if (entries.length > 0) {
|
|
@@ -1727,7 +1730,7 @@ async function initTemplate(slug, options) {
|
|
|
1727
1730
|
await fs7.ensureDir(resolved);
|
|
1728
1731
|
}
|
|
1729
1732
|
await applyTemplate(selectedSlug, { dir: targetDir, yes: true });
|
|
1730
|
-
const configPath =
|
|
1733
|
+
const configPath = path7.join(resolved, "axis.config.json");
|
|
1731
1734
|
if (!await fs7.pathExists(configPath)) {
|
|
1732
1735
|
const axisConfig = createTemplateConfig(selectedSlug);
|
|
1733
1736
|
await fs7.writeJSON(configPath, axisConfig, { spaces: 2 });
|
|
@@ -1742,7 +1745,7 @@ async function initTemplate(slug, options) {
|
|
|
1742
1745
|
|
|
1743
1746
|
// src/template/template-diff.ts
|
|
1744
1747
|
import fs8 from "fs-extra";
|
|
1745
|
-
import
|
|
1748
|
+
import path8 from "path";
|
|
1746
1749
|
import chalk5 from "chalk";
|
|
1747
1750
|
import ora4 from "ora";
|
|
1748
1751
|
async function diffTemplate(slug, options) {
|
|
@@ -1755,10 +1758,10 @@ async function diffTemplate(slug, options) {
|
|
|
1755
1758
|
spinner.fail(err.message);
|
|
1756
1759
|
process.exit(1);
|
|
1757
1760
|
}
|
|
1758
|
-
const baseDir =
|
|
1761
|
+
const baseDir = path8.resolve(options.dir || ".");
|
|
1759
1762
|
const entries = [];
|
|
1760
1763
|
for (const file of detail.files) {
|
|
1761
|
-
const localPath =
|
|
1764
|
+
const localPath = path8.join(baseDir, file.path);
|
|
1762
1765
|
if (!await fs8.pathExists(localPath)) {
|
|
1763
1766
|
entries.push({ path: file.path, status: "added" });
|
|
1764
1767
|
continue;
|
|
@@ -1839,12 +1842,12 @@ async function collectLocalFiles(dir, base) {
|
|
|
1839
1842
|
}
|
|
1840
1843
|
for (const entry of entries) {
|
|
1841
1844
|
if (ignore.has(entry.name)) continue;
|
|
1842
|
-
const fullPath =
|
|
1845
|
+
const fullPath = path8.join(dir, entry.name);
|
|
1843
1846
|
if (entry.isDirectory()) {
|
|
1844
1847
|
const nested = await collectLocalFiles(fullPath, root);
|
|
1845
1848
|
results.push(...nested);
|
|
1846
1849
|
} else {
|
|
1847
|
-
results.push(
|
|
1850
|
+
results.push(path8.relative(root, fullPath).replace(/\\/g, "/"));
|
|
1848
1851
|
}
|
|
1849
1852
|
}
|
|
1850
1853
|
return results;
|
|
@@ -1852,7 +1855,7 @@ async function collectLocalFiles(dir, base) {
|
|
|
1852
1855
|
|
|
1853
1856
|
// src/template/template-check.ts
|
|
1854
1857
|
import fs9 from "fs-extra";
|
|
1855
|
-
import
|
|
1858
|
+
import path9 from "path";
|
|
1856
1859
|
import chalk6 from "chalk";
|
|
1857
1860
|
|
|
1858
1861
|
// src/theme/brand-core.ts
|
|
@@ -2520,9 +2523,9 @@ function checkTailwindSetup(baseDirInput) {
|
|
|
2520
2523
|
return { name: "tailwind.config", severity: "warn", message: "tailwind.config.ts\uC5D0 AXIS \uD1A0\uD070 \uC124\uC815\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" };
|
|
2521
2524
|
}
|
|
2522
2525
|
for (const file of otherFiles) {
|
|
2523
|
-
const
|
|
2524
|
-
if (existsSync2(
|
|
2525
|
-
if (hasTokensPresetReference(readFileSync2(
|
|
2526
|
+
const path16 = join2(baseDir, file);
|
|
2527
|
+
if (existsSync2(path16)) {
|
|
2528
|
+
if (hasTokensPresetReference(readFileSync2(path16, "utf8"))) {
|
|
2526
2529
|
return { name: "tailwind.config", severity: "pass", message: `${file}${PRESET_PASS_SUFFIX}` };
|
|
2527
2530
|
}
|
|
2528
2531
|
return { name: "tailwind.config", severity: "warn", message: `${file} \uC874\uC7AC (TypeScript \uAD8C\uC7A5)` };
|
|
@@ -2538,7 +2541,7 @@ var SEVERITY_ICON = {
|
|
|
2538
2541
|
fail: chalk6.red("FAIL")
|
|
2539
2542
|
};
|
|
2540
2543
|
async function collectCheckResults(dir) {
|
|
2541
|
-
const baseDir =
|
|
2544
|
+
const baseDir = path9.resolve(dir || ".");
|
|
2542
2545
|
const results = [];
|
|
2543
2546
|
results.push(await checkFileExists(baseDir, "axis.config.json", "axis.config.json"));
|
|
2544
2547
|
results.push(checkTailwindSetup(baseDir));
|
|
@@ -2583,7 +2586,7 @@ async function runCheck(dir) {
|
|
|
2583
2586
|
return { pass: passCount, warn: warnCount, fail: failCount };
|
|
2584
2587
|
}
|
|
2585
2588
|
async function checkFileExists(baseDir, fileName, label) {
|
|
2586
|
-
const exists = await fs9.pathExists(
|
|
2589
|
+
const exists = await fs9.pathExists(path9.join(baseDir, fileName));
|
|
2587
2590
|
return {
|
|
2588
2591
|
name: label,
|
|
2589
2592
|
severity: exists ? "pass" : "fail",
|
|
@@ -2599,7 +2602,7 @@ async function checkUtils(baseDir) {
|
|
|
2599
2602
|
"utils.ts"
|
|
2600
2603
|
];
|
|
2601
2604
|
for (const candidate of candidates) {
|
|
2602
|
-
const fullPath =
|
|
2605
|
+
const fullPath = path9.join(baseDir, candidate);
|
|
2603
2606
|
if (await fs9.pathExists(fullPath)) {
|
|
2604
2607
|
const content = await fs9.readFile(fullPath, "utf-8");
|
|
2605
2608
|
const hasCn = content.includes("function cn");
|
|
@@ -2617,7 +2620,7 @@ async function checkUtils(baseDir) {
|
|
|
2617
2620
|
};
|
|
2618
2621
|
}
|
|
2619
2622
|
async function checkDependencies(baseDir) {
|
|
2620
|
-
const pkgPath =
|
|
2623
|
+
const pkgPath = path9.join(baseDir, "package.json");
|
|
2621
2624
|
if (!await fs9.pathExists(pkgPath)) {
|
|
2622
2625
|
return {
|
|
2623
2626
|
name: "package.json",
|
|
@@ -2791,11 +2794,11 @@ function registerCheckCommand(program2) {
|
|
|
2791
2794
|
|
|
2792
2795
|
// src/theme/index.ts
|
|
2793
2796
|
import chalk8 from "chalk";
|
|
2794
|
-
import
|
|
2797
|
+
import path11 from "path";
|
|
2795
2798
|
|
|
2796
2799
|
// src/theme/theme-add.ts
|
|
2797
2800
|
import { accessSync, constants, existsSync as existsSync3, readFileSync as readFileSync3, realpathSync, unlinkSync, writeFileSync } from "fs";
|
|
2798
|
-
import
|
|
2801
|
+
import path10 from "path";
|
|
2799
2802
|
var TOKENS_DEPENDENCY_RANGE = `^${MIN_BRAND_TOKENS_VERSION}`;
|
|
2800
2803
|
var THEME_PACKAGE = "@axis-ds/theme";
|
|
2801
2804
|
function readText(file) {
|
|
@@ -2867,17 +2870,17 @@ function compareVersions(a, b) {
|
|
|
2867
2870
|
function realPathInside(baseDir, file) {
|
|
2868
2871
|
const realBase = realpathSync(baseDir);
|
|
2869
2872
|
const realPath = realpathSync(file);
|
|
2870
|
-
const relPath =
|
|
2871
|
-
const inside = relPath !== "" && !relPath.startsWith("..") && !
|
|
2873
|
+
const relPath = path10.relative(realBase, realPath);
|
|
2874
|
+
const inside = relPath !== "" && !relPath.startsWith("..") && !path10.isAbsolute(relPath);
|
|
2872
2875
|
return { inside, realPath };
|
|
2873
2876
|
}
|
|
2874
2877
|
function isStylesheet(realPath) {
|
|
2875
|
-
return
|
|
2878
|
+
return path10.extname(realPath).toLowerCase() === ".css";
|
|
2876
2879
|
}
|
|
2877
2880
|
function detectInstallCommand(baseDir) {
|
|
2878
|
-
if (existsSync3(
|
|
2879
|
-
if (existsSync3(
|
|
2880
|
-
if (existsSync3(
|
|
2881
|
+
if (existsSync3(path10.join(baseDir, "pnpm-lock.yaml"))) return "pnpm install";
|
|
2882
|
+
if (existsSync3(path10.join(baseDir, "yarn.lock"))) return "yarn install";
|
|
2883
|
+
if (existsSync3(path10.join(baseDir, "package-lock.json"))) return "npm install";
|
|
2881
2884
|
return "pnpm install";
|
|
2882
2885
|
}
|
|
2883
2886
|
function hasDependency2(pkg, name) {
|
|
@@ -2893,7 +2896,7 @@ function isPlainObject2(value) {
|
|
|
2893
2896
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2894
2897
|
}
|
|
2895
2898
|
function planThemeAdd(baseDirInput, brand) {
|
|
2896
|
-
const baseDir =
|
|
2899
|
+
const baseDir = path10.resolve(baseDirInput);
|
|
2897
2900
|
const plan = {
|
|
2898
2901
|
baseDir,
|
|
2899
2902
|
brand,
|
|
@@ -2905,7 +2908,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
2905
2908
|
installCommand: detectInstallCommand(baseDir),
|
|
2906
2909
|
writes: []
|
|
2907
2910
|
};
|
|
2908
|
-
const configFile =
|
|
2911
|
+
const configFile = path10.join(baseDir, AXIS_CONFIG_FILE);
|
|
2909
2912
|
const configText = readText(configFile);
|
|
2910
2913
|
if (configText === null) {
|
|
2911
2914
|
plan.errors.push({ kind: "no-config" });
|
|
@@ -2971,7 +2974,7 @@ function planThemeAdd(baseDirInput, brand) {
|
|
|
2971
2974
|
} else {
|
|
2972
2975
|
plan.css = { configuredMissing: location.configuredMissing, action: "manual", otherBrands: [] };
|
|
2973
2976
|
}
|
|
2974
|
-
const pkgFile =
|
|
2977
|
+
const pkgFile = path10.join(baseDir, "package.json");
|
|
2975
2978
|
const pkgText = readText(pkgFile);
|
|
2976
2979
|
const installed = plan.tokens.version;
|
|
2977
2980
|
const upgrade = installed !== void 0 && (compareVersions(installed, MIN_BRAND_TOKENS_VERSION) ?? 0) < 0;
|
|
@@ -3031,8 +3034,8 @@ function applyThemeAdd(plan) {
|
|
|
3031
3034
|
if (current !== w.before) {
|
|
3032
3035
|
throw new Error(`${w.file} \uC774 \uACC4\uD68D \uB4A4\uC5D0 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`);
|
|
3033
3036
|
}
|
|
3034
|
-
const where = realPathInside(plan.baseDir, w.before === null ?
|
|
3035
|
-
if (!where.inside && !(w.before === null &&
|
|
3037
|
+
const where = realPathInside(plan.baseDir, w.before === null ? path10.dirname(w.file) : w.file);
|
|
3038
|
+
if (!where.inside && !(w.before === null && path10.dirname(w.file) === plan.baseDir)) {
|
|
3036
3039
|
throw new Error(`${w.file} \uC758 \uC2E4\uC81C \uC704\uCE58(${where.realPath})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`);
|
|
3037
3040
|
}
|
|
3038
3041
|
if (!w.file.endsWith(".json") && !isStylesheet(where.realPath)) {
|
|
@@ -3044,7 +3047,7 @@ function applyThemeAdd(plan) {
|
|
|
3044
3047
|
throw new Error(`${w.file}: \uBE0C\uB79C\uB4DC import \uAC00 \uC815\uD655\uD788 1\uC904\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3045
3048
|
}
|
|
3046
3049
|
try {
|
|
3047
|
-
accessSync(w.before === null ?
|
|
3050
|
+
accessSync(w.before === null ? path10.dirname(w.file) : w.file, constants.W_OK);
|
|
3048
3051
|
} catch (err) {
|
|
3049
3052
|
throw new Error(`${w.file} \uC5D0 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errorMessage(err)}).`);
|
|
3050
3053
|
}
|
|
@@ -3195,7 +3198,7 @@ function renderThemeInfo(result, name) {
|
|
|
3195
3198
|
return { lines, exitCode: 0 };
|
|
3196
3199
|
}
|
|
3197
3200
|
function rel(plan, file) {
|
|
3198
|
-
return
|
|
3201
|
+
return path11.relative(plan.baseDir, file) || file;
|
|
3199
3202
|
}
|
|
3200
3203
|
function renderThemeAdd(plan, written) {
|
|
3201
3204
|
const error = plan.errors[0];
|
|
@@ -3345,15 +3348,15 @@ function print(output) {
|
|
|
3345
3348
|
function registerThemeCommand(program2) {
|
|
3346
3349
|
const themeCmd = program2.command("theme").description("\uBE0C\uB79C\uB4DC \uD14C\uB9C8 (@axis-ds/tokens \uBE0C\uB79C\uB4DC)");
|
|
3347
3350
|
themeCmd.command("list").alias("ls").description("\uC124\uCE58\uB41C @axis-ds/tokens \uC758 \uBE0C\uB79C\uB4DC \uBAA9\uB85D").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action((options) => {
|
|
3348
|
-
const baseDir =
|
|
3351
|
+
const baseDir = path11.resolve(options.dir || ".");
|
|
3349
3352
|
print(renderThemeList(listBrands(baseDir)));
|
|
3350
3353
|
});
|
|
3351
3354
|
themeCmd.command("info <brand>").description("\uBE0C\uB79C\uB4DC \uC0C1\uC138: import \uACBD\uB85C \xB7 Provider \uC608\uC2DC \xB7 \uC8FC\uC694 \uD1A0\uD070 \xB7 \uBCF4\uC815 \uB0B4\uC5ED").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action((name, options) => {
|
|
3352
|
-
const baseDir =
|
|
3355
|
+
const baseDir = path11.resolve(options.dir || ".");
|
|
3353
3356
|
print(renderThemeInfo(getBrand(baseDir, name), name));
|
|
3354
3357
|
});
|
|
3355
3358
|
themeCmd.command("add <brand>").description("\uBE0C\uB79C\uB4DC \uC801\uC6A9: CSS import \xB7 package.json \uC758\uC874\uC131 \xB7 axis.config.json brand (\uC124\uCE58\uB294 \uC548\uB0B4\uB9CC)").option("-d, --dir <path>", "\uB300\uC0C1 \uB514\uB809\uD1A0\uB9AC").action((name, options) => {
|
|
3356
|
-
const baseDir =
|
|
3359
|
+
const baseDir = path11.resolve(options.dir || ".");
|
|
3357
3360
|
const plan = planThemeAdd(baseDir, name);
|
|
3358
3361
|
let written = [];
|
|
3359
3362
|
if (plan.errors.length === 0) {
|
|
@@ -3372,11 +3375,461 @@ function registerThemeCommand(program2) {
|
|
|
3372
3375
|
import chalk10 from "chalk";
|
|
3373
3376
|
import prompts2 from "prompts";
|
|
3374
3377
|
|
|
3378
|
+
// src/registry/schema.ts
|
|
3379
|
+
import { createHash } from "crypto";
|
|
3380
|
+
var REGISTRY_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
3381
|
+
var REGISTRY_NAME_MAX_LENGTH = 64;
|
|
3382
|
+
function isValidRegistryName(name) {
|
|
3383
|
+
return typeof name === "string" && name.length > 0 && name.length <= REGISTRY_NAME_MAX_LENGTH && REGISTRY_NAME_PATTERN.test(name);
|
|
3384
|
+
}
|
|
3385
|
+
var REGISTRY_PUBLIC_BASE_URL = "https://axis-design-system.pages.dev/r";
|
|
3386
|
+
function redactRegistryUrl(raw) {
|
|
3387
|
+
return maskQueryAndHash(redactUserinfo(raw));
|
|
3388
|
+
}
|
|
3389
|
+
function maskQueryAndHash(value) {
|
|
3390
|
+
const hashAt = value.indexOf("#");
|
|
3391
|
+
let head = hashAt >= 0 ? value.slice(0, hashAt) : value;
|
|
3392
|
+
const queryAt = head.indexOf("?");
|
|
3393
|
+
if (queryAt >= 0) head = `${head.slice(0, queryAt)}?***`;
|
|
3394
|
+
return hashAt >= 0 ? `${head}#***` : head;
|
|
3395
|
+
}
|
|
3396
|
+
function redactUserinfo(raw) {
|
|
3397
|
+
let parsed = null;
|
|
3398
|
+
try {
|
|
3399
|
+
parsed = new URL(raw);
|
|
3400
|
+
} catch {
|
|
3401
|
+
parsed = null;
|
|
3402
|
+
}
|
|
3403
|
+
if (parsed && (parsed.username || parsed.password)) {
|
|
3404
|
+
parsed.username = "";
|
|
3405
|
+
parsed.password = "";
|
|
3406
|
+
const href = parsed.href;
|
|
3407
|
+
const scheme = `${parsed.protocol}//`;
|
|
3408
|
+
return href.startsWith(scheme) ? `${scheme}***@${href.slice(scheme.length)}` : `***@${href}`;
|
|
3409
|
+
}
|
|
3410
|
+
const authPrefix = /^\s*[A-Za-z][A-Za-z0-9+.-]*:[/\\]*/.exec(raw)?.[0] ?? "";
|
|
3411
|
+
const authority = raw.slice(authPrefix.length).split(/[/\\]/)[0];
|
|
3412
|
+
const authorityAt = authority.lastIndexOf("@");
|
|
3413
|
+
if (authPrefix && authorityAt >= 0) return `${authPrefix}***${raw.slice(authPrefix.length + authorityAt)}`;
|
|
3414
|
+
if (parsed && (parsed.protocol === "http:" || parsed.protocol === "https:")) return raw;
|
|
3415
|
+
const at = raw.lastIndexOf("@");
|
|
3416
|
+
if (at < 0) return raw;
|
|
3417
|
+
const prefix = /^\s*[A-Za-z][A-Za-z0-9+.-]*:[/\\]*/.exec(raw)?.[0] ?? "";
|
|
3418
|
+
if (prefix.length > at) return raw;
|
|
3419
|
+
return `${prefix}***${raw.slice(at)}`;
|
|
3420
|
+
}
|
|
3421
|
+
var DEFAULT_DEPENDENCY_BASES = [REGISTRY_PUBLIC_BASE_URL];
|
|
3422
|
+
function trimBase(base) {
|
|
3423
|
+
return base.replace(/\/+$/, "");
|
|
3424
|
+
}
|
|
3425
|
+
function registryDependencyName(dep, allowedBases = DEFAULT_DEPENDENCY_BASES) {
|
|
3426
|
+
if (REGISTRY_NAME_PATTERN.test(dep) && dep.length <= REGISTRY_NAME_MAX_LENGTH) return dep;
|
|
3427
|
+
if (/\s/.test(dep) || dep.includes("?") || dep.includes("#")) return null;
|
|
3428
|
+
let url;
|
|
3429
|
+
try {
|
|
3430
|
+
url = new URL(dep);
|
|
3431
|
+
} catch {
|
|
3432
|
+
return null;
|
|
3433
|
+
}
|
|
3434
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
3435
|
+
if (url.username || url.password || url.search || url.hash) return null;
|
|
3436
|
+
for (const raw of allowedBases) {
|
|
3437
|
+
const prefix = `${trimBase(raw)}/`;
|
|
3438
|
+
if (!dep.startsWith(prefix) || !dep.endsWith(".json")) continue;
|
|
3439
|
+
const name = dep.slice(prefix.length, -".json".length);
|
|
3440
|
+
if (isValidRegistryName(name)) return name;
|
|
3441
|
+
}
|
|
3442
|
+
return null;
|
|
3443
|
+
}
|
|
3444
|
+
function registryDependencyArray(obj, where, allowedBases) {
|
|
3445
|
+
const names = [];
|
|
3446
|
+
for (const dep of stringArray(obj, "registryDependencies", where)) {
|
|
3447
|
+
const name = registryDependencyName(dep, allowedBases);
|
|
3448
|
+
if (name === null) {
|
|
3449
|
+
throw new Error(
|
|
3450
|
+
`${where}: registryDependencies \uC758 ${JSON.stringify(redactRegistryUrl(dep).slice(0, 120))} \uB294 \uD56D\uBAA9 \uC774\uB984\uC774\uB098 <\uB808\uC9C0\uC2A4\uD2B8\uB9AC base>/<\uC774\uB984>.json \uD615\uD0DC\uAC00 \uC544\uB2D9\uB2C8\uB2E4(\uBC1B\uB294 base: ${allowedBases.map(trimBase).join(", ")})`
|
|
3451
|
+
);
|
|
3452
|
+
}
|
|
3453
|
+
if (!names.includes(name)) names.push(name);
|
|
3454
|
+
}
|
|
3455
|
+
return names;
|
|
3456
|
+
}
|
|
3457
|
+
function parseJsonText(text, where) {
|
|
3458
|
+
try {
|
|
3459
|
+
return JSON.parse(text);
|
|
3460
|
+
} catch {
|
|
3461
|
+
const head = text.slice(0, 40).replace(/\s+/g, " ").trim();
|
|
3462
|
+
throw new Error(`${where}: JSON \uC774 \uC544\uB2D9\uB2C8\uB2E4(\uC55E\uBD80\uBD84: ${JSON.stringify(head)})`);
|
|
3463
|
+
}
|
|
3464
|
+
}
|
|
3465
|
+
function isRecord(v) {
|
|
3466
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3467
|
+
}
|
|
3468
|
+
function optionalString(obj, key, where) {
|
|
3469
|
+
const v = obj[key];
|
|
3470
|
+
if (v === void 0) return void 0;
|
|
3471
|
+
if (typeof v !== "string") throw new Error(`${where}: ${key} \uAC00 \uBB38\uC790\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3472
|
+
return v;
|
|
3473
|
+
}
|
|
3474
|
+
function stringArray(obj, key, where) {
|
|
3475
|
+
const v = obj[key];
|
|
3476
|
+
if (v === void 0) return [];
|
|
3477
|
+
if (!Array.isArray(v) || v.some((s) => typeof s !== "string" || s.length === 0)) {
|
|
3478
|
+
throw new Error(`${where}: ${key} \uB294 \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uBB38\uC790\uC5F4 \uBC30\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4`);
|
|
3479
|
+
}
|
|
3480
|
+
return v;
|
|
3481
|
+
}
|
|
3482
|
+
var DEPENDENCY_SPEC_PATTERN = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*(?:@[0-9A-Za-z.^~<>=*+| -]+)?$/;
|
|
3483
|
+
function dependencyArray(obj, key, where) {
|
|
3484
|
+
const list = stringArray(obj, key, where);
|
|
3485
|
+
const bad = list.find((s) => s.length > 214 || !DEPENDENCY_SPEC_PATTERN.test(s));
|
|
3486
|
+
if (bad !== void 0) {
|
|
3487
|
+
throw new Error(`${where}: ${key} \uC5D0 \uD328\uD0A4\uC9C0 \uC774\uB984 \uADDC\uCE59\uC5D0 \uB9DE\uC9C0 \uC54A\uB294 \uAC12\uC774 \uC788\uC2B5\uB2C8\uB2E4(${JSON.stringify(bad.slice(0, 60))})`);
|
|
3488
|
+
}
|
|
3489
|
+
return list;
|
|
3490
|
+
}
|
|
3491
|
+
function requireType(obj, where) {
|
|
3492
|
+
const type = obj.type;
|
|
3493
|
+
if (typeof type !== "string" || !type.startsWith("registry:")) {
|
|
3494
|
+
throw new Error(`${where}: type \uC774 registry:* \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3495
|
+
}
|
|
3496
|
+
return type;
|
|
3497
|
+
}
|
|
3498
|
+
function validateRegistryIndex(data, where = "index.json") {
|
|
3499
|
+
if (!isRecord(data)) throw new Error(`${where}: \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3500
|
+
const version = data.version;
|
|
3501
|
+
if (typeof version !== "string" || version.length === 0) {
|
|
3502
|
+
throw new Error(`${where}: version \uC774 \uC5C6\uC2B5\uB2C8\uB2E4`);
|
|
3503
|
+
}
|
|
3504
|
+
if (!Array.isArray(data.items)) throw new Error(`${where}: items \uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3505
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3506
|
+
const items = data.items.map((raw, i) => {
|
|
3507
|
+
const at = `${where} items[${i}]`;
|
|
3508
|
+
if (!isRecord(raw)) throw new Error(`${at}: \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3509
|
+
if (!isValidRegistryName(raw.name)) throw new Error(`${at}: name \uC774 slug \uADDC\uCE59\uC5D0 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
|
|
3510
|
+
if (seen.has(raw.name)) throw new Error(`${at}: name '${raw.name}' \uAC00 \uC911\uBCF5\uC785\uB2C8\uB2E4`);
|
|
3511
|
+
seen.add(raw.name);
|
|
3512
|
+
const sha256 = optionalString(raw, "sha256", at);
|
|
3513
|
+
if (sha256 !== void 0 && !/^[0-9a-f]{64}$/.test(sha256)) {
|
|
3514
|
+
throw new Error(`${at}: sha256 \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3515
|
+
}
|
|
3516
|
+
return {
|
|
3517
|
+
name: raw.name,
|
|
3518
|
+
type: requireType(raw, at),
|
|
3519
|
+
title: optionalString(raw, "title", at),
|
|
3520
|
+
description: optionalString(raw, "description", at),
|
|
3521
|
+
...sha256 !== void 0 ? { sha256 } : {}
|
|
3522
|
+
};
|
|
3523
|
+
});
|
|
3524
|
+
return {
|
|
3525
|
+
name: optionalString(data, "name", where),
|
|
3526
|
+
homepage: optionalString(data, "homepage", where),
|
|
3527
|
+
version,
|
|
3528
|
+
items
|
|
3529
|
+
};
|
|
3530
|
+
}
|
|
3531
|
+
function validateRegistryItem(data, expectedName, where = `${expectedName}.json`, dependencyBases = DEFAULT_DEPENDENCY_BASES) {
|
|
3532
|
+
if (!isRecord(data)) throw new Error(`${where}: \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3533
|
+
if (data.name !== expectedName) {
|
|
3534
|
+
throw new Error(`${where}: name \uC774 '${expectedName}' \uAC00 \uC544\uB2D9\uB2C8\uB2E4(${JSON.stringify(data.name)})`);
|
|
3535
|
+
}
|
|
3536
|
+
const type = requireType(data, where);
|
|
3537
|
+
if (!Array.isArray(data.files) || data.files.length === 0) {
|
|
3538
|
+
throw new Error(`${where}: files \uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4`);
|
|
3539
|
+
}
|
|
3540
|
+
const files = data.files.map((raw, i) => {
|
|
3541
|
+
const at = `${where} files[${i}]`;
|
|
3542
|
+
if (!isRecord(raw)) throw new Error(`${at}: \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3543
|
+
if (typeof raw.path !== "string" || raw.path.length === 0 || raw.path.includes("\0")) {
|
|
3544
|
+
throw new Error(`${at}: path \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4`);
|
|
3545
|
+
}
|
|
3546
|
+
if (typeof raw.content !== "string") throw new Error(`${at}: content \uAC00 \uBB38\uC790\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3547
|
+
const fileType = optionalString(raw, "type", at);
|
|
3548
|
+
const target = optionalString(raw, "target", at);
|
|
3549
|
+
return {
|
|
3550
|
+
path: raw.path,
|
|
3551
|
+
content: raw.content,
|
|
3552
|
+
...fileType !== void 0 ? { type: fileType } : {},
|
|
3553
|
+
...target !== void 0 ? { target } : {}
|
|
3554
|
+
};
|
|
3555
|
+
});
|
|
3556
|
+
return {
|
|
3557
|
+
name: expectedName,
|
|
3558
|
+
type,
|
|
3559
|
+
title: optionalString(data, "title", where),
|
|
3560
|
+
description: optionalString(data, "description", where),
|
|
3561
|
+
dependencies: dependencyArray(data, "dependencies", where),
|
|
3562
|
+
devDependencies: dependencyArray(data, "devDependencies", where),
|
|
3563
|
+
// URL 형태는 이름으로 바꿔 둡니다. 호출한 쪽(add 의 collectItems)은 이름만 봅니다
|
|
3564
|
+
registryDependencies: registryDependencyArray(data, where, dependencyBases),
|
|
3565
|
+
files
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
function sha256Hex(text) {
|
|
3569
|
+
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
3570
|
+
}
|
|
3571
|
+
function checkItemSha256(item, entry, where = `${item.name}.json`) {
|
|
3572
|
+
if (entry.sha256 === void 0) return;
|
|
3573
|
+
if (item.files.length !== 1) {
|
|
3574
|
+
throw new Error(`${where}: index.json \uC5D0 sha256 \uC774 \uC788\uB294\uB370 files \uAC00 ${item.files.length}\uAC1C\uB77C sha256 \uC744 \uB300\uC870\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4`);
|
|
3575
|
+
}
|
|
3576
|
+
const actual = sha256Hex(item.files[0].content);
|
|
3577
|
+
if (actual !== entry.sha256) {
|
|
3578
|
+
throw new Error(`${where}: content sha256 \uC774 index.json \uACFC \uB2E4\uB985\uB2C8\uB2E4`);
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
|
|
3582
|
+
// src/registry/remote.ts
|
|
3583
|
+
var DEFAULT_REGISTRY_URL = REGISTRY_PUBLIC_BASE_URL;
|
|
3584
|
+
var DEFAULT_REGISTRY_TIMEOUT_MS = 5e3;
|
|
3585
|
+
var LEGACY_DEFAULT_REGISTRY_URL = "https://axis.minu.best/r";
|
|
3586
|
+
var LEGACY_REGISTRY_NOTICE = `axis.config.json \uC758 registry \uAC00 \uC885\uC804 \uAE30\uBCF8 \uC8FC\uC18C(${LEGACY_DEFAULT_REGISTRY_URL})\uB77C \uC0C8 \uAE30\uBCF8 \uC8FC\uC18C(${REGISTRY_PUBLIC_BASE_URL})\uB85C \uC870\uD68C\uD574\uC694. axis.config.json \uC758 registry \uB97C \uACE0\uCE58\uBA74 \uC774 \uC548\uB0B4\uAC00 \uC0AC\uB77C\uC838\uC694`;
|
|
3587
|
+
function isLegacyDefaultRegistryUrl(value) {
|
|
3588
|
+
let normalized;
|
|
3589
|
+
try {
|
|
3590
|
+
normalized = normalizeRegistryBaseUrl(value.trim());
|
|
3591
|
+
} catch {
|
|
3592
|
+
return false;
|
|
3593
|
+
}
|
|
3594
|
+
return normalized === LEGACY_DEFAULT_REGISTRY_URL;
|
|
3595
|
+
}
|
|
3596
|
+
function resolveRegistryUrl(options) {
|
|
3597
|
+
const env = options.env ?? process.env;
|
|
3598
|
+
const fromEnv = env.AXIS_REGISTRY_URL?.trim();
|
|
3599
|
+
if (fromEnv) return { url: fromEnv, source: "env" };
|
|
3600
|
+
const fromConfig = typeof options.config?.registry === "string" ? options.config.registry.trim() : "";
|
|
3601
|
+
if (fromConfig) {
|
|
3602
|
+
if (isLegacyDefaultRegistryUrl(fromConfig)) {
|
|
3603
|
+
return { url: DEFAULT_REGISTRY_URL, source: "config", migratedFrom: fromConfig };
|
|
3604
|
+
}
|
|
3605
|
+
return { url: fromConfig, source: "config" };
|
|
3606
|
+
}
|
|
3607
|
+
return { url: DEFAULT_REGISTRY_URL, source: "default" };
|
|
3608
|
+
}
|
|
3609
|
+
function normalizeRegistryBaseUrl(raw) {
|
|
3610
|
+
const shown = redactRegistryUrl(raw);
|
|
3611
|
+
if (/\s/.test(raw)) throw new Error(`\uB808\uC9C0\uC2A4\uD2B8\uB9AC URL \uC5D0 \uACF5\uBC31\uC744 \uB458 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${JSON.stringify(shown)}`);
|
|
3612
|
+
if (raw.includes("?") || raw.includes("#")) throw new Error(`\uB808\uC9C0\uC2A4\uD2B8\uB9AC URL \uC5D0 \uCFFC\uB9AC \xB7 \uD574\uC2DC\uB97C \uB458 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${shown}`);
|
|
3613
|
+
let parsed;
|
|
3614
|
+
try {
|
|
3615
|
+
parsed = new URL(raw);
|
|
3616
|
+
} catch {
|
|
3617
|
+
throw new Error(`\uB808\uC9C0\uC2A4\uD2B8\uB9AC URL \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4: ${shown}`);
|
|
3618
|
+
}
|
|
3619
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
3620
|
+
throw new Error(`\uB808\uC9C0\uC2A4\uD2B8\uB9AC URL \uC740 http \xB7 https \uB9CC \uC9C0\uC6D0\uD569\uB2C8\uB2E4: ${shown}`);
|
|
3621
|
+
}
|
|
3622
|
+
if (parsed.username || parsed.password) {
|
|
3623
|
+
throw new Error(`\uB808\uC9C0\uC2A4\uD2B8\uB9AC URL \uC5D0 \uC0AC\uC6A9\uC790 \uC815\uBCF4(userinfo)\uB97C \uB458 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${shown}`);
|
|
3624
|
+
}
|
|
3625
|
+
if (parsed.search || parsed.hash) throw new Error(`\uB808\uC9C0\uC2A4\uD2B8\uB9AC URL \uC5D0 \uCFFC\uB9AC \xB7 \uD574\uC2DC\uB97C \uB458 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${shown}`);
|
|
3626
|
+
return `${parsed.protocol}//${parsed.host}${parsed.pathname.replace(/\/+$/, "")}`;
|
|
3627
|
+
}
|
|
3628
|
+
var RegistryAccessError = class extends Error {
|
|
3629
|
+
constructor(message) {
|
|
3630
|
+
super(message);
|
|
3631
|
+
this.name = "RegistryAccessError";
|
|
3632
|
+
}
|
|
3633
|
+
};
|
|
3634
|
+
async function fetchRegistryJson(url, options = {}) {
|
|
3635
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_REGISTRY_TIMEOUT_MS;
|
|
3636
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
3637
|
+
if (!fetchImpl) throw new RegistryAccessError("\uC774 Node \uB7F0\uD0C0\uC784\uC5D0\uB294 fetch \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(Node 18 \uC774\uC0C1 \uD544\uC694)");
|
|
3638
|
+
const shown = redactRegistryUrl(url);
|
|
3639
|
+
const controller = new AbortController();
|
|
3640
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
3641
|
+
const describe = (error) => {
|
|
3642
|
+
if (controller.signal.aborted) return new RegistryAccessError(`${shown}: ${timeoutMs}ms \uC548\uC5D0 \uC751\uB2F5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4`);
|
|
3643
|
+
const cause = error?.cause;
|
|
3644
|
+
const detail = cause?.code ?? cause?.message ?? (error instanceof Error ? error.message : String(error));
|
|
3645
|
+
return new RegistryAccessError(`${shown}: \uC694\uCCAD \uC2E4\uD328(${detail})`);
|
|
3646
|
+
};
|
|
3647
|
+
let text;
|
|
3648
|
+
try {
|
|
3649
|
+
let res;
|
|
3650
|
+
try {
|
|
3651
|
+
res = await fetchImpl(url, { signal: controller.signal, headers: { accept: "application/json" } });
|
|
3652
|
+
} catch (error) {
|
|
3653
|
+
throw describe(error);
|
|
3654
|
+
}
|
|
3655
|
+
if (!res.ok) {
|
|
3656
|
+
await res.text().catch(() => void 0);
|
|
3657
|
+
throw new RegistryAccessError(`${shown}: HTTP ${res.status}`);
|
|
3658
|
+
}
|
|
3659
|
+
try {
|
|
3660
|
+
text = await res.text();
|
|
3661
|
+
} catch (error) {
|
|
3662
|
+
throw describe(error);
|
|
3663
|
+
}
|
|
3664
|
+
} finally {
|
|
3665
|
+
clearTimeout(timer);
|
|
3666
|
+
}
|
|
3667
|
+
return parseJsonText(text, shown);
|
|
3668
|
+
}
|
|
3669
|
+
|
|
3375
3670
|
// src/init/init.ts
|
|
3376
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as
|
|
3377
|
-
import
|
|
3671
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync5, lstatSync as lstatSync2, readFileSync as readFileSync4, realpathSync as realpathSync3, statSync as statSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
3672
|
+
import path13 from "path";
|
|
3378
3673
|
import chalk9 from "chalk";
|
|
3674
|
+
import fs11 from "fs-extra";
|
|
3675
|
+
|
|
3676
|
+
// src/add/safe-write.ts
|
|
3677
|
+
import { constants as fsConstants, existsSync as existsSync4, lstatSync, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
|
|
3678
|
+
import path12 from "path";
|
|
3379
3679
|
import fs10 from "fs-extra";
|
|
3680
|
+
var NEW_FILE_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | (fsConstants.O_NOFOLLOW ?? 0);
|
|
3681
|
+
var OVERWRITE_FLAGS = fsConstants.O_WRONLY | (fsConstants.O_NOFOLLOW ?? 0);
|
|
3682
|
+
var HARDLINK_ERROR_CODE = "EAXISHARDLINK";
|
|
3683
|
+
var NOT_REGULAR_ERROR_CODE = "EAXISNOTREG";
|
|
3684
|
+
function codedError(code, message) {
|
|
3685
|
+
const e = new Error(message);
|
|
3686
|
+
e.code = code;
|
|
3687
|
+
return e;
|
|
3688
|
+
}
|
|
3689
|
+
function isSameOrInside(parent, child, impl = path12) {
|
|
3690
|
+
const rel3 = impl.relative(parent, child);
|
|
3691
|
+
if (rel3 === "") return true;
|
|
3692
|
+
return !(rel3 === ".." || rel3.startsWith(`..${impl.sep}`) || impl.isAbsolute(rel3));
|
|
3693
|
+
}
|
|
3694
|
+
function nearestExisting(p) {
|
|
3695
|
+
let cur = p;
|
|
3696
|
+
while (!existsSync4(cur)) {
|
|
3697
|
+
const up = path12.dirname(cur);
|
|
3698
|
+
if (up === cur) return cur;
|
|
3699
|
+
cur = up;
|
|
3700
|
+
}
|
|
3701
|
+
return cur;
|
|
3702
|
+
}
|
|
3703
|
+
function escapeReason(root, target, options = {}) {
|
|
3704
|
+
const realRoot = realpathSync2(root);
|
|
3705
|
+
if (!isSameOrInside(path12.resolve(root), path12.resolve(target)) || path12.resolve(target) === path12.resolve(root)) {
|
|
3706
|
+
return `\uACBD\uB85C\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4(${target})`;
|
|
3707
|
+
}
|
|
3708
|
+
const anchor = nearestExisting(path12.dirname(target));
|
|
3709
|
+
const realAnchor = realpathSync2(anchor);
|
|
3710
|
+
if (!isSameOrInside(realRoot, realAnchor)) {
|
|
3711
|
+
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`;
|
|
3712
|
+
}
|
|
3713
|
+
let st = null;
|
|
3714
|
+
try {
|
|
3715
|
+
st = lstatSync(target);
|
|
3716
|
+
} catch {
|
|
3717
|
+
st = null;
|
|
3718
|
+
}
|
|
3719
|
+
if (st) {
|
|
3720
|
+
if (st.isDirectory()) return `\uAC19\uC740 \uC774\uB984\uC758 \uB514\uB809\uD130\uB9AC\uAC00 \uC788\uC2B5\uB2C8\uB2E4(${target})`;
|
|
3721
|
+
const shown = path12.relative(path12.resolve(root), path12.resolve(target)).split(path12.sep).join("/");
|
|
3722
|
+
let realTarget;
|
|
3723
|
+
try {
|
|
3724
|
+
realTarget = realpathSync2(target);
|
|
3725
|
+
} catch {
|
|
3726
|
+
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)`;
|
|
3727
|
+
}
|
|
3728
|
+
if (!isSameOrInside(realRoot, realTarget) && !(options.allowOutsideLink && st.isSymbolicLink())) {
|
|
3729
|
+
return `\uAE30\uC874 \uD30C\uC77C\uC758 \uC2E4\uC81C \uC704\uCE58(${realTarget})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
|
|
3730
|
+
}
|
|
3731
|
+
let followed;
|
|
3732
|
+
try {
|
|
3733
|
+
followed = statSync2(realTarget);
|
|
3734
|
+
} catch {
|
|
3735
|
+
return `\uAE30\uC874 \uD30C\uC77C \uC815\uBCF4\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${target})`;
|
|
3736
|
+
}
|
|
3737
|
+
if (followed.isDirectory()) {
|
|
3738
|
+
return `\uAC19\uC740 \uC774\uB984\uC758 \uB9C1\uD06C\uAC00 \uB514\uB809\uD130\uB9AC(${realTarget})\uB97C \uAC00\uB9AC\uD0B5\uB2C8\uB2E4(${target})`;
|
|
3739
|
+
}
|
|
3740
|
+
if (!followed.isFile()) {
|
|
3741
|
+
const where = st.isSymbolicLink() ? `\uB9C1\uD06C \uB300\uC0C1(${realTarget})\uC774` : "\uAE30\uC874 \uD30C\uC77C\uC774";
|
|
3742
|
+
return `${where} \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2C8\uB77C \uBE44\uAD50 \xB7 \uB36E\uC5B4\uC4F0\uAE30\uB97C \uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${shown})`;
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
return null;
|
|
3746
|
+
}
|
|
3747
|
+
function isSymlink(p) {
|
|
3748
|
+
try {
|
|
3749
|
+
return lstatSync(p).isSymbolicLink();
|
|
3750
|
+
} catch {
|
|
3751
|
+
return false;
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
function outsideLinkTarget(root, target) {
|
|
3755
|
+
if (!isSymlink(target)) return null;
|
|
3756
|
+
try {
|
|
3757
|
+
const realTarget = realpathSync2(target);
|
|
3758
|
+
return isSameOrInside(realpathSync2(root), realTarget) ? null : realTarget;
|
|
3759
|
+
} catch {
|
|
3760
|
+
return null;
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3763
|
+
function hardLinkCount(target) {
|
|
3764
|
+
try {
|
|
3765
|
+
const st = lstatSync(target);
|
|
3766
|
+
return st.isFile() && st.nlink >= 2 ? st.nlink : null;
|
|
3767
|
+
} catch {
|
|
3768
|
+
return null;
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
function hardLinkMessage(shownPath, nlink) {
|
|
3772
|
+
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`;
|
|
3773
|
+
}
|
|
3774
|
+
function writtenOutside(root, target) {
|
|
3775
|
+
const realRoot = realpathSync2(root);
|
|
3776
|
+
let realTarget;
|
|
3777
|
+
try {
|
|
3778
|
+
realTarget = realpathSync2(target);
|
|
3779
|
+
} catch {
|
|
3780
|
+
return target;
|
|
3781
|
+
}
|
|
3782
|
+
return isSameOrInside(realRoot, realTarget) ? null : realTarget;
|
|
3783
|
+
}
|
|
3784
|
+
async function writeNoFollow(target, content, mode) {
|
|
3785
|
+
let actual = mode;
|
|
3786
|
+
let fd;
|
|
3787
|
+
if (mode === "overwrite") {
|
|
3788
|
+
try {
|
|
3789
|
+
fd = await fs10.open(target, OVERWRITE_FLAGS);
|
|
3790
|
+
} catch (e) {
|
|
3791
|
+
if (e.code !== "ENOENT") throw e;
|
|
3792
|
+
actual = "new";
|
|
3793
|
+
fd = await fs10.open(target, NEW_FILE_FLAGS, 438);
|
|
3794
|
+
}
|
|
3795
|
+
} else {
|
|
3796
|
+
fd = await fs10.open(target, NEW_FILE_FLAGS, 438);
|
|
3797
|
+
}
|
|
3798
|
+
try {
|
|
3799
|
+
if (actual === "overwrite") {
|
|
3800
|
+
const st = await fs10.fstat(fd);
|
|
3801
|
+
if (!st.isFile()) throw codedError(NOT_REGULAR_ERROR_CODE, `${target} \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3802
|
+
if (st.nlink >= 2) throw codedError(HARDLINK_ERROR_CODE, hardLinkMessage(target, st.nlink));
|
|
3803
|
+
await fs10.ftruncate(fd, 0);
|
|
3804
|
+
}
|
|
3805
|
+
await fs10.writeFile(fd, content);
|
|
3806
|
+
} finally {
|
|
3807
|
+
await fs10.close(fd);
|
|
3808
|
+
}
|
|
3809
|
+
return actual;
|
|
3810
|
+
}
|
|
3811
|
+
async function overwriteFollowingLinks(target, content) {
|
|
3812
|
+
const fd = await fs10.open(target, fsConstants.O_WRONLY | fsConstants.O_CREAT, 438);
|
|
3813
|
+
try {
|
|
3814
|
+
const st = await fs10.fstat(fd);
|
|
3815
|
+
if (!st.isFile()) throw codedError(NOT_REGULAR_ERROR_CODE, `${target} \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4`);
|
|
3816
|
+
if (st.nlink >= 2) throw codedError(HARDLINK_ERROR_CODE, hardLinkMessage(target, st.nlink));
|
|
3817
|
+
await fs10.ftruncate(fd, 0);
|
|
3818
|
+
await fs10.writeFile(fd, content);
|
|
3819
|
+
} finally {
|
|
3820
|
+
await fs10.close(fd);
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3823
|
+
function checkParentInside(root, target) {
|
|
3824
|
+
const realRoot = realpathSync2(root);
|
|
3825
|
+
const realParent = realpathSync2(path12.dirname(target));
|
|
3826
|
+
if (!isSameOrInside(realRoot, realParent)) {
|
|
3827
|
+
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`;
|
|
3828
|
+
}
|
|
3829
|
+
return escapeReason(root, target);
|
|
3830
|
+
}
|
|
3831
|
+
|
|
3832
|
+
// src/init/init.ts
|
|
3380
3833
|
var CLSX_RANGE = "^2.1.1";
|
|
3381
3834
|
var TAILWIND_MERGE_RANGES = {
|
|
3382
3835
|
tailwind4: "^3.4.0",
|
|
@@ -3411,8 +3864,29 @@ function describeTailwindBasis(tailwind) {
|
|
|
3411
3864
|
return "tailwindcss \uB97C \uCC3E\uC9C0 \uBABB\uD574 \uAE30\uBCF8\uAC12(Tailwind 3)";
|
|
3412
3865
|
}
|
|
3413
3866
|
var UTILS_TS_CONTENT = `import { type ClassValue, clsx } from "clsx";
|
|
3414
|
-
import {
|
|
3867
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
3868
|
+
|
|
3869
|
+
/**
|
|
3870
|
+
* \`shadow-[shadow:<CSS \uBCC0\uC218 \uCC38\uC870>]\` \uCC98\uB7FC \`shadow:\` \uD0C0\uC785 \uD78C\uD2B8\uAC00 \uBD99\uC740 \uC784\uC758\uAC12 \uADF8\uB9BC\uC790 \uD074\uB798\uC2A4\uC778\uC9C0 \uD310\uC815
|
|
3871
|
+
*
|
|
3872
|
+
* tailwind-merge \uAE30\uBCF8 \uC124\uC815\uC740 \uC774 \uD074\uB798\uC2A4\uB97C \uADF8\uB9BC\uC790 \uC0C9(shadow-color) \uADF8\uB8F9\uC73C\uB85C \uBD84\uB958\uD574\uC11C
|
|
3873
|
+
* \`cn(\uAE30\uBCF8, "shadow-none")\` \uC774 \uAE30\uBCF8 \uADF8\uB9BC\uC790\uB97C \uC9C0\uC6B0\uC9C0 \uBABB\uD558\uACE0, \`shadow-black/50\` \uC740 \uADF8\uB9BC\uC790\uB97C \uD1B5\uC9F8\uB85C \uC9C0\uC6B4\uB2E4.
|
|
3874
|
+
* \uADF8\uB9BC\uC790(shadow) \uADF8\uB8F9\uC5D0 \uB4F1\uB85D\uD574 \uC885\uC804 \`shadow-sm\` \xB7 \`shadow-lg\` \uC640 \uAC19\uC740 \uBCD1\uD569 \uACB0\uACFC\uB97C \uB0B8\uB2E4(WI-0025 U4).
|
|
3875
|
+
*/
|
|
3876
|
+
const isArbitraryShadowWithHint = (value: string) => /^\\[shadow:.+\\]$/.test(value);
|
|
3415
3877
|
|
|
3878
|
+
const twMerge = extendTailwindMerge({
|
|
3879
|
+
extend: {
|
|
3880
|
+
classGroups: {
|
|
3881
|
+
shadow: [{ shadow: [isArbitraryShadowWithHint] }],
|
|
3882
|
+
},
|
|
3883
|
+
},
|
|
3884
|
+
});
|
|
3885
|
+
|
|
3886
|
+
/**
|
|
3887
|
+
* Tailwind CSS \uD074\uB798\uC2A4\uB97C \uBCD1\uD569\uD558\uB294 \uC720\uD2F8\uB9AC\uD2F0 \uD568\uC218
|
|
3888
|
+
* clsx\uB85C \uC870\uAC74\uBD80 \uD074\uB798\uC2A4\uB97C \uCC98\uB9AC\uD558\uACE0 tailwind-merge\uB85C \uCDA9\uB3CC\uC744 \uD574\uACB0
|
|
3889
|
+
*/
|
|
3416
3890
|
export function cn(...inputs: ClassValue[]) {
|
|
3417
3891
|
return twMerge(clsx(inputs));
|
|
3418
3892
|
}
|
|
@@ -3430,7 +3904,7 @@ var TAILWIND4_TOKENS_VERSION = TAILWIND4_MIN_AXIS_VERSION;
|
|
|
3430
3904
|
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.";
|
|
3431
3905
|
function readPackageJsonSafe(baseDir) {
|
|
3432
3906
|
try {
|
|
3433
|
-
const text = readFileSync4(
|
|
3907
|
+
const text = readFileSync4(path13.join(baseDir, "package.json"), "utf8");
|
|
3434
3908
|
const parsed = JSON.parse(text.startsWith(BOM) ? text.slice(1) : text);
|
|
3435
3909
|
return isPlainObject2(parsed) ? parsed : void 0;
|
|
3436
3910
|
} catch {
|
|
@@ -3495,7 +3969,7 @@ function addCommandFor(installCommand, deps) {
|
|
|
3495
3969
|
return `pnpm add ${specs}`;
|
|
3496
3970
|
}
|
|
3497
3971
|
function planUtilsDependencies(baseDirInput) {
|
|
3498
|
-
const baseDir =
|
|
3972
|
+
const baseDir = path13.resolve(baseDirInput);
|
|
3499
3973
|
const installCommand = detectInstallCommand(baseDir);
|
|
3500
3974
|
const tailwind0 = detectTailwind(baseDir);
|
|
3501
3975
|
const ranges0 = selectUtilsDependencies(tailwind0);
|
|
@@ -3508,8 +3982,8 @@ function planUtilsDependencies(baseDirInput) {
|
|
|
3508
3982
|
installCommand,
|
|
3509
3983
|
addCommand: addCommandFor(installCommand, ranges0)
|
|
3510
3984
|
};
|
|
3511
|
-
const pkgFile =
|
|
3512
|
-
if (!
|
|
3985
|
+
const pkgFile = path13.join(baseDir, "package.json");
|
|
3986
|
+
if (!existsSync5(pkgFile)) return plan;
|
|
3513
3987
|
const unwritable = (reason) => ({ ...plan, action: "unwritable", reason });
|
|
3514
3988
|
let where;
|
|
3515
3989
|
try {
|
|
@@ -3562,8 +4036,8 @@ var defaultWriteFile = (file, data) => writeFileSync2(file, data);
|
|
|
3562
4036
|
function applyUtilsDependencies(baseDirInput, plan, writeFile = defaultWriteFile) {
|
|
3563
4037
|
const w = plan.write;
|
|
3564
4038
|
if (plan.action !== "add" || !w) return false;
|
|
3565
|
-
const baseDir =
|
|
3566
|
-
const current =
|
|
4039
|
+
const baseDir = path13.resolve(baseDirInput);
|
|
4040
|
+
const current = existsSync5(w.file) ? readFileSync4(w.file, "utf8") : null;
|
|
3567
4041
|
if (current !== w.before) {
|
|
3568
4042
|
throw new Error(`${w.file} \uC774 \uACC4\uD68D \uB4A4\uC5D0 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`);
|
|
3569
4043
|
}
|
|
@@ -3614,29 +4088,206 @@ function reportDependencies(plan, log) {
|
|
|
3614
4088
|
if (plan.addCommand.includes('"tailwind-merge@')) logBasis();
|
|
3615
4089
|
}
|
|
3616
4090
|
}
|
|
4091
|
+
async function existingConfig(baseDir) {
|
|
4092
|
+
try {
|
|
4093
|
+
return await readAxisConfig(baseDir);
|
|
4094
|
+
} catch {
|
|
4095
|
+
return null;
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
function configStateNote(state) {
|
|
4099
|
+
if (state === "created") return "axis.config.json \uC740 \uC774\uBBF8 \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4.";
|
|
4100
|
+
if (state === "updated") return "axis.config.json \uC740 \uC774\uBBF8 \uAC31\uC2E0\uD588\uC2B5\uB2C8\uB2E4.";
|
|
4101
|
+
return "axis.config.json \uC740 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4(\uC774\uBBF8 \uAC19\uC740 \uB0B4\uC6A9).";
|
|
4102
|
+
}
|
|
4103
|
+
function nonEmptyString(value) {
|
|
4104
|
+
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
4105
|
+
}
|
|
4106
|
+
function errCode(e) {
|
|
4107
|
+
return e.code ?? e.message;
|
|
4108
|
+
}
|
|
4109
|
+
function planUtilsWrite(baseDirInput, utilsPath) {
|
|
4110
|
+
const baseDir = path13.resolve(baseDirInput);
|
|
4111
|
+
const shown = path13.relative(baseDir, utilsPath).split(path13.sep).join("/") || utilsPath;
|
|
4112
|
+
let st;
|
|
4113
|
+
try {
|
|
4114
|
+
st = lstatSync2(utilsPath);
|
|
4115
|
+
} catch (e) {
|
|
4116
|
+
if (e.code === "ENOENT") return { action: "create" };
|
|
4117
|
+
return { action: "reject", reason: `${shown} \uC758 \uC815\uBCF4\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
|
|
4118
|
+
}
|
|
4119
|
+
if (st.isSymbolicLink()) {
|
|
4120
|
+
let real;
|
|
4121
|
+
try {
|
|
4122
|
+
real = realpathSync3(utilsPath);
|
|
4123
|
+
} catch {
|
|
4124
|
+
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` };
|
|
4125
|
+
}
|
|
4126
|
+
let outside = null;
|
|
4127
|
+
try {
|
|
4128
|
+
outside = isSameOrInside(realpathSync3(baseDir), real) ? null : real;
|
|
4129
|
+
} catch {
|
|
4130
|
+
outside = null;
|
|
4131
|
+
}
|
|
4132
|
+
let target;
|
|
4133
|
+
try {
|
|
4134
|
+
target = statSync3(real);
|
|
4135
|
+
} catch (e) {
|
|
4136
|
+
return { action: "reject", reason: `${shown} \uB9C1\uD06C \uB300\uC0C1(${real})\uC758 \uC815\uBCF4\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
|
|
4137
|
+
}
|
|
4138
|
+
if (target.isDirectory()) return { action: "reject", reason: `${shown} \uB9C1\uD06C\uAC00 \uB514\uB809\uD130\uB9AC(${real})\uB97C \uAC00\uB9AC\uD0B5\uB2C8\uB2E4` };
|
|
4139
|
+
if (!target.isFile()) return { action: "reject", reason: `${shown} \uB9C1\uD06C \uB300\uC0C1(${real})\uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2D9\uB2C8\uB2E4` };
|
|
4140
|
+
let content2;
|
|
4141
|
+
try {
|
|
4142
|
+
content2 = readFileSync4(utilsPath, "utf8");
|
|
4143
|
+
} catch (e) {
|
|
4144
|
+
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)})` };
|
|
4145
|
+
}
|
|
4146
|
+
if (content2 === UTILS_TS_CONTENT) return { action: "keep", link: { outside } };
|
|
4147
|
+
const what = outside !== null ? `\uD504\uB85C\uC81D\uD2B8 \uBC16(${outside})\uC744 \uAC00\uB9AC\uD0A4\uB294 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C` : "\uD504\uB85C\uC81D\uD2B8 \uC548\uC744 \uAC00\uB9AC\uD0A4\uB294 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C";
|
|
4148
|
+
return {
|
|
4149
|
+
action: "reject",
|
|
4150
|
+
reason: `\uAE30\uC874 ${shown} \uC774 ${what} \uB36E\uC5B4\uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uB0B4\uC6A9\uC774 init \uC758 utils \uC640 \uB2E4\uB984). \uB9C1\uD06C\uB294 \uB530\uB77C\uAC00 \uC4F0\uC9C0 \uC54A\uC73C\uB2C8 \uB9C1\uD06C\uB97C \uC9C0\uC6B0\uAC70\uB098 \uC2E4\uC81C \uD30C\uC77C\uB85C \uBC14\uAFBC \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694`
|
|
4151
|
+
};
|
|
4152
|
+
}
|
|
4153
|
+
if (st.isDirectory()) return { action: "reject", reason: `${shown} \uC774\uB984\uC758 \uB514\uB809\uD130\uB9AC\uAC00 \uC788\uC5B4 \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4` };
|
|
4154
|
+
if (!st.isFile()) return { action: "reject", reason: `${shown} \uC774 \uC77C\uBC18 \uD30C\uC77C\uC774 \uC544\uB2C8\uB77C \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4` };
|
|
4155
|
+
let content;
|
|
4156
|
+
try {
|
|
4157
|
+
content = readFileSync4(utilsPath, "utf8");
|
|
4158
|
+
} catch (e) {
|
|
4159
|
+
return { action: "reject", reason: `\uAE30\uC874 ${shown} \uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
|
|
4160
|
+
}
|
|
4161
|
+
if (content === UTILS_TS_CONTENT) return { action: "keep" };
|
|
4162
|
+
const nlink = hardLinkCount(utilsPath);
|
|
4163
|
+
if (nlink !== null) return { action: "reject", reason: hardLinkMessage(shown, nlink) };
|
|
4164
|
+
try {
|
|
4165
|
+
accessSync2(utilsPath, constants2.W_OK);
|
|
4166
|
+
} catch (e) {
|
|
4167
|
+
return { action: "reject", reason: `\uAE30\uC874 ${shown} \uC5D0 \uC4F8 \uAD8C\uD55C\uC774 \uC5C6\uC5B4 \uB36E\uC5B4\uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errCode(e)})` };
|
|
4168
|
+
}
|
|
4169
|
+
return { action: "overwrite" };
|
|
4170
|
+
}
|
|
3617
4171
|
async function runInit(baseDirInput, answers, registryUrl, log = console.log) {
|
|
3618
|
-
const baseDir =
|
|
4172
|
+
const baseDir = path13.resolve(baseDirInput);
|
|
4173
|
+
const current = await existingConfig(baseDir);
|
|
4174
|
+
const existingRegistry = nonEmptyString(current?.registry);
|
|
4175
|
+
const migratedRegistry = existingRegistry !== void 0 && isLegacyDefaultRegistryUrl(existingRegistry);
|
|
4176
|
+
const registry = existingRegistry !== void 0 && !migratedRegistry ? existingRegistry : registryUrl;
|
|
4177
|
+
const existingAgenticDir = nonEmptyString(current?.agenticDir);
|
|
3619
4178
|
const plan = planUtilsDependencies(baseDir);
|
|
3620
4179
|
const tailwind4 = isTailwind4(plan.tailwind);
|
|
3621
4180
|
const axisConfig = createInitConfig(
|
|
3622
4181
|
{
|
|
3623
4182
|
componentsDir: answers.componentsDir,
|
|
4183
|
+
agenticDir: existingAgenticDir,
|
|
3624
4184
|
tailwindConfig: tailwind4 ? void 0 : answers.tailwindConfig,
|
|
3625
4185
|
globalCss: answers.globalCss
|
|
3626
4186
|
},
|
|
3627
|
-
|
|
4187
|
+
registry
|
|
3628
4188
|
);
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
4189
|
+
const configPath = path13.join(baseDir, "axis.config.json");
|
|
4190
|
+
const nextText = `${JSON.stringify(axisConfig, null, 2)}
|
|
4191
|
+
`;
|
|
4192
|
+
const rejects = [];
|
|
4193
|
+
let previousText = null;
|
|
4194
|
+
try {
|
|
4195
|
+
previousText = await fs11.readFile(configPath, "utf8");
|
|
4196
|
+
} catch (e) {
|
|
4197
|
+
if (e.code !== "ENOENT") {
|
|
4198
|
+
rejects.push(`\uAE30\uC874 axis.config.json \uC744 \uC77D\uC9C0 \uBABB\uD574 \uBE44\uAD50\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(${errCode(e)})`);
|
|
4199
|
+
}
|
|
4200
|
+
}
|
|
4201
|
+
if (previousText !== null && previousText !== nextText) {
|
|
4202
|
+
try {
|
|
4203
|
+
const st = statSync3(configPath);
|
|
4204
|
+
if (st.isFile() && st.nlink >= 2) rejects.push(hardLinkMessage("axis.config.json", st.nlink));
|
|
4205
|
+
} catch {
|
|
4206
|
+
}
|
|
4207
|
+
}
|
|
4208
|
+
const utilsPath = path13.resolve(baseDir, answers.componentsDir, "utils.ts");
|
|
4209
|
+
const utilsPlan = planUtilsWrite(baseDir, utilsPath);
|
|
4210
|
+
if (utilsPlan.action === "reject") rejects.push(utilsPlan.reason);
|
|
4211
|
+
if (rejects.length > 0) {
|
|
4212
|
+
log(chalk9.red("\u2717 \uC4F8 \uC218 \uC5C6\uB294 \uD30C\uC77C\uC774 \uC788\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4(axis.config.json \xB7 utils.ts \xB7 package.json \uADF8\uB300\uB85C)."));
|
|
4213
|
+
for (const r of rejects) log(chalk9.red(` - ${r}`));
|
|
4214
|
+
process.exitCode = 1;
|
|
4215
|
+
return;
|
|
4216
|
+
}
|
|
4217
|
+
let configState;
|
|
4218
|
+
if (previousText === null) {
|
|
4219
|
+
try {
|
|
4220
|
+
await fs11.writeFile(configPath, nextText, { flag: "wx" });
|
|
4221
|
+
} catch (err) {
|
|
4222
|
+
const reason = err.code === "EEXIST" ? "\uAC80\uC0AC \uB4A4 \uC4F0\uAE30 \uC9C1\uC804\uC5D0 \uAC19\uC740 \uC774\uB984\uC758 \uD30C\uC77C\uC774 \uC0DD\uACBC\uC2B5\uB2C8\uB2E4(\uB3D9\uC2DC \uACBD\uD569)" : err.message;
|
|
4223
|
+
log(chalk9.red(`\u2717 axis.config.json \uC744 \uB9CC\uB4E4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${reason}. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`));
|
|
4224
|
+
process.exitCode = 1;
|
|
4225
|
+
return;
|
|
4226
|
+
}
|
|
4227
|
+
configState = "created";
|
|
4228
|
+
log(chalk9.green("\u2713 axis.config.json \uC0DD\uC131 \uC644\uB8CC"));
|
|
4229
|
+
} else if (previousText === nextText) {
|
|
4230
|
+
configState = "kept";
|
|
4231
|
+
log(chalk9.green("\u2713 axis.config.json \uC720\uC9C0(\uC774\uBBF8 \uAC19\uC740 \uB0B4\uC6A9)"));
|
|
4232
|
+
} else {
|
|
4233
|
+
try {
|
|
4234
|
+
await overwriteFollowingLinks(configPath, nextText);
|
|
4235
|
+
} catch (err) {
|
|
4236
|
+
const reason = err.code === HARDLINK_ERROR_CODE ? `\uAC80\uC0AC \uB4A4 \uC4F0\uAE30 \uC9C1\uC804\uC5D0 \uB2E4\uB978 \uACBD\uB85C\uC640 \uD558\uB4DC\uB9C1\uD06C\uB85C \uC774\uC5B4\uC84C\uC2B5\uB2C8\uB2E4(\uB3D9\uC2DC \uACBD\uD569, D19)` : err.message;
|
|
4237
|
+
log(chalk9.red(`\u2717 axis.config.json \uC744 \uC4F0\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${reason}. \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`));
|
|
4238
|
+
process.exitCode = 1;
|
|
4239
|
+
return;
|
|
4240
|
+
}
|
|
4241
|
+
configState = "updated";
|
|
4242
|
+
const registryNote = migratedRegistry ? "registry \uB97C \uC0C8 \uAE30\uBCF8 \uC8FC\uC18C\uB85C \uAC31\uC2E0" : existingRegistry !== void 0 ? "registry \uB294 \uAE30\uC874 \uAC12 \uC720\uC9C0" : "registry \uB294 \uAE30\uBCF8\uAC12";
|
|
4243
|
+
const agenticNote = existingAgenticDir !== void 0 ? ", agenticDir \uB294 \uAE30\uC874 \uAC12 \uC720\uC9C0" : "";
|
|
4244
|
+
log(chalk9.green(`\u2713 axis.config.json \uAC31\uC2E0(\uAE30\uC874 \uD30C\uC77C\uC744 init \uAC12\uC73C\uB85C \uB2E4\uC2DC \uC500, ${registryNote}${agenticNote})`));
|
|
4245
|
+
if (migratedRegistry && existingRegistry !== void 0) {
|
|
4246
|
+
log(
|
|
4247
|
+
chalk9.yellow(
|
|
4248
|
+
` registry \uB97C \uC0C8 \uAE30\uBCF8 \uC8FC\uC18C(${redactRegistryUrl(registry)})\uB85C \uAC31\uC2E0\uD588\uC2B5\uB2C8\uB2E4(\uC885\uC804 axis.minu.best: ${redactRegistryUrl(existingRegistry)}).`
|
|
4249
|
+
)
|
|
4250
|
+
);
|
|
4251
|
+
}
|
|
4252
|
+
const dropped = current ? Object.keys(current).filter((k) => !(k in axisConfig) && current[k] !== void 0) : [];
|
|
4253
|
+
if (dropped.length > 0) {
|
|
4254
|
+
log(chalk9.yellow(` \uAE30\uC874 \uC124\uC815\uC5D0\uC11C \uBE60\uC9C4 \uD0A4: ${dropped.join(", ")} (\uD544\uC694\uD558\uBA74 axis.config.json \uC5D0 \uB2E4\uC2DC \uC801\uC5B4 \uC8FC\uC138\uC694)`));
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
let utilsStateNote = "utils.ts \uB294 \uBC14\uAFB8\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4(\uC774\uBBF8 \uAC19\uC740 \uB0B4\uC6A9).";
|
|
4258
|
+
if (utilsPlan.action === "keep") {
|
|
4259
|
+
if (utilsPlan.link === void 0) log(chalk9.green("\u2713 utils.ts \uC720\uC9C0(\uC774\uBBF8 \uAC19\uC740 \uB0B4\uC6A9)"));
|
|
4260
|
+
else if (utilsPlan.link.outside === null) log(chalk9.green("\u2713 utils.ts \uC720\uC9C0(\uC774\uBBF8 \uAC19\uC740 \uB0B4\uC6A9, \uB9C1\uD06C)"));
|
|
4261
|
+
else log(chalk9.green(`\u2713 utils.ts \uC720\uC9C0(\uC774\uBBF8 \uAC19\uC740 \uB0B4\uC6A9, \uB9C1\uD06C \uB300\uC0C1\uC774 \uD504\uB85C\uC81D\uD2B8 \uBC16: ${utilsPlan.link.outside})`));
|
|
4262
|
+
} else {
|
|
4263
|
+
let actual;
|
|
4264
|
+
try {
|
|
4265
|
+
await fs11.ensureDir(path13.dirname(utilsPath));
|
|
4266
|
+
actual = await writeNoFollow(utilsPath, UTILS_TS_CONTENT, utilsPlan.action === "create" ? "new" : "overwrite");
|
|
4267
|
+
} catch (err) {
|
|
4268
|
+
const code = err.code;
|
|
4269
|
+
const reason = code === HARDLINK_ERROR_CODE ? "\uAC80\uC0AC \uB4A4 \uC4F0\uAE30 \uC9C1\uC804\uC5D0 \uB2E4\uB978 \uACBD\uB85C\uC640 \uD558\uB4DC\uB9C1\uD06C\uB85C \uC774\uC5B4\uC84C\uC2B5\uB2C8\uB2E4(\uB3D9\uC2DC \uACBD\uD569, D19)" : code === "ELOOP" || code === "EEXIST" ? "\uAC80\uC0AC \uB4A4 \uC4F0\uAE30 \uC9C1\uC804\uC5D0 \uAC19\uC740 \uC774\uB984\uC758 \uD30C\uC77C \xB7 \uB9C1\uD06C\uAC00 \uC0DD\uACBC\uC2B5\uB2C8\uB2E4(\uB3D9\uC2DC \uACBD\uD569)" : err.message;
|
|
4270
|
+
log(
|
|
4271
|
+
chalk9.red(
|
|
4272
|
+
utilsPlan.action === "create" ? `\u2717 utils.ts \uB97C \uB9CC\uB4E4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${reason}.` : `\u2717 utils.ts \uB97C \uC4F0\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${reason}. \uADF8 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`
|
|
4273
|
+
)
|
|
4274
|
+
);
|
|
4275
|
+
log(chalk9.yellow(` ${configStateNote(configState)}`));
|
|
4276
|
+
process.exitCode = 1;
|
|
4277
|
+
return;
|
|
4278
|
+
}
|
|
4279
|
+
log(
|
|
4280
|
+
chalk9.green(
|
|
4281
|
+
actual === "new" ? "\u2713 utils.ts \uC0DD\uC131 \uC644\uB8CC" : "\u2713 utils.ts \uB36E\uC5B4\uC500(\uAE30\uC874 \uB0B4\uC6A9\uACFC \uB2EC\uB77C init \uC758 utils \uB85C \uB2E4\uC2DC \uC500)"
|
|
4282
|
+
)
|
|
4283
|
+
);
|
|
4284
|
+
utilsStateNote = actual === "new" ? "utils.ts \uB294 \uC774\uBBF8 \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4." : "utils.ts \uB294 \uC774\uBBF8 \uB36E\uC5B4\uC37C\uC2B5\uB2C8\uB2E4.";
|
|
4285
|
+
}
|
|
3635
4286
|
try {
|
|
3636
4287
|
applyUtilsDependencies(baseDir, plan);
|
|
3637
4288
|
} catch (err) {
|
|
3638
4289
|
log(chalk9.red(`\u2717 package.json \uC744 \uC4F0\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${err.message}`));
|
|
3639
|
-
log(chalk9.yellow(
|
|
4290
|
+
log(chalk9.yellow(` ${configStateNote(configState)} ${utilsStateNote}`));
|
|
3640
4291
|
log(chalk9.yellow(` utils.ts \uC758\uC874\uC131 \uC124\uCE58: ${chalk9.cyan(plan.addCommand)}`));
|
|
3641
4292
|
process.exitCode = 1;
|
|
3642
4293
|
return;
|
|
@@ -3659,7 +4310,7 @@ ${head}`));
|
|
|
3659
4310
|
}
|
|
3660
4311
|
|
|
3661
4312
|
// src/init/index.ts
|
|
3662
|
-
function registerInitCommand(program2, registryUrl) {
|
|
4313
|
+
function registerInitCommand(program2, registryUrl = DEFAULT_REGISTRY_URL) {
|
|
3663
4314
|
program2.command("init").description("\uD504\uB85C\uC81D\uD2B8\uC5D0 AXIS Design System \uCD08\uAE30\uD654").option("-y, --yes", "\uAE30\uBCF8\uAC12\uC73C\uB85C \uC790\uB3D9 \uC124\uC815").action(async (options) => {
|
|
3664
4315
|
console.log(chalk10.blue("\n\u{1F3A8} AXIS Design System \uCD08\uAE30\uD654\n"));
|
|
3665
4316
|
const tailwind4 = isTailwind4(planUtilsDependencies(process.cwd()).tailwind);
|
|
@@ -3687,108 +4338,803 @@ function registerInitCommand(program2, registryUrl) {
|
|
|
3687
4338
|
});
|
|
3688
4339
|
}
|
|
3689
4340
|
|
|
3690
|
-
// src/index.ts
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
4341
|
+
// src/add/index.ts
|
|
4342
|
+
import chalk11 from "chalk";
|
|
4343
|
+
import prompts3 from "prompts";
|
|
4344
|
+
|
|
4345
|
+
// src/add/add.ts
|
|
4346
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
|
|
4347
|
+
import path15 from "path";
|
|
4348
|
+
import fs12 from "fs-extra";
|
|
4349
|
+
|
|
4350
|
+
// src/registry/bundled.ts
|
|
4351
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
4352
|
+
import path14 from "path";
|
|
4353
|
+
import { fileURLToPath } from "url";
|
|
4354
|
+
function findBundledRegistryDir(moduleUrl = import.meta.url) {
|
|
4355
|
+
const here = path14.dirname(fileURLToPath(moduleUrl));
|
|
4356
|
+
for (const dir of [path14.join(here, "registry"), path14.join(here, "..", "registry")]) {
|
|
4357
|
+
if (existsSync6(path14.join(dir, "index.json"))) return dir;
|
|
4358
|
+
}
|
|
4359
|
+
return null;
|
|
4360
|
+
}
|
|
4361
|
+
function readBundledJson(dir, fileName) {
|
|
4362
|
+
const file = path14.join(dir, fileName);
|
|
4363
|
+
let text;
|
|
3698
4364
|
try {
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
4365
|
+
text = readFileSync5(file, "utf8");
|
|
4366
|
+
} catch {
|
|
4367
|
+
throw new Error(`\uB3D9\uBD09 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 ${fileName} \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4(${dir})`);
|
|
4368
|
+
}
|
|
4369
|
+
return parseJsonText(text, `\uB3D9\uBD09 \uB808\uC9C0\uC2A4\uD2B8\uB9AC ${fileName}`);
|
|
4370
|
+
}
|
|
4371
|
+
|
|
4372
|
+
// src/registry/index.ts
|
|
4373
|
+
var RegistryError = class extends Error {
|
|
4374
|
+
constructor(code, message) {
|
|
4375
|
+
super(message);
|
|
4376
|
+
this.code = code;
|
|
4377
|
+
this.name = "RegistryError";
|
|
4378
|
+
}
|
|
4379
|
+
};
|
|
4380
|
+
function bundledFallbackMessage(version, reason, kind = "access") {
|
|
4381
|
+
const lead = kind === "invalid" ? "\uC6D0\uACA9 \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC751\uB2F5\uC774 \uD615\uC2DD \uAC80\uC99D\uC744 \uD1B5\uACFC\uD558\uC9C0 \uBABB\uD574" : "\uC6D0\uACA9 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC811\uADFC\uD558\uC9C0 \uBABB\uD574";
|
|
4382
|
+
return `${lead} CLI \uC5D0 \uD3EC\uD568\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC(version ${version})\uB97C \uC0AC\uC6A9\uD569\uB2C8\uB2E4. (\uC6D0\uC778: ${reason})`;
|
|
4383
|
+
}
|
|
4384
|
+
function fallbackKindOf(error) {
|
|
4385
|
+
return error instanceof RegistryAccessError ? "access" : "invalid";
|
|
4386
|
+
}
|
|
4387
|
+
function versionMismatchMessage(remoteVersion, bundledVersion) {
|
|
4388
|
+
return `\uC6D0\uACA9 \uB808\uC9C0\uC2A4\uD2B8\uB9AC(version ${remoteVersion})\uC640 CLI \uC5D0 \uD3EC\uD568\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC(version ${bundledVersion})\uC758 version \uC774 \uB2E4\uB985\uB2C8\uB2E4. \uC6D0\uACA9 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uC6B0\uC120 \uC0AC\uC6A9\uD569\uB2C8\uB2E4.`;
|
|
4389
|
+
}
|
|
4390
|
+
function messageOf(error) {
|
|
4391
|
+
return error instanceof Error ? error.message : String(error);
|
|
4392
|
+
}
|
|
4393
|
+
var RegistryClient = class {
|
|
4394
|
+
baseUrl;
|
|
4395
|
+
baseUrlError;
|
|
4396
|
+
bundledDir;
|
|
4397
|
+
timeoutMs;
|
|
4398
|
+
fetchImpl;
|
|
4399
|
+
notify;
|
|
4400
|
+
mode = null;
|
|
4401
|
+
indexPromise = null;
|
|
4402
|
+
bundledIndex = null;
|
|
4403
|
+
fallbackAnnounced = false;
|
|
4404
|
+
constructor(options) {
|
|
4405
|
+
let baseUrl = null;
|
|
4406
|
+
let baseUrlError = null;
|
|
4407
|
+
if (options.url !== null) {
|
|
4408
|
+
try {
|
|
4409
|
+
baseUrl = normalizeRegistryBaseUrl(options.url);
|
|
4410
|
+
} catch (error) {
|
|
4411
|
+
baseUrlError = messageOf(error);
|
|
4412
|
+
}
|
|
4413
|
+
} else {
|
|
4414
|
+
baseUrlError = "\uC6D0\uACA9 \uB808\uC9C0\uC2A4\uD2B8\uB9AC URL \uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4";
|
|
4415
|
+
}
|
|
4416
|
+
this.baseUrl = baseUrl;
|
|
4417
|
+
this.baseUrlError = baseUrlError;
|
|
4418
|
+
this.bundledDir = options.bundledDir === void 0 ? findBundledRegistryDir() : options.bundledDir;
|
|
4419
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_REGISTRY_TIMEOUT_MS;
|
|
4420
|
+
this.fetchImpl = options.fetchImpl;
|
|
4421
|
+
this.notify = options.notify ?? ((message) => console.warn(message));
|
|
4422
|
+
}
|
|
4423
|
+
/** 지금 쓰는 출처. index 를 읽기 전에는 null 입니다 */
|
|
4424
|
+
get origin() {
|
|
4425
|
+
return this.mode;
|
|
4426
|
+
}
|
|
4427
|
+
/** 레지스트리 목록(index.json) */
|
|
4428
|
+
getIndex() {
|
|
4429
|
+
if (!this.indexPromise) this.indexPromise = this.loadIndex();
|
|
4430
|
+
return this.indexPromise;
|
|
4431
|
+
}
|
|
4432
|
+
/** 항목 하나. 이름 검사 → index 확인 → 항목 조회 순서입니다 */
|
|
4433
|
+
async getItem(name) {
|
|
4434
|
+
if (!isValidRegistryName(name)) {
|
|
4435
|
+
throw new RegistryError(
|
|
4436
|
+
"invalid-name",
|
|
4437
|
+
`'${name}' \uB294 \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uD56D\uBAA9 \uC774\uB984 \uADDC\uCE59(\uC18C\uBB38\uC790 \xB7 \uC22B\uC790 \xB7 \uD558\uC774\uD508)\uC5D0 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`
|
|
3703
4438
|
);
|
|
3704
|
-
process.exit(1);
|
|
3705
4439
|
}
|
|
3706
|
-
const
|
|
3707
|
-
const
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
4440
|
+
const index = await this.getIndex();
|
|
4441
|
+
const entry = index.items.find((it) => it.name === name);
|
|
4442
|
+
if (!entry) {
|
|
4443
|
+
throw new RegistryError("not-found", `'${name}' \uD56D\uBAA9\uC774 \uB808\uC9C0\uC2A4\uD2B8\uB9AC(version ${index.version})\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4`);
|
|
4444
|
+
}
|
|
4445
|
+
if (this.mode === "remote" && this.baseUrl) {
|
|
4446
|
+
try {
|
|
4447
|
+
const data = await fetchRegistryJson(`${this.baseUrl}/${name}.json`, this.fetchOptions());
|
|
4448
|
+
const item = validateRegistryItem(data, name, `${name}.json`, this.remoteDependencyBases());
|
|
4449
|
+
checkItemSha256(item, entry);
|
|
4450
|
+
return item;
|
|
4451
|
+
} catch (error) {
|
|
4452
|
+
await this.switchToBundled(messageOf(error), fallbackKindOf(error));
|
|
4453
|
+
return this.readBundledItem(name);
|
|
4454
|
+
}
|
|
4455
|
+
}
|
|
4456
|
+
return this.readBundledItem(name);
|
|
4457
|
+
}
|
|
4458
|
+
/** 원격 응답의 의존 URL 로 받아 주는 base: 지금 조회 중인 원격 base 와 공개 기본 base(D11) */
|
|
4459
|
+
remoteDependencyBases() {
|
|
4460
|
+
const bases = [REGISTRY_PUBLIC_BASE_URL];
|
|
4461
|
+
if (this.baseUrl && this.baseUrl !== REGISTRY_PUBLIC_BASE_URL) bases.unshift(this.baseUrl);
|
|
4462
|
+
return bases;
|
|
4463
|
+
}
|
|
4464
|
+
fetchOptions() {
|
|
4465
|
+
return { timeoutMs: this.timeoutMs, ...this.fetchImpl ? { fetchImpl: this.fetchImpl } : {} };
|
|
4466
|
+
}
|
|
4467
|
+
async loadIndex() {
|
|
4468
|
+
let remoteError;
|
|
4469
|
+
let kind = "access";
|
|
4470
|
+
if (this.baseUrl) {
|
|
4471
|
+
try {
|
|
4472
|
+
const data = await fetchRegistryJson(`${this.baseUrl}/index.json`, this.fetchOptions());
|
|
4473
|
+
const index = validateRegistryIndex(data, `${this.baseUrl}/index.json`);
|
|
4474
|
+
this.mode = "remote";
|
|
4475
|
+
this.warnVersionMismatch(index.version);
|
|
4476
|
+
return index;
|
|
4477
|
+
} catch (error) {
|
|
4478
|
+
remoteError = messageOf(error);
|
|
4479
|
+
kind = fallbackKindOf(error);
|
|
4480
|
+
}
|
|
4481
|
+
} else {
|
|
4482
|
+
remoteError = this.baseUrlError ?? "\uC6D0\uACA9 \uB808\uC9C0\uC2A4\uD2B8\uB9AC URL \uC774 \uC5C6\uC2B5\uB2C8\uB2E4";
|
|
4483
|
+
}
|
|
4484
|
+
return this.switchToBundled(remoteError, kind);
|
|
4485
|
+
}
|
|
4486
|
+
/** 동봉본 index 를 읽습니다(성공하면 한 번만). 실패하면 이유를 돌려줍니다 */
|
|
4487
|
+
loadBundledIndex() {
|
|
4488
|
+
if (this.bundledIndex) return { index: this.bundledIndex };
|
|
4489
|
+
if (!this.bundledDir) return { error: "CLI \uC5D0 \uD3EC\uD568\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4" };
|
|
4490
|
+
try {
|
|
4491
|
+
this.bundledIndex = validateRegistryIndex(readBundledJson(this.bundledDir, "index.json"), "\uB3D9\uBD09 \uB808\uC9C0\uC2A4\uD2B8\uB9AC index.json");
|
|
4492
|
+
return { index: this.bundledIndex };
|
|
4493
|
+
} catch (error) {
|
|
4494
|
+
return { error: messageOf(error) };
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
warnVersionMismatch(remoteVersion) {
|
|
4498
|
+
const bundled = this.loadBundledIndex();
|
|
4499
|
+
if ("index" in bundled && bundled.index.version !== remoteVersion) {
|
|
4500
|
+
this.notify(versionMismatchMessage(remoteVersion, bundled.index.version));
|
|
4501
|
+
}
|
|
4502
|
+
}
|
|
4503
|
+
async switchToBundled(reason, kind = "access") {
|
|
4504
|
+
const bundled = this.loadBundledIndex();
|
|
4505
|
+
if ("error" in bundled) {
|
|
4506
|
+
throw new RegistryError(
|
|
4507
|
+
"unavailable",
|
|
4508
|
+
`\uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC6D0\uACA9: ${reason} / \uB3D9\uBD09\uBCF8: ${bundled.error}`
|
|
3714
4509
|
);
|
|
3715
|
-
process.exit(1);
|
|
3716
4510
|
}
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
4511
|
+
this.mode = "bundled";
|
|
4512
|
+
this.indexPromise = Promise.resolve(bundled.index);
|
|
4513
|
+
if (!this.fallbackAnnounced) {
|
|
4514
|
+
this.fallbackAnnounced = true;
|
|
4515
|
+
this.notify(bundledFallbackMessage(bundled.index.version, reason, kind));
|
|
4516
|
+
}
|
|
4517
|
+
return bundled.index;
|
|
4518
|
+
}
|
|
4519
|
+
readBundledItem(name) {
|
|
4520
|
+
const index = this.bundledIndex;
|
|
4521
|
+
const entry = index?.items.find((it) => it.name === name);
|
|
4522
|
+
if (!index || !entry || !this.bundledDir) {
|
|
4523
|
+
throw new RegistryError(
|
|
4524
|
+
"not-found",
|
|
4525
|
+
`'${name}' \uD56D\uBAA9\uC774 CLI \uC5D0 \uD3EC\uD568\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC(version ${index?.version ?? "\uC54C \uC218 \uC5C6\uC74C"})\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4`
|
|
4526
|
+
);
|
|
4527
|
+
}
|
|
4528
|
+
try {
|
|
4529
|
+
const item = validateRegistryItem(readBundledJson(this.bundledDir, `${name}.json`), name, `${name}.json`, DEFAULT_DEPENDENCY_BASES);
|
|
4530
|
+
checkItemSha256(item, entry);
|
|
4531
|
+
return item;
|
|
4532
|
+
} catch (error) {
|
|
4533
|
+
throw new RegistryError("unavailable", `CLI \uC5D0 \uD3EC\uD568\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 '${name}' \uD56D\uBAA9\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${messageOf(error)}`);
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4536
|
+
};
|
|
4537
|
+
|
|
4538
|
+
// src/add/add.ts
|
|
4539
|
+
var AGENTIC_PREFIX = "agentic-";
|
|
4540
|
+
function applyAgenticAlias(name, agentic) {
|
|
4541
|
+
if (!agentic || name.startsWith(AGENTIC_PREFIX)) return name;
|
|
4542
|
+
return `${AGENTIC_PREFIX}${name}`;
|
|
4543
|
+
}
|
|
4544
|
+
function describeMissingName(requested, resolved, index, agentic) {
|
|
4545
|
+
const names = new Set(index.items.map((it) => it.name));
|
|
4546
|
+
if (!isValidRegistryName(resolved)) {
|
|
4547
|
+
return `'${requested}': \uC774\uB984 \uADDC\uCE59(\uC18C\uBB38\uC790 \xB7 \uC22B\uC790 \xB7 \uD558\uC774\uD508)\uC5D0 \uB9DE\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`;
|
|
4548
|
+
}
|
|
4549
|
+
if (agentic && resolved !== requested && names.has(requested)) {
|
|
4550
|
+
return `'${requested}': Agentic UI \uC5D0 '${resolved}' \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. '${requested}' \uB294 Core UI \uD56D\uBAA9\uC774\uB2C8 --agentic \uC5C6\uC774 \uC2E4\uD589\uD558\uC138\uC694`;
|
|
4551
|
+
}
|
|
4552
|
+
if (!agentic && names.has(`${AGENTIC_PREFIX}${requested}`)) {
|
|
4553
|
+
return `'${requested}': \uC5C6\uC2B5\uB2C8\uB2E4. Agentic UI \uD56D\uBAA9 '${AGENTIC_PREFIX}${requested}' \uB97C \uB73B\uD588\uB2E4\uBA74 \uC804\uCCB4 \uC774\uB984\uC744 \uC4F0\uAC70\uB098 --agentic \uC744 \uBD99\uC774\uC138\uC694`;
|
|
4554
|
+
}
|
|
4555
|
+
return `'${requested}': \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4`;
|
|
4556
|
+
}
|
|
4557
|
+
function layoutFromConfig(root, config) {
|
|
4558
|
+
const componentsRaw = config.componentsDir;
|
|
4559
|
+
if (typeof componentsRaw !== "string" || componentsRaw.trim() === "") {
|
|
4560
|
+
throw new Error("axis.config.json \uC5D0 componentsDir \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. 'npx @axis-ds/cli init' \uC744 \uB2E4\uC2DC \uC2E4\uD589\uD558\uAC70\uB098 \uC9C1\uC811 \uC801\uC73C\uC138\uC694");
|
|
4561
|
+
}
|
|
4562
|
+
const agenticRaw = config.agenticDir;
|
|
4563
|
+
if (agenticRaw !== void 0 && (typeof agenticRaw !== "string" || agenticRaw.trim() === "")) {
|
|
4564
|
+
throw new Error("axis.config.json \uC758 agenticDir \uAC00 \uBB38\uC790\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4");
|
|
4565
|
+
}
|
|
4566
|
+
const componentsDir = componentsRaw.replace(/\\/g, "/");
|
|
4567
|
+
const agenticDir = typeof agenticRaw === "string" ? agenticRaw.replace(/\\/g, "/") : path15.posix.join(path15.posix.dirname(componentsDir), "agentic");
|
|
4568
|
+
return { root: path15.resolve(root), componentsDir, agenticDir };
|
|
4569
|
+
}
|
|
4570
|
+
function toPosix(p, impl = path15) {
|
|
4571
|
+
return p.split(impl.sep).join("/");
|
|
4572
|
+
}
|
|
4573
|
+
function itemKind(item) {
|
|
4574
|
+
if (item.type === "registry:lib") return "lib";
|
|
4575
|
+
return item.name.startsWith(AGENTIC_PREFIX) ? "agentic" : "ui";
|
|
4576
|
+
}
|
|
4577
|
+
var INSTALL_FILE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)*\.tsx?$/;
|
|
4578
|
+
function registryPathProblem(p) {
|
|
4579
|
+
if (p.length === 0) return "\uBE44\uC5B4 \uC788\uC74C";
|
|
4580
|
+
if (p.includes("\0")) return "NUL \uBB38\uC790";
|
|
4581
|
+
if (p.includes("\\")) return "\uC5ED\uC2AC\uB798\uC2DC";
|
|
4582
|
+
if (p.startsWith("/") || /^[A-Za-z]:/.test(p)) return "\uC808\uB300 \uACBD\uB85C";
|
|
4583
|
+
const segments = p.split("/");
|
|
4584
|
+
if (segments.some((seg) => seg === "" || seg === "." || seg === "..")) return "`..` \xB7 `.` \xB7 \uBE48 \uC138\uADF8\uBA3C\uD2B8";
|
|
4585
|
+
return null;
|
|
4586
|
+
}
|
|
4587
|
+
function placeFile(layout, item, filePath, target) {
|
|
4588
|
+
for (const p of target === void 0 ? [filePath] : [filePath, target]) {
|
|
4589
|
+
const problem = registryPathProblem(p);
|
|
4590
|
+
if (problem) throw new Error(`${item.name}: \uD30C\uC77C \uACBD\uB85C\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(${JSON.stringify(p)}, ${problem})`);
|
|
4591
|
+
}
|
|
4592
|
+
const base = path15.posix.basename(filePath);
|
|
4593
|
+
if (!INSTALL_FILE_NAME_PATTERN.test(base)) {
|
|
4594
|
+
throw new Error(`${item.name}: \uD30C\uC77C \uACBD\uB85C\uAC00 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(${JSON.stringify(filePath)}, \uD30C\uC77C \uC774\uB984\uC740 .ts \xB7 .tsx \uB9CC \uC124\uCE58\uD569\uB2C8\uB2E4)`);
|
|
4595
|
+
}
|
|
4596
|
+
const dir = itemKind(item) === "agentic" ? layout.agenticDir : layout.componentsDir;
|
|
4597
|
+
return path15.resolve(layout.root, dir, base);
|
|
4598
|
+
}
|
|
4599
|
+
function stripExt(p) {
|
|
4600
|
+
return p.replace(/\.(?:tsx?|jsx?|mjs|cjs)$/, "");
|
|
4601
|
+
}
|
|
4602
|
+
function buildImportTargets(entries) {
|
|
4603
|
+
const exact = /* @__PURE__ */ new Map();
|
|
4604
|
+
const lib = /* @__PURE__ */ new Map();
|
|
4605
|
+
for (const { item, file, target } of entries) {
|
|
4606
|
+
const rel3 = stripExt(file.path.replace(/\\/g, "/").replace(/^\.?\//, ""));
|
|
4607
|
+
exact.set(`@/${rel3}`, target);
|
|
4608
|
+
if (itemKind(item) === "lib") lib.set(path15.posix.basename(rel3), target);
|
|
4609
|
+
}
|
|
4610
|
+
return { exact, lib };
|
|
4611
|
+
}
|
|
4612
|
+
function nonCodeRanges(src) {
|
|
4613
|
+
const comments = [];
|
|
4614
|
+
const strings = [];
|
|
4615
|
+
function scanTemplate(start) {
|
|
4616
|
+
let i = start + 1;
|
|
4617
|
+
let seg = start;
|
|
4618
|
+
while (i < src.length) {
|
|
4619
|
+
const c = src[i];
|
|
4620
|
+
if (c === "\\") {
|
|
4621
|
+
i += 2;
|
|
4622
|
+
} else if (c === "`") {
|
|
4623
|
+
strings.push([seg, i + 1]);
|
|
4624
|
+
return i + 1;
|
|
4625
|
+
} else if (c === "$" && src[i + 1] === "{") {
|
|
4626
|
+
strings.push([seg, i]);
|
|
4627
|
+
i = scanCode(i + 2, true);
|
|
4628
|
+
seg = i;
|
|
4629
|
+
i++;
|
|
4630
|
+
} else {
|
|
4631
|
+
i++;
|
|
4632
|
+
}
|
|
4633
|
+
}
|
|
4634
|
+
strings.push([seg, src.length]);
|
|
4635
|
+
return src.length;
|
|
4636
|
+
}
|
|
4637
|
+
function scanCode(start, untilBrace) {
|
|
4638
|
+
let i = start;
|
|
4639
|
+
let depth = 0;
|
|
4640
|
+
while (i < src.length) {
|
|
4641
|
+
const c = src[i];
|
|
4642
|
+
if (c === "/" && src[i + 1] === "/") {
|
|
4643
|
+
const end = src.indexOf("\n", i);
|
|
4644
|
+
const stop = end === -1 ? src.length : end;
|
|
4645
|
+
comments.push([i, stop]);
|
|
4646
|
+
i = stop;
|
|
4647
|
+
} else if (c === "/" && src[i + 1] === "*") {
|
|
4648
|
+
const end = src.indexOf("*/", i + 2);
|
|
4649
|
+
const stop = end === -1 ? src.length : end + 2;
|
|
4650
|
+
comments.push([i, stop]);
|
|
4651
|
+
i = stop;
|
|
4652
|
+
} else if (c === '"' || c === "'") {
|
|
4653
|
+
const s = i;
|
|
4654
|
+
i++;
|
|
4655
|
+
while (i < src.length && src[i] !== c && src[i] !== "\n") {
|
|
4656
|
+
if (src[i] === "\\") i++;
|
|
4657
|
+
i++;
|
|
3729
4658
|
}
|
|
4659
|
+
i = Math.min(i + 1, src.length);
|
|
4660
|
+
strings.push([s, i]);
|
|
4661
|
+
} else if (c === "`") {
|
|
4662
|
+
i = scanTemplate(i);
|
|
4663
|
+
} else if (c === "{") {
|
|
4664
|
+
depth++;
|
|
4665
|
+
i++;
|
|
4666
|
+
} else if (c === "}") {
|
|
4667
|
+
if (untilBrace && depth === 0) return i;
|
|
4668
|
+
depth = Math.max(0, depth - 1);
|
|
4669
|
+
i++;
|
|
4670
|
+
} else {
|
|
4671
|
+
i++;
|
|
3730
4672
|
}
|
|
3731
|
-
await fs11.ensureDir(path12.dirname(filePath));
|
|
3732
|
-
await fs11.writeFile(filePath, file.content);
|
|
3733
4673
|
}
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
4674
|
+
return src.length;
|
|
4675
|
+
}
|
|
4676
|
+
scanCode(0, false);
|
|
4677
|
+
return { comments, strings };
|
|
4678
|
+
}
|
|
4679
|
+
function insideRanges(ranges, at) {
|
|
4680
|
+
return ranges.some(([a, b]) => at >= a && at < b);
|
|
4681
|
+
}
|
|
4682
|
+
var SPECIFIER_PATTERN = /(\bfrom\s*|\bimport\s*\(\s*|\bimport\s+|\brequire\s*\(\s*)(["'])(@\/[^"'\n]+)\2/g;
|
|
4683
|
+
var STANDARD_LIB_PATTERN = /^@\/registry\/[^/]+\/lib\/(.+)$/;
|
|
4684
|
+
function relativeSpecifier(fromFile, toFile, impl = path15) {
|
|
4685
|
+
let rel3 = toPosix(impl.relative(impl.dirname(fromFile), stripExt(toFile)), impl);
|
|
4686
|
+
if (!rel3.startsWith(".")) rel3 = `./${rel3}`;
|
|
4687
|
+
return rel3;
|
|
4688
|
+
}
|
|
4689
|
+
function rewriteImports(content, fileTarget, targets) {
|
|
4690
|
+
const rewritten = [];
|
|
4691
|
+
const unresolved = [];
|
|
4692
|
+
const { comments, strings } = nonCodeRanges(content);
|
|
4693
|
+
const out = content.replace(SPECIFIER_PATTERN, (whole, lead, quote, spec, offset) => {
|
|
4694
|
+
if (insideRanges(comments, offset) || insideRanges(strings, offset)) return whole;
|
|
4695
|
+
let target = targets.exact.get(spec);
|
|
4696
|
+
if (target === void 0) {
|
|
4697
|
+
const m = STANDARD_LIB_PATTERN.exec(spec);
|
|
4698
|
+
if (m) target = targets.lib.get(m[1]);
|
|
4699
|
+
}
|
|
4700
|
+
if (target === void 0) {
|
|
4701
|
+
if (spec.startsWith("@/registry/")) unresolved.push(spec);
|
|
4702
|
+
return whole;
|
|
4703
|
+
}
|
|
4704
|
+
const to = relativeSpecifier(fileTarget, target);
|
|
4705
|
+
rewritten.push({ from: spec, to, target });
|
|
4706
|
+
return `${lead}${quote}${to}${quote}`;
|
|
4707
|
+
});
|
|
4708
|
+
return { content: out, rewritten, unresolved };
|
|
4709
|
+
}
|
|
4710
|
+
var RESOLVE_EXTS = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", "/index.ts", "/index.tsx", "/index.js"];
|
|
4711
|
+
function relativeSpecifierResolves(fromFile, spec) {
|
|
4712
|
+
const base = path15.resolve(path15.dirname(fromFile), spec);
|
|
4713
|
+
return RESOLVE_EXTS.some((ext) => {
|
|
4714
|
+
try {
|
|
4715
|
+
return statSync4(base + ext).isFile();
|
|
4716
|
+
} catch {
|
|
4717
|
+
return false;
|
|
3738
4718
|
}
|
|
3739
|
-
}
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
4719
|
+
});
|
|
4720
|
+
}
|
|
4721
|
+
async function collectItems(client, roots) {
|
|
4722
|
+
const first = await collectOnce(client, roots);
|
|
4723
|
+
if (first.origin === "remote" && client.origin === "bundled") return collectOnce(client, roots);
|
|
4724
|
+
return first;
|
|
4725
|
+
}
|
|
4726
|
+
async function collectOnce(client, roots) {
|
|
4727
|
+
const index = await client.getIndex();
|
|
4728
|
+
const origin = client.origin;
|
|
4729
|
+
const known = new Set(index.items.map((it) => it.name));
|
|
4730
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4731
|
+
const items = [];
|
|
4732
|
+
const missingDeps = [];
|
|
4733
|
+
async function visit(name) {
|
|
4734
|
+
if (visited.has(name)) return;
|
|
4735
|
+
visited.add(name);
|
|
4736
|
+
const item = await client.getItem(name);
|
|
4737
|
+
for (const dep of item.registryDependencies) {
|
|
4738
|
+
if (!known.has(dep)) {
|
|
4739
|
+
missingDeps.push({ name: dep, from: name });
|
|
4740
|
+
continue;
|
|
4741
|
+
}
|
|
4742
|
+
await visit(dep);
|
|
4743
|
+
}
|
|
4744
|
+
items.push(item);
|
|
4745
|
+
}
|
|
4746
|
+
for (const root of roots) await visit(root);
|
|
4747
|
+
return { items, missingDeps, origin };
|
|
4748
|
+
}
|
|
4749
|
+
function planFiles(layout, items) {
|
|
4750
|
+
const errors = [];
|
|
4751
|
+
const placed = [];
|
|
4752
|
+
const byTarget = /* @__PURE__ */ new Map();
|
|
4753
|
+
for (const item of items) {
|
|
4754
|
+
for (const file of item.files) {
|
|
4755
|
+
let target;
|
|
4756
|
+
try {
|
|
4757
|
+
target = placeFile(layout, item, file.path, file.target);
|
|
4758
|
+
} catch (error) {
|
|
4759
|
+
errors.push(error.message);
|
|
4760
|
+
continue;
|
|
4761
|
+
}
|
|
4762
|
+
const prev = byTarget.get(target);
|
|
4763
|
+
if (prev !== void 0) {
|
|
4764
|
+
errors.push(`${item.name}: ${toPosix(path15.relative(layout.root, target))} \uB97C ${prev} \uC640 \uD568\uAED8 \uC501\uB2C8\uB2E4(\uAC19\uC740 \uC704\uCE58)`);
|
|
4765
|
+
continue;
|
|
4766
|
+
}
|
|
4767
|
+
byTarget.set(target, item.name);
|
|
4768
|
+
placed.push({ item, file, target });
|
|
4769
|
+
}
|
|
4770
|
+
}
|
|
4771
|
+
const targets = buildImportTargets(placed);
|
|
4772
|
+
const files = [];
|
|
4773
|
+
for (const { item, file, target } of placed) {
|
|
4774
|
+
const r = rewriteImports(file.content, target, targets);
|
|
4775
|
+
for (const spec of r.unresolved) {
|
|
4776
|
+
errors.push(`${item.name}: import '${spec}' \uB97C \uC124\uCE58 \uC704\uCE58\uB85C \uBC14\uAFC0 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(registryDependencies \uC5D0 \uD574\uB2F9 \uD56D\uBAA9\uC774 \uC5C6\uC74C)`);
|
|
4777
|
+
}
|
|
4778
|
+
files.push({ item, sourcePath: file.path, target, content: r.content, rewritten: r.rewritten });
|
|
4779
|
+
}
|
|
4780
|
+
for (const f of files) {
|
|
4781
|
+
const reason = escapeReason(layout.root, f.target, { allowOutsideLink: true });
|
|
4782
|
+
if (reason) errors.push(`${f.item.name}: ${reason}. \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
|
|
4783
|
+
}
|
|
4784
|
+
return { files, errors };
|
|
4785
|
+
}
|
|
4786
|
+
function missingDependencies(root, items) {
|
|
4787
|
+
const installCommand = detectInstallCommand(root);
|
|
4788
|
+
let pkg;
|
|
4789
|
+
try {
|
|
4790
|
+
const text = readFileSync6(path15.join(root, "package.json"), "utf8").replace(/^/, "");
|
|
4791
|
+
const parsed = JSON.parse(text);
|
|
4792
|
+
pkg = isPlainObject2(parsed) ? parsed : void 0;
|
|
4793
|
+
} catch {
|
|
4794
|
+
pkg = void 0;
|
|
4795
|
+
}
|
|
4796
|
+
const ranges = selectUtilsDependencies(detectTailwind(root, pkg));
|
|
4797
|
+
const specs = {};
|
|
4798
|
+
for (const item of items) {
|
|
4799
|
+
for (const dep of item.dependencies) {
|
|
4800
|
+
const name = dependencyName(dep);
|
|
4801
|
+
if (pkg !== void 0 && hasDependency2(pkg, name) !== void 0) continue;
|
|
4802
|
+
if (name in specs) continue;
|
|
4803
|
+
const explicit = dep.length > name.length ? dep.slice(name.length + 1) : void 0;
|
|
4804
|
+
specs[name] = explicit ?? ranges[name];
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
const sorted = {};
|
|
4808
|
+
for (const name of Object.keys(specs).sort()) sorted[name] = specs[name];
|
|
4809
|
+
return { specs: sorted, installCommand };
|
|
4810
|
+
}
|
|
4811
|
+
function dependencyName(spec) {
|
|
4812
|
+
const at = spec.indexOf("@", spec.startsWith("@") ? 1 : 0);
|
|
4813
|
+
return at > 0 ? spec.slice(0, at) : spec;
|
|
4814
|
+
}
|
|
4815
|
+
function addCommandForSpecs(installCommand, specs) {
|
|
4816
|
+
const args = Object.entries(specs).map(([name, range]) => range ? `"${name}@${range}"` : name).join(" ");
|
|
4817
|
+
if (installCommand.startsWith("yarn")) return `yarn add ${args}`;
|
|
4818
|
+
if (installCommand.startsWith("npm")) return `npm install ${args}`;
|
|
4819
|
+
return `pnpm add ${args}`;
|
|
4820
|
+
}
|
|
4821
|
+
function rel2(root, p) {
|
|
4822
|
+
return toPosix(path15.relative(root, p));
|
|
4823
|
+
}
|
|
4824
|
+
async function runAdd(cwd, requested, options, ctx) {
|
|
4825
|
+
const log = ctx.log ?? console.log;
|
|
4826
|
+
const error = ctx.error ?? console.error;
|
|
4827
|
+
const root = path15.resolve(cwd);
|
|
4828
|
+
const result = { exitCode: 1, written: [], overwritten: [], unchanged: [], skipped: [] };
|
|
4829
|
+
if (requested.length === 0) {
|
|
4830
|
+
error("\uCD94\uAC00\uD560 \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984\uC744 \uD558\uB098 \uC774\uC0C1 \uC801\uC73C\uC138\uC694. \uBAA9\uB85D: npx @axis-ds/cli list");
|
|
4831
|
+
return result;
|
|
4832
|
+
}
|
|
4833
|
+
let config;
|
|
4834
|
+
try {
|
|
4835
|
+
config = await readAxisConfig(root);
|
|
4836
|
+
} catch (e) {
|
|
4837
|
+
error(`axis.config.json \uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${e.message}`);
|
|
4838
|
+
return result;
|
|
4839
|
+
}
|
|
4840
|
+
if (!config) {
|
|
4841
|
+
error(
|
|
4842
|
+
"axis.config.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.\n \uD574\uACB0: \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0\uC11C 'npx @axis-ds/cli init'\uC744 \uC2E4\uD589\uD558\uC138\uC694.\n \uCC38\uACE0: https://axis.minu.best/docs/guides/quick-start"
|
|
3744
4843
|
);
|
|
3745
|
-
|
|
4844
|
+
return result;
|
|
3746
4845
|
}
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
4846
|
+
let layout;
|
|
4847
|
+
try {
|
|
4848
|
+
layout = layoutFromConfig(root, config);
|
|
4849
|
+
} catch (e) {
|
|
4850
|
+
error(e.message);
|
|
4851
|
+
return result;
|
|
4852
|
+
}
|
|
4853
|
+
let index;
|
|
4854
|
+
try {
|
|
4855
|
+
index = await ctx.client.getIndex();
|
|
4856
|
+
} catch (e) {
|
|
4857
|
+
error(`\uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${e.message}`);
|
|
4858
|
+
return result;
|
|
4859
|
+
}
|
|
4860
|
+
const names = new Set(index.items.map((it) => it.name));
|
|
4861
|
+
const resolved = [];
|
|
4862
|
+
const missing = [];
|
|
4863
|
+
for (const req of requested) {
|
|
4864
|
+
const name = applyAgenticAlias(req, options.agentic);
|
|
4865
|
+
if (!isValidRegistryName(name) || !names.has(name)) missing.push(describeMissingName(req, name, index, options.agentic));
|
|
4866
|
+
else if (!resolved.includes(name)) resolved.push(name);
|
|
4867
|
+
}
|
|
4868
|
+
if (missing.length > 0) {
|
|
4869
|
+
error(`\uCEF4\uD3EC\uB10C\uD2B8\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC124\uCE58\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4(\uB808\uC9C0\uC2A4\uD2B8\uB9AC version ${index.version}).`);
|
|
4870
|
+
for (const m of missing) error(` - ${m}`);
|
|
4871
|
+
error(" \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uBAA9\uB85D: npx @axis-ds/cli list");
|
|
4872
|
+
return result;
|
|
4873
|
+
}
|
|
4874
|
+
let items;
|
|
4875
|
+
try {
|
|
4876
|
+
const collected = await collectItems(ctx.client, resolved);
|
|
4877
|
+
if (collected.missingDeps.length > 0) {
|
|
4878
|
+
error("\uB808\uC9C0\uC2A4\uD2B8\uB9AC \uD56D\uBAA9\uC758 \uC758\uC874 \uD56D\uBAA9\uC774 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0 \uC5C6\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC124\uCE58\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
|
|
4879
|
+
for (const d of collected.missingDeps) error(` - ${d.from} \u2192 ${d.name}`);
|
|
4880
|
+
return result;
|
|
4881
|
+
}
|
|
4882
|
+
items = collected.items;
|
|
4883
|
+
} catch (e) {
|
|
4884
|
+
const msg = e instanceof RegistryError ? e.message : `\uB808\uC9C0\uC2A4\uD2B8\uB9AC \uD56D\uBAA9\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${e.message}`;
|
|
4885
|
+
error(msg);
|
|
4886
|
+
return result;
|
|
4887
|
+
}
|
|
4888
|
+
const plan = planFiles(layout, items);
|
|
4889
|
+
if (plan.errors.length > 0) {
|
|
4890
|
+
error("\uC124\uCE58\uD560 \uC218 \uC5C6\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
|
|
4891
|
+
for (const e of plan.errors) error(` - ${e}`);
|
|
4892
|
+
return result;
|
|
4893
|
+
}
|
|
4894
|
+
const existing = /* @__PURE__ */ new Map();
|
|
4895
|
+
const readErrors = [];
|
|
4896
|
+
for (const file of plan.files) {
|
|
4897
|
+
if (!existsSync7(file.target)) {
|
|
4898
|
+
existing.set(file, null);
|
|
4899
|
+
continue;
|
|
4900
|
+
}
|
|
4901
|
+
try {
|
|
4902
|
+
existing.set(file, readFileSync6(file.target, "utf8"));
|
|
4903
|
+
} catch (e) {
|
|
4904
|
+
readErrors.push(
|
|
4905
|
+
`${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})`
|
|
4906
|
+
);
|
|
4907
|
+
}
|
|
4908
|
+
}
|
|
4909
|
+
if (readErrors.length > 0) {
|
|
4910
|
+
error("\uC124\uCE58\uD560 \uC218 \uC5C6\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
|
|
4911
|
+
for (const e of readErrors) error(` - ${e}`);
|
|
4912
|
+
return result;
|
|
4913
|
+
}
|
|
4914
|
+
const decisions = [];
|
|
4915
|
+
for (const file of plan.files) {
|
|
4916
|
+
const current = existing.get(file) ?? null;
|
|
4917
|
+
if (current === null) {
|
|
4918
|
+
decisions.push({ file, action: "write" });
|
|
4919
|
+
continue;
|
|
4920
|
+
}
|
|
4921
|
+
if (current === file.content) {
|
|
4922
|
+
decisions.push({ file, action: "unchanged" });
|
|
4923
|
+
continue;
|
|
4924
|
+
}
|
|
4925
|
+
if (options.overwrite) {
|
|
4926
|
+
decisions.push({ file, action: "overwrite" });
|
|
4927
|
+
} else if (options.yes || !ctx.confirm) {
|
|
4928
|
+
decisions.push({ file, action: "skip" });
|
|
4929
|
+
} else {
|
|
4930
|
+
const ok = await ctx.confirm(`${rel2(root, file.target)} \uC758 \uB0B4\uC6A9\uC774 \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC640 \uB2E4\uB985\uB2C8\uB2E4. \uB36E\uC5B4\uC4F0\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`);
|
|
4931
|
+
decisions.push({ file, action: ok ? "overwrite" : "skip" });
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4934
|
+
const outsideLinks = /* @__PURE__ */ new Map();
|
|
4935
|
+
for (const d of decisions) {
|
|
4936
|
+
const outside = outsideLinkTarget(root, d.file.target);
|
|
4937
|
+
if (outside !== null) outsideLinks.set(d.file, outside);
|
|
4938
|
+
}
|
|
4939
|
+
const linkErrors = decisions.filter((d) => (d.action === "write" || d.action === "overwrite") && isSymlink(d.file.target)).map((d) => {
|
|
4940
|
+
const outside = outsideLinks.get(d.file);
|
|
4941
|
+
const what = outside !== void 0 ? `\uD504\uB85C\uC81D\uD2B8 \uBC16(${outside})\uC744 \uAC00\uB9AC\uD0A4\uB294 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C` : "\uD504\uB85C\uC81D\uD2B8 \uC548\uC744 \uAC00\uB9AC\uD0A4\uB294 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C";
|
|
4942
|
+
return `${d.file.item.name}: \uAE30\uC874 \uD30C\uC77C ${rel2(root, d.file.target)} \uC774 ${what} \uB36E\uC5B4\uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uB9C1\uD06C\uB294 \uB530\uB77C\uAC00 \uC4F0\uC9C0 \uC54A\uC73C\uB2C8 \uB9C1\uD06C\uB97C \uC9C0\uC6B0\uAC70\uB098 \uC2E4\uC81C \uD30C\uC77C\uB85C \uBC14\uAFBC \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694`;
|
|
4943
|
+
});
|
|
4944
|
+
for (const d of decisions) {
|
|
4945
|
+
if (d.action !== "overwrite") continue;
|
|
4946
|
+
const nlink = hardLinkCount(d.file.target);
|
|
4947
|
+
if (nlink !== null) linkErrors.push(`${d.file.item.name}: ${hardLinkMessage(rel2(root, d.file.target), nlink)}`);
|
|
4948
|
+
}
|
|
4949
|
+
if (linkErrors.length > 0) {
|
|
4950
|
+
error("\uC124\uCE58\uD560 \uC218 \uC5C6\uC5B4 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
|
|
4951
|
+
for (const e of linkErrors) error(` - ${e}`);
|
|
4952
|
+
return result;
|
|
4953
|
+
}
|
|
4954
|
+
const stopWriting = (p, reason, tail = "\uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.") => {
|
|
4955
|
+
error(`${p}: ${reason}. ${tail}`);
|
|
4956
|
+
if (result.written.length > 0) {
|
|
4957
|
+
error(`\uC774\uBBF8 \uC4F4 \uD30C\uC77C(${result.written.length}):`);
|
|
4958
|
+
for (const w of result.written) error(` ${result.overwritten.includes(w) ? "~" : "+"} ${w}`);
|
|
4959
|
+
}
|
|
4960
|
+
return { ...result, exitCode: 1 };
|
|
3782
4961
|
};
|
|
3783
|
-
|
|
3784
|
-
|
|
4962
|
+
for (const d of decisions) {
|
|
4963
|
+
const p = rel2(root, d.file.target);
|
|
4964
|
+
if (d.action === "unchanged") {
|
|
4965
|
+
result.unchanged.push(p);
|
|
4966
|
+
continue;
|
|
4967
|
+
}
|
|
4968
|
+
if (d.action === "skip") {
|
|
4969
|
+
result.skipped.push(p);
|
|
4970
|
+
continue;
|
|
4971
|
+
}
|
|
4972
|
+
let actual = d.action === "write" ? "new" : "overwrite";
|
|
4973
|
+
try {
|
|
4974
|
+
const before = escapeReason(root, d.file.target);
|
|
4975
|
+
if (before) return stopWriting(p, before);
|
|
4976
|
+
await fs12.ensureDir(path15.dirname(d.file.target));
|
|
4977
|
+
const after = checkParentInside(root, d.file.target);
|
|
4978
|
+
if (after) return stopWriting(p, after);
|
|
4979
|
+
actual = await writeNoFollow(d.file.target, d.file.content, actual);
|
|
4980
|
+
} catch (e) {
|
|
4981
|
+
const code = e.code;
|
|
4982
|
+
if (code === "ELOOP" || code === "EEXIST" && isSymlink(d.file.target)) {
|
|
4983
|
+
return stopWriting(p, "\uAC80\uC0AC \uB4A4 \uC4F0\uAE30 \uC9C1\uC804\uC5D0 \uB9C1\uD06C\uB85C \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4(\uB3D9\uC2DC \uACBD\uD569)");
|
|
4984
|
+
}
|
|
4985
|
+
if (code === HARDLINK_ERROR_CODE) {
|
|
4986
|
+
return stopWriting(
|
|
4987
|
+
p,
|
|
4988
|
+
"\uAC80\uC0AC \uB4A4 \uC4F0\uAE30 \uC9C1\uC804\uC5D0 \uB2E4\uB978 \uACBD\uB85C\uC640 \uD558\uB4DC\uB9C1\uD06C\uB85C \uC774\uC5B4\uC84C\uC2B5\uB2C8\uB2E4(\uB3D9\uC2DC \uACBD\uD569)",
|
|
4989
|
+
"\uADF8 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4(D19). \uD558\uB4DC\uB9C1\uD06C\uB97C \uB04A\uC740 \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694."
|
|
4990
|
+
);
|
|
4991
|
+
}
|
|
4992
|
+
if (code === "EEXIST") {
|
|
4993
|
+
return stopWriting(
|
|
4994
|
+
p,
|
|
4995
|
+
"\uC0C8 \uD30C\uC77C\uB85C \uD310\uC815\uD55C \uB4A4(\uD655\uC778 \uB300\uAE30 \uC911 \uB4F1) \uAC19\uC740 \uC774\uB984\uC758 \uD30C\uC77C\uC774 \uC0DD\uACBC\uC2B5\uB2C8\uB2E4(\uB3D9\uC2DC \uACBD\uD569)",
|
|
4996
|
+
"\uADF8 \uD30C\uC77C\uC740 \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uB0B4\uC6A9\uC744 \uD655\uC778\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694."
|
|
4997
|
+
);
|
|
4998
|
+
}
|
|
4999
|
+
return stopWriting(p, `\uC4F0\uAE30 \uC2E4\uD328(${e.message})`);
|
|
5000
|
+
}
|
|
5001
|
+
const outside = writtenOutside(root, d.file.target);
|
|
5002
|
+
if (outside !== null) {
|
|
5003
|
+
return stopWriting(
|
|
5004
|
+
p,
|
|
5005
|
+
`\uC4F4 \uB4A4 \uD655\uC778\uD55C \uC2E4\uC81C \uC704\uCE58(${outside})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4(\uAC80\uC0AC\uC640 \uC4F0\uAE30 \uC0AC\uC774\uC5D0 \uC0C1\uC704 \uB514\uB809\uD130\uB9AC\uAC00 \uBC14\uB010 \uB3D9\uC2DC \uACBD\uD569)`,
|
|
5006
|
+
`\uADF8 \uD30C\uC77C\uC740 \uC9C0\uC6B0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. ${outside} \uB97C \uC9C1\uC811 \uD655\uC778\uD558\uC138\uC694.`
|
|
5007
|
+
);
|
|
5008
|
+
}
|
|
5009
|
+
result.written.push(p);
|
|
5010
|
+
if (actual === "overwrite") result.overwritten.push(p);
|
|
5011
|
+
}
|
|
5012
|
+
const broken = [];
|
|
5013
|
+
for (const d of decisions) {
|
|
5014
|
+
if (d.action === "skip") continue;
|
|
5015
|
+
for (const r of d.file.rewritten) {
|
|
5016
|
+
if (!relativeSpecifierResolves(d.file.target, r.to)) {
|
|
5017
|
+
broken.push(`${rel2(root, d.file.target)}: '${r.to}'(\uC6D0\uB798 '${r.from}')\uAC00 \uAC00\uB9AC\uD0A4\uB294 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4`);
|
|
5018
|
+
}
|
|
5019
|
+
}
|
|
3785
5020
|
}
|
|
3786
|
-
|
|
3787
|
-
|
|
5021
|
+
const itemNames = items.map((it) => it.name);
|
|
5022
|
+
log(`\uC124\uCE58 \uD56D\uBAA9(${items.length}): ${itemNames.join(", ")}`);
|
|
5023
|
+
for (const p of result.written) {
|
|
5024
|
+
if (result.overwritten.includes(p)) log(` ~ ${p} (\uB36E\uC5B4\uC500)`);
|
|
5025
|
+
else log(` + ${p}`);
|
|
3788
5026
|
}
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
});
|
|
5027
|
+
const outsideRel = new Set([...outsideLinks.keys()].map((f) => rel2(root, f.target)));
|
|
5028
|
+
for (const p of result.unchanged) {
|
|
5029
|
+
log(outsideRel.has(p) ? ` = ${p} (\uAC19\uC740 \uB0B4\uC6A9\uC774\uB77C \uAC74\uB108\uB700, \uB9C1\uD06C \uB300\uC0C1\uC774 \uD504\uB85C\uC81D\uD2B8 \uBC16)` : ` = ${p} (\uAC19\uC740 \uB0B4\uC6A9\uC774\uB77C \uAC74\uB108\uB700)`);
|
|
5030
|
+
}
|
|
5031
|
+
if (result.skipped.length > 0) {
|
|
5032
|
+
log(`\uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 \uD30C\uC77C ${result.skipped.length}\uAC1C\uB97C \uAC74\uB108\uB6F0\uC5C8\uC2B5\uB2C8\uB2E4(\uB36E\uC5B4\uC4F0\uB824\uBA74 --overwrite):`);
|
|
5033
|
+
for (const p of result.skipped) log(outsideRel.has(p) ? ` - ${p} (\uB9C1\uD06C \uB300\uC0C1\uC774 \uD504\uB85C\uC81D\uD2B8 \uBC16)` : ` - ${p}`);
|
|
5034
|
+
}
|
|
5035
|
+
if (broken.length > 0) {
|
|
5036
|
+
error("\uC124\uCE58\uD55C \uD30C\uC77C\uC758 import \uAC00 \uD480\uB9AC\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4:");
|
|
5037
|
+
for (const b of broken) error(` - ${b}`);
|
|
5038
|
+
return { ...result, exitCode: 1 };
|
|
5039
|
+
}
|
|
5040
|
+
const deps = missingDependencies(root, items);
|
|
5041
|
+
if (Object.keys(deps.specs).length > 0) {
|
|
5042
|
+
log("\npackage.json \uC5D0 \uC5C6\uB294 \uC758\uC874\uC131(\uC124\uCE58\uB294 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4):");
|
|
5043
|
+
log(` ${addCommandForSpecs(deps.installCommand, deps.specs)}`);
|
|
5044
|
+
}
|
|
5045
|
+
return { ...result, exitCode: 0 };
|
|
5046
|
+
}
|
|
5047
|
+
function groupIndex(index) {
|
|
5048
|
+
const ui = [];
|
|
5049
|
+
const agentic = [];
|
|
5050
|
+
for (const it of index.items) {
|
|
5051
|
+
const kind = itemKind(it);
|
|
5052
|
+
if (kind === "lib") continue;
|
|
5053
|
+
const entry = { name: it.name, title: it.title, description: it.description };
|
|
5054
|
+
(kind === "agentic" ? agentic : ui).push(entry);
|
|
5055
|
+
}
|
|
5056
|
+
return { ui, agentic };
|
|
5057
|
+
}
|
|
5058
|
+
async function createClientFor(cwd, notify, env = process.env) {
|
|
5059
|
+
let config = null;
|
|
5060
|
+
try {
|
|
5061
|
+
config = await readAxisConfig(path15.resolve(cwd));
|
|
5062
|
+
} catch {
|
|
5063
|
+
config = null;
|
|
5064
|
+
}
|
|
5065
|
+
const resolved = resolveRegistryUrl({ config, env });
|
|
5066
|
+
const say = notify ?? ((message) => console.warn(message));
|
|
5067
|
+
if (resolved.migratedFrom !== void 0) say(LEGACY_REGISTRY_NOTICE);
|
|
5068
|
+
return new RegistryClient({ url: resolved.url, ...notify ? { notify } : {} });
|
|
5069
|
+
}
|
|
5070
|
+
|
|
5071
|
+
// src/add/index.ts
|
|
5072
|
+
function createConfirm(interactive) {
|
|
5073
|
+
if (!interactive) return void 0;
|
|
5074
|
+
return async (message) => {
|
|
5075
|
+
const { overwrite } = await prompts3({ type: "confirm", name: "overwrite", message, initial: false });
|
|
5076
|
+
return overwrite === true;
|
|
5077
|
+
};
|
|
5078
|
+
}
|
|
5079
|
+
var defaultCreateClient = (cwd) => createClientFor(cwd, (m) => console.warn(chalk11.yellow(m)));
|
|
5080
|
+
function registerAddCommand(program2, deps = {}) {
|
|
5081
|
+
program2.command("add <components...>").description("\uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uD504\uB85C\uC81D\uD2B8\uC5D0 \uBCF5\uC0AC(registryDependencies \uD3EC\uD568)").option("--agentic", "\uC774\uB984 \uC55E\uC5D0 agentic- \uB97C \uBD99\uC5EC \uCC3E\uC74C(\uC804\uCCB4 \uC774\uB984\uB3C4 \uD5C8\uC6A9)").option("-y, --yes", "\uBB3B\uC9C0 \uC54A\uACE0 \uC9C4\uD589. \uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 \uD30C\uC77C\uC740 \uAC74\uB108\uB700").option("--overwrite", "\uB0B4\uC6A9\uC774 \uB2E4\uB978 \uAE30\uC874 \uD30C\uC77C\uC744 \uB36E\uC5B4\uC500").action(async (components, options) => {
|
|
5082
|
+
const client = await (deps.createClient ?? defaultCreateClient)(process.cwd());
|
|
5083
|
+
const confirm = createConfirm((deps.isInteractive ?? (() => process.stdin.isTTY === true))());
|
|
5084
|
+
const result = await runAdd(process.cwd(), components, options, {
|
|
5085
|
+
client,
|
|
5086
|
+
log: (...a) => console.log(...a),
|
|
5087
|
+
error: (...a) => console.error(chalk11.red(a.map(String).join(" "))),
|
|
5088
|
+
...confirm ? { confirm } : {}
|
|
5089
|
+
});
|
|
5090
|
+
process.exitCode = result.exitCode;
|
|
5091
|
+
});
|
|
5092
|
+
}
|
|
5093
|
+
function registerListCommand(program2, deps = {}) {
|
|
5094
|
+
program2.command("list").description("\uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC758 \uCEF4\uD3EC\uB10C\uD2B8 \uBAA9\uB85D").option("--category <type>", "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130 (ui, agentic)").action(async (options) => {
|
|
5095
|
+
if (options.category !== void 0 && options.category !== "ui" && options.category !== "agentic") {
|
|
5096
|
+
console.error(chalk11.red(`--category \uB294 ui \uB610\uB294 agentic \uC785\uB2C8\uB2E4(\uBC1B\uC740 \uAC12: ${options.category})`));
|
|
5097
|
+
process.exitCode = 1;
|
|
5098
|
+
return;
|
|
5099
|
+
}
|
|
5100
|
+
const client = await (deps.createClient ?? defaultCreateClient)(process.cwd());
|
|
5101
|
+
let groups;
|
|
5102
|
+
let version;
|
|
5103
|
+
try {
|
|
5104
|
+
const index = await client.getIndex();
|
|
5105
|
+
groups = groupIndex(index);
|
|
5106
|
+
version = index.version;
|
|
5107
|
+
} catch (e) {
|
|
5108
|
+
console.error(chalk11.red(`\uB808\uC9C0\uC2A4\uD2B8\uB9AC\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${e.message}`));
|
|
5109
|
+
process.exitCode = 1;
|
|
5110
|
+
return;
|
|
5111
|
+
}
|
|
5112
|
+
const total = groups.ui.length + groups.agentic.length;
|
|
5113
|
+
const origin = client.origin === "bundled" ? "CLI \uC5D0 \uD3EC\uD568\uB41C \uB808\uC9C0\uC2A4\uD2B8\uB9AC" : "\uC6D0\uACA9 \uB808\uC9C0\uC2A4\uD2B8\uB9AC";
|
|
5114
|
+
console.log(chalk11.blue(`
|
|
5115
|
+
\u{1F4E6} AXIS Design System \uCEF4\uD3EC\uB10C\uD2B8 ${total}\uAC1C (${origin}, version ${version})
|
|
5116
|
+
`));
|
|
5117
|
+
const show = (label, items) => {
|
|
5118
|
+
console.log(chalk11.bold(`${label} (${items.length})`));
|
|
5119
|
+
for (const c of items) {
|
|
5120
|
+
console.log(` ${chalk11.cyan(c.name.padEnd(32))} ${chalk11.gray(c.description ?? c.title ?? "")}`);
|
|
5121
|
+
}
|
|
5122
|
+
console.log();
|
|
5123
|
+
};
|
|
5124
|
+
if (!options.category || options.category === "ui") show("Core UI", groups.ui);
|
|
5125
|
+
if (!options.category || options.category === "agentic") show("Agentic UI", groups.agentic);
|
|
5126
|
+
console.log(chalk11.gray("\uC0AC\uC6A9\uBC95: npx @axis-ds/cli add <\uC774\uB984...> (\uC608: add button input card)"));
|
|
5127
|
+
console.log(chalk11.gray("Agentic: npx @axis-ds/cli add run-progress --agentic (= add agentic-run-progress)\n"));
|
|
5128
|
+
});
|
|
5129
|
+
}
|
|
5130
|
+
|
|
5131
|
+
// src/index.ts
|
|
5132
|
+
var { version: CLI_VERSION } = createRequire2(import.meta.url)("../package.json");
|
|
5133
|
+
var program = new Command();
|
|
5134
|
+
program.name("axis").description("AXIS Design System CLI - shadcn \uD638\uD658 \uCEF4\uD3EC\uB10C\uD2B8 \uC124\uCE58 \uB3C4\uAD6C").version(CLI_VERSION);
|
|
5135
|
+
registerInitCommand(program);
|
|
5136
|
+
registerAddCommand(program);
|
|
5137
|
+
registerListCommand(program);
|
|
3792
5138
|
var monetCmd = program.command("monet").description("Monet Design \uCEF4\uD3EC\uB10C\uD2B8 \uAD00\uB9AC (https://monet.design)");
|
|
3793
5139
|
monetCmd.command("list").alias("ls").description("Monet \uCE74\uD14C\uACE0\uB9AC \uBAA9\uB85D").action(async () => {
|
|
3794
5140
|
const client = new MonetClient();
|
|
@@ -3807,24 +5153,24 @@ monetCmd.command("import").alias("i").description("\uD074\uB9BD\uBCF4\uB4DC\uC5D
|
|
|
3807
5153
|
await client.importFromClipboard();
|
|
3808
5154
|
});
|
|
3809
5155
|
monetCmd.command("setup").description("Monet MCP \uC11C\uBC84 \uC124\uC815 \uC548\uB0B4").action(() => {
|
|
3810
|
-
console.log(
|
|
3811
|
-
console.log(
|
|
3812
|
-
console.log(
|
|
3813
|
-
console.log(
|
|
3814
|
-
console.log(
|
|
3815
|
-
console.log(
|
|
3816
|
-
console.log(
|
|
3817
|
-
console.log(
|
|
5156
|
+
console.log(chalk12.blue("\n\u{1F527} Monet MCP \uC11C\uBC84 \uC124\uC815\n"));
|
|
5157
|
+
console.log(chalk12.bold("1. API \uD0A4 \uBC1C\uAE09:"));
|
|
5158
|
+
console.log(chalk12.cyan(" https://monet.design/mcp\n"));
|
|
5159
|
+
console.log(chalk12.bold("2. \uD658\uACBD \uBCC0\uC218 \uC124\uC815:"));
|
|
5160
|
+
console.log(chalk12.gray(" .env \uD30C\uC77C\uC5D0 \uCD94\uAC00:"));
|
|
5161
|
+
console.log(chalk12.cyan(" MONET_API_KEY=your-api-key-here\n"));
|
|
5162
|
+
console.log(chalk12.bold("3. Claude Code MCP \uC124\uC815:"));
|
|
5163
|
+
console.log(chalk12.gray(" .claude/mcp.json\uC5D0\uC11C monet \uC11C\uBC84 \uD65C\uC131\uD654:\n"));
|
|
3818
5164
|
console.log(
|
|
3819
|
-
|
|
5165
|
+
chalk12.cyan(` "monet": {
|
|
3820
5166
|
"url": "https://www.monet.design/api/remote/mcp",
|
|
3821
5167
|
"headers": { "Authorization": "Bearer \${MONET_API_KEY}" },
|
|
3822
5168
|
"disabled": false
|
|
3823
5169
|
}
|
|
3824
5170
|
`)
|
|
3825
5171
|
);
|
|
3826
|
-
console.log(
|
|
3827
|
-
console.log(
|
|
5172
|
+
console.log(chalk12.bold("4. Claude Code \uC7AC\uC2DC\uC791 \uD6C4 \uC0AC\uC6A9:"));
|
|
5173
|
+
console.log(chalk12.gray(' "monet\uC5D0\uC11C hero \uCEF4\uD3EC\uB10C\uD2B8 \uCC3E\uC544\uC918"\n'));
|
|
3828
5174
|
});
|
|
3829
5175
|
var v0Cmd = program.command("v0").description("V0 (v0.app) \uCF54\uB4DC \uBCC0\uD658 \uBC0F \uD1B5\uD569");
|
|
3830
5176
|
v0Cmd.command("convert <file>").alias("c").description("V0 \uCF54\uB4DC\uB97C AXIS \uC2A4\uD0C0\uC77C\uB85C \uBCC0\uD658").option("-o, --output <path>", "\uCD9C\uB825 \uD30C\uC77C \uACBD\uB85C").action(async (file, options) => {
|
|
@@ -3861,18 +5207,18 @@ libraryCmd.command("collect").alias("c").description("\uC678\uBD80 \uC18C\uC2A4\
|
|
|
3861
5207
|
total += result.collected;
|
|
3862
5208
|
failed += result.failed;
|
|
3863
5209
|
}
|
|
3864
|
-
console.log(
|
|
5210
|
+
console.log(chalk12.blue(`
|
|
3865
5211
|
\u{1F4CA} \uC218\uC9D1 \uC644\uB8CC: ${total}\uAC1C \uCEF4\uD3EC\uB10C\uD2B8`));
|
|
3866
5212
|
if (failed > 0) {
|
|
3867
|
-
console.log(
|
|
5213
|
+
console.log(chalk12.yellow(` \uC2E4\uD328: ${failed}\uAC1C`));
|
|
3868
5214
|
}
|
|
3869
5215
|
});
|
|
3870
5216
|
libraryCmd.command("list").alias("ls").description("\uB77C\uC774\uBE0C\uB7EC\uB9AC \uCEF4\uD3EC\uB10C\uD2B8 \uBAA9\uB85D").option("-c, --category <category>", "\uCE74\uD14C\uACE0\uB9AC \uD544\uD130").option("-s, --source <source>", "\uC18C\uC2A4 \uD544\uD130").action(async (options) => {
|
|
3871
5217
|
const curator = new LibraryCurator();
|
|
3872
5218
|
const index = await curator.loadIndex();
|
|
3873
5219
|
if (!index) {
|
|
3874
|
-
console.log(
|
|
3875
|
-
console.log(
|
|
5220
|
+
console.log(chalk12.yellow("\n\u26A0\uFE0F \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC778\uB371\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
5221
|
+
console.log(chalk12.gray(" \uD574\uACB0: npx @axis-ds/cli library collect \uBA85\uB839\uC5B4\uB85C \uC218\uC9D1\uC744 \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694.\n"));
|
|
3876
5222
|
return;
|
|
3877
5223
|
}
|
|
3878
5224
|
let components = index.components;
|
|
@@ -3882,7 +5228,7 @@ libraryCmd.command("list").alias("ls").description("\uB77C\uC774\uBE0C\uB7EC\uB9
|
|
|
3882
5228
|
if (options.source) {
|
|
3883
5229
|
components = components.filter((c) => c.source.type === options.source);
|
|
3884
5230
|
}
|
|
3885
|
-
console.log(
|
|
5231
|
+
console.log(chalk12.blue(`
|
|
3886
5232
|
\u{1F4E6} Library Components (${components.length}\uAC1C)
|
|
3887
5233
|
`));
|
|
3888
5234
|
const byCategory = /* @__PURE__ */ new Map();
|
|
@@ -3894,14 +5240,14 @@ libraryCmd.command("list").alias("ls").description("\uB77C\uC774\uBE0C\uB7EC\uB9
|
|
|
3894
5240
|
byCategory.get(cat).push(comp);
|
|
3895
5241
|
}
|
|
3896
5242
|
for (const [category, items] of byCategory) {
|
|
3897
|
-
console.log(
|
|
5243
|
+
console.log(chalk12.bold(`${category} (${items.length})`));
|
|
3898
5244
|
for (const item of items.slice(0, 10)) {
|
|
3899
5245
|
console.log(
|
|
3900
|
-
` ${
|
|
5246
|
+
` ${chalk12.cyan(item.name.padEnd(25))} ${chalk12.gray(item.source.type.padEnd(8))} ${chalk12.gray(item.description.slice(0, 40))}`
|
|
3901
5247
|
);
|
|
3902
5248
|
}
|
|
3903
5249
|
if (items.length > 10) {
|
|
3904
|
-
console.log(
|
|
5250
|
+
console.log(chalk12.gray(` ... \uC678 ${items.length - 10}\uAC1C`));
|
|
3905
5251
|
}
|
|
3906
5252
|
console.log();
|
|
3907
5253
|
}
|
|
@@ -3913,21 +5259,21 @@ libraryCmd.command("search <query>").alias("s").description("\uCEF4\uD3EC\uB10C\
|
|
|
3913
5259
|
source: options.source
|
|
3914
5260
|
});
|
|
3915
5261
|
if (results.length === 0) {
|
|
3916
|
-
console.log(
|
|
5262
|
+
console.log(chalk12.yellow(`
|
|
3917
5263
|
'${query}'\uC5D0 \uB300\uD55C \uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
|
|
3918
5264
|
`));
|
|
3919
5265
|
return;
|
|
3920
5266
|
}
|
|
3921
|
-
console.log(
|
|
5267
|
+
console.log(chalk12.blue(`
|
|
3922
5268
|
\u{1F50D} '${query}' \uAC80\uC0C9 \uACB0\uACFC (${results.length}\uAC1C)
|
|
3923
5269
|
`));
|
|
3924
5270
|
for (const comp of results.slice(0, 20)) {
|
|
3925
5271
|
console.log(
|
|
3926
|
-
` ${
|
|
5272
|
+
` ${chalk12.cyan(comp.name.padEnd(25))} ${chalk12.gray(comp.source.type.padEnd(8))} ${chalk12.gray(comp.category.padEnd(12))} ${chalk12.gray(comp.description.slice(0, 30))}`
|
|
3927
5273
|
);
|
|
3928
5274
|
}
|
|
3929
5275
|
if (results.length > 20) {
|
|
3930
|
-
console.log(
|
|
5276
|
+
console.log(chalk12.gray(`
|
|
3931
5277
|
... \uC678 ${results.length - 20}\uAC1C`));
|
|
3932
5278
|
}
|
|
3933
5279
|
console.log();
|
|
@@ -3941,12 +5287,12 @@ libraryCmd.command("publish").description("\uC0AC\uC774\uD2B8\uC5D0 \uB77C\uC774
|
|
|
3941
5287
|
const publisher2 = new Publisher();
|
|
3942
5288
|
const index = await curator.loadIndex();
|
|
3943
5289
|
if (!index) {
|
|
3944
|
-
console.log(
|
|
3945
|
-
console.log(
|
|
5290
|
+
console.log(chalk12.yellow("\n\u26A0\uFE0F \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC778\uB371\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
5291
|
+
console.log(chalk12.gray(" \uD574\uACB0: npx @axis-ds/cli library collect \uBA85\uB839\uC5B4\uB85C \uC218\uC9D1\uC744 \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694.\n"));
|
|
3946
5292
|
return;
|
|
3947
5293
|
}
|
|
3948
|
-
console.log(
|
|
3949
|
-
console.log(
|
|
5294
|
+
console.log(chalk12.blue("\n\u{1F4E4} Library \uBC30\uCE58\n"));
|
|
5295
|
+
console.log(chalk12.gray(`\uCD1D ${index.stats.total}\uAC1C \uCEF4\uD3EC\uB10C\uD2B8
|
|
3950
5296
|
`));
|
|
3951
5297
|
if (options.clean) {
|
|
3952
5298
|
await publisher2.clean(options.output);
|
|
@@ -3957,17 +5303,17 @@ libraryCmd.command("publish").description("\uC0AC\uC774\uD2B8\uC5D0 \uB77C\uC774
|
|
|
3957
5303
|
generateSearchIndex: true
|
|
3958
5304
|
});
|
|
3959
5305
|
if (result.success) {
|
|
3960
|
-
console.log(
|
|
5306
|
+
console.log(chalk12.green(`
|
|
3961
5307
|
\u2713 \uBC30\uCE58 \uC644\uB8CC`));
|
|
3962
|
-
console.log(
|
|
3963
|
-
console.log(
|
|
3964
|
-
console.log(
|
|
3965
|
-
console.log(
|
|
5308
|
+
console.log(chalk12.gray(` - \uCD9C\uB825 \uB514\uB809\uD1A0\uB9AC: ${result.outputDir}`));
|
|
5309
|
+
console.log(chalk12.gray(` - \uC0DD\uC131\uB41C \uD30C\uC77C: ${result.files.length}\uAC1C`));
|
|
5310
|
+
console.log(chalk12.gray(` - \uCE74\uD14C\uACE0\uB9AC: ${result.stats.categoriesPublished}\uAC1C`));
|
|
5311
|
+
console.log(chalk12.gray(` - \uAC80\uC0C9 \uC778\uB371\uC2A4: ${result.stats.searchIndexSize}\uAC1C \uD56D\uBAA9`));
|
|
3966
5312
|
} else {
|
|
3967
|
-
console.log(
|
|
5313
|
+
console.log(chalk12.red(`
|
|
3968
5314
|
\u2717 \uBC30\uCE58 \uC2E4\uD328`));
|
|
3969
5315
|
for (const error of result.errors) {
|
|
3970
|
-
console.log(
|
|
5316
|
+
console.log(chalk12.red(` - ${error}`));
|
|
3971
5317
|
}
|
|
3972
5318
|
}
|
|
3973
5319
|
console.log();
|
|
@@ -3976,64 +5322,4 @@ registerSyncCommand(program);
|
|
|
3976
5322
|
registerTemplateCommand(program);
|
|
3977
5323
|
registerCheckCommand(program);
|
|
3978
5324
|
registerThemeCommand(program);
|
|
3979
|
-
async function getComponentInfo(name, category) {
|
|
3980
|
-
const localComponents = {
|
|
3981
|
-
button: {
|
|
3982
|
-
name: "button",
|
|
3983
|
-
type: "ui",
|
|
3984
|
-
description: "Primary button component",
|
|
3985
|
-
dependencies: ["@radix-ui/react-slot", "class-variance-authority", "clsx", "tailwind-merge"],
|
|
3986
|
-
files: [
|
|
3987
|
-
{
|
|
3988
|
-
path: "button.tsx",
|
|
3989
|
-
content: `import * as React from "react"
|
|
3990
|
-
import { Slot } from "@radix-ui/react-slot"
|
|
3991
|
-
import { cva, type VariantProps } from "class-variance-authority"
|
|
3992
|
-
import { cn } from "./utils"
|
|
3993
|
-
|
|
3994
|
-
const buttonVariants = cva(
|
|
3995
|
-
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
3996
|
-
{
|
|
3997
|
-
variants: {
|
|
3998
|
-
variant: {
|
|
3999
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
4000
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
4001
|
-
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
4002
|
-
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
4003
|
-
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
4004
|
-
link: "text-primary underline-offset-4 hover:underline",
|
|
4005
|
-
},
|
|
4006
|
-
size: {
|
|
4007
|
-
sm: "h-8 px-3 text-xs",
|
|
4008
|
-
default: "h-10 px-4 py-2",
|
|
4009
|
-
lg: "h-12 px-6 text-base",
|
|
4010
|
-
icon: "h-10 w-10",
|
|
4011
|
-
},
|
|
4012
|
-
},
|
|
4013
|
-
defaultVariants: { variant: "default", size: "default" },
|
|
4014
|
-
}
|
|
4015
|
-
)
|
|
4016
|
-
|
|
4017
|
-
export interface ButtonProps
|
|
4018
|
-
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
4019
|
-
VariantProps<typeof buttonVariants> {
|
|
4020
|
-
asChild?: boolean
|
|
4021
|
-
}
|
|
4022
|
-
|
|
4023
|
-
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
4024
|
-
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
4025
|
-
const Comp = asChild ? Slot : "button"
|
|
4026
|
-
return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
|
|
4027
|
-
}
|
|
4028
|
-
)
|
|
4029
|
-
Button.displayName = "Button"
|
|
4030
|
-
|
|
4031
|
-
export { Button, buttonVariants }
|
|
4032
|
-
`
|
|
4033
|
-
}
|
|
4034
|
-
]
|
|
4035
|
-
}
|
|
4036
|
-
};
|
|
4037
|
-
return localComponents[name] || null;
|
|
4038
|
-
}
|
|
4039
5325
|
program.parse();
|