@glass-ui-kit/cli 0.2.5 → 1.0.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/dist/index.js +410 -19
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command6 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
7
|
import chalk2 from "chalk";
|
|
@@ -122,8 +122,20 @@ function exists(filePath, baseDir = process.cwd()) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
// src/utils/get-project-info.ts
|
|
125
|
+
import path4 from "path";
|
|
125
126
|
import { spawn } from "child_process";
|
|
127
|
+
function resolveProjectRoot(cwdOption, cwd = process.cwd()) {
|
|
128
|
+
return cwdOption ? path4.resolve(cwd, cwdOption) : cwd;
|
|
129
|
+
}
|
|
130
|
+
function getLockfilePath(projectRoot = process.cwd(), existsAtPath = exists) {
|
|
131
|
+
if (existsAtPath("bun.lock", projectRoot)) return "bun.lock";
|
|
132
|
+
if (existsAtPath("bun.lockb", projectRoot)) return "bun.lockb";
|
|
133
|
+
if (existsAtPath("pnpm-lock.yaml", projectRoot)) return "pnpm-lock.yaml";
|
|
134
|
+
if (existsAtPath("yarn.lock", projectRoot)) return "yarn.lock";
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
126
137
|
async function getPackageManager(projectRoot = process.cwd()) {
|
|
138
|
+
if (exists("bun.lock", projectRoot)) return "bun";
|
|
127
139
|
if (exists("bun.lockb", projectRoot)) return "bun";
|
|
128
140
|
if (exists("pnpm-lock.yaml", projectRoot)) return "pnpm";
|
|
129
141
|
if (exists("yarn.lock", projectRoot)) return "yarn";
|
|
@@ -519,7 +531,7 @@ import chalk4 from "chalk";
|
|
|
519
531
|
import { Command as Command2 } from "commander";
|
|
520
532
|
|
|
521
533
|
// src/utils/registry.ts
|
|
522
|
-
import
|
|
534
|
+
import path5 from "path";
|
|
523
535
|
import os from "os";
|
|
524
536
|
import fs2 from "fs/promises";
|
|
525
537
|
|
|
@@ -553,8 +565,8 @@ var registryIndexSchema = z.array(registryItemSchema);
|
|
|
553
565
|
|
|
554
566
|
// src/utils/registry.ts
|
|
555
567
|
var DEFAULT_REGISTRY_URL = "https://ui-glass.vercel.app/registry.json";
|
|
556
|
-
var CACHE_DIR =
|
|
557
|
-
var CACHE_FILE =
|
|
568
|
+
var CACHE_DIR = path5.join(os.homedir(), ".glass-ui");
|
|
569
|
+
var CACHE_FILE = path5.join(CACHE_DIR, "registry.json");
|
|
558
570
|
var CACHE_TTL = 1e3 * 60 * 60 * 24;
|
|
559
571
|
function getRegistryUrl() {
|
|
560
572
|
return process.env.GLASS_UI_REGISTRY_URL || DEFAULT_REGISTRY_URL;
|
|
@@ -585,6 +597,12 @@ async function writeCache(data) {
|
|
|
585
597
|
} catch {
|
|
586
598
|
}
|
|
587
599
|
}
|
|
600
|
+
function getErrorMessage(error, fallback) {
|
|
601
|
+
if (error instanceof Error && error.message.length > 0) {
|
|
602
|
+
return error.message;
|
|
603
|
+
}
|
|
604
|
+
return fallback;
|
|
605
|
+
}
|
|
588
606
|
async function fetchRegistry() {
|
|
589
607
|
const cachedRegistry = await readCache();
|
|
590
608
|
if (cachedRegistry) {
|
|
@@ -595,7 +613,7 @@ async function fetchRegistry() {
|
|
|
595
613
|
try {
|
|
596
614
|
response = await fetch(url);
|
|
597
615
|
} catch (error) {
|
|
598
|
-
throw new Error("Network error: Unable to connect to registry.
|
|
616
|
+
throw new Error(getErrorMessage(error, "Network error: Unable to connect to registry."));
|
|
599
617
|
}
|
|
600
618
|
if (!response.ok) {
|
|
601
619
|
throw new Error(`Registry unavailable. URL: ${url} (Status: ${response.status})`);
|
|
@@ -603,15 +621,14 @@ async function fetchRegistry() {
|
|
|
603
621
|
let data;
|
|
604
622
|
try {
|
|
605
623
|
data = await response.json();
|
|
606
|
-
} catch {
|
|
607
|
-
throw new Error("Invalid response: Registry returned non-JSON data.");
|
|
624
|
+
} catch (error) {
|
|
625
|
+
throw new Error(getErrorMessage(error, "Invalid response: Registry returned non-JSON data."));
|
|
608
626
|
}
|
|
609
627
|
const parsed = registryIndexSchema.safeParse(data);
|
|
610
628
|
if (!parsed.success) {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
);
|
|
629
|
+
const issue = parsed.error.issues[0];
|
|
630
|
+
const location = issue?.path.length ? issue.path.join(".") : "registry";
|
|
631
|
+
throw new Error(`${issue?.message ?? "Schema validation failed"}: ${location}`);
|
|
615
632
|
}
|
|
616
633
|
await writeCache(parsed.data);
|
|
617
634
|
return parsed.data;
|
|
@@ -697,7 +714,7 @@ function resolveTargetDir(config, hasSrc, explicitPath) {
|
|
|
697
714
|
}
|
|
698
715
|
|
|
699
716
|
// src/utils/add/planner.ts
|
|
700
|
-
import
|
|
717
|
+
import path6 from "path";
|
|
701
718
|
|
|
702
719
|
// src/utils/transformers.ts
|
|
703
720
|
function transformImports(content, config) {
|
|
@@ -725,8 +742,8 @@ function buildWritePlan(items, config, hasSrc, options) {
|
|
|
725
742
|
const targetDir = resolveTargetDir(config, hasSrc, options.path);
|
|
726
743
|
return items.flatMap(
|
|
727
744
|
(item) => item.files.filter((file) => Boolean(file.content)).map((file) => {
|
|
728
|
-
const fileName =
|
|
729
|
-
const filePath =
|
|
745
|
+
const fileName = path6.basename(file.path);
|
|
746
|
+
const filePath = path6.join(targetDir, fileName);
|
|
730
747
|
return {
|
|
731
748
|
filePath,
|
|
732
749
|
content: transformImports(file.content || "", config),
|
|
@@ -737,7 +754,7 @@ function buildWritePlan(items, config, hasSrc, options) {
|
|
|
737
754
|
}
|
|
738
755
|
|
|
739
756
|
// src/utils/add/run-add.ts
|
|
740
|
-
import
|
|
757
|
+
import path7 from "path";
|
|
741
758
|
import chalk3 from "chalk";
|
|
742
759
|
var defaultRuntime2 = {
|
|
743
760
|
cwd: () => process.cwd(),
|
|
@@ -752,11 +769,11 @@ var defaultRuntime2 = {
|
|
|
752
769
|
function buildMissingComponentsMessage(names) {
|
|
753
770
|
return `Components not found: ${names.join(", ")}.`;
|
|
754
771
|
}
|
|
755
|
-
function
|
|
756
|
-
return cwdOption ?
|
|
772
|
+
function resolveProjectRoot2(cwdOption, cwd) {
|
|
773
|
+
return cwdOption ? path7.resolve(cwd, cwdOption) : cwd;
|
|
757
774
|
}
|
|
758
775
|
async function runAddCommand(componentNames = [], options = {}, runtime = defaultRuntime2) {
|
|
759
|
-
const projectRoot =
|
|
776
|
+
const projectRoot = resolveProjectRoot2(options.cwd, runtime.cwd?.() ?? process.cwd());
|
|
760
777
|
if (options.depsOnly && options.install === false) {
|
|
761
778
|
throw new Error("invalid-install-combination");
|
|
762
779
|
}
|
|
@@ -878,9 +895,383 @@ function createAddAction(deps = {
|
|
|
878
895
|
}
|
|
879
896
|
var add = new Command2().name("add").description("Add one or more components to your project").argument("[components...]", "The components to add").option("--all", "Add all available components").option("--overwrite", "Replace existing component files").option("--path <dir>", "Use a custom output directory").option("--no-install", "Skip dependency installation").option("--deps-only", "Install dependencies without writing component files").option("--cwd <path>", "Run the command against another project directory").action(createAddAction());
|
|
880
897
|
|
|
898
|
+
// src/commands/list.ts
|
|
899
|
+
import chalk5 from "chalk";
|
|
900
|
+
import { Command as Command3 } from "commander";
|
|
901
|
+
|
|
902
|
+
// src/utils/list/run-list.ts
|
|
903
|
+
var defaultRuntime3 = {
|
|
904
|
+
fetchRegistry
|
|
905
|
+
};
|
|
906
|
+
async function runListCommand(options = {}, runtime = defaultRuntime3) {
|
|
907
|
+
const registry = await runtime.fetchRegistry();
|
|
908
|
+
if (options.json) {
|
|
909
|
+
return JSON.stringify(registry, null, 2);
|
|
910
|
+
}
|
|
911
|
+
return registry.map((item) => item.name).join("\n");
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// src/commands/list.ts
|
|
915
|
+
async function runListCommand2(options = {}, runtime = defaultRuntime3) {
|
|
916
|
+
return runListCommand(options, runtime);
|
|
917
|
+
}
|
|
918
|
+
function createListAction(deps = {
|
|
919
|
+
runListCommand: runListCommand2,
|
|
920
|
+
error: console.error,
|
|
921
|
+
log: console.log,
|
|
922
|
+
exit: process.exit
|
|
923
|
+
}) {
|
|
924
|
+
return async (options = {}) => {
|
|
925
|
+
try {
|
|
926
|
+
const output = await deps.runListCommand({ json: options.json === true });
|
|
927
|
+
if (output.length > 0) {
|
|
928
|
+
deps.log(output);
|
|
929
|
+
}
|
|
930
|
+
} catch (error) {
|
|
931
|
+
deps.error(chalk5.red("\nList failed:"));
|
|
932
|
+
if (error instanceof Error) {
|
|
933
|
+
deps.error(chalk5.gray(error.message));
|
|
934
|
+
} else {
|
|
935
|
+
deps.error(chalk5.gray(String(error)));
|
|
936
|
+
}
|
|
937
|
+
deps.exit(1);
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
var list = new Command3().name("list").description("List available components from the registry").option("--json", "Output the validated registry payload as JSON", false).action(createListAction());
|
|
942
|
+
|
|
943
|
+
// src/commands/info.ts
|
|
944
|
+
import chalk6 from "chalk";
|
|
945
|
+
import { Command as Command4 } from "commander";
|
|
946
|
+
|
|
947
|
+
// src/utils/info/format-info.ts
|
|
948
|
+
function formatDependencySection(label, values) {
|
|
949
|
+
return `${label}: ${values && values.length > 0 ? values.join(", ") : "None"}`;
|
|
950
|
+
}
|
|
951
|
+
function formatInfo(item) {
|
|
952
|
+
const lines = [
|
|
953
|
+
`Name: ${item.name}`,
|
|
954
|
+
`Type: ${item.type}`,
|
|
955
|
+
"Files:",
|
|
956
|
+
...item.files.map((file) => `- ${file.path} (${file.type})`),
|
|
957
|
+
formatDependencySection("Dependencies", item.dependencies),
|
|
958
|
+
formatDependencySection("Dev Dependencies", item.devDependencies),
|
|
959
|
+
formatDependencySection("Registry Dependencies", item.registryDependencies)
|
|
960
|
+
];
|
|
961
|
+
if (item.meta?.requiresBlur !== void 0) {
|
|
962
|
+
lines.push(`Requires Blur: ${item.meta.requiresBlur}`);
|
|
963
|
+
}
|
|
964
|
+
return lines.join("\n");
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// src/utils/info/run-info.ts
|
|
968
|
+
var defaultRuntime4 = {
|
|
969
|
+
fetchRegistry,
|
|
970
|
+
getItem
|
|
971
|
+
};
|
|
972
|
+
async function runInfoCommand(componentName, options = {}, runtime = defaultRuntime4) {
|
|
973
|
+
const registry = await runtime.fetchRegistry();
|
|
974
|
+
const item = runtime.getItem(registry, componentName);
|
|
975
|
+
if (!item) {
|
|
976
|
+
throw new Error(`Component not found: "${componentName}"`);
|
|
977
|
+
}
|
|
978
|
+
if (options.json) {
|
|
979
|
+
return JSON.stringify(item, null, 2);
|
|
980
|
+
}
|
|
981
|
+
return formatInfo(item);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/commands/info.ts
|
|
985
|
+
async function runInfoCommand2(componentName, options = {}, runtime = defaultRuntime4) {
|
|
986
|
+
return runInfoCommand(componentName, options, runtime);
|
|
987
|
+
}
|
|
988
|
+
function createInfoAction(deps = {
|
|
989
|
+
runInfoCommand: runInfoCommand2,
|
|
990
|
+
error: console.error,
|
|
991
|
+
log: console.log,
|
|
992
|
+
exit: process.exit
|
|
993
|
+
}) {
|
|
994
|
+
return async (componentName, options = {}) => {
|
|
995
|
+
try {
|
|
996
|
+
const output = await deps.runInfoCommand(componentName, { json: options.json === true });
|
|
997
|
+
if (output.length > 0) {
|
|
998
|
+
deps.log(output);
|
|
999
|
+
}
|
|
1000
|
+
} catch (error) {
|
|
1001
|
+
deps.error(chalk6.red("\nInfo failed:"));
|
|
1002
|
+
if (error instanceof Error) {
|
|
1003
|
+
deps.error(chalk6.gray(error.message));
|
|
1004
|
+
} else {
|
|
1005
|
+
deps.error(chalk6.gray(String(error)));
|
|
1006
|
+
}
|
|
1007
|
+
deps.exit(1);
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
var info = new Command4().name("info").description("Show details for a single registry component").argument("<component>", "The exact component name to inspect").option("--json", "Output the validated registry item as JSON", false).action(createInfoAction());
|
|
1012
|
+
|
|
1013
|
+
// src/commands/doctor.ts
|
|
1014
|
+
import chalk7 from "chalk";
|
|
1015
|
+
import { Command as Command5 } from "commander";
|
|
1016
|
+
|
|
1017
|
+
// src/utils/doctor/format-doctor.ts
|
|
1018
|
+
function formatCheck(check) {
|
|
1019
|
+
const icon = check.status === "ok" ? "\u2713" : check.status === "warn" ? "!" : "\u2716";
|
|
1020
|
+
const lines = [`${icon} ${check.id} \u2014 ${check.summary}`];
|
|
1021
|
+
if (check.detail) {
|
|
1022
|
+
lines.push(` Next step: ${check.detail}`);
|
|
1023
|
+
}
|
|
1024
|
+
return lines.join("\n");
|
|
1025
|
+
}
|
|
1026
|
+
function formatDoctorReport(report) {
|
|
1027
|
+
const aliasLine = report.config.aliases ? `- Aliases: components=${report.config.aliases.components}, utils=${report.config.aliases.utils}` : "- Aliases: missing";
|
|
1028
|
+
return [
|
|
1029
|
+
"Glass UI Doctor",
|
|
1030
|
+
`Project root: ${report.projectRoot}`,
|
|
1031
|
+
`Init readiness: ${report.readiness.init ? "ready" : "not ready"}`,
|
|
1032
|
+
`Add readiness: ${report.readiness.add ? "ready" : "not ready"}`,
|
|
1033
|
+
"",
|
|
1034
|
+
"Detected state:",
|
|
1035
|
+
`- Framework: ${report.framework.value} (${report.framework.source})`,
|
|
1036
|
+
`- Package manager: ${report.packageManager.value} (${report.packageManager.source})`,
|
|
1037
|
+
`- Config: ${report.config.path} (${report.config.source})`,
|
|
1038
|
+
`- CSS: ${report.css.path ?? "unresolved"} (${report.css.source}, ${report.css.exists ? "exists" : "missing"})`,
|
|
1039
|
+
aliasLine,
|
|
1040
|
+
"",
|
|
1041
|
+
"Checks:",
|
|
1042
|
+
...report.checks.map(formatCheck)
|
|
1043
|
+
].join("\n");
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// src/utils/doctor/inspect-project.ts
|
|
1047
|
+
import { z as z2 } from "zod";
|
|
1048
|
+
var configSchema = z2.object({
|
|
1049
|
+
framework: z2.enum(["react", "next", "vite", "astro", "remix", "unknown"]),
|
|
1050
|
+
style: z2.string(),
|
|
1051
|
+
css: z2.string().min(1),
|
|
1052
|
+
aliases: z2.object({
|
|
1053
|
+
components: z2.string().min(1),
|
|
1054
|
+
utils: z2.string().min(1)
|
|
1055
|
+
})
|
|
1056
|
+
});
|
|
1057
|
+
function buildChecks(report) {
|
|
1058
|
+
const checks = [];
|
|
1059
|
+
if (report.config.source === "detected") {
|
|
1060
|
+
checks.push({ id: "config", status: "ok", summary: "Found valid glass.config.json." });
|
|
1061
|
+
} else if (report.config.source === "missing") {
|
|
1062
|
+
checks.push({
|
|
1063
|
+
id: "config",
|
|
1064
|
+
status: "error",
|
|
1065
|
+
summary: "glass.config.json was not found.",
|
|
1066
|
+
detail: "Run `glass-ui init` in this project before running `glass-ui add`."
|
|
1067
|
+
});
|
|
1068
|
+
} else {
|
|
1069
|
+
checks.push({
|
|
1070
|
+
id: "config",
|
|
1071
|
+
status: "error",
|
|
1072
|
+
summary: "glass.config.json is invalid.",
|
|
1073
|
+
detail: report.config.error ?? "Fix the config JSON and try doctor again."
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
if (report.framework.source === "detected") {
|
|
1077
|
+
checks.push({
|
|
1078
|
+
id: "framework",
|
|
1079
|
+
status: "ok",
|
|
1080
|
+
summary: `Detected framework: ${report.framework.value}.`
|
|
1081
|
+
});
|
|
1082
|
+
} else {
|
|
1083
|
+
checks.push({
|
|
1084
|
+
id: "framework",
|
|
1085
|
+
status: "warn",
|
|
1086
|
+
summary: `Could not confidently detect the framework; using ${report.framework.value}.`,
|
|
1087
|
+
detail: "Check package.json dependencies or pass an explicit framework during `glass-ui init`."
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
if (report.packageManager.source === "detected") {
|
|
1091
|
+
checks.push({
|
|
1092
|
+
id: "package-manager",
|
|
1093
|
+
status: "ok",
|
|
1094
|
+
summary: `Detected package manager: ${report.packageManager.value}.`
|
|
1095
|
+
});
|
|
1096
|
+
} else {
|
|
1097
|
+
checks.push({
|
|
1098
|
+
id: "package-manager",
|
|
1099
|
+
status: "warn",
|
|
1100
|
+
summary: `No lockfile found; defaulting to ${report.packageManager.value}.`,
|
|
1101
|
+
detail: "Create or commit the lockfile used by this project to confirm the package manager."
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
if (report.css.path && report.css.exists && report.css.source === "detected") {
|
|
1105
|
+
checks.push({
|
|
1106
|
+
id: "css",
|
|
1107
|
+
status: "ok",
|
|
1108
|
+
summary: `CSS file is available at ${report.css.path}.`
|
|
1109
|
+
});
|
|
1110
|
+
} else if (report.css.path && report.css.exists) {
|
|
1111
|
+
checks.push({
|
|
1112
|
+
id: "css",
|
|
1113
|
+
status: "warn",
|
|
1114
|
+
summary: `CSS path was inferred as ${report.css.path}.`,
|
|
1115
|
+
detail: "Save the CSS path in glass.config.json to confirm it explicitly."
|
|
1116
|
+
});
|
|
1117
|
+
} else if (report.css.path) {
|
|
1118
|
+
checks.push({
|
|
1119
|
+
id: "css",
|
|
1120
|
+
status: "warn",
|
|
1121
|
+
summary: `CSS file is missing at ${report.css.path}.`,
|
|
1122
|
+
detail: "Create the CSS file or update glass.config.json to point at the correct path."
|
|
1123
|
+
});
|
|
1124
|
+
} else {
|
|
1125
|
+
checks.push({
|
|
1126
|
+
id: "css",
|
|
1127
|
+
status: "warn",
|
|
1128
|
+
summary: "Could not resolve a CSS file path.",
|
|
1129
|
+
detail: "Set the css field in glass.config.json or rerun `glass-ui init`."
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
if (report.config.aliases) {
|
|
1133
|
+
checks.push({
|
|
1134
|
+
id: "aliases",
|
|
1135
|
+
status: "ok",
|
|
1136
|
+
summary: "Detected components and utils aliases."
|
|
1137
|
+
});
|
|
1138
|
+
} else {
|
|
1139
|
+
checks.push({
|
|
1140
|
+
id: "aliases",
|
|
1141
|
+
status: "error",
|
|
1142
|
+
summary: "Components and utils aliases are missing.",
|
|
1143
|
+
detail: "Save both aliases in glass.config.json so generated imports resolve correctly."
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
if (report.readiness.add) {
|
|
1147
|
+
checks.push({ id: "add-readiness", status: "ok", summary: "Project is ready for add." });
|
|
1148
|
+
} else {
|
|
1149
|
+
checks.push({
|
|
1150
|
+
id: "add-readiness",
|
|
1151
|
+
status: "error",
|
|
1152
|
+
summary: "Project is not ready for add.",
|
|
1153
|
+
detail: "Create a valid glass.config.json with aliases before adding components."
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
return checks;
|
|
1157
|
+
}
|
|
1158
|
+
async function inspectProject(options = {}, runtime) {
|
|
1159
|
+
const projectRoot = resolveProjectRoot(options.cwd, runtime.cwd());
|
|
1160
|
+
if (!runtime.exists(".", projectRoot)) {
|
|
1161
|
+
throw new Error(
|
|
1162
|
+
`Could not inspect directory "${projectRoot}": path does not exist or is not accessible.`
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
const hasPackageJson = runtime.exists("package.json", projectRoot);
|
|
1166
|
+
const frameworkValue = await runtime.getFramework(projectRoot);
|
|
1167
|
+
const frameworkSource = hasPackageJson && frameworkValue !== "unknown" ? "detected" : "inferred";
|
|
1168
|
+
const packageManagerValue = await runtime.getPackageManager(projectRoot);
|
|
1169
|
+
const packageManagerSource = getLockfilePath(projectRoot, runtime.exists) ? "detected" : "inferred";
|
|
1170
|
+
let config = {
|
|
1171
|
+
path: "glass.config.json",
|
|
1172
|
+
source: "missing"
|
|
1173
|
+
};
|
|
1174
|
+
if (runtime.exists("glass.config.json", projectRoot)) {
|
|
1175
|
+
try {
|
|
1176
|
+
const parsed = configSchema.parse(
|
|
1177
|
+
JSON.parse(await runtime.readFile("glass.config.json", projectRoot))
|
|
1178
|
+
);
|
|
1179
|
+
config = {
|
|
1180
|
+
path: "glass.config.json",
|
|
1181
|
+
source: "detected",
|
|
1182
|
+
css: parsed.css,
|
|
1183
|
+
aliases: parsed.aliases
|
|
1184
|
+
};
|
|
1185
|
+
} catch (error) {
|
|
1186
|
+
config = {
|
|
1187
|
+
path: "glass.config.json",
|
|
1188
|
+
source: "invalid",
|
|
1189
|
+
error: error instanceof Error ? `Invalid config: ${error.message}` : "Invalid config."
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
const cssPath = config.css ?? runtime.getCssPath(frameworkValue, projectRoot);
|
|
1194
|
+
const cssSource = config.css ? "detected" : cssPath ? "inferred" : "missing";
|
|
1195
|
+
const cssExists = cssPath ? runtime.exists(cssPath, projectRoot) : false;
|
|
1196
|
+
const readiness = {
|
|
1197
|
+
init: true,
|
|
1198
|
+
add: config.source === "detected" && Boolean(config.aliases?.components) && Boolean(config.aliases?.utils)
|
|
1199
|
+
};
|
|
1200
|
+
const reportWithoutChecks = {
|
|
1201
|
+
projectRoot,
|
|
1202
|
+
framework: { value: frameworkValue, source: frameworkSource },
|
|
1203
|
+
packageManager: { value: packageManagerValue, source: packageManagerSource },
|
|
1204
|
+
config,
|
|
1205
|
+
css: {
|
|
1206
|
+
path: cssPath,
|
|
1207
|
+
exists: cssExists,
|
|
1208
|
+
source: cssSource
|
|
1209
|
+
},
|
|
1210
|
+
readiness
|
|
1211
|
+
};
|
|
1212
|
+
return {
|
|
1213
|
+
...reportWithoutChecks,
|
|
1214
|
+
checks: buildChecks(reportWithoutChecks)
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
// src/utils/doctor/run-doctor.ts
|
|
1219
|
+
var defaultRuntime5 = {
|
|
1220
|
+
cwd: () => process.cwd(),
|
|
1221
|
+
exists,
|
|
1222
|
+
readFile,
|
|
1223
|
+
writeFile,
|
|
1224
|
+
getFramework,
|
|
1225
|
+
getPackageManager,
|
|
1226
|
+
getCssPath,
|
|
1227
|
+
installDependencies,
|
|
1228
|
+
inspectProject,
|
|
1229
|
+
formatDoctorReport
|
|
1230
|
+
};
|
|
1231
|
+
async function runDoctorCommand(options = {}, runtime = defaultRuntime5) {
|
|
1232
|
+
const resolvedRuntime = { ...defaultRuntime5, ...runtime };
|
|
1233
|
+
const report = await resolvedRuntime.inspectProject(options, resolvedRuntime);
|
|
1234
|
+
if (options.json) {
|
|
1235
|
+
return JSON.stringify(report, null, 2);
|
|
1236
|
+
}
|
|
1237
|
+
return resolvedRuntime.formatDoctorReport(report);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
// src/commands/doctor.ts
|
|
1241
|
+
async function runDoctorCommand2(options = {}, runtime = defaultRuntime5) {
|
|
1242
|
+
return runDoctorCommand(options, runtime);
|
|
1243
|
+
}
|
|
1244
|
+
function createDoctorAction(deps = {
|
|
1245
|
+
runDoctorCommand: runDoctorCommand2,
|
|
1246
|
+
error: console.error,
|
|
1247
|
+
log: console.log,
|
|
1248
|
+
exit: process.exit
|
|
1249
|
+
}) {
|
|
1250
|
+
return async (options = {}) => {
|
|
1251
|
+
try {
|
|
1252
|
+
const output = await deps.runDoctorCommand({ cwd: options.cwd, json: options.json === true });
|
|
1253
|
+
if (output.length > 0) {
|
|
1254
|
+
deps.log(output);
|
|
1255
|
+
}
|
|
1256
|
+
} catch (error) {
|
|
1257
|
+
deps.error(chalk7.red("\nDoctor failed:"));
|
|
1258
|
+
if (error instanceof Error) {
|
|
1259
|
+
deps.error(chalk7.gray(error.message));
|
|
1260
|
+
} else {
|
|
1261
|
+
deps.error(chalk7.gray(String(error)));
|
|
1262
|
+
}
|
|
1263
|
+
deps.exit(1);
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
var doctor = new Command5().name("doctor").description("Diagnose whether a project is ready to use the CLI").option("--cwd <path>", "Run the command against another project directory").option("--json", "Output the diagnostic report as JSON", false).action(createDoctorAction());
|
|
1268
|
+
|
|
881
1269
|
// src/index.ts
|
|
882
|
-
var program = new
|
|
1270
|
+
var program = new Command6();
|
|
883
1271
|
program.name("glass-ui").description("The Glass UI CLI - Add glassmorphism components to your app").version("0.2.5");
|
|
884
1272
|
program.addCommand(init);
|
|
885
1273
|
program.addCommand(add);
|
|
1274
|
+
program.addCommand(list);
|
|
1275
|
+
program.addCommand(info);
|
|
1276
|
+
program.addCommand(doctor);
|
|
886
1277
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glass-ui-kit/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "The official CLI for Glass UI. Add glassmorphism components to your React projects in seconds.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"glassmorphism",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"directory": "packages/cli"
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
|
-
"author": "
|
|
23
|
+
"author": "jntellez (https://jntellez.dev)",
|
|
24
24
|
"type": "module",
|
|
25
25
|
"bin": {
|
|
26
26
|
"glass-ui": "./dist/index.js"
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"vitest": "^3.2.4",
|
|
45
45
|
"tsup": "^8.0.1",
|
|
46
46
|
"typescript": "^5.3.3",
|
|
47
|
-
"@glass-ui-kit/
|
|
48
|
-
"@glass-ui-kit/
|
|
47
|
+
"@glass-ui-kit/tsconfig": "0.0.1",
|
|
48
|
+
"@glass-ui-kit/schema": "0.0.1"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|