starwind 0.0.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 ADDED
@@ -0,0 +1,638 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ PATHS,
4
+ fileExists,
5
+ getConfig,
6
+ highlighter,
7
+ init,
8
+ installDependencies,
9
+ requestPackageManager,
10
+ sleep,
11
+ updateConfig
12
+ } from "./chunk-JUEM67WU.js";
13
+
14
+ // src/index.ts
15
+ import { Command } from "commander";
16
+
17
+ // src/utils/component.ts
18
+ import * as path from "node:path";
19
+ import { fileURLToPath } from "node:url";
20
+ import fs from "fs-extra";
21
+
22
+ // src/utils/registry.ts
23
+ import { registry } from "@starwind-ui/core";
24
+ import { z } from "zod";
25
+ var componentSchema = z.object({
26
+ name: z.string(),
27
+ version: z.string(),
28
+ dependencies: z.array(z.string()).default([]),
29
+ type: z.enum(["component"])
30
+ });
31
+ var registrySchema = z.array(componentSchema);
32
+ async function getRegistry() {
33
+ try {
34
+ return registrySchema.parse(registry);
35
+ } catch (error) {
36
+ console.error("Failed to load registry:", error);
37
+ throw error;
38
+ }
39
+ }
40
+ async function getComponent(name) {
41
+ const registry2 = await getRegistry();
42
+ return registry2.find((component) => component.name === name);
43
+ }
44
+ async function getAllComponents() {
45
+ return getRegistry();
46
+ }
47
+
48
+ // src/utils/component.ts
49
+ import semver from "semver";
50
+ async function copyComponent(name, overwrite = false) {
51
+ const config = await getConfig();
52
+ const currentComponents = Array.isArray(config.components) ? config.components : [];
53
+ if (!overwrite && currentComponents.some((component) => component.name === name)) {
54
+ const existingComponent = currentComponents.find((c) => c.name === name);
55
+ return {
56
+ status: "skipped",
57
+ name,
58
+ version: existingComponent?.version
59
+ };
60
+ }
61
+ const componentDir = path.join(config.componentDir, "starwind", name);
62
+ try {
63
+ await fs.ensureDir(componentDir);
64
+ const pkgUrl = import.meta.resolve?.(PATHS.STARWIND_CORE);
65
+ if (!pkgUrl) {
66
+ throw new Error(`Could not resolve ${PATHS.STARWIND_CORE} package, is it installed?`);
67
+ }
68
+ const coreDir = path.dirname(fileURLToPath(pkgUrl));
69
+ const sourceDir = path.join(coreDir, PATHS.STARWIND_CORE_COMPONENTS, name);
70
+ const files = await fs.readdir(sourceDir);
71
+ for (const file of files) {
72
+ const sourcePath = path.join(sourceDir, file);
73
+ const destPath = path.join(componentDir, file);
74
+ await fs.copy(sourcePath, destPath, { overwrite: true });
75
+ }
76
+ const registry2 = await getRegistry();
77
+ const componentInfo = registry2.find((c) => c.name === name);
78
+ if (!componentInfo) {
79
+ throw new Error(`Component ${name} not found in registry`);
80
+ }
81
+ return {
82
+ status: "installed",
83
+ name,
84
+ version: componentInfo.version
85
+ };
86
+ } catch (error) {
87
+ return {
88
+ status: "failed",
89
+ name,
90
+ error: error instanceof Error ? error.message : "Unknown error"
91
+ };
92
+ }
93
+ }
94
+ async function removeComponent(name, componentDir) {
95
+ try {
96
+ const componentPath = path.join(componentDir, "starwind", name);
97
+ if (await fs.pathExists(componentPath)) {
98
+ await fs.remove(componentPath);
99
+ return { name, status: "removed" };
100
+ } else {
101
+ return {
102
+ name,
103
+ status: "failed",
104
+ error: "Component directory not found"
105
+ };
106
+ }
107
+ } catch (error) {
108
+ return {
109
+ name,
110
+ status: "failed",
111
+ error: error instanceof Error ? error.message : "Unknown error"
112
+ };
113
+ }
114
+ }
115
+ async function updateComponent(name, currentVersion) {
116
+ try {
117
+ const registryComponent = await getComponent(name);
118
+ if (!registryComponent) {
119
+ return {
120
+ name,
121
+ status: "failed",
122
+ error: "Component not found in registry"
123
+ };
124
+ }
125
+ if (!semver.gt(registryComponent.version, currentVersion)) {
126
+ return {
127
+ name,
128
+ status: "skipped",
129
+ oldVersion: currentVersion,
130
+ newVersion: registryComponent.version
131
+ };
132
+ }
133
+ const result = await copyComponent(name, true);
134
+ if (result.status === "installed") {
135
+ return {
136
+ name,
137
+ status: "updated",
138
+ oldVersion: currentVersion,
139
+ newVersion: result.version
140
+ };
141
+ } else {
142
+ return {
143
+ name,
144
+ status: "failed",
145
+ error: result.error || "Failed to update component"
146
+ };
147
+ }
148
+ } catch (error) {
149
+ return {
150
+ name,
151
+ status: "failed",
152
+ error: error instanceof Error ? error.message : "Unknown error"
153
+ };
154
+ }
155
+ }
156
+
157
+ // src/utils/prompts.ts
158
+ import { confirm, multiselect } from "@clack/prompts";
159
+ async function selectComponents() {
160
+ const components = await getAllComponents();
161
+ const selected = await multiselect({
162
+ message: "Select components to add",
163
+ options: components.map((component) => ({
164
+ label: component.name,
165
+ value: component.name
166
+ })),
167
+ required: false
168
+ });
169
+ if (typeof selected === "symbol") {
170
+ return [];
171
+ }
172
+ return selected;
173
+ }
174
+ async function confirmInstall(component) {
175
+ if (component.dependencies.length === 0) return true;
176
+ const confirmed = await confirm({
177
+ message: `This component requires the following dependencies: ${component.dependencies.join(", ")}. Install them?`
178
+ });
179
+ if (typeof confirmed === "symbol") {
180
+ return false;
181
+ }
182
+ return confirmed;
183
+ }
184
+
185
+ // src/utils/install.ts
186
+ async function installComponent(name) {
187
+ const component = await getComponent(name);
188
+ if (!component) {
189
+ return {
190
+ status: "failed",
191
+ name,
192
+ error: "Component not found in registry"
193
+ };
194
+ }
195
+ if (component.dependencies.length > 0) {
196
+ const confirmed = await confirmInstall(component);
197
+ if (!confirmed) {
198
+ return {
199
+ status: "failed",
200
+ name,
201
+ error: "Installation cancelled by user"
202
+ };
203
+ }
204
+ try {
205
+ const pm = await requestPackageManager();
206
+ await installDependencies(component.dependencies, pm);
207
+ } catch (error) {
208
+ return {
209
+ status: "failed",
210
+ name,
211
+ error: `Failed to install dependencies: ${error instanceof Error ? error.message : String(error)}`
212
+ };
213
+ }
214
+ }
215
+ return await copyComponent(name);
216
+ }
217
+
218
+ // src/utils/validate.ts
219
+ async function isValidComponent(component, availableComponents) {
220
+ const components = availableComponents || await getAllComponents();
221
+ return components.some((c) => c.name === component);
222
+ }
223
+
224
+ // src/commands/add.ts
225
+ import * as p from "@clack/prompts";
226
+ var { init: init2 } = await import("./init-JA2KC6GS.js");
227
+ async function add(components, options) {
228
+ try {
229
+ p.intro(highlighter.title(" Welcome to the Starwind CLI "));
230
+ const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
231
+ if (!configExists) {
232
+ const shouldInit = await p.confirm({
233
+ message: `Starwind configuration not found. Would you like to run ${highlighter.info("starwind init")} now?`,
234
+ initialValue: true
235
+ });
236
+ if (p.isCancel(shouldInit)) {
237
+ p.cancel("Operation cancelled");
238
+ process.exit(0);
239
+ }
240
+ if (shouldInit) {
241
+ await init2(true);
242
+ } else {
243
+ p.log.error(
244
+ `Please initialize starwind with ${highlighter.info("starwind init")} before adding components`
245
+ );
246
+ process.exit(1);
247
+ }
248
+ }
249
+ let componentsToInstall = [];
250
+ if (options?.all) {
251
+ const availableComponents = await getAllComponents();
252
+ componentsToInstall = availableComponents.map((c) => c.name);
253
+ p.log.info(`Adding all ${componentsToInstall.length} available components...`);
254
+ } else if (components && components.length > 0) {
255
+ const availableComponents = await getAllComponents();
256
+ const { valid, invalid } = await components.reduce(
257
+ async (accPromise, component) => {
258
+ const acc = await accPromise;
259
+ const isValid = await isValidComponent(component, availableComponents);
260
+ if (isValid) {
261
+ acc.valid.push(component);
262
+ } else {
263
+ acc.invalid.push(component);
264
+ }
265
+ return acc;
266
+ },
267
+ Promise.resolve({ valid: [], invalid: [] })
268
+ );
269
+ if (invalid.length > 0) {
270
+ p.log.warn(
271
+ `${highlighter.warn("Invalid components found:")}
272
+ ${invalid.map((name) => ` ${name}`).join("\n")}`
273
+ );
274
+ }
275
+ if (valid.length > 0) {
276
+ componentsToInstall = valid;
277
+ } else {
278
+ p.log.warn(`${highlighter.warn("No valid components to install")}`);
279
+ p.cancel("Operation cancelled");
280
+ return process.exit(0);
281
+ }
282
+ } else {
283
+ const selected = await selectComponents();
284
+ if (!selected) {
285
+ p.cancel("No components selected");
286
+ return process.exit(0);
287
+ }
288
+ componentsToInstall = selected;
289
+ }
290
+ if (componentsToInstall.length === 0) {
291
+ p.log.warn(`${highlighter.warn("No components selected")}`);
292
+ p.cancel("Operation cancelled");
293
+ return process.exit(0);
294
+ }
295
+ const confirmed = await p.confirm({
296
+ message: `Install ${componentsToInstall.map((comp) => highlighter.info(comp)).join(", ")} ${componentsToInstall.length > 1 ? "components" : "component"}?`
297
+ });
298
+ if (!confirmed || p.isCancel(confirmed)) {
299
+ p.cancel("Operation cancelled");
300
+ return process.exit(0);
301
+ }
302
+ const results = {
303
+ installed: [],
304
+ skipped: [],
305
+ failed: []
306
+ };
307
+ const installedComponents = [];
308
+ for (const comp of componentsToInstall) {
309
+ const result = await installComponent(comp);
310
+ switch (result.status) {
311
+ case "installed":
312
+ results.installed.push(result);
313
+ installedComponents.push({ name: result.name, version: result.version });
314
+ break;
315
+ case "skipped":
316
+ results.skipped.push(result);
317
+ break;
318
+ case "failed":
319
+ results.failed.push(result);
320
+ break;
321
+ }
322
+ }
323
+ if (installedComponents.length > 0) {
324
+ try {
325
+ await updateConfig({ components: installedComponents }, { appendComponents: true });
326
+ } catch (error) {
327
+ p.log.error(
328
+ `Failed to update config: ${error instanceof Error ? error.message : "Unknown error"}`
329
+ );
330
+ process.exit(1);
331
+ }
332
+ }
333
+ p.log.message(`
334
+
335
+ ${highlighter.underline("Installation Summary")}`);
336
+ if (results.installed.length > 0) {
337
+ p.log.success(
338
+ `${highlighter.success("Successfully installed components:")}
339
+ ${results.installed.map((r) => ` ${r.name} v${r.version}`).join("\n")}`
340
+ );
341
+ }
342
+ if (results.skipped.length > 0) {
343
+ p.log.warn(
344
+ `${highlighter.warn("Skipped components (already installed):")}
345
+ ${results.skipped.map((r) => ` ${r.name} v${r.version}`).join("\n")}`
346
+ );
347
+ }
348
+ if (results.failed.length > 0) {
349
+ p.log.error(
350
+ `${highlighter.error("Failed to install components:")}
351
+ ${results.failed.map((r) => ` ${r.name} - ${r.error}`).join("\n")}`
352
+ );
353
+ }
354
+ await sleep(1e3);
355
+ p.outro("Enjoy using Starwind UI \u{1F680}");
356
+ } catch (error) {
357
+ p.log.error(error instanceof Error ? error.message : "Failed to add components");
358
+ p.cancel("Operation cancelled");
359
+ process.exit(1);
360
+ }
361
+ }
362
+
363
+ // src/commands/remove.ts
364
+ import * as p2 from "@clack/prompts";
365
+ async function remove(components, options) {
366
+ try {
367
+ p2.intro(highlighter.title(" Welcome to the Starwind CLI "));
368
+ const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
369
+ if (!configExists) {
370
+ p2.log.error("No Starwind configuration found. Please run starwind init first.");
371
+ process.exit(1);
372
+ }
373
+ const config = await getConfig();
374
+ const installedComponents = config.components;
375
+ if (installedComponents.length === 0) {
376
+ p2.log.warn("No components are currently installed.");
377
+ process.exit(0);
378
+ }
379
+ let componentsToRemove = [];
380
+ if (options?.all) {
381
+ componentsToRemove = installedComponents.map((comp) => comp.name);
382
+ p2.log.info(`Removing all ${componentsToRemove.length} installed components...`);
383
+ } else if (components && components.length > 0) {
384
+ const invalid = components.filter(
385
+ (comp) => !installedComponents.some((ic) => ic.name === comp)
386
+ );
387
+ if (invalid.length > 0) {
388
+ p2.log.warn(
389
+ `${highlighter.warn("Components not found:")}
390
+ ${invalid.map((name) => ` ${name}`).join("\n")}`
391
+ );
392
+ }
393
+ componentsToRemove = components.filter(
394
+ (comp) => installedComponents.some((ic) => ic.name === comp)
395
+ );
396
+ if (componentsToRemove.length === 0) {
397
+ p2.log.warn("No valid components to remove");
398
+ process.exit(0);
399
+ }
400
+ } else {
401
+ const choices = installedComponents.map((comp) => ({
402
+ value: comp.name,
403
+ label: comp.name
404
+ }));
405
+ const selected = await p2.multiselect({
406
+ message: "Select components to remove",
407
+ options: choices
408
+ });
409
+ if (p2.isCancel(selected)) {
410
+ p2.cancel("Operation cancelled");
411
+ process.exit(0);
412
+ }
413
+ componentsToRemove = selected;
414
+ }
415
+ if (componentsToRemove.length === 0) {
416
+ p2.log.warn("No components selected for removal");
417
+ process.exit(0);
418
+ }
419
+ const confirmed = await p2.confirm({
420
+ message: `Remove ${componentsToRemove.map((comp) => highlighter.info(comp)).join(", ")} ${componentsToRemove.length > 1 ? "components" : "component"}?`
421
+ });
422
+ if (!confirmed || p2.isCancel(confirmed)) {
423
+ p2.cancel("Operation cancelled");
424
+ process.exit(0);
425
+ }
426
+ const results = {
427
+ removed: [],
428
+ failed: []
429
+ };
430
+ for (const comp of componentsToRemove) {
431
+ const result = await removeComponent(comp, config.componentDir);
432
+ if (result.status === "removed") {
433
+ results.removed.push(result);
434
+ } else {
435
+ results.failed.push(result);
436
+ }
437
+ }
438
+ const updatedComponents = config.components.filter(
439
+ (comp) => !componentsToRemove.includes(comp.name)
440
+ );
441
+ await updateConfig(
442
+ {
443
+ ...config,
444
+ components: updatedComponents
445
+ },
446
+ { appendComponents: false }
447
+ );
448
+ p2.log.message(`
449
+
450
+ ${highlighter.underline("Removal Summary")}`);
451
+ if (results.removed.length > 0) {
452
+ p2.log.success(
453
+ `${highlighter.success("Successfully removed components:")}
454
+ ${results.removed.map((r) => ` ${r.name}`).join("\n")}`
455
+ );
456
+ }
457
+ if (results.failed.length > 0) {
458
+ p2.log.error(
459
+ `${highlighter.error("Failed to remove components:")}
460
+ ${results.failed.map((r) => ` ${r.name} - ${r.error}`).join("\n")}`
461
+ );
462
+ }
463
+ await sleep(1e3);
464
+ if (results.removed.length > 0) {
465
+ p2.outro("Components removed successfully \u{1F5D1}\uFE0F");
466
+ } else {
467
+ p2.cancel("Errors occurred while removing components");
468
+ process.exit(1);
469
+ }
470
+ } catch (error) {
471
+ p2.log.error(error instanceof Error ? error.message : "Failed to remove components");
472
+ p2.cancel("Operation cancelled");
473
+ process.exit(1);
474
+ }
475
+ }
476
+
477
+ // src/commands/update.ts
478
+ import * as p3 from "@clack/prompts";
479
+ async function update(components, options) {
480
+ try {
481
+ p3.intro(highlighter.title(" Welcome to the Starwind CLI "));
482
+ const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
483
+ if (!configExists) {
484
+ p3.log.error("No Starwind configuration found. Please run starwind init first.");
485
+ process.exit(1);
486
+ }
487
+ const config = await getConfig();
488
+ const installedComponents = config.components;
489
+ if (installedComponents.length === 0) {
490
+ p3.log.warn("No components are currently installed.");
491
+ process.exit(0);
492
+ }
493
+ let componentsToUpdate = [];
494
+ if (options?.all) {
495
+ componentsToUpdate = installedComponents.map((comp) => comp.name);
496
+ p3.log.info(`Checking updates for all ${componentsToUpdate.length} installed components...`);
497
+ } else if (components && components.length > 0) {
498
+ const invalid = components.filter(
499
+ (comp) => !installedComponents.some((ic) => ic.name === comp)
500
+ );
501
+ if (invalid.length > 0) {
502
+ p3.log.warn(
503
+ `${highlighter.warn("Components not found in project:")}
504
+ ${invalid.map((name) => ` ${name}`).join("\n")}`
505
+ );
506
+ }
507
+ componentsToUpdate = components.filter(
508
+ (comp) => installedComponents.some((ic) => ic.name === comp)
509
+ );
510
+ if (componentsToUpdate.length === 0) {
511
+ p3.log.warn("No valid components to update");
512
+ process.exit(0);
513
+ }
514
+ } else {
515
+ const choices = installedComponents.map((comp) => ({
516
+ value: comp.name,
517
+ label: comp.name
518
+ }));
519
+ const selected = await p3.multiselect({
520
+ message: "Select components to update",
521
+ options: choices
522
+ });
523
+ if (p3.isCancel(selected)) {
524
+ p3.cancel("Operation cancelled");
525
+ process.exit(0);
526
+ }
527
+ componentsToUpdate = selected;
528
+ }
529
+ if (componentsToUpdate.length === 0) {
530
+ p3.log.warn("No components selected for update");
531
+ process.exit(0);
532
+ }
533
+ const confirmed = await p3.confirm({
534
+ message: `Check for updates to ${componentsToUpdate.map((comp) => highlighter.info(comp)).join(", ")} ${componentsToUpdate.length > 1 ? "components" : "component"}?`
535
+ });
536
+ if (!confirmed || p3.isCancel(confirmed)) {
537
+ p3.cancel("Operation cancelled");
538
+ process.exit(0);
539
+ }
540
+ const results = {
541
+ updated: [],
542
+ skipped: [],
543
+ failed: []
544
+ };
545
+ for (const comp of componentsToUpdate) {
546
+ const currentVersion = installedComponents.find((ic) => ic.name === comp)?.version;
547
+ if (!currentVersion) {
548
+ results.failed.push({
549
+ name: comp,
550
+ status: "failed",
551
+ error: "Could not determine current version"
552
+ });
553
+ continue;
554
+ }
555
+ const result = await updateComponent(comp, currentVersion);
556
+ switch (result.status) {
557
+ case "updated":
558
+ results.updated.push(result);
559
+ break;
560
+ case "skipped":
561
+ results.skipped.push(result);
562
+ break;
563
+ case "failed":
564
+ results.failed.push(result);
565
+ break;
566
+ }
567
+ }
568
+ if (results.updated.length > 0) {
569
+ try {
570
+ const updatedComponentNames = new Set(results.updated.map((r) => r.name));
571
+ const currentComponents = config.components.filter(
572
+ (comp) => !updatedComponentNames.has(comp.name)
573
+ );
574
+ const updatedComponents = [
575
+ ...currentComponents,
576
+ ...results.updated.map((r) => ({
577
+ name: r.name,
578
+ version: r.newVersion
579
+ }))
580
+ ];
581
+ await updateConfig(
582
+ {
583
+ components: updatedComponents
584
+ },
585
+ { appendComponents: false }
586
+ );
587
+ } catch (error) {
588
+ p3.log.error(
589
+ `Failed to update config: ${error instanceof Error ? error.message : "Unknown error"}`
590
+ );
591
+ process.exit(1);
592
+ }
593
+ }
594
+ p3.log.message(`
595
+
596
+ ${highlighter.underline("Update Summary")}`);
597
+ if (results.skipped.length > 0) {
598
+ p3.log.info(
599
+ `${highlighter.info("Components already up to date:")}
600
+ ${results.skipped.map((r) => ` ${r.name} (${r.newVersion})`).join("\n")}`
601
+ );
602
+ }
603
+ if (results.updated.length > 0) {
604
+ p3.log.success(
605
+ `${highlighter.success("Successfully updated components:")}
606
+ ${results.updated.map((r) => ` ${r.name} (${r.oldVersion} \u2192 ${r.newVersion})`).join("\n")}`
607
+ );
608
+ }
609
+ if (results.failed.length > 0) {
610
+ p3.log.error(
611
+ `${highlighter.error("Failed to update components:")}
612
+ ${results.failed.map((r) => ` ${r.name} - ${r.error}`).join("\n")}`
613
+ );
614
+ }
615
+ await sleep(1e3);
616
+ if (results.updated.length > 0) {
617
+ p3.outro("Components updated successfully \u{1F680}");
618
+ } else if (results.skipped.length > 0 && results.failed.length === 0) {
619
+ p3.outro("All components are up to date \u2728");
620
+ } else {
621
+ p3.cancel("No components were updated");
622
+ process.exit(1);
623
+ }
624
+ } catch (error) {
625
+ p3.log.error(error instanceof Error ? error.message : "Failed to update components");
626
+ p3.cancel("Operation cancelled");
627
+ process.exit(1);
628
+ }
629
+ }
630
+
631
+ // src/index.ts
632
+ var program = new Command().name("starwind").description("Add beautifully designed components to your Astro applications").version("0.0.1");
633
+ program.command("init").description("Initialize your project with Starwind").option("--no-install", "Skip dependency installation").action(() => init(false));
634
+ 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);
635
+ 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").action(update);
636
+ 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);
637
+ program.parse();
638
+ //# sourceMappingURL=index.js.map