starwind 1.11.2 → 1.12.1

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 DELETED
@@ -1,1977 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/index.ts
4
- import { Command } from "commander";
5
-
6
- // package.json
7
- var package_default = {
8
- name: "starwind",
9
- version: "1.11.2",
10
- description: "Add beautifully designed components to your Astro applications",
11
- license: "MIT",
12
- author: {
13
- name: "webreaper",
14
- url: "https://x.com/BowTiedWebReapr"
15
- },
16
- repository: {
17
- type: "git",
18
- url: "https://github.com/starwind-ui/starwind-ui.git",
19
- directory: "packages/cli"
20
- },
21
- keywords: [
22
- "starwind",
23
- "starwind ui",
24
- "starwind cli",
25
- "astro",
26
- "astro component",
27
- "astro ui",
28
- "astro ui library",
29
- "tailwind",
30
- "components",
31
- "add component"
32
- ],
33
- type: "module",
34
- bin: {
35
- starwind: "./dist/index.js"
36
- },
37
- main: "./dist/index.js",
38
- types: "./dist/index.d.ts",
39
- files: [
40
- "dist"
41
- ],
42
- scripts: {
43
- build: "tsup",
44
- dev: "tsup --watch",
45
- "cli:link": "pnpm link --global",
46
- "cli:unlink": "pnpm rm --global starwind",
47
- test: "vitest",
48
- "test:run": "vitest run",
49
- "test:coverage": "vitest run --coverage",
50
- typecheck: "tsc --noEmit",
51
- "format:check": 'prettier --check "**/*.{ts,tsx,md,json}"',
52
- "format:write": 'prettier --write "**/*.{ts,tsx,md,json}" --cache',
53
- "publish:beta": "pnpm publish --tag beta --access public",
54
- "publish:next": "pnpm publish --tag next --access public",
55
- "publish:release": "pnpm publish --access public"
56
- },
57
- dependencies: {
58
- "@clack/prompts": "0.11.0",
59
- "@starwind-ui/core": "1.11.2",
60
- chalk: "5.4.1",
61
- commander: "14.0.0",
62
- execa: "9.6.0",
63
- "fs-extra": "11.2.0",
64
- semver: "7.7.2",
65
- zod: "3.25.74"
66
- },
67
- devDependencies: {
68
- "@types/fs-extra": "11.0.4",
69
- "@types/node": "24.0.10",
70
- "@types/prompts": "2.4.9",
71
- "@types/semver": "7.5.8",
72
- tsup: "8.5.0"
73
- },
74
- engines: {
75
- node: "^20.6.0 || >=22.0.0"
76
- }
77
- };
78
-
79
- // src/commands/add.ts
80
- import * as p6 from "@clack/prompts";
81
- import { execa as execa2 } from "execa";
82
-
83
- // src/utils/constants.ts
84
- var MIN_ASTRO_VERSION = "5.0.0";
85
- var PATHS = {
86
- STARWIND_CORE: "@starwind-ui/core",
87
- STARWIND_CORE_COMPONENTS: "src/components",
88
- STARWIND_REMOTE_COMPONENT_REGISTRY: "https://starwind.dev/registry.json",
89
- STARWIND_PRO_REGISTRY: "https://pro.starwind.dev/r/{name}",
90
- LOCAL_CSS_FILE: "src/styles/starwind.css",
91
- LOCAL_CONFIG_FILE: "starwind.config.json",
92
- LOCAL_STYLES_DIR: "src/styles",
93
- LOCAL_COMPONENTS_DIR: "src/components"
94
- };
95
- var ASTRO_PACKAGES = {
96
- core: "astro@latest"
97
- };
98
- var OTHER_PACKAGES = {
99
- tailwindCore: "tailwindcss@^4",
100
- tailwindVite: "@tailwindcss/vite@^4",
101
- tailwindForms: "@tailwindcss/forms@^0.5",
102
- tailwindAnimate: "tw-animate-css@^1",
103
- tailwindVariants: "tailwind-variants@^3",
104
- tailwindMerge: "tailwind-merge@^3",
105
- tablerIcons: "@tabler/icons@^3"
106
- };
107
- function getOtherPackages() {
108
- return Object.values(OTHER_PACKAGES);
109
- }
110
-
111
- // src/utils/fs.ts
112
- import fs from "fs-extra";
113
- async function ensureDirectory(dir) {
114
- await fs.ensureDir(dir);
115
- }
116
- async function readJsonFile(filePath) {
117
- return fs.readJson(filePath);
118
- }
119
- async function writeJsonFile(filePath, data) {
120
- await fs.writeJson(filePath, data, { spaces: 2 });
121
- }
122
- async function fileExists(filePath) {
123
- return fs.pathExists(filePath);
124
- }
125
- async function writeCssFile(filePath, content) {
126
- await fs.writeFile(filePath, content, "utf-8");
127
- }
128
-
129
- // src/utils/config.ts
130
- var defaultConfig = {
131
- $schema: "https://starwind.dev/config-schema.json",
132
- tailwind: {
133
- css: "src/styles/starwind.css",
134
- baseColor: "neutral",
135
- cssVariables: true
136
- },
137
- // aliases: {
138
- // components: "@/components",
139
- // },
140
- componentDir: "src/components/starwind",
141
- components: []
142
- };
143
- async function getConfig() {
144
- try {
145
- if (await fileExists(PATHS.LOCAL_CONFIG_FILE)) {
146
- const config = await readJsonFile(PATHS.LOCAL_CONFIG_FILE);
147
- return {
148
- ...defaultConfig,
149
- ...config,
150
- components: Array.isArray(config.components) ? config.components : []
151
- };
152
- }
153
- } catch (error) {
154
- console.error("Error reading config:", error);
155
- }
156
- return defaultConfig;
157
- }
158
- async function updateConfig(updates, options = { appendComponents: true }) {
159
- const currentConfig = await getConfig();
160
- const currentComponents = Array.isArray(currentConfig.components) ? currentConfig.components : [];
161
- const newConfig = {
162
- ...currentConfig,
163
- tailwind: {
164
- ...currentConfig.tailwind,
165
- ...updates.tailwind || {}
166
- },
167
- componentDir: updates.componentDir ? updates.componentDir : currentConfig.componentDir,
168
- components: updates.components ? options.appendComponents ? [...currentComponents, ...updates.components] : updates.components : currentComponents
169
- };
170
- try {
171
- await writeJsonFile(PATHS.LOCAL_CONFIG_FILE, newConfig);
172
- } catch (error) {
173
- throw new Error(
174
- `Failed to update config: ${error instanceof Error ? error.message : "Unknown error"}`
175
- );
176
- }
177
- }
178
-
179
- // src/utils/highlighter.ts
180
- import chalk from "chalk";
181
- var highlighter = {
182
- error: chalk.red,
183
- warn: chalk.yellow,
184
- info: chalk.cyan,
185
- infoBright: chalk.cyanBright,
186
- success: chalk.greenBright,
187
- underline: chalk.underline,
188
- title: chalk.bgBlue
189
- };
190
-
191
- // src/utils/install.ts
192
- import * as p3 from "@clack/prompts";
193
-
194
- // src/utils/component.ts
195
- import * as path from "path";
196
- import { fileURLToPath } from "url";
197
- import * as p from "@clack/prompts";
198
- import fs2 from "fs-extra";
199
- import semver from "semver";
200
-
201
- // src/utils/registry.ts
202
- import { registry as localRegistry } from "@starwind-ui/core";
203
- import { z } from "zod";
204
- var REGISTRY_CONFIG = {
205
- // Set to 'remote' to fetch from remote server or 'local' to use the imported registry
206
- SOURCE: "local"
207
- };
208
- var componentSchema = z.object({
209
- name: z.string(),
210
- version: z.string(),
211
- dependencies: z.array(z.string()).default([]),
212
- type: z.enum(["component"])
213
- });
214
- var registryRootSchema = z.object({
215
- $schema: z.string().optional(),
216
- components: z.array(componentSchema)
217
- });
218
- var registryCache = /* @__PURE__ */ new Map();
219
- async function getRegistry(forceRefresh = false) {
220
- const cacheKey = REGISTRY_CONFIG.SOURCE === "remote" ? PATHS.STARWIND_REMOTE_COMPONENT_REGISTRY : "local-registry";
221
- if (!forceRefresh && registryCache.has(cacheKey)) {
222
- return registryCache.get(cacheKey);
223
- }
224
- const registryPromise = REGISTRY_CONFIG.SOURCE === "remote" ? fetchRemoteRegistry() : Promise.resolve(getLocalRegistry());
225
- registryCache.set(cacheKey, registryPromise);
226
- return registryPromise;
227
- }
228
- async function fetchRemoteRegistry() {
229
- try {
230
- const response = await fetch(PATHS.STARWIND_REMOTE_COMPONENT_REGISTRY);
231
- if (!response.ok) {
232
- throw new Error(`Failed to fetch registry: ${response.status} ${response.statusText}`);
233
- }
234
- const data = await response.json();
235
- const parsedRegistry = registryRootSchema.parse(data);
236
- return parsedRegistry.components;
237
- } catch (error) {
238
- console.error("Failed to load remote registry:", error);
239
- throw error;
240
- }
241
- }
242
- function getLocalRegistry() {
243
- try {
244
- const components = localRegistry.map((comp) => componentSchema.parse(comp));
245
- return components;
246
- } catch (error) {
247
- console.error("Failed to validate local registry:", error);
248
- throw error;
249
- }
250
- }
251
- async function getComponent(name, forceRefresh = false) {
252
- const registry = await getRegistry(forceRefresh);
253
- return registry.find((component) => component.name === name);
254
- }
255
- async function getAllComponents(forceRefresh = false) {
256
- return getRegistry(forceRefresh);
257
- }
258
-
259
- // src/utils/component.ts
260
- async function copyComponent(name, overwrite = false) {
261
- const config = await getConfig();
262
- const currentComponents = Array.isArray(config.components) ? config.components : [];
263
- if (!overwrite && currentComponents.some((component) => component.name === name)) {
264
- const existingComponent = currentComponents.find((c) => c.name === name);
265
- return {
266
- status: "skipped",
267
- name,
268
- version: existingComponent?.version
269
- };
270
- }
271
- const componentDir = path.join(config.componentDir, "starwind", name);
272
- try {
273
- await fs2.ensureDir(componentDir);
274
- const pkgUrl = import.meta.resolve?.(PATHS.STARWIND_CORE);
275
- if (!pkgUrl) {
276
- throw new Error(`Could not resolve ${PATHS.STARWIND_CORE} package, is it installed?`);
277
- }
278
- const coreDir = path.dirname(fileURLToPath(pkgUrl));
279
- const sourceDir = path.join(coreDir, PATHS.STARWIND_CORE_COMPONENTS, name);
280
- const files = await fs2.readdir(sourceDir);
281
- for (const file of files) {
282
- const sourcePath = path.join(sourceDir, file);
283
- const destPath = path.join(componentDir, file);
284
- await fs2.copy(sourcePath, destPath, { overwrite: true });
285
- }
286
- const registry = await getRegistry();
287
- const componentInfo = registry.find((c) => c.name === name);
288
- if (!componentInfo) {
289
- throw new Error(`Component ${name} not found in registry`);
290
- }
291
- return {
292
- status: "installed",
293
- name,
294
- version: componentInfo.version
295
- };
296
- } catch (error) {
297
- return {
298
- status: "failed",
299
- name,
300
- error: error instanceof Error ? error.message : "Unknown error"
301
- };
302
- }
303
- }
304
- async function removeComponent(name, componentDir) {
305
- try {
306
- const componentPath = path.join(componentDir, "starwind", name);
307
- if (await fs2.pathExists(componentPath)) {
308
- await fs2.remove(componentPath);
309
- return { name, status: "removed" };
310
- } else {
311
- return {
312
- name,
313
- status: "failed",
314
- error: "Component directory not found"
315
- };
316
- }
317
- } catch (error) {
318
- return {
319
- name,
320
- status: "failed",
321
- error: error instanceof Error ? error.message : "Unknown error"
322
- };
323
- }
324
- }
325
- async function updateComponent(name, currentVersion, skipConfirm) {
326
- try {
327
- const registryComponent = await getComponent(name);
328
- if (!registryComponent) {
329
- return {
330
- name,
331
- status: "failed",
332
- error: "Component not found in registry"
333
- };
334
- }
335
- if (!semver.gt(registryComponent.version, currentVersion)) {
336
- return {
337
- name,
338
- status: "skipped",
339
- oldVersion: currentVersion,
340
- newVersion: registryComponent.version
341
- };
342
- }
343
- let confirmUpdate = true;
344
- if (!skipConfirm) {
345
- const confirmedResult = await p.confirm({
346
- message: `Update component ${highlighter.info(
347
- name
348
- )} from ${highlighter.warn(`v${currentVersion}`)} to ${highlighter.success(
349
- `v${registryComponent.version}`
350
- )}? This will override the existing implementation.`
351
- });
352
- if (p.isCancel(confirmedResult)) {
353
- p.cancel("Update cancelled.");
354
- return {
355
- name,
356
- status: "skipped",
357
- oldVersion: currentVersion,
358
- newVersion: registryComponent.version
359
- // Still useful to return the target version
360
- };
361
- }
362
- confirmUpdate = confirmedResult;
363
- }
364
- if (!confirmUpdate) {
365
- p.log.info(`Skipping update for ${highlighter.info(name)}`);
366
- return {
367
- name,
368
- status: "skipped",
369
- oldVersion: currentVersion,
370
- newVersion: registryComponent.version
371
- };
372
- }
373
- const result = await copyComponent(name, true);
374
- if (result.status === "installed") {
375
- return {
376
- name,
377
- status: "updated",
378
- oldVersion: currentVersion,
379
- newVersion: result.version
380
- };
381
- } else {
382
- return {
383
- name,
384
- status: "failed",
385
- error: result.error || "Failed to update component"
386
- };
387
- }
388
- } catch (error) {
389
- return {
390
- name,
391
- status: "failed",
392
- error: error instanceof Error ? error.message : "Unknown error"
393
- };
394
- }
395
- }
396
-
397
- // src/utils/dependency-resolver.ts
398
- import semver2 from "semver";
399
- async function filterUninstalledDependencies(dependencies) {
400
- try {
401
- const pkg = await readJsonFile("package.json");
402
- const installedDeps = { ...pkg.dependencies || {}, ...pkg.devDependencies || {} };
403
- const dependenciesToInstall = [];
404
- for (const dep of dependencies) {
405
- let packageName;
406
- let requiredVersion;
407
- if (dep.startsWith("@")) {
408
- const lastAtIndex = dep.lastIndexOf("@");
409
- if (lastAtIndex > 0) {
410
- packageName = dep.substring(0, lastAtIndex);
411
- requiredVersion = dep.substring(lastAtIndex + 1);
412
- } else {
413
- packageName = dep;
414
- requiredVersion = "*";
415
- }
416
- } else {
417
- const atIndex = dep.indexOf("@");
418
- if (atIndex > 0) {
419
- packageName = dep.substring(0, atIndex);
420
- requiredVersion = dep.substring(atIndex + 1);
421
- } else {
422
- packageName = dep;
423
- requiredVersion = "*";
424
- }
425
- }
426
- const installedVersion = installedDeps[packageName];
427
- if (!installedVersion) {
428
- dependenciesToInstall.push(dep);
429
- } else if (requiredVersion && requiredVersion !== "*") {
430
- const cleanInstalledVersion = semver2.clean(installedVersion) || installedVersion.replace(/^[\^~>=<= ]+/, "");
431
- try {
432
- if (!semver2.satisfies(cleanInstalledVersion, requiredVersion)) {
433
- dependenciesToInstall.push(dep);
434
- }
435
- } catch (error) {
436
- dependenciesToInstall.push(dep);
437
- }
438
- }
439
- }
440
- return dependenciesToInstall;
441
- } catch (error) {
442
- return dependencies;
443
- }
444
- }
445
- function parseStarwindDependency(dependency) {
446
- const starwindPattern = /^@starwind-ui\/core\/([^@]+)@(.+)$/;
447
- const match = dependency.match(starwindPattern);
448
- if (!match) {
449
- return null;
450
- }
451
- const [, name, version] = match;
452
- return {
453
- name,
454
- version,
455
- originalSpec: dependency
456
- };
457
- }
458
- function isStarwindDependency(dependency) {
459
- return parseStarwindDependency(dependency) !== null;
460
- }
461
- async function getInstalledComponentVersion(componentName) {
462
- try {
463
- const config = await getConfig();
464
- const installedComponent = config.components.find((comp) => comp.name === componentName);
465
- return installedComponent?.version;
466
- } catch {
467
- return void 0;
468
- }
469
- }
470
- async function resolveStarwindDependency(dependency) {
471
- const parsed = parseStarwindDependency(dependency);
472
- if (!parsed) {
473
- return {
474
- component: dependency,
475
- requiredVersion: "",
476
- needsInstall: false,
477
- needsUpdate: false,
478
- isStarwindComponent: false
479
- };
480
- }
481
- const currentVersion = await getInstalledComponentVersion(parsed.name);
482
- const registryComponent = await getComponent(parsed.name);
483
- if (!registryComponent) {
484
- throw new Error(`Starwind component "${parsed.name}" not found in registry`);
485
- }
486
- let needsInstall = false;
487
- let needsUpdate = false;
488
- if (!currentVersion) {
489
- needsInstall = true;
490
- } else {
491
- if (!semver2.satisfies(currentVersion, parsed.version)) {
492
- if (semver2.satisfies(registryComponent.version, parsed.version)) {
493
- needsUpdate = true;
494
- } else {
495
- throw new Error(
496
- `No version of "${parsed.name}" satisfies requirement "${parsed.version}". Latest available: ${registryComponent.version}, currently installed: ${currentVersion}`
497
- );
498
- }
499
- }
500
- }
501
- return {
502
- component: parsed.name,
503
- currentVersion,
504
- requiredVersion: parsed.version,
505
- needsInstall,
506
- needsUpdate,
507
- isStarwindComponent: true
508
- };
509
- }
510
- async function resolveAllStarwindDependencies(componentNames, resolved = /* @__PURE__ */ new Set()) {
511
- const resolutions = [];
512
- for (const componentName of componentNames) {
513
- if (resolved.has(componentName)) {
514
- continue;
515
- }
516
- resolved.add(componentName);
517
- const component = await getComponent(componentName);
518
- if (!component) {
519
- throw new Error(`Component "${componentName}" not found in registry`);
520
- }
521
- for (const dependency of component.dependencies) {
522
- const resolution = await resolveStarwindDependency(dependency);
523
- if (resolution && resolution.isStarwindComponent) {
524
- if (resolution.needsInstall || resolution.needsUpdate) {
525
- resolutions.push(resolution);
526
- }
527
- const nestedResolutions = await resolveAllStarwindDependencies(
528
- [resolution.component],
529
- resolved
530
- );
531
- resolutions.push(...nestedResolutions);
532
- }
533
- }
534
- }
535
- const uniqueResolutions = /* @__PURE__ */ new Map();
536
- for (const resolution of resolutions) {
537
- const existing = uniqueResolutions.get(resolution.component);
538
- if (!existing) {
539
- uniqueResolutions.set(resolution.component, resolution);
540
- } else {
541
- if (resolution.needsInstall && !existing.needsInstall) {
542
- uniqueResolutions.set(resolution.component, resolution);
543
- }
544
- }
545
- }
546
- return Array.from(uniqueResolutions.values());
547
- }
548
- function separateDependencies(dependencies) {
549
- const starwindDependencies = [];
550
- const npmDependencies = [];
551
- for (const dependency of dependencies) {
552
- if (isStarwindDependency(dependency)) {
553
- starwindDependencies.push(dependency);
554
- } else {
555
- npmDependencies.push(dependency);
556
- }
557
- }
558
- return { starwindDependencies, npmDependencies };
559
- }
560
-
561
- // src/utils/package-manager.ts
562
- import * as p2 from "@clack/prompts";
563
- import { execa } from "execa";
564
- async function requestPackageManager() {
565
- const pm = await p2.select({
566
- message: "Select your preferred package manager",
567
- options: [
568
- { value: "pnpm", label: "pnpm", hint: "Default" },
569
- { value: "npm", label: "npm" },
570
- { value: "yarn", label: "yarn" },
571
- { value: "bun", label: "bun" }
572
- ]
573
- });
574
- if (p2.isCancel(pm)) {
575
- p2.log.warn("No package manager selected, defaulting to npm");
576
- return "npm";
577
- }
578
- return pm;
579
- }
580
- function getCurrentPackageManager() {
581
- const userAgent = process.env.npm_config_user_agent;
582
- if (userAgent) {
583
- if (userAgent.includes("pnpm")) {
584
- return "pnpm";
585
- } else if (userAgent.includes("yarn")) {
586
- return "yarn";
587
- } else if (userAgent.includes("npm")) {
588
- return "npm";
589
- } else if (userAgent.includes("bun")) {
590
- return "bun";
591
- }
592
- }
593
- return null;
594
- }
595
- async function getDefaultPackageManager() {
596
- const current = getCurrentPackageManager();
597
- if (current) {
598
- return current;
599
- }
600
- if (await fileExists("yarn.lock")) {
601
- return "yarn";
602
- } else if (await fileExists("pnpm-lock.yaml")) {
603
- return "pnpm";
604
- } else {
605
- return "npm";
606
- }
607
- }
608
- async function getShadcnCommand() {
609
- const pm = await getDefaultPackageManager();
610
- switch (pm) {
611
- case "pnpm":
612
- return ["pnpm", ["dlx", "shadcn@3"]];
613
- case "yarn":
614
- return ["yarn", ["dlx", "shadcn@3"]];
615
- case "bun":
616
- return ["bunx", ["shadcn@3"]];
617
- case "npm":
618
- default:
619
- return ["npx", ["shadcn@3"]];
620
- }
621
- }
622
- async function installDependencies(packages, pm, dev = false, force = false) {
623
- const args = [
624
- pm === "npm" ? "install" : "add",
625
- ...packages,
626
- dev ? pm === "npm" || pm === "pnpm" ? "-D" : "--dev" : "",
627
- force ? "--force" : ""
628
- ].filter(Boolean);
629
- await execa(pm, args);
630
- }
631
-
632
- // src/utils/prompts.ts
633
- import { confirm as confirm2, multiselect } from "@clack/prompts";
634
- async function selectComponents() {
635
- const components = await getAllComponents();
636
- const selected = await multiselect({
637
- message: "Select components to add",
638
- options: components.map((component) => ({
639
- label: component.name,
640
- value: component.name
641
- })),
642
- required: false
643
- });
644
- if (typeof selected === "symbol") {
645
- return [];
646
- }
647
- return selected;
648
- }
649
- async function confirmStarwindDependencies(componentNames) {
650
- try {
651
- const resolutions = await resolveAllStarwindDependencies(componentNames);
652
- if (resolutions.length === 0) {
653
- return true;
654
- }
655
- const toInstall = resolutions.filter((r) => r.needsInstall);
656
- const toUpdate = resolutions.filter((r) => r.needsUpdate);
657
- let message = "This component has Starwind component dependencies:\n\n";
658
- if (toInstall.length > 0) {
659
- message += `${highlighter.info("Components to install:")}
660
- `;
661
- for (const dep of toInstall) {
662
- message += ` \u2022 ${dep.component} (requires ${dep.requiredVersion})
663
- `;
664
- }
665
- message += "\n";
666
- }
667
- if (toUpdate.length > 0) {
668
- message += `${highlighter.warn("Components to update:")}
669
- `;
670
- for (const dep of toUpdate) {
671
- message += ` \u2022 ${dep.component} (${dep.currentVersion} \u2192 latest, requires ${dep.requiredVersion})
672
- `;
673
- }
674
- message += "\n";
675
- }
676
- message += "Proceed with installation?";
677
- const confirmed = await confirm2({ message });
678
- if (typeof confirmed === "symbol") {
679
- return false;
680
- }
681
- return confirmed;
682
- } catch (error) {
683
- console.error("Error resolving Starwind dependencies:", error);
684
- const confirmed = await confirm2({
685
- message: `Error resolving dependencies: ${error instanceof Error ? error.message : "Unknown error"}. Continue anyway?`
686
- });
687
- if (typeof confirmed === "symbol") {
688
- return false;
689
- }
690
- return confirmed;
691
- }
692
- }
693
- async function getStarwindDependencyResolutions(componentNames) {
694
- return resolveAllStarwindDependencies(componentNames);
695
- }
696
- async function confirmInstall(component) {
697
- if (component.dependencies.length === 0) return true;
698
- const { starwindDependencies, npmDependencies } = separateDependencies(component.dependencies);
699
- if (npmDependencies.length > 0) {
700
- const dependenciesToInstall = await filterUninstalledDependencies(npmDependencies);
701
- if (dependenciesToInstall.length > 0) {
702
- const confirmed = await confirm2({
703
- message: `This component requires the following npm dependencies: ${dependenciesToInstall.join(", ")}. Install them?`
704
- });
705
- if (typeof confirmed === "symbol" || !confirmed) {
706
- return false;
707
- }
708
- }
709
- }
710
- if (starwindDependencies.length > 0) {
711
- const confirmed = await confirmStarwindDependencies([component.name]);
712
- if (!confirmed) {
713
- return false;
714
- }
715
- }
716
- return true;
717
- }
718
-
719
- // src/utils/install.ts
720
- async function installComponent(name) {
721
- const component = await getComponent(name);
722
- if (!component) {
723
- return {
724
- status: "failed",
725
- name,
726
- error: "Component not found in registry"
727
- };
728
- }
729
- let dependencyResults = [];
730
- if (component.dependencies.length > 0) {
731
- const confirmed = await confirmInstall(component);
732
- if (!confirmed) {
733
- return {
734
- status: "failed",
735
- name,
736
- error: "Installation cancelled by user"
737
- };
738
- }
739
- const { starwindDependencies, npmDependencies } = separateDependencies(component.dependencies);
740
- if (npmDependencies.length > 0) {
741
- try {
742
- const dependenciesToInstall = await filterUninstalledDependencies(npmDependencies);
743
- if (dependenciesToInstall.length > 0) {
744
- const pm = await requestPackageManager();
745
- const installTasks = [
746
- {
747
- title: `Installing ${dependenciesToInstall.length === 1 ? "dependency" : "dependencies"}`,
748
- task: async () => {
749
- await installDependencies(dependenciesToInstall, pm);
750
- return `${highlighter.info("Dependencies installed successfully")}`;
751
- }
752
- }
753
- ];
754
- await p3.tasks(installTasks);
755
- } else {
756
- p3.log.info(
757
- `${highlighter.info("All npm dependencies are already installed with valid versions")}`
758
- );
759
- }
760
- } catch (error) {
761
- return {
762
- status: "failed",
763
- name,
764
- error: `Failed to install npm dependencies: ${error instanceof Error ? error.message : String(error)}`
765
- };
766
- }
767
- }
768
- if (starwindDependencies.length > 0) {
769
- let resolutions = [];
770
- try {
771
- resolutions = await getStarwindDependencyResolutions([name]);
772
- } catch (error) {
773
- console.warn(
774
- "Proceeding without Starwind dependency installs due to resolution error:",
775
- error
776
- );
777
- resolutions = [];
778
- }
779
- if (resolutions.length > 0) {
780
- const installResults = await installStarwindDependencies(resolutions);
781
- dependencyResults = installResults;
782
- const failedDeps = installResults.filter((r) => r.status === "failed");
783
- if (failedDeps.length > 0) {
784
- return {
785
- status: "failed",
786
- name,
787
- error: `Failed to install Starwind dependencies: ${failedDeps.map((r) => r.name).join(", ")}`,
788
- dependencyResults
789
- };
790
- }
791
- }
792
- }
793
- }
794
- const result = await copyComponent(name);
795
- if (dependencyResults.length > 0) {
796
- return {
797
- ...result,
798
- dependencyResults
799
- };
800
- }
801
- return result;
802
- }
803
- async function installStarwindDependencies(resolutions) {
804
- const results = [];
805
- const componentsToInstall = [];
806
- const componentsToUpdate = [];
807
- for (const resolution of resolutions) {
808
- if (resolution.needsInstall) {
809
- const result = await copyComponent(resolution.component);
810
- results.push(result);
811
- if (result.status === "installed" && result.version) {
812
- componentsToInstall.push({ name: result.name, version: result.version });
813
- }
814
- } else if (resolution.needsUpdate) {
815
- const result = await copyComponent(resolution.component, true);
816
- results.push(result);
817
- if (result.status === "installed" && result.version) {
818
- componentsToUpdate.push({ name: result.name, version: result.version });
819
- }
820
- }
821
- }
822
- if (componentsToInstall.length > 0) {
823
- try {
824
- await updateConfig({ components: componentsToInstall }, { appendComponents: true });
825
- } catch (error) {
826
- console.error("Failed to update config after installing new dependencies:", error);
827
- }
828
- }
829
- if (componentsToUpdate.length > 0) {
830
- try {
831
- await updateExistingComponents(componentsToUpdate);
832
- } catch (error) {
833
- console.error("Failed to update config after updating dependencies:", error);
834
- }
835
- }
836
- return results;
837
- }
838
- async function updateExistingComponents(componentsToUpdate) {
839
- const config = await getConfig();
840
- const updatedComponents = [...config.components];
841
- for (const componentUpdate of componentsToUpdate) {
842
- const existingIndex = updatedComponents.findIndex((comp) => comp.name === componentUpdate.name);
843
- if (existingIndex >= 0) {
844
- updatedComponents[existingIndex] = {
845
- name: componentUpdate.name,
846
- version: componentUpdate.version
847
- };
848
- } else {
849
- updatedComponents.push(componentUpdate);
850
- }
851
- }
852
- await updateConfig({ components: updatedComponents }, { appendComponents: false });
853
- }
854
-
855
- // src/utils/shadcn-config.ts
856
- var COMPONENTS_JSON_PATH = "components.json";
857
- function createDefaultShadcnConfig(cssFilePath, baseColor = "neutral") {
858
- return {
859
- $schema: "https://ui.shadcn.com/schema.json",
860
- registries: {
861
- "@starwind-pro": {
862
- url: PATHS.STARWIND_PRO_REGISTRY,
863
- headers: {
864
- Authorization: "Bearer ${STARWIND_LICENSE_KEY}"
865
- }
866
- }
867
- },
868
- aliases: {
869
- components: "@/components",
870
- utils: "@/lib/utils"
871
- },
872
- tailwind: {
873
- config: "",
874
- css: cssFilePath,
875
- baseColor,
876
- cssVariables: true
877
- },
878
- style: "default",
879
- rsc: true
880
- };
881
- }
882
- async function componentsJsonExists() {
883
- return fileExists(COMPONENTS_JSON_PATH);
884
- }
885
- async function readComponentsJson() {
886
- try {
887
- return await readJsonFile(COMPONENTS_JSON_PATH);
888
- } catch (error) {
889
- throw new Error(`Failed to read components.json: ${error}`);
890
- }
891
- }
892
- async function writeComponentsJson(config) {
893
- try {
894
- await writeJsonFile(COMPONENTS_JSON_PATH, config);
895
- } catch (error) {
896
- throw new Error(`Failed to write components.json: ${error}`);
897
- }
898
- }
899
- function addStarwindProRegistry(config) {
900
- const updatedConfig = { ...config };
901
- if (!updatedConfig.registries) {
902
- updatedConfig.registries = {};
903
- }
904
- updatedConfig.registries["@starwind-pro"] = {
905
- url: PATHS.STARWIND_PRO_REGISTRY,
906
- headers: {
907
- Authorization: "Bearer ${STARWIND_LICENSE_KEY}"
908
- }
909
- };
910
- return updatedConfig;
911
- }
912
- async function setupShadcnProConfig(cssFilePath, baseColor = "neutral") {
913
- const exists = await componentsJsonExists();
914
- if (!exists) {
915
- const config = createDefaultShadcnConfig(cssFilePath, baseColor);
916
- await writeComponentsJson(config);
917
- } else {
918
- const existingConfig = await readComponentsJson();
919
- const updatedConfig = addStarwindProRegistry(existingConfig);
920
- await writeComponentsJson(updatedConfig);
921
- }
922
- }
923
- async function hasStarwindProRegistry() {
924
- if (!await componentsJsonExists()) {
925
- return false;
926
- }
927
- try {
928
- const config = await readComponentsJson();
929
- const starwindProRegistry = config.registries?.["@starwind-pro"];
930
- if (!starwindProRegistry?.url) {
931
- return false;
932
- }
933
- const url = starwindProRegistry.url;
934
- const isAuthorized = url.startsWith("http://localhost") || url.startsWith("https://pro.starwind.dev");
935
- return isAuthorized;
936
- } catch {
937
- return false;
938
- }
939
- }
940
-
941
- // src/utils/sleep.ts
942
- var sleep = async (ms) => {
943
- await new Promise((resolve) => setTimeout(resolve, ms));
944
- };
945
-
946
- // src/utils/validate.ts
947
- async function isValidComponent(component, availableComponents) {
948
- const components = availableComponents || await getAllComponents();
949
- return components.some((c) => c.name === component);
950
- }
951
-
952
- // src/commands/init.ts
953
- import path2 from "path";
954
- import * as p5 from "@clack/prompts";
955
- import semver4 from "semver";
956
-
957
- // src/templates/starwind.css.ts
958
- var tailwindConfig = `@import "tailwindcss";
959
- @import "tw-animate-css";
960
- @plugin "@tailwindcss/forms";
961
- @custom-variant dark (&:where(.dark, .dark *));
962
-
963
- @theme {
964
- --animate-accordion-down: accordion-down 0.2s ease-out;
965
- --animate-accordion-up: accordion-up 0.2s ease-out;
966
-
967
- @keyframes accordion-down {
968
- from {
969
- height: 0;
970
- }
971
- to {
972
- height: var(--starwind-accordion-content-height);
973
- }
974
- }
975
-
976
- @keyframes accordion-up {
977
- from {
978
- height: var(--starwind-accordion-content-height);
979
- }
980
- to {
981
- height: 0;
982
- }
983
- }
984
- }
985
-
986
- @theme inline {
987
- --color-background: var(--background);
988
- --color-foreground: var(--foreground);
989
- --color-card: var(--card);
990
- --color-card-foreground: var(--card-foreground);
991
- --color-popover: var(--popover);
992
- --color-popover-foreground: var(--popover-foreground);
993
- --color-primary: var(--primary);
994
- --color-primary-foreground: var(--primary-foreground);
995
- --color-primary-accent: var(--primary-accent);
996
- --color-secondary: var(--secondary);
997
- --color-secondary-foreground: var(--secondary-foreground);
998
- --color-secondary-accent: var(--secondary-accent);
999
- --color-muted: var(--muted);
1000
- --color-muted-foreground: var(--muted-foreground);
1001
- --color-accent: var(--accent);
1002
- --color-accent-foreground: var(--accent-foreground);
1003
- --color-info: var(--info);
1004
- --color-info-foreground: var(--info-foreground);
1005
- --color-success: var(--success);
1006
- --color-success-foreground: var(--success-foreground);
1007
- --color-warning: var(--warning);
1008
- --color-warning-foreground: var(--warning-foreground);
1009
- --color-error: var(--error);
1010
- --color-error-foreground: var(--error-foreground);
1011
- --color-border: var(--border);
1012
- --color-input: var(--input);
1013
- --color-outline: var(--outline);
1014
-
1015
- --radius-xs: calc(var(--radius) - 0.375rem);
1016
- --radius-sm: calc(var(--radius) - 0.25rem);
1017
- --radius-md: calc(var(--radius) - 0.125rem);
1018
- --radius-lg: var(--radius);
1019
- --radius-xl: calc(var(--radius) + 0.25rem);
1020
- --radius-2xl: calc(var(--radius) + 0.5rem);
1021
- --radius-3xl: calc(var(--radius) + 1rem);
1022
- }
1023
-
1024
- :root {
1025
- --background: var(--color-white);
1026
- --foreground: var(--color-neutral-950);
1027
- --card: var(--color-white);
1028
- --card-foreground: var(--color-neutral-950);
1029
- --popover: var(--color-white);
1030
- --popover-foreground: var(--color-neutral-950);
1031
- --primary: var(--color-blue-700);
1032
- --primary-foreground: var(--color-neutral-50);
1033
- --primary-accent: var(--color-blue-700);
1034
- --secondary: var(--color-fuchsia-700);
1035
- --secondary-foreground: var(--color-neutral-50);
1036
- --secondary-accent: var(--color-fuchsia-700);
1037
- --muted: var(--color-neutral-100);
1038
- --muted-foreground: var(--color-neutral-600);
1039
- --accent: var(--color-neutral-100);
1040
- --accent-foreground: var(--color-neutral-900);
1041
- --info: var(--color-sky-300);
1042
- --info-foreground: var(--color-sky-950);
1043
- --success: var(--color-green-300);
1044
- --success-foreground: var(--color-green-950);
1045
- --warning: var(--color-amber-300);
1046
- --warning-foreground: var(--color-amber-950);
1047
- --error: var(--color-red-700);
1048
- --error-foreground: var(--color-neutral-50);
1049
- --border: var(--color-neutral-200);
1050
- --input: var(--color-neutral-200);
1051
- --outline: var(--color-neutral-400);
1052
- --radius: 0.625rem;
1053
- }
1054
-
1055
- .dark {
1056
- --background: var(--color-neutral-950);
1057
- --foreground: var(--color-neutral-50);
1058
- --card: var(--color-neutral-900);
1059
- --card-foreground: var(--color-neutral-50);
1060
- --popover: var(--color-neutral-800);
1061
- --popover-foreground: var(--color-neutral-50);
1062
- --primary: var(--color-blue-700);
1063
- --primary-foreground: var(--color-neutral-50);
1064
- --primary-accent: var(--color-blue-400);
1065
- --secondary: var(--color-fuchsia-700);
1066
- --secondary-foreground: var(--color-neutral-50);
1067
- --secondary-accent: var(--color-fuchsia-400);
1068
- --muted: var(--color-neutral-800);
1069
- --muted-foreground: var(--color-neutral-400);
1070
- --accent: var(--color-neutral-700);
1071
- --accent-foreground: var(--color-neutral-100);
1072
- --info: var(--color-sky-300);
1073
- --info-foreground: var(--color-sky-950);
1074
- --success: var(--color-green-300);
1075
- --success-foreground: var(--color-green-950);
1076
- --warning: var(--color-amber-300);
1077
- --warning-foreground: var(--color-amber-950);
1078
- --error: var(--color-red-800);
1079
- --error-foreground: var(--color-neutral-50);
1080
- --border: --alpha(var(--color-neutral-50) / 10%);
1081
- --input: --alpha(var(--color-neutral-50) / 15%);
1082
- --outline: var(--color-neutral-500);
1083
- }
1084
-
1085
- @layer base {
1086
- * {
1087
- @apply border-border outline-outline/50;
1088
- }
1089
- body {
1090
- @apply bg-background text-foreground scheme-light dark:scheme-dark;
1091
- }
1092
- button {
1093
- @apply cursor-pointer;
1094
- }
1095
- }
1096
- `;
1097
-
1098
- // src/utils/astro-config.ts
1099
- import * as p4 from "@clack/prompts";
1100
- import fs3 from "fs-extra";
1101
- import semver3 from "semver";
1102
- var CONFIG_EXTENSIONS = ["ts", "js", "mjs", "cjs"];
1103
- async function findAstroConfig() {
1104
- for (const ext of CONFIG_EXTENSIONS) {
1105
- const configPath = `astro.config.${ext}`;
1106
- if (await fileExists(configPath)) {
1107
- return configPath;
1108
- }
1109
- }
1110
- return null;
1111
- }
1112
- async function getAstroVersion() {
1113
- try {
1114
- const pkg = await readJsonFile("package.json");
1115
- if (pkg.dependencies?.astro) {
1116
- const astroVersion = pkg.dependencies.astro.replace(/^\^|~/, "");
1117
- return astroVersion;
1118
- }
1119
- p4.log.error(
1120
- highlighter.error(
1121
- "Astro seems not installed in your project, please check your package.json"
1122
- )
1123
- );
1124
- return null;
1125
- } catch (error) {
1126
- const errorMessage = error instanceof Error ? error.message : "An unknown error occurred";
1127
- p4.log.error(highlighter.error(`Failed to check Astro version: ${errorMessage}`));
1128
- return null;
1129
- }
1130
- }
1131
- async function setupAstroConfig() {
1132
- try {
1133
- let configPath = await findAstroConfig();
1134
- let content = "";
1135
- if (configPath) {
1136
- content = await fs3.readFile(configPath, "utf-8");
1137
- } else {
1138
- configPath = "astro.config.ts";
1139
- content = `import { defineConfig } from "astro/config";
1140
-
1141
- export default defineConfig({});
1142
- `;
1143
- }
1144
- if (!content.includes('import tailwindcss from "@tailwindcss/vite"')) {
1145
- content = `import tailwindcss from "@tailwindcss/vite";
1146
- ${content}`;
1147
- }
1148
- const configStart = content.indexOf("defineConfig(") + "defineConfig(".length;
1149
- const configEnd = content.lastIndexOf(");");
1150
- let config = content.slice(configStart, configEnd);
1151
- config = config.trim().replace(/^{|}$/g, "").trim();
1152
- const astroVersion = await getAstroVersion();
1153
- if (astroVersion && semver3.lt(astroVersion, "5.7.0")) {
1154
- if (!config.includes("experimental")) {
1155
- config += `
1156
- experimental: {
1157
- svg: true,
1158
- },`;
1159
- } else if (!config.includes("svg: true") && !config.includes("svg: {")) {
1160
- const expEnd = config.indexOf("experimental:") + "experimental:".length;
1161
- const blockStart = config.indexOf("{", expEnd) + 1;
1162
- config = config.slice(0, blockStart) + `
1163
- svg: true,` + config.slice(blockStart);
1164
- }
1165
- }
1166
- if (!config.includes("vite:")) {
1167
- config += `
1168
- vite: {
1169
- plugins: [tailwindcss()],
1170
- },`;
1171
- } else if (!config.includes("plugins: [")) {
1172
- const viteEnd = config.indexOf("vite:") + "vite:".length;
1173
- const blockStart = config.indexOf("{", viteEnd) + 1;
1174
- config = config.slice(0, blockStart) + `
1175
- plugins: [tailwindcss()],` + config.slice(blockStart);
1176
- } else if (!config.includes("tailwindcss()")) {
1177
- const pluginsStart = config.indexOf("plugins:") + "plugins:".length;
1178
- const arrayStart = config.indexOf("[", pluginsStart) + 1;
1179
- config = config.slice(0, arrayStart) + `tailwindcss(), ` + config.slice(arrayStart);
1180
- }
1181
- const newContent = `${content.slice(0, configStart)}{
1182
- ${config}
1183
- }${content.slice(configEnd)}`;
1184
- await fs3.writeFile(configPath, newContent, "utf-8");
1185
- return true;
1186
- } catch (error) {
1187
- const errorMessage = error instanceof Error ? error.message : "An unknown error occurred";
1188
- p4.log.error(highlighter.error(`Failed to setup Astro config: ${errorMessage}`));
1189
- return false;
1190
- }
1191
- }
1192
-
1193
- // src/commands/init.ts
1194
- async function init(withinAdd = false, options) {
1195
- if (!withinAdd) {
1196
- p5.intro(highlighter.title(" Welcome to the Starwind CLI "));
1197
- }
1198
- try {
1199
- if (!await fileExists("package.json")) {
1200
- throw new Error(
1201
- "No package.json found. Please run this command in the root of your project."
1202
- );
1203
- }
1204
- const pkg = await readJsonFile("package.json");
1205
- const installTasks = [];
1206
- const configTasks = [];
1207
- let configChoices;
1208
- if (options?.defaults) {
1209
- configChoices = {
1210
- installLocation: PATHS.LOCAL_COMPONENTS_DIR,
1211
- cssFile: PATHS.LOCAL_CSS_FILE,
1212
- twBaseColor: "neutral"
1213
- };
1214
- if (!withinAdd) {
1215
- p5.log.info("Using default configuration values");
1216
- }
1217
- } else {
1218
- configChoices = await p5.group(
1219
- {
1220
- // ask where to install components
1221
- installLocation: () => p5.text({
1222
- message: "What is your components directory?",
1223
- placeholder: PATHS.LOCAL_COMPONENTS_DIR,
1224
- initialValue: PATHS.LOCAL_COMPONENTS_DIR,
1225
- validate(value) {
1226
- if (value.length === 0) return `Value is required!`;
1227
- if (path2.isAbsolute(value)) return `Please use a relative path`;
1228
- if (value.includes("..")) return `Path traversal is not allowed`;
1229
- const invalidChars = /[<>:"|?*]/;
1230
- if (invalidChars.test(value)) return `Path contains invalid characters`;
1231
- const systemDirs = ["windows", "program files", "system32"];
1232
- if (systemDirs.some((dir) => value.toLowerCase().startsWith(dir))) {
1233
- return `Cannot install in system directories`;
1234
- }
1235
- }
1236
- }),
1237
- // ask where to add the css file
1238
- cssFile: () => p5.text({
1239
- message: `Where would you like to add the Tailwind ${highlighter.info(".css")} file?`,
1240
- placeholder: PATHS.LOCAL_CSS_FILE,
1241
- initialValue: PATHS.LOCAL_CSS_FILE,
1242
- validate(value) {
1243
- if (value.length === 0) return `Value is required!`;
1244
- if (!value.endsWith(".css")) return `File must end with .css extension`;
1245
- if (path2.isAbsolute(value)) return `Please use a relative path`;
1246
- if (value.includes("..")) return `Path traversal is not allowed`;
1247
- const invalidChars = /[<>:"|?*]/;
1248
- if (invalidChars.test(value)) return `Path contains invalid characters`;
1249
- const systemDirs = ["windows", "program files", "system32"];
1250
- if (systemDirs.some((dir) => value.toLowerCase().startsWith(dir))) {
1251
- return `Cannot use system directories`;
1252
- }
1253
- const basename = path2.basename(value, ".css");
1254
- if (!basename || basename.trim().length === 0) {
1255
- return `Invalid filename`;
1256
- }
1257
- }
1258
- }),
1259
- twBaseColor: () => p5.select({
1260
- message: "What Tailwind base color would you like to use?",
1261
- initialValue: "neutral",
1262
- options: [
1263
- { label: "Neutral (default)", value: "neutral" },
1264
- { label: "Stone", value: "stone" },
1265
- { label: "Zinc", value: "zinc" },
1266
- { label: "Gray", value: "gray" },
1267
- { label: "Slate", value: "slate" }
1268
- ]
1269
- })
1270
- },
1271
- {
1272
- // On Cancel callback that wraps the group
1273
- // So if the user cancels one of the prompts in the group this function will be called
1274
- onCancel: () => {
1275
- p5.cancel("Operation cancelled.");
1276
- process.exit(0);
1277
- }
1278
- }
1279
- );
1280
- }
1281
- const cssFileDir = path2.dirname(configChoices.cssFile);
1282
- const componentInstallDir = path2.join(configChoices.installLocation, "starwind");
1283
- configTasks.push({
1284
- title: "Creating project structure",
1285
- task: async () => {
1286
- await ensureDirectory(componentInstallDir);
1287
- await ensureDirectory(cssFileDir);
1288
- await sleep(250);
1289
- return "Created project structure";
1290
- }
1291
- });
1292
- configTasks.push({
1293
- title: "Setup Astro config file",
1294
- task: async () => {
1295
- const success = await setupAstroConfig();
1296
- if (!success) {
1297
- throw new Error("Failed to setup Astro config");
1298
- }
1299
- await sleep(250);
1300
- return "Astro config setup completed";
1301
- }
1302
- });
1303
- const cssFileExists = await fileExists(configChoices.cssFile);
1304
- let updatedTailwindConfig = tailwindConfig;
1305
- if (configChoices.twBaseColor !== "neutral") {
1306
- updatedTailwindConfig = updatedTailwindConfig.replace(
1307
- /--color-neutral-/g,
1308
- `--color-${configChoices.twBaseColor}-`
1309
- );
1310
- }
1311
- if (cssFileExists) {
1312
- const shouldOverride = options?.defaults ? true : await p5.confirm({
1313
- message: `${highlighter.info(configChoices.cssFile)} already exists. Do you want to override it?`
1314
- });
1315
- if (p5.isCancel(shouldOverride)) {
1316
- p5.cancel("Operation cancelled");
1317
- return process.exit(0);
1318
- }
1319
- if (!shouldOverride) {
1320
- p5.log.info("Skipping Tailwind CSS configuration");
1321
- } else {
1322
- configTasks.push({
1323
- title: "Creating Tailwind CSS configuration",
1324
- task: async () => {
1325
- await writeCssFile(configChoices.cssFile, updatedTailwindConfig);
1326
- await sleep(250);
1327
- return "Created Tailwind configuration";
1328
- }
1329
- });
1330
- }
1331
- } else {
1332
- configTasks.push({
1333
- title: "Creating Tailwind CSS configuration",
1334
- task: async () => {
1335
- await writeCssFile(configChoices.cssFile, updatedTailwindConfig);
1336
- await sleep(250);
1337
- return "Created Tailwind configuration";
1338
- }
1339
- });
1340
- }
1341
- configTasks.push({
1342
- title: "Updating project configuration",
1343
- task: async () => {
1344
- await updateConfig({
1345
- tailwind: {
1346
- css: configChoices.cssFile,
1347
- baseColor: configChoices.twBaseColor,
1348
- cssVariables: true
1349
- },
1350
- // aliases: {
1351
- // components: "@/components",
1352
- // },
1353
- componentDir: configChoices.installLocation,
1354
- components: []
1355
- });
1356
- await sleep(250);
1357
- return "Updated project starwind configuration";
1358
- }
1359
- });
1360
- if (options?.pro) {
1361
- const alreadyHasPro = await hasStarwindProRegistry();
1362
- if (!alreadyHasPro) {
1363
- if (!withinAdd) {
1364
- p5.log.info(highlighter.info("Setting up Starwind Pro configuration..."));
1365
- }
1366
- configTasks.push({
1367
- title: "Setting up Starwind Pro registry",
1368
- task: async () => {
1369
- await setupShadcnProConfig(configChoices.cssFile, configChoices.twBaseColor);
1370
- await sleep(250);
1371
- return "Configured Starwind Pro registry in components.json";
1372
- }
1373
- });
1374
- } else {
1375
- if (!withinAdd) {
1376
- p5.log.info(highlighter.info("Starwind Pro registry already configured"));
1377
- }
1378
- }
1379
- }
1380
- const pm = options?.defaults ? await getDefaultPackageManager() : await requestPackageManager();
1381
- if (pkg.dependencies?.astro) {
1382
- const astroVersion = pkg.dependencies.astro.replace(/^\^|~/, "");
1383
- if (!semver4.gte(astroVersion, MIN_ASTRO_VERSION)) {
1384
- const shouldUpgrade = options?.defaults ? true : await p5.confirm({
1385
- message: `Starwind requires Astro v${MIN_ASTRO_VERSION} or higher. Would you like to upgrade from v${astroVersion}?`,
1386
- initialValue: true
1387
- });
1388
- if (p5.isCancel(shouldUpgrade)) {
1389
- p5.cancel("Operation cancelled");
1390
- return process.exit(0);
1391
- }
1392
- if (!shouldUpgrade) {
1393
- p5.cancel("Astro v5 or higher is required to use Starwind");
1394
- return process.exit(1);
1395
- }
1396
- installTasks.push({
1397
- title: "Upgrading Astro",
1398
- task: async () => {
1399
- await installDependencies([ASTRO_PACKAGES.core], pm);
1400
- return "Upgraded Astro successfully";
1401
- }
1402
- });
1403
- }
1404
- } else {
1405
- const shouldInstall2 = options?.defaults ? true : await p5.confirm({
1406
- message: `Starwind requires Astro v${MIN_ASTRO_VERSION} or higher. Would you like to install it?`,
1407
- initialValue: true
1408
- });
1409
- if (p5.isCancel(shouldInstall2)) {
1410
- p5.cancel("Operation cancelled");
1411
- return process.exit(0);
1412
- }
1413
- if (!shouldInstall2) {
1414
- p5.cancel("Astro is required to use Starwind");
1415
- return process.exit(1);
1416
- }
1417
- installTasks.push({
1418
- title: `Installing ${ASTRO_PACKAGES.core}`,
1419
- task: async () => {
1420
- await installDependencies([ASTRO_PACKAGES.core], pm);
1421
- return `Installed ${highlighter.info(ASTRO_PACKAGES.core)} successfully`;
1422
- }
1423
- });
1424
- }
1425
- const otherPackages = getOtherPackages();
1426
- const shouldInstall = options?.defaults ? true : await p5.confirm({
1427
- message: `Install ${highlighter.info(otherPackages.join(", "))} using ${highlighter.info(pm)}?`
1428
- });
1429
- if (p5.isCancel(shouldInstall)) {
1430
- p5.cancel("Operation cancelled");
1431
- return process.exit(0);
1432
- }
1433
- if (shouldInstall) {
1434
- installTasks.push({
1435
- title: `Installing packages`,
1436
- task: async () => {
1437
- await installDependencies(getOtherPackages(), pm, false, false);
1438
- return `${highlighter.info("Packages installed successfully")}`;
1439
- }
1440
- });
1441
- } else {
1442
- p5.log.warn(
1443
- highlighter.warn(`Skipped installation of packages. Make sure to install them manually`)
1444
- );
1445
- }
1446
- if (installTasks.length > 0) {
1447
- await p5.tasks(installTasks);
1448
- }
1449
- if (configTasks.length > 0) {
1450
- await p5.tasks(configTasks);
1451
- }
1452
- await sleep(250);
1453
- let nextStepsMessage = `Make sure your layout imports the ${highlighter.infoBright(configChoices.cssFile)} file`;
1454
- if (options?.pro) {
1455
- nextStepsMessage += `
1456
-
1457
- Starwind Pro is now configured! You can install pro components using:
1458
- ${highlighter.info("npx starwind@latest add @starwind-pro/component-name")}
1459
-
1460
- Make sure to set your ${highlighter.infoBright("STARWIND_LICENSE_KEY")} environment variable.`;
1461
- }
1462
- p5.note(nextStepsMessage, "Next steps");
1463
- if (!withinAdd) {
1464
- sleep(1e3);
1465
- const outroMessage = options?.pro ? "Enjoy using Starwind UI with Pro components! \u{1F680}\u2728" : "Enjoy using Starwind UI \u{1F680}";
1466
- p5.outro(outroMessage);
1467
- }
1468
- } catch (error) {
1469
- p5.log.error(error instanceof Error ? error.message : "Failed to add components");
1470
- p5.cancel("Operation cancelled");
1471
- process.exit(1);
1472
- }
1473
- }
1474
-
1475
- // src/commands/add.ts
1476
- async function add(components, options) {
1477
- try {
1478
- p6.intro(highlighter.title(" Welcome to the Starwind CLI "));
1479
- const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
1480
- if (!configExists) {
1481
- const shouldInit = await p6.confirm({
1482
- message: `Starwind configuration not found. Would you like to run ${highlighter.info("starwind init")} now?`,
1483
- initialValue: true
1484
- });
1485
- if (p6.isCancel(shouldInit)) {
1486
- p6.cancel("Operation cancelled");
1487
- process.exit(0);
1488
- }
1489
- if (shouldInit) {
1490
- await init(true);
1491
- } else {
1492
- p6.log.error(
1493
- `Please initialize starwind with ${highlighter.info("starwind init")} before adding components`
1494
- );
1495
- process.exit(1);
1496
- }
1497
- }
1498
- let componentsToInstall = [];
1499
- const registryComponents = [];
1500
- let registryResults = null;
1501
- if (options?.all) {
1502
- const availableComponents = await getAllComponents();
1503
- componentsToInstall = availableComponents.map((c) => c.name);
1504
- p6.log.info(`Adding all ${componentsToInstall.length} available components...`);
1505
- } else if (components && components.length > 0) {
1506
- const regularComponents = [];
1507
- for (const component of components) {
1508
- if (component.startsWith("@")) {
1509
- registryComponents.push(component);
1510
- } else {
1511
- regularComponents.push(component);
1512
- }
1513
- }
1514
- if (registryComponents.length > 0) {
1515
- const hasProRegistry = await hasStarwindProRegistry();
1516
- if (!hasProRegistry) {
1517
- const shouldSetupPro = await p6.confirm({
1518
- message: `Starwind Pro registry not configured. Would you like to set it up now to install ${registryComponents.join(", ")}?`,
1519
- initialValue: true
1520
- });
1521
- if (p6.isCancel(shouldSetupPro)) {
1522
- p6.cancel("Operation cancelled");
1523
- process.exit(0);
1524
- }
1525
- if (shouldSetupPro) {
1526
- p6.log.info(highlighter.info("Setting up Starwind Pro configuration..."));
1527
- let cssFile = PATHS.LOCAL_CSS_FILE;
1528
- let baseColor = "neutral";
1529
- try {
1530
- const config = await getConfig();
1531
- cssFile = config.tailwind?.css || PATHS.LOCAL_CSS_FILE;
1532
- baseColor = config.tailwind?.baseColor || "neutral";
1533
- } catch {
1534
- }
1535
- await setupShadcnProConfig(cssFile, baseColor);
1536
- p6.log.success("Starwind Pro registry configured successfully!");
1537
- } else {
1538
- p6.log.error("Cannot install registry components without Starwind Pro configuration");
1539
- p6.cancel("Operation cancelled");
1540
- process.exit(1);
1541
- }
1542
- }
1543
- p6.log.info(`Installing registry components: ${registryComponents.join(", ")}`);
1544
- const [command, baseArgs] = await getShadcnCommand();
1545
- registryResults = {
1546
- success: [],
1547
- failed: []
1548
- };
1549
- for (const registryComponent of registryComponents) {
1550
- try {
1551
- p6.log.info(`Installing ${highlighter.info(registryComponent)} via shadcn...`);
1552
- await execa2(command, [...baseArgs, "add", registryComponent], {
1553
- stdio: "inherit",
1554
- cwd: process.cwd()
1555
- });
1556
- registryResults.success.push(registryComponent);
1557
- } catch (error) {
1558
- registryResults.failed.push(registryComponent);
1559
- }
1560
- }
1561
- }
1562
- if (regularComponents.length > 0) {
1563
- const availableComponents = await getAllComponents();
1564
- const { valid, invalid } = await regularComponents.reduce(
1565
- async (accPromise, component) => {
1566
- const acc = await accPromise;
1567
- const isValid = await isValidComponent(component, availableComponents);
1568
- if (isValid) {
1569
- acc.valid.push(component);
1570
- } else {
1571
- acc.invalid.push(component);
1572
- }
1573
- return acc;
1574
- },
1575
- Promise.resolve({ valid: [], invalid: [] })
1576
- );
1577
- if (invalid.length > 0) {
1578
- p6.log.warn(
1579
- `${highlighter.warn("Invalid components found:")}
1580
- ${invalid.map((name) => ` ${name}`).join("\n")}`
1581
- );
1582
- }
1583
- if (valid.length > 0) {
1584
- componentsToInstall = valid;
1585
- } else if (registryComponents.length === 0) {
1586
- p6.log.warn(`${highlighter.warn("No valid components to install")}`);
1587
- p6.cancel("Operation cancelled");
1588
- return process.exit(0);
1589
- }
1590
- }
1591
- } else {
1592
- const selected = await selectComponents();
1593
- if (!selected) {
1594
- p6.cancel("No components selected");
1595
- return process.exit(0);
1596
- }
1597
- componentsToInstall = selected;
1598
- }
1599
- if (componentsToInstall.length === 0 && registryComponents.length === 0) {
1600
- p6.log.warn(`${highlighter.warn("No components selected")}`);
1601
- p6.cancel("Operation cancelled");
1602
- return process.exit(0);
1603
- }
1604
- const results = {
1605
- installed: [],
1606
- skipped: [],
1607
- failed: []
1608
- };
1609
- const installedComponents = [];
1610
- for (const comp of componentsToInstall) {
1611
- const result = await installComponent(comp);
1612
- switch (result.status) {
1613
- case "installed":
1614
- results.installed.push(result);
1615
- installedComponents.push({ name: result.name, version: result.version });
1616
- if (result.dependencyResults) {
1617
- for (const depResult of result.dependencyResults) {
1618
- switch (depResult.status) {
1619
- case "installed":
1620
- results.installed.push(depResult);
1621
- break;
1622
- case "skipped":
1623
- results.skipped.push(depResult);
1624
- break;
1625
- case "failed":
1626
- results.failed.push(depResult);
1627
- break;
1628
- }
1629
- }
1630
- }
1631
- break;
1632
- case "skipped":
1633
- results.skipped.push(result);
1634
- break;
1635
- case "failed":
1636
- results.failed.push(result);
1637
- if (result.dependencyResults) {
1638
- for (const depResult of result.dependencyResults) {
1639
- switch (depResult.status) {
1640
- case "installed":
1641
- results.installed.push(depResult);
1642
- break;
1643
- case "skipped":
1644
- results.skipped.push(depResult);
1645
- break;
1646
- case "failed":
1647
- results.failed.push(depResult);
1648
- break;
1649
- }
1650
- }
1651
- }
1652
- break;
1653
- }
1654
- }
1655
- if (installedComponents.length > 0) {
1656
- try {
1657
- await updateConfig({ components: installedComponents }, { appendComponents: true });
1658
- } catch (error) {
1659
- p6.log.error(
1660
- `Failed to update config: ${error instanceof Error ? error.message : "Unknown error"}`
1661
- );
1662
- process.exit(1);
1663
- }
1664
- }
1665
- p6.log.message(`
1666
-
1667
- ${highlighter.underline("Installation Summary")}`);
1668
- if (results.failed.length > 0) {
1669
- p6.log.error(
1670
- `${highlighter.error("Failed to install components:")}
1671
- ${results.failed.map((r) => ` ${r.name} - ${r.error}`).join("\n")}`
1672
- );
1673
- }
1674
- if (results.skipped.length > 0) {
1675
- p6.log.warn(
1676
- `${highlighter.warn("Skipped components (already installed):")}
1677
- ${results.skipped.map((r) => ` ${r.name} v${r.version}`).join("\n")}`
1678
- );
1679
- }
1680
- if (results.installed.length > 0) {
1681
- p6.log.success(
1682
- `${highlighter.success("Successfully installed components:")}
1683
- ${results.installed.map((r) => ` ${r.name} v${r.version}`).join("\n")}`
1684
- );
1685
- }
1686
- if (registryResults) {
1687
- if (registryResults.failed.length > 0) {
1688
- p6.log.error(
1689
- `${highlighter.error("Failed to install registry components:")}
1690
- ${registryResults.failed.map((name) => ` ${name} - see the error message above for further details`).join("\n")}`
1691
- );
1692
- }
1693
- if (registryResults.success.length > 0) {
1694
- p6.log.success(
1695
- `${highlighter.success("Successfully installed registry components:")}
1696
- ${registryResults.success.map((name) => ` ${name}`).join("\n")}`
1697
- );
1698
- }
1699
- }
1700
- await sleep(1e3);
1701
- p6.outro("Enjoy using Starwind UI \u{1F680}");
1702
- } catch (error) {
1703
- p6.log.error(error instanceof Error ? error.message : "Failed to add components");
1704
- p6.cancel("Operation cancelled");
1705
- process.exit(1);
1706
- }
1707
- }
1708
-
1709
- // src/commands/remove.ts
1710
- import * as p7 from "@clack/prompts";
1711
- async function remove(components, options) {
1712
- try {
1713
- p7.intro(highlighter.title(" Welcome to the Starwind CLI "));
1714
- const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
1715
- if (!configExists) {
1716
- p7.log.error("No Starwind configuration found. Please run starwind init first.");
1717
- process.exit(1);
1718
- }
1719
- const config = await getConfig();
1720
- const installedComponents = config.components;
1721
- if (installedComponents.length === 0) {
1722
- p7.log.warn("No components are currently installed.");
1723
- process.exit(0);
1724
- }
1725
- let componentsToRemove = [];
1726
- if (options?.all) {
1727
- componentsToRemove = installedComponents.map((comp) => comp.name);
1728
- p7.log.info(`Removing all ${componentsToRemove.length} installed components...`);
1729
- } else if (components && components.length > 0) {
1730
- const invalid = components.filter(
1731
- (comp) => !installedComponents.some((ic) => ic.name === comp)
1732
- );
1733
- if (invalid.length > 0) {
1734
- p7.log.warn(
1735
- `${highlighter.warn("Components not found:")}
1736
- ${invalid.map((name) => ` ${name}`).join("\n")}`
1737
- );
1738
- }
1739
- componentsToRemove = components.filter(
1740
- (comp) => installedComponents.some((ic) => ic.name === comp)
1741
- );
1742
- if (componentsToRemove.length === 0) {
1743
- p7.log.warn("No valid components to remove");
1744
- process.exit(0);
1745
- }
1746
- } else {
1747
- const choices = installedComponents.map((comp) => ({
1748
- value: comp.name,
1749
- label: comp.name
1750
- }));
1751
- const selected = await p7.multiselect({
1752
- message: "Select components to remove",
1753
- options: choices
1754
- });
1755
- if (p7.isCancel(selected)) {
1756
- p7.cancel("Operation cancelled");
1757
- process.exit(0);
1758
- }
1759
- componentsToRemove = selected;
1760
- }
1761
- if (componentsToRemove.length === 0) {
1762
- p7.log.warn("No components selected for removal");
1763
- process.exit(0);
1764
- }
1765
- const confirmed = await p7.confirm({
1766
- message: `Remove ${componentsToRemove.map((comp) => highlighter.info(comp)).join(", ")} ${componentsToRemove.length > 1 ? "components" : "component"}?`
1767
- });
1768
- if (!confirmed || p7.isCancel(confirmed)) {
1769
- p7.cancel("Operation cancelled");
1770
- process.exit(0);
1771
- }
1772
- const results = {
1773
- removed: [],
1774
- failed: []
1775
- };
1776
- for (const comp of componentsToRemove) {
1777
- const result = await removeComponent(comp, config.componentDir);
1778
- if (result.status === "removed") {
1779
- results.removed.push(result);
1780
- } else {
1781
- results.failed.push(result);
1782
- }
1783
- }
1784
- const updatedComponents = config.components.filter(
1785
- (comp) => !componentsToRemove.includes(comp.name)
1786
- );
1787
- await updateConfig(
1788
- {
1789
- ...config,
1790
- components: updatedComponents
1791
- },
1792
- { appendComponents: false }
1793
- );
1794
- p7.log.message(`
1795
-
1796
- ${highlighter.underline("Removal Summary")}`);
1797
- if (results.failed.length > 0) {
1798
- p7.log.error(
1799
- `${highlighter.error("Failed to remove components:")}
1800
- ${results.failed.map((r) => ` ${r.name} - ${r.error}`).join("\n")}`
1801
- );
1802
- }
1803
- if (results.removed.length > 0) {
1804
- p7.log.success(
1805
- `${highlighter.success("Successfully removed components:")}
1806
- ${results.removed.map((r) => ` ${r.name}`).join("\n")}`
1807
- );
1808
- }
1809
- await sleep(1e3);
1810
- if (results.removed.length > 0) {
1811
- p7.outro("Components removed successfully \u{1F5D1}\uFE0F");
1812
- } else {
1813
- p7.cancel("Errors occurred while removing components");
1814
- process.exit(1);
1815
- }
1816
- } catch (error) {
1817
- p7.log.error(error instanceof Error ? error.message : "Failed to remove components");
1818
- p7.cancel("Operation cancelled");
1819
- process.exit(1);
1820
- }
1821
- }
1822
-
1823
- // src/commands/update.ts
1824
- import * as p8 from "@clack/prompts";
1825
- async function update(components, options) {
1826
- try {
1827
- p8.intro(highlighter.title(" Welcome to the Starwind CLI "));
1828
- const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
1829
- if (!configExists) {
1830
- p8.log.error("No Starwind configuration found. Please run starwind init first.");
1831
- process.exit(1);
1832
- }
1833
- const config = await getConfig();
1834
- const installedComponents = config.components;
1835
- if (installedComponents.length === 0) {
1836
- p8.log.warn("No components are currently installed.");
1837
- process.exit(0);
1838
- }
1839
- let componentsToUpdate = [];
1840
- if (options?.all) {
1841
- componentsToUpdate = installedComponents.map((comp) => comp.name);
1842
- p8.log.info(`Checking updates for all ${componentsToUpdate.length} installed components...`);
1843
- } else if (components && components.length > 0) {
1844
- const invalid = components.filter(
1845
- (comp) => !installedComponents.some((ic) => ic.name === comp)
1846
- );
1847
- if (invalid.length > 0) {
1848
- p8.log.warn(
1849
- `${highlighter.warn("Components not found in project:")}
1850
- ${invalid.map((name) => ` ${name}`).join("\n")}`
1851
- );
1852
- }
1853
- componentsToUpdate = components.filter(
1854
- (comp) => installedComponents.some((ic) => ic.name === comp)
1855
- );
1856
- if (componentsToUpdate.length === 0) {
1857
- p8.log.warn("No valid components to update");
1858
- process.exit(0);
1859
- }
1860
- } else {
1861
- const choices = installedComponents.map((comp) => ({
1862
- value: comp.name,
1863
- label: comp.name
1864
- }));
1865
- const selected = await p8.multiselect({
1866
- message: "Select components to update",
1867
- options: choices
1868
- });
1869
- if (p8.isCancel(selected)) {
1870
- p8.cancel("Operation cancelled");
1871
- process.exit(0);
1872
- }
1873
- componentsToUpdate = selected;
1874
- }
1875
- if (componentsToUpdate.length === 0) {
1876
- p8.log.warn("No components selected for update");
1877
- process.exit(0);
1878
- }
1879
- const results = {
1880
- updated: [],
1881
- skipped: [],
1882
- failed: []
1883
- };
1884
- for (const comp of componentsToUpdate) {
1885
- const currentVersion = installedComponents.find((ic) => ic.name === comp)?.version;
1886
- if (!currentVersion) {
1887
- results.failed.push({
1888
- name: comp,
1889
- status: "failed",
1890
- error: "Could not determine current version"
1891
- });
1892
- continue;
1893
- }
1894
- const result = await updateComponent(comp, currentVersion, options?.yes);
1895
- switch (result.status) {
1896
- case "updated":
1897
- results.updated.push(result);
1898
- break;
1899
- case "skipped":
1900
- results.skipped.push(result);
1901
- break;
1902
- case "failed":
1903
- results.failed.push(result);
1904
- break;
1905
- }
1906
- }
1907
- if (results.updated.length > 0) {
1908
- try {
1909
- const updatedComponentNames = new Set(results.updated.map((r) => r.name));
1910
- const currentComponents = config.components.filter(
1911
- (comp) => !updatedComponentNames.has(comp.name)
1912
- );
1913
- const updatedComponents = [
1914
- ...currentComponents,
1915
- ...results.updated.map((r) => ({
1916
- name: r.name,
1917
- version: r.newVersion
1918
- }))
1919
- ];
1920
- await updateConfig(
1921
- {
1922
- components: updatedComponents
1923
- },
1924
- { appendComponents: false }
1925
- );
1926
- } catch (error) {
1927
- p8.log.error(
1928
- `Failed to update config: ${error instanceof Error ? error.message : "Unknown error"}`
1929
- );
1930
- process.exit(1);
1931
- }
1932
- }
1933
- p8.log.message(`
1934
-
1935
- ${highlighter.underline("Update Summary")}`);
1936
- if (results.failed.length > 0) {
1937
- p8.log.error(
1938
- `${highlighter.error("Failed to update components:")}
1939
- ${results.failed.map((r) => ` ${r.name} - ${r.error}`).join("\n")}`
1940
- );
1941
- }
1942
- if (results.skipped.length > 0) {
1943
- p8.log.info(
1944
- `${highlighter.info("Components already up to date or skipped:")}
1945
- ${results.skipped.map((r) => ` ${r.name} (${r.oldVersion})`).join("\n")}`
1946
- );
1947
- }
1948
- if (results.updated.length > 0) {
1949
- p8.log.success(
1950
- `${highlighter.success("Successfully updated components:")}
1951
- ${results.updated.map((r) => ` ${r.name} (${r.oldVersion} \u2192 ${r.newVersion})`).join("\n")}`
1952
- );
1953
- }
1954
- await sleep(1e3);
1955
- if (results.updated.length > 0) {
1956
- p8.outro("Components updated successfully \u{1F680}");
1957
- } else if (results.skipped.length > 0 && results.failed.length === 0) {
1958
- p8.outro("Components already up to date or skipped \u2728");
1959
- } else {
1960
- p8.cancel("No components were updated");
1961
- process.exit(1);
1962
- }
1963
- } catch (error) {
1964
- p8.log.error(error instanceof Error ? error.message : "Failed to update components");
1965
- p8.cancel("Operation cancelled");
1966
- process.exit(1);
1967
- }
1968
- }
1969
-
1970
- // src/index.ts
1971
- var program = new Command().name("starwind").description("Add beautifully designed components to your Astro applications").version(package_default.version);
1972
- program.command("init").description("Initialize your project with Starwind").option("-d, --defaults", "Use default values for all prompts").option("-p, --pro", "Initialize with Starwind Pro setup").action((options) => init(false, { defaults: options.defaults, pro: options.pro }));
1973
- program.command("add").description("Add Starwind components to your project").argument("[components...]", "The components to add (space separated)").allowExcessArguments().option("-a, --all", "Add all available components").action(add);
1974
- program.command("update").description("Update Starwind components to their latest versions").argument("[components...]", "The components to update (space separated)").allowExcessArguments().option("-a, --all", "Update all installed components").option("-y, --yes", "Skip confirmation prompts").action(update);
1975
- program.command("remove").description("Remove Starwind components from your project").argument("[components...]", "The components to remove (space separated)").allowExcessArguments().option("-a, --all", "Remove all installed components").action(remove);
1976
- program.parse();
1977
- //# sourceMappingURL=index.js.map