@glass-ui-kit/cli 0.2.3 → 0.2.5
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/LICENSE +21 -0
- package/README.md +44 -44
- package/dist/index.js +561 -219
- package/package.json +60 -59
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Juan Tellez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
# @glass-ui-kit/cli
|
|
2
|
-
|
|
3
|
-
The official CLI for Glass UI. Add premium glassmorphism components to your React projects in seconds.
|
|
4
|
-
|
|
5
|
-
## init
|
|
6
|
-
|
|
7
|
-
Use the `init` command to initialize the project configuration.
|
|
8
|
-
|
|
9
|
-
The `init` command:
|
|
10
|
-
|
|
11
|
-
1. Creates a `glass.config.json` file.
|
|
12
|
-
2. Generates the `cn` utility at `src/lib/utils.ts`.
|
|
13
|
-
3. Installs necessary dependencies (`clsx`, `tailwind-merge`).
|
|
14
|
-
4. Injects Glass Physics variables into your global CSS.
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npx @glass-ui-kit/cli init
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## add
|
|
22
|
-
|
|
23
|
-
Use the `add` command to add components to your project.
|
|
24
|
-
The `add` command downloads the component source code and places it directly into your project.
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npx @glass-ui-kit/cli add [component]
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Example
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
npx @glass-ui-kit/cli add card
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Documentation
|
|
39
|
-
|
|
40
|
-
Visit [https://ui-glass.vercel.app](https://ui-glass.vercel.app) to view the registry and documentation.
|
|
41
|
-
|
|
42
|
-
## License
|
|
43
|
-
|
|
44
|
-
Licensed under the [MIT license](https://github.com/jntellez/glass-ui/blob/master/LICENSE).
|
|
1
|
+
# @glass-ui-kit/cli
|
|
2
|
+
|
|
3
|
+
The official CLI for Glass UI. Add premium glassmorphism components to your React projects in seconds.
|
|
4
|
+
|
|
5
|
+
## init
|
|
6
|
+
|
|
7
|
+
Use the `init` command to initialize the project configuration.
|
|
8
|
+
|
|
9
|
+
The `init` command:
|
|
10
|
+
|
|
11
|
+
1. Creates a `glass.config.json` file.
|
|
12
|
+
2. Generates the `cn` utility at `src/lib/utils.ts`.
|
|
13
|
+
3. Installs necessary dependencies (`clsx`, `tailwind-merge`).
|
|
14
|
+
4. Injects Glass Physics variables into your global CSS.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx @glass-ui-kit/cli init
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## add
|
|
22
|
+
|
|
23
|
+
Use the `add` command to add components to your project.
|
|
24
|
+
The `add` command downloads the component source code and places it directly into your project.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx @glass-ui-kit/cli add [component]
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Example
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx @glass-ui-kit/cli add card
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Documentation
|
|
39
|
+
|
|
40
|
+
Visit [https://ui-glass.vercel.app](https://ui-glass.vercel.app) to view the registry and documentation.
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
Licensed under the [MIT license](https://github.com/jntellez/glass-ui/blob/master/LICENSE).
|
package/dist/index.js
CHANGED
|
@@ -4,47 +4,140 @@
|
|
|
4
4
|
import { Command as Command3 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
|
-
import
|
|
7
|
+
import chalk2 from "chalk";
|
|
8
8
|
import { Command } from "commander";
|
|
9
|
+
|
|
10
|
+
// src/utils/init/options.ts
|
|
11
|
+
import path from "path";
|
|
12
|
+
var SUPPORTED_INIT_FRAMEWORKS = ["react", "vite", "next", "remix"];
|
|
13
|
+
function resolveInitOptions(options = {}, currentWorkingDirectory = process.cwd()) {
|
|
14
|
+
validateFrameworkOverride(options.framework);
|
|
15
|
+
return {
|
|
16
|
+
projectRoot: path.resolve(currentWorkingDirectory, options.cwd ?? "."),
|
|
17
|
+
cssOverride: options.css,
|
|
18
|
+
componentsAliasOverride: options.components,
|
|
19
|
+
utilsAliasOverride: options.utils,
|
|
20
|
+
frameworkOverride: options.framework,
|
|
21
|
+
force: options.force === true,
|
|
22
|
+
install: options.install !== false
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function validateFrameworkOverride(framework) {
|
|
26
|
+
if (framework === void 0) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (SUPPORTED_INIT_FRAMEWORKS.includes(framework)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Unsupported framework "${framework}". Supported values: ${SUPPORTED_INIT_FRAMEWORKS.join(", ")}.`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/utils/init/paths.ts
|
|
9
38
|
import path2 from "path";
|
|
39
|
+
function resolveInitPaths({
|
|
40
|
+
projectRoot,
|
|
41
|
+
hasSrc,
|
|
42
|
+
framework,
|
|
43
|
+
detectedCssPath,
|
|
44
|
+
cssOverride,
|
|
45
|
+
componentsAliasOverride,
|
|
46
|
+
utilsAliasOverride
|
|
47
|
+
}) {
|
|
48
|
+
let baseDir = hasSrc ? "src" : "";
|
|
49
|
+
if (framework === "remix") {
|
|
50
|
+
baseDir = "app";
|
|
51
|
+
}
|
|
52
|
+
let cssPath = cssOverride ?? detectedCssPath;
|
|
53
|
+
if (!cssPath) {
|
|
54
|
+
if (framework === "next") {
|
|
55
|
+
cssPath = hasSrc ? "src/app/globals.css" : "app/globals.css";
|
|
56
|
+
} else if (framework === "remix") {
|
|
57
|
+
cssPath = "app/app.css";
|
|
58
|
+
} else {
|
|
59
|
+
cssPath = hasSrc ? "src/index.css" : "index.css";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const defaultComponentsAlias = `${framework === "remix" ? "~" : "@"}/components/ui`;
|
|
63
|
+
const defaultUtilsAlias = `${framework === "remix" ? "~" : "@"}/lib/utils`;
|
|
64
|
+
const componentsAlias = componentsAliasOverride ?? defaultComponentsAlias;
|
|
65
|
+
const utilsAlias = utilsAliasOverride ?? defaultUtilsAlias;
|
|
66
|
+
const utilsRelativePath = resolveUtilsRelativePath(utilsAlias, baseDir);
|
|
67
|
+
const utilsPath = path2.join(projectRoot, utilsRelativePath);
|
|
68
|
+
const aliasPrefix = framework === "remix" ? "~" : "@";
|
|
69
|
+
return {
|
|
70
|
+
framework,
|
|
71
|
+
cssPath,
|
|
72
|
+
utilsRelativePath,
|
|
73
|
+
utilsPath,
|
|
74
|
+
aliasPrefix,
|
|
75
|
+
config: {
|
|
76
|
+
framework,
|
|
77
|
+
style: "default",
|
|
78
|
+
css: cssPath,
|
|
79
|
+
aliases: {
|
|
80
|
+
components: componentsAlias,
|
|
81
|
+
utils: utilsAlias
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function resolveUtilsRelativePath(utilsAlias, baseDir) {
|
|
87
|
+
const aliasBody = stripAliasPrefix(utilsAlias);
|
|
88
|
+
const relativePath = baseDir && !aliasBody.startsWith(`${baseDir}/`) ? path2.posix.join(baseDir, aliasBody) : aliasBody;
|
|
89
|
+
return path2.posix.extname(relativePath) ? relativePath : `${relativePath}.ts`;
|
|
90
|
+
}
|
|
91
|
+
function stripAliasPrefix(alias) {
|
|
92
|
+
return alias.replace(/^[@~]\//, "");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/utils/init/run-init.ts
|
|
96
|
+
import chalk from "chalk";
|
|
10
97
|
|
|
11
98
|
// src/utils/filesystem.ts
|
|
12
99
|
import fs from "fs";
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
100
|
+
import path3 from "path";
|
|
101
|
+
function resolveFromBaseDir(filePath, baseDir = process.cwd()) {
|
|
102
|
+
return path3.resolve(baseDir, filePath);
|
|
103
|
+
}
|
|
104
|
+
async function writeFile(filePath, content, baseDir = process.cwd()) {
|
|
105
|
+
const absolutePath = resolveFromBaseDir(filePath, baseDir);
|
|
106
|
+
const dir = path3.dirname(absolutePath);
|
|
17
107
|
if (!fs.existsSync(dir)) {
|
|
18
108
|
await fs.promises.mkdir(dir, { recursive: true });
|
|
19
109
|
}
|
|
20
110
|
await fs.promises.writeFile(absolutePath, content, "utf-8");
|
|
21
111
|
return absolutePath;
|
|
22
112
|
}
|
|
23
|
-
async function readFile(filePath) {
|
|
24
|
-
const absolutePath =
|
|
113
|
+
async function readFile(filePath, baseDir = process.cwd()) {
|
|
114
|
+
const absolutePath = resolveFromBaseDir(filePath, baseDir);
|
|
25
115
|
if (!fs.existsSync(absolutePath)) {
|
|
26
116
|
throw new Error(`File not found: ${filePath}`);
|
|
27
117
|
}
|
|
28
118
|
return await fs.promises.readFile(absolutePath, "utf-8");
|
|
29
119
|
}
|
|
30
|
-
function exists(filePath) {
|
|
31
|
-
return fs.existsSync(
|
|
120
|
+
function exists(filePath, baseDir = process.cwd()) {
|
|
121
|
+
return fs.existsSync(resolveFromBaseDir(filePath, baseDir));
|
|
32
122
|
}
|
|
33
123
|
|
|
34
124
|
// src/utils/get-project-info.ts
|
|
35
125
|
import { spawn } from "child_process";
|
|
36
|
-
async function getPackageManager() {
|
|
37
|
-
if (exists("bun.lockb")) return "bun";
|
|
38
|
-
if (exists("pnpm-lock.yaml")) return "pnpm";
|
|
39
|
-
if (exists("yarn.lock")) return "yarn";
|
|
126
|
+
async function getPackageManager(projectRoot = process.cwd()) {
|
|
127
|
+
if (exists("bun.lockb", projectRoot)) return "bun";
|
|
128
|
+
if (exists("pnpm-lock.yaml", projectRoot)) return "pnpm";
|
|
129
|
+
if (exists("yarn.lock", projectRoot)) return "yarn";
|
|
40
130
|
return "npm";
|
|
41
131
|
}
|
|
42
|
-
async function getFramework() {
|
|
43
|
-
if (!exists("package.json")) return "unknown";
|
|
132
|
+
async function getFramework(projectRoot = process.cwd()) {
|
|
133
|
+
if (!exists("package.json", projectRoot)) return "unknown";
|
|
44
134
|
try {
|
|
45
|
-
const content = await readFile("package.json");
|
|
135
|
+
const content = await readFile("package.json", projectRoot);
|
|
46
136
|
const pkg = JSON.parse(content);
|
|
47
137
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
138
|
+
if (deps["@remix-run/react"] || deps["@remix-run/dev"] || deps["@react-router/dev"] || deps["@react-router/node"]) {
|
|
139
|
+
return "remix";
|
|
140
|
+
}
|
|
48
141
|
if (deps["next"]) return "next";
|
|
49
142
|
if (deps["astro"]) return "astro";
|
|
50
143
|
if (deps["vite"]) return "vite";
|
|
@@ -53,23 +146,26 @@ async function getFramework() {
|
|
|
53
146
|
}
|
|
54
147
|
return "unknown";
|
|
55
148
|
}
|
|
56
|
-
function getCssPath(framework) {
|
|
149
|
+
function getCssPath(framework, projectRoot = process.cwd()) {
|
|
57
150
|
const paths = {
|
|
151
|
+
react: ["src/index.css", "src/main.css", "src/style.css", "index.css"],
|
|
58
152
|
next: ["app/globals.css", "src/app/globals.css", "styles/globals.css"],
|
|
59
153
|
vite: ["src/index.css", "src/main.css", "src/style.css"],
|
|
60
154
|
astro: ["src/styles/global.css", "src/global.css"],
|
|
155
|
+
remix: ["app/app.css", "app/tailwind.css", "app/globals.css", "app/styles/tailwind.css"],
|
|
61
156
|
unknown: ["src/index.css", "styles.css"]
|
|
62
157
|
};
|
|
63
158
|
for (const p of paths[framework] || []) {
|
|
64
|
-
if (exists(p)) return p;
|
|
159
|
+
if (exists(p, projectRoot)) return p;
|
|
65
160
|
}
|
|
66
161
|
return paths[framework]?.[0] || null;
|
|
67
162
|
}
|
|
68
|
-
async function installDependencies(deps, pm) {
|
|
163
|
+
async function installDependencies(deps, pm, projectRoot = process.cwd()) {
|
|
69
164
|
const installCmd = pm === "npm" ? "install" : "add";
|
|
70
165
|
console.log(`Running ${pm} ${installCmd}...`);
|
|
71
166
|
return new Promise((resolve, reject) => {
|
|
72
167
|
const child = spawn(pm, [installCmd, ...deps], {
|
|
168
|
+
cwd: projectRoot,
|
|
73
169
|
stdio: "inherit",
|
|
74
170
|
shell: true
|
|
75
171
|
});
|
|
@@ -184,74 +280,88 @@ body {
|
|
|
184
280
|
color: var(--foreground);
|
|
185
281
|
}
|
|
186
282
|
|
|
187
|
-
@
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
283
|
+
@utility glass {
|
|
284
|
+
background-color: var(--glass-bg);
|
|
285
|
+
border-width: 1px;
|
|
286
|
+
border-style: solid;
|
|
287
|
+
border-color: var(--glass-border);
|
|
288
|
+
backdrop-filter: blur(var(--glass-blur));
|
|
289
|
+
box-shadow: var(--glass-shadow);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
@utility glass-strong {
|
|
293
|
+
--glass-bg: var(--glass-bg-strong);
|
|
294
|
+
--glass-border: var(--glass-border-strong);
|
|
295
|
+
--glass-blur: var(--glass-blur-strong);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@utility glass-soft {
|
|
299
|
+
--glass-bg: var(--glass-bg-soft);
|
|
300
|
+
--glass-border: var(--glass-border-soft);
|
|
301
|
+
--glass-blur: var(--glass-blur-soft);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
@utility input-sm {
|
|
305
|
+
height: 1.5rem;
|
|
306
|
+
padding-left: 0.5rem;
|
|
307
|
+
padding-right: 0.5rem;
|
|
308
|
+
font-size: 0.75rem;
|
|
309
|
+
line-height: 1rem;
|
|
310
|
+
gap: 0.375rem;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
@utility btn-sm {
|
|
314
|
+
height: 1.5rem;
|
|
315
|
+
padding-left: 0.5rem;
|
|
316
|
+
padding-right: 0.5rem;
|
|
317
|
+
font-size: 0.75rem;
|
|
318
|
+
line-height: 1rem;
|
|
319
|
+
gap: 0.375rem;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
@utility input-md {
|
|
323
|
+
height: 2rem;
|
|
324
|
+
padding-top: 0.5rem;
|
|
325
|
+
padding-bottom: 0.5rem;
|
|
326
|
+
padding-left: 0.625rem;
|
|
327
|
+
padding-right: 0.625rem;
|
|
328
|
+
font-size: 0.875rem;
|
|
329
|
+
line-height: 1.25rem;
|
|
330
|
+
gap: 0.5rem;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
@utility btn-md {
|
|
334
|
+
height: 2rem;
|
|
335
|
+
padding-top: 0.5rem;
|
|
336
|
+
padding-bottom: 0.5rem;
|
|
337
|
+
padding-left: 0.625rem;
|
|
338
|
+
padding-right: 0.625rem;
|
|
339
|
+
font-size: 0.875rem;
|
|
340
|
+
line-height: 1.25rem;
|
|
341
|
+
gap: 0.5rem;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
@utility input-lg {
|
|
345
|
+
height: 2.5rem;
|
|
346
|
+
padding-left: 0.875rem;
|
|
347
|
+
padding-right: 0.875rem;
|
|
348
|
+
font-size: 1rem;
|
|
349
|
+
line-height: 1.5rem;
|
|
350
|
+
gap: 0.625rem;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
@utility btn-lg {
|
|
354
|
+
height: 2.5rem;
|
|
355
|
+
padding-left: 0.875rem;
|
|
356
|
+
padding-right: 0.875rem;
|
|
357
|
+
font-size: 1rem;
|
|
358
|
+
line-height: 1.5rem;
|
|
359
|
+
gap: 0.625rem;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
@utility btn-icon {
|
|
363
|
+
padding: 0;
|
|
364
|
+
aspect-ratio: 1 / 1;
|
|
255
365
|
}
|
|
256
366
|
`;
|
|
257
367
|
|
|
@@ -264,106 +374,152 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
264
374
|
}
|
|
265
375
|
`;
|
|
266
376
|
|
|
267
|
-
// src/
|
|
268
|
-
var
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
377
|
+
// src/utils/init/run-init.ts
|
|
378
|
+
var defaultRuntime = {
|
|
379
|
+
cwd: () => process.cwd(),
|
|
380
|
+
exists,
|
|
381
|
+
readFile,
|
|
382
|
+
writeFile,
|
|
383
|
+
getFramework,
|
|
384
|
+
getPackageManager,
|
|
385
|
+
getCssPath,
|
|
386
|
+
installDependencies,
|
|
387
|
+
log: console.log
|
|
388
|
+
};
|
|
389
|
+
async function runInitCommand(options = {}, runtime = defaultRuntime) {
|
|
390
|
+
const resolvedOptions = resolveInitOptions(options, runtime.cwd());
|
|
391
|
+
runtime.log(chalk.bold("\nInitializing Glass UI..."));
|
|
392
|
+
const framework = resolvedOptions.frameworkOverride ?? await runtime.getFramework(resolvedOptions.projectRoot);
|
|
393
|
+
const pm = await runtime.getPackageManager(resolvedOptions.projectRoot);
|
|
394
|
+
const configPath = "glass.config.json";
|
|
395
|
+
const hasSrc = runtime.exists("src", resolvedOptions.projectRoot);
|
|
396
|
+
const plan = resolveInitPaths({
|
|
397
|
+
projectRoot: resolvedOptions.projectRoot,
|
|
398
|
+
hasSrc,
|
|
399
|
+
framework,
|
|
400
|
+
detectedCssPath: runtime.getCssPath(framework, resolvedOptions.projectRoot),
|
|
401
|
+
cssOverride: resolvedOptions.cssOverride,
|
|
402
|
+
componentsAliasOverride: resolvedOptions.componentsAliasOverride,
|
|
403
|
+
utilsAliasOverride: resolvedOptions.utilsAliasOverride
|
|
404
|
+
});
|
|
405
|
+
const writes = [
|
|
406
|
+
{
|
|
407
|
+
filePath: configPath,
|
|
408
|
+
content: JSON.stringify(plan.config, null, 2),
|
|
409
|
+
label: "glass.config.json"
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
filePath: plan.utilsRelativePath,
|
|
413
|
+
content: UTILS_CN,
|
|
414
|
+
label: plan.utilsRelativePath
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
filePath: plan.cssPath,
|
|
418
|
+
content: `@import "tailwindcss";
|
|
419
|
+
|
|
420
|
+
${GLASS_BASE_STYLES}`,
|
|
421
|
+
label: plan.cssPath
|
|
312
422
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
} catch (e) {
|
|
423
|
+
];
|
|
424
|
+
for (const write of writes.slice(0, 2)) {
|
|
425
|
+
const alreadyExists = runtime.exists(write.filePath, resolvedOptions.projectRoot);
|
|
426
|
+
if (alreadyExists && !resolvedOptions.force) {
|
|
427
|
+
runtime.log(chalk.yellow(` Skipped ${write.label} (already exists)`));
|
|
428
|
+
continue;
|
|
321
429
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
430
|
+
await runtime.writeFile(write.filePath, write.content, resolvedOptions.projectRoot);
|
|
431
|
+
runtime.log(
|
|
432
|
+
alreadyExists ? chalk.green(` Replaced ${write.label}`) : chalk.green(` Created ${write.label}`)
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
const cssWrite = writes[2];
|
|
436
|
+
const cssAlreadyExists = runtime.exists(cssWrite.filePath, resolvedOptions.projectRoot);
|
|
437
|
+
if (!cssAlreadyExists) {
|
|
438
|
+
await runtime.writeFile(cssWrite.filePath, cssWrite.content, resolvedOptions.projectRoot);
|
|
439
|
+
runtime.log(chalk.green(` Created ${cssWrite.label}`));
|
|
440
|
+
} else if (resolvedOptions.force) {
|
|
441
|
+
await runtime.writeFile(cssWrite.filePath, cssWrite.content, resolvedOptions.projectRoot);
|
|
442
|
+
runtime.log(chalk.green(` Replaced ${cssWrite.label}`));
|
|
443
|
+
} else {
|
|
444
|
+
const existingCss = await runtime.readFile(cssWrite.filePath, resolvedOptions.projectRoot) ?? "";
|
|
445
|
+
if (existingCss.includes("--glass-bg")) {
|
|
446
|
+
runtime.log(chalk.yellow(` Skipped ${cssWrite.label} (already exists)`));
|
|
332
447
|
} else {
|
|
333
|
-
|
|
448
|
+
const updatedCss = `${existingCss.trimEnd()}
|
|
449
|
+
|
|
450
|
+
${GLASS_BASE_STYLES}
|
|
451
|
+
`;
|
|
452
|
+
await runtime.writeFile(cssWrite.filePath, updatedCss, resolvedOptions.projectRoot);
|
|
453
|
+
runtime.log(chalk.green(` Updated ${cssWrite.label} with Glass tokens`));
|
|
334
454
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
console.log(chalk.bold.green("\nSetup complete."));
|
|
343
|
-
console.log(`Try adding a component:
|
|
344
|
-
`);
|
|
345
|
-
console.log(
|
|
346
|
-
chalk.cyan(` ${runCommand} @glass-ui-kit/cli@latest add card`)
|
|
455
|
+
}
|
|
456
|
+
if (resolvedOptions.install) {
|
|
457
|
+
runtime.log(chalk.cyan(` Installing dependencies (clsx, tailwind-merge, lucide-react)...`));
|
|
458
|
+
await runtime.installDependencies(
|
|
459
|
+
["clsx", "tailwind-merge", "lucide-react"],
|
|
460
|
+
pm,
|
|
461
|
+
resolvedOptions.projectRoot
|
|
347
462
|
);
|
|
348
|
-
|
|
463
|
+
} else {
|
|
464
|
+
runtime.log(chalk.gray(" Skipped dependency installation (--no-install)."));
|
|
465
|
+
}
|
|
466
|
+
const runCommand = pm === "bun" ? "bunx" : pm === "pnpm" ? "pnpm dlx" : "npx";
|
|
467
|
+
runtime.log(chalk.bold.green("\nSetup complete."));
|
|
468
|
+
runtime.log(chalk.gray(` Project root: ${resolvedOptions.projectRoot}`));
|
|
469
|
+
runtime.log(chalk.gray(` Framework: ${plan.framework}`));
|
|
470
|
+
runtime.log("Try adding a component:\n");
|
|
471
|
+
runtime.log(chalk.cyan(` ${runCommand} @glass-ui-kit/cli@latest add card`));
|
|
472
|
+
runtime.log("");
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// src/commands/init.ts
|
|
476
|
+
var InitCommandError = class extends Error {
|
|
477
|
+
};
|
|
478
|
+
async function runInitCommand2(options = {}, runtime = defaultRuntime) {
|
|
479
|
+
try {
|
|
480
|
+
await runInitCommand(options, runtime);
|
|
349
481
|
} catch (error) {
|
|
350
|
-
console.error(chalk.red("\nInitialization failed:"));
|
|
351
482
|
if (error instanceof Error) {
|
|
352
|
-
|
|
353
|
-
} else {
|
|
354
|
-
console.error(chalk.gray(String(error)));
|
|
483
|
+
throw new InitCommandError(error.message);
|
|
355
484
|
}
|
|
356
|
-
|
|
485
|
+
throw new InitCommandError(String(error));
|
|
357
486
|
}
|
|
358
|
-
}
|
|
487
|
+
}
|
|
488
|
+
function createInitAction(deps = {
|
|
489
|
+
runInitCommand: runInitCommand2,
|
|
490
|
+
error: console.error,
|
|
491
|
+
exit: process.exit
|
|
492
|
+
}) {
|
|
493
|
+
return async (options = {}) => {
|
|
494
|
+
try {
|
|
495
|
+
await deps.runInitCommand({
|
|
496
|
+
cwd: options.cwd,
|
|
497
|
+
css: options.css,
|
|
498
|
+
components: options.components,
|
|
499
|
+
utils: options.utils,
|
|
500
|
+
framework: options.framework,
|
|
501
|
+
force: options.force === true,
|
|
502
|
+
install: options.install
|
|
503
|
+
});
|
|
504
|
+
} catch (error) {
|
|
505
|
+
deps.error(chalk2.red("\nInitialization failed:"));
|
|
506
|
+
if (error instanceof Error) {
|
|
507
|
+
deps.error(chalk2.gray(error.message));
|
|
508
|
+
} else {
|
|
509
|
+
deps.error(chalk2.gray(String(error)));
|
|
510
|
+
}
|
|
511
|
+
deps.exit(1);
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
var init = new Command().name("init").description("Initialize configuration and dependencies").option("-y, --yes", "Skip confirmation prompt", false).option("--cwd <path>", "Run the command against another project directory").option("--css <path>", "Use a custom CSS file instead of autodetecting one").option("--components <alias>", "Set the components alias saved in glass.config.json").option("--utils <alias>", "Set the utils alias saved in glass.config.json").option("--framework <name>", "Force the framework instead of autodetecting it").option("--force", "Overwrite generated files if they already exist").option("--no-install", "Skip dependency installation").action(createInitAction());
|
|
359
516
|
|
|
360
517
|
// src/commands/add.ts
|
|
361
|
-
import
|
|
518
|
+
import chalk4 from "chalk";
|
|
362
519
|
import { Command as Command2 } from "commander";
|
|
363
|
-
import path4 from "path";
|
|
364
520
|
|
|
365
521
|
// src/utils/registry.ts
|
|
366
|
-
import
|
|
522
|
+
import path4 from "path";
|
|
367
523
|
import os from "os";
|
|
368
524
|
import fs2 from "fs/promises";
|
|
369
525
|
|
|
@@ -397,8 +553,8 @@ var registryIndexSchema = z.array(registryItemSchema);
|
|
|
397
553
|
|
|
398
554
|
// src/utils/registry.ts
|
|
399
555
|
var DEFAULT_REGISTRY_URL = "https://ui-glass.vercel.app/registry.json";
|
|
400
|
-
var CACHE_DIR =
|
|
401
|
-
var CACHE_FILE =
|
|
556
|
+
var CACHE_DIR = path4.join(os.homedir(), ".glass-ui");
|
|
557
|
+
var CACHE_FILE = path4.join(CACHE_DIR, "registry.json");
|
|
402
558
|
var CACHE_TTL = 1e3 * 60 * 60 * 24;
|
|
403
559
|
function getRegistryUrl() {
|
|
404
560
|
return process.env.GLASS_UI_REGISTRY_URL || DEFAULT_REGISTRY_URL;
|
|
@@ -439,14 +595,10 @@ async function fetchRegistry() {
|
|
|
439
595
|
try {
|
|
440
596
|
response = await fetch(url);
|
|
441
597
|
} catch (error) {
|
|
442
|
-
throw new Error(
|
|
443
|
-
"Network error: Unable to connect to registry. Check your internet connection."
|
|
444
|
-
);
|
|
598
|
+
throw new Error("Network error: Unable to connect to registry. Check your internet connection.");
|
|
445
599
|
}
|
|
446
600
|
if (!response.ok) {
|
|
447
|
-
throw new Error(
|
|
448
|
-
`Registry unavailable. URL: ${url} (Status: ${response.status})`
|
|
449
|
-
);
|
|
601
|
+
throw new Error(`Registry unavailable. URL: ${url} (Status: ${response.status})`);
|
|
450
602
|
}
|
|
451
603
|
let data;
|
|
452
604
|
try {
|
|
@@ -467,6 +619,85 @@ async function fetchRegistry() {
|
|
|
467
619
|
function getItem(registry, name) {
|
|
468
620
|
return registry.find((item) => item.name === name);
|
|
469
621
|
}
|
|
622
|
+
function getItems(registry, names) {
|
|
623
|
+
const items = [];
|
|
624
|
+
const missing = [];
|
|
625
|
+
for (const name of names) {
|
|
626
|
+
const item = getItem(registry, name);
|
|
627
|
+
if (item) {
|
|
628
|
+
items.push(item);
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
missing.push(name);
|
|
632
|
+
}
|
|
633
|
+
return { items, missing };
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// src/utils/add/selection.ts
|
|
637
|
+
function dedupeNames(names) {
|
|
638
|
+
const uniqueNames = [];
|
|
639
|
+
const seen = /* @__PURE__ */ new Set();
|
|
640
|
+
for (const name of names) {
|
|
641
|
+
if (seen.has(name)) {
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
seen.add(name);
|
|
645
|
+
uniqueNames.push(name);
|
|
646
|
+
}
|
|
647
|
+
return uniqueNames;
|
|
648
|
+
}
|
|
649
|
+
function resolveAddSelection(registry, requestedNames, selectAll) {
|
|
650
|
+
if (selectAll && requestedNames.length > 0) {
|
|
651
|
+
return { ok: false, reason: "invalid-combination" };
|
|
652
|
+
}
|
|
653
|
+
if (selectAll) {
|
|
654
|
+
return { ok: true, items: registry };
|
|
655
|
+
}
|
|
656
|
+
const uniqueRequestedNames = dedupeNames(requestedNames);
|
|
657
|
+
if (uniqueRequestedNames.length === 0) {
|
|
658
|
+
return { ok: false, reason: "empty-selection" };
|
|
659
|
+
}
|
|
660
|
+
const { items, missing } = getItems(registry, uniqueRequestedNames);
|
|
661
|
+
if (missing.length > 0) {
|
|
662
|
+
return { ok: false, reason: "missing-components", names: missing };
|
|
663
|
+
}
|
|
664
|
+
return { ok: true, items };
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// src/utils/add/dependencies.ts
|
|
668
|
+
function collectDependencies(items) {
|
|
669
|
+
const dependencies = [];
|
|
670
|
+
const seen = /* @__PURE__ */ new Set();
|
|
671
|
+
for (const item of items) {
|
|
672
|
+
for (const dependency of item.dependencies || []) {
|
|
673
|
+
if (seen.has(dependency)) {
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
seen.add(dependency);
|
|
677
|
+
dependencies.push(dependency);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return dependencies;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// src/utils/add/paths.ts
|
|
684
|
+
function resolveTargetDir(config, hasSrc, explicitPath) {
|
|
685
|
+
if (explicitPath) {
|
|
686
|
+
return explicitPath;
|
|
687
|
+
}
|
|
688
|
+
const targetDirAlias = config.aliases.components || "@/components/ui";
|
|
689
|
+
const relativeAliasPath = targetDirAlias.replace(/^[@~]\//, "");
|
|
690
|
+
if (config.framework === "remix") {
|
|
691
|
+
return `./app/${relativeAliasPath}`;
|
|
692
|
+
}
|
|
693
|
+
if (hasSrc) {
|
|
694
|
+
return `./src/${relativeAliasPath}`;
|
|
695
|
+
}
|
|
696
|
+
return `./${relativeAliasPath}`;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/utils/add/planner.ts
|
|
700
|
+
import path5 from "path";
|
|
470
701
|
|
|
471
702
|
// src/utils/transformers.ts
|
|
472
703
|
function transformImports(content, config) {
|
|
@@ -489,56 +720,167 @@ function transformImports(content, config) {
|
|
|
489
720
|
return transformed;
|
|
490
721
|
}
|
|
491
722
|
|
|
492
|
-
// src/
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
723
|
+
// src/utils/add/planner.ts
|
|
724
|
+
function buildWritePlan(items, config, hasSrc, options) {
|
|
725
|
+
const targetDir = resolveTargetDir(config, hasSrc, options.path);
|
|
726
|
+
return items.flatMap(
|
|
727
|
+
(item) => item.files.filter((file) => Boolean(file.content)).map((file) => {
|
|
728
|
+
const fileName = path5.basename(file.path);
|
|
729
|
+
const filePath = path5.join(targetDir, fileName);
|
|
730
|
+
return {
|
|
731
|
+
filePath,
|
|
732
|
+
content: transformImports(file.content || "", config),
|
|
733
|
+
action: !options.overwrite && options.exists(filePath) ? "skip-existing" : "write"
|
|
734
|
+
};
|
|
735
|
+
})
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// src/utils/add/run-add.ts
|
|
740
|
+
import path6 from "path";
|
|
741
|
+
import chalk3 from "chalk";
|
|
742
|
+
var defaultRuntime2 = {
|
|
743
|
+
cwd: () => process.cwd(),
|
|
744
|
+
exists,
|
|
745
|
+
readFile,
|
|
746
|
+
writeFile,
|
|
747
|
+
fetchRegistry,
|
|
748
|
+
getPackageManager,
|
|
749
|
+
installDependencies,
|
|
750
|
+
log: console.log
|
|
751
|
+
};
|
|
752
|
+
function buildMissingComponentsMessage(names) {
|
|
753
|
+
return `Components not found: ${names.join(", ")}.`;
|
|
754
|
+
}
|
|
755
|
+
function resolveProjectRoot(cwdOption, cwd) {
|
|
756
|
+
return cwdOption ? path6.resolve(cwd, cwdOption) : cwd;
|
|
757
|
+
}
|
|
758
|
+
async function runAddCommand(componentNames = [], options = {}, runtime = defaultRuntime2) {
|
|
759
|
+
const projectRoot = resolveProjectRoot(options.cwd, runtime.cwd?.() ?? process.cwd());
|
|
760
|
+
if (options.depsOnly && options.install === false) {
|
|
761
|
+
throw new Error("invalid-install-combination");
|
|
762
|
+
}
|
|
763
|
+
if (!runtime.exists("glass.config.json", projectRoot)) {
|
|
764
|
+
throw new Error("config-not-found");
|
|
765
|
+
}
|
|
766
|
+
const config = JSON.parse(await runtime.readFile("glass.config.json", projectRoot));
|
|
767
|
+
runtime.log(chalk3.bold("Fetching components..."));
|
|
768
|
+
const registry = await runtime.fetchRegistry();
|
|
769
|
+
const selection = resolveAddSelection(registry, componentNames, Boolean(options.all));
|
|
770
|
+
if (!selection.ok) {
|
|
771
|
+
if (selection.reason === "invalid-combination") {
|
|
772
|
+
throw new Error("invalid-combination");
|
|
500
773
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
console.log(chalk2.bold(`Fetching component: ${componentName}...`));
|
|
504
|
-
const registry = await fetchRegistry();
|
|
505
|
-
const item = getItem(registry, componentName);
|
|
506
|
-
if (!item) {
|
|
507
|
-
console.error(chalk2.red(`Component '${componentName}' not found.`));
|
|
508
|
-
process.exit(1);
|
|
774
|
+
if (selection.reason === "missing-components") {
|
|
775
|
+
throw new Error(buildMissingComponentsMessage(selection.names || []));
|
|
509
776
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
777
|
+
throw new Error("empty-selection");
|
|
778
|
+
}
|
|
779
|
+
const shouldWrite = options.depsOnly !== true;
|
|
780
|
+
const shouldInstall = options.install !== false;
|
|
781
|
+
if (shouldWrite) {
|
|
782
|
+
const plannedWrites = buildWritePlan(
|
|
783
|
+
selection.items,
|
|
784
|
+
config,
|
|
785
|
+
runtime.exists("src", projectRoot),
|
|
786
|
+
{
|
|
787
|
+
exists: (filePath) => runtime.exists(filePath, projectRoot),
|
|
788
|
+
overwrite: options.overwrite,
|
|
789
|
+
path: options.path
|
|
790
|
+
}
|
|
791
|
+
);
|
|
792
|
+
for (const file of plannedWrites) {
|
|
793
|
+
if (file.action === "skip-existing") {
|
|
794
|
+
runtime.log(chalk3.yellow(` Skipped ${file.filePath} (already exists)`));
|
|
518
795
|
continue;
|
|
519
796
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
console.log(chalk2.green(` Created ${filePath}`));
|
|
523
|
-
}
|
|
524
|
-
if (item.dependencies?.length) {
|
|
525
|
-
console.log(chalk2.cyan(` Installing dependencies...`));
|
|
526
|
-
await installDependencies(item.dependencies, pm);
|
|
797
|
+
await runtime.writeFile(file.filePath, file.content, projectRoot);
|
|
798
|
+
runtime.log(chalk3.green(` Created ${file.filePath}`));
|
|
527
799
|
}
|
|
528
|
-
|
|
529
|
-
|
|
800
|
+
}
|
|
801
|
+
const dependencies = collectDependencies(selection.items);
|
|
802
|
+
if (shouldInstall && dependencies.length > 0) {
|
|
803
|
+
const pm = await runtime.getPackageManager(projectRoot);
|
|
804
|
+
runtime.log(chalk3.cyan(" Installing dependencies..."));
|
|
805
|
+
await runtime.installDependencies(dependencies, pm, projectRoot);
|
|
806
|
+
}
|
|
807
|
+
runtime.log(chalk3.bold.green("\nDone."));
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// src/commands/add.ts
|
|
811
|
+
var AddCommandError = class extends Error {
|
|
812
|
+
constructor(code, message) {
|
|
813
|
+
super(message);
|
|
814
|
+
this.code = code;
|
|
815
|
+
}
|
|
816
|
+
code;
|
|
817
|
+
};
|
|
818
|
+
async function runAddCommand2(componentNames = [], options = {}, runtime = defaultRuntime2) {
|
|
819
|
+
try {
|
|
820
|
+
await runAddCommand(componentNames, options, runtime);
|
|
530
821
|
} catch (error) {
|
|
531
|
-
console.error(chalk2.red("\nOperation failed:"));
|
|
532
822
|
if (error instanceof Error) {
|
|
533
|
-
|
|
823
|
+
if (error.message === "config-not-found") {
|
|
824
|
+
throw new AddCommandError("config-not-found", "Configuration file not found.");
|
|
825
|
+
}
|
|
826
|
+
if (error.message === "invalid-combination") {
|
|
827
|
+
throw new AddCommandError(
|
|
828
|
+
"invalid-combination",
|
|
829
|
+
"Cannot combine --all with specific component names."
|
|
830
|
+
);
|
|
831
|
+
}
|
|
832
|
+
if (error.message === "invalid-install-combination") {
|
|
833
|
+
throw new AddCommandError(
|
|
834
|
+
"invalid-combination",
|
|
835
|
+
"Cannot combine --deps-only with --no-install."
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
if (error.message === "empty-selection") {
|
|
839
|
+
throw new AddCommandError(
|
|
840
|
+
"empty-selection",
|
|
841
|
+
"Please specify at least one component or use --all."
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
if (error.message.startsWith("Components not found:")) {
|
|
845
|
+
throw new AddCommandError("missing-components", error.message);
|
|
846
|
+
}
|
|
534
847
|
}
|
|
535
|
-
|
|
848
|
+
throw error;
|
|
536
849
|
}
|
|
537
|
-
}
|
|
850
|
+
}
|
|
851
|
+
function createAddAction(deps = {
|
|
852
|
+
runAddCommand: runAddCommand2,
|
|
853
|
+
error: console.error,
|
|
854
|
+
log: console.log,
|
|
855
|
+
exit: process.exit
|
|
856
|
+
}) {
|
|
857
|
+
return async (componentNames = [], options = {}) => {
|
|
858
|
+
try {
|
|
859
|
+
await deps.runAddCommand(componentNames, options);
|
|
860
|
+
} catch (error) {
|
|
861
|
+
if (error instanceof AddCommandError) {
|
|
862
|
+
if (error.code === "config-not-found") {
|
|
863
|
+
deps.error(chalk4.red(error.message));
|
|
864
|
+
deps.log(chalk4.gray("Please run the init command first:"));
|
|
865
|
+
deps.log(chalk4.cyan(" npx @glass-ui-kit/cli@latest init"));
|
|
866
|
+
deps.exit(1);
|
|
867
|
+
}
|
|
868
|
+
deps.error(chalk4.red(error.message));
|
|
869
|
+
deps.exit(1);
|
|
870
|
+
}
|
|
871
|
+
deps.error(chalk4.red("\nOperation failed:"));
|
|
872
|
+
if (error instanceof Error) {
|
|
873
|
+
deps.error(chalk4.gray(` ${error.message}`));
|
|
874
|
+
}
|
|
875
|
+
deps.exit(1);
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
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());
|
|
538
880
|
|
|
539
881
|
// src/index.ts
|
|
540
882
|
var program = new Command3();
|
|
541
|
-
program.name("glass-ui").description("The Glass UI CLI - Add glassmorphism components to your app").version("0.
|
|
883
|
+
program.name("glass-ui").description("The Glass UI CLI - Add glassmorphism components to your app").version("0.2.5");
|
|
542
884
|
program.addCommand(init);
|
|
543
885
|
program.addCommand(add);
|
|
544
886
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,59 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@glass-ui-kit/cli",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "The official CLI for Glass UI. Add glassmorphism components to your React projects in seconds.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"glassmorphism",
|
|
7
|
-
"design-system",
|
|
8
|
-
"react",
|
|
9
|
-
"cli",
|
|
10
|
-
"ui",
|
|
11
|
-
"tailwind"
|
|
12
|
-
],
|
|
13
|
-
"homepage": "https://github.com/jntellez/glass-ui#readme",
|
|
14
|
-
"bugs": {
|
|
15
|
-
"url": "https://github.com/jntellez/glass-ui/issues"
|
|
16
|
-
},
|
|
17
|
-
"repository": {
|
|
18
|
-
"type": "git",
|
|
19
|
-
"url": "git+https://github.com/jntellez/glass-ui.git",
|
|
20
|
-
"directory": "packages/cli"
|
|
21
|
-
},
|
|
22
|
-
"license": "MIT",
|
|
23
|
-
"author": "Glass UI Team",
|
|
24
|
-
"type": "module",
|
|
25
|
-
"bin": {
|
|
26
|
-
"glass-ui": "./dist/index.js"
|
|
27
|
-
},
|
|
28
|
-
"files": [
|
|
29
|
-
"dist",
|
|
30
|
-
"README.md"
|
|
31
|
-
],
|
|
32
|
-
"engines": {
|
|
33
|
-
"node": ">=18.0.0"
|
|
34
|
-
},
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@glass-ui-kit/cli",
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"description": "The official CLI for Glass UI. Add glassmorphism components to your React projects in seconds.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"glassmorphism",
|
|
7
|
+
"design-system",
|
|
8
|
+
"react",
|
|
9
|
+
"cli",
|
|
10
|
+
"ui",
|
|
11
|
+
"tailwind"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/jntellez/glass-ui#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/jntellez/glass-ui/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/jntellez/glass-ui.git",
|
|
20
|
+
"directory": "packages/cli"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "Glass UI Team",
|
|
24
|
+
"type": "module",
|
|
25
|
+
"bin": {
|
|
26
|
+
"glass-ui": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18.0.0"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"chalk": "^5.3.0",
|
|
37
|
+
"commander": "^11.1.0",
|
|
38
|
+
"node-fetch": "^3.3.2",
|
|
39
|
+
"zod": "^3.22.4"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^20.11.0",
|
|
43
|
+
"bun-types": "latest",
|
|
44
|
+
"vitest": "^3.2.4",
|
|
45
|
+
"tsup": "^8.0.1",
|
|
46
|
+
"typescript": "^5.3.3",
|
|
47
|
+
"@glass-ui-kit/schema": "0.0.1",
|
|
48
|
+
"@glass-ui-kit/tsconfig": "0.0.1"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"sync": "node scripts/sync-styles.mjs",
|
|
55
|
+
"build": "pnpm run sync && tsup src/index.ts --format esm --clean",
|
|
56
|
+
"dev": "pnpm run sync && bun run ./src/index.ts",
|
|
57
|
+
"lint": "eslint src",
|
|
58
|
+
"test": "vitest run"
|
|
59
|
+
}
|
|
60
|
+
}
|