starwind 1.16.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +370 -71
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command, Option } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "starwind",
|
|
9
|
-
version: "
|
|
9
|
+
version: "2.0.0",
|
|
10
10
|
description: "Add beautifully designed components to your Astro applications",
|
|
11
11
|
license: "MIT",
|
|
12
12
|
homepage: "https://starwind.dev/",
|
|
@@ -44,7 +44,7 @@ var package_default = {
|
|
|
44
44
|
scripts: {
|
|
45
45
|
build: "tsup",
|
|
46
46
|
dev: "tsup --watch",
|
|
47
|
-
"cli:link": "pnpm
|
|
47
|
+
"cli:link": "pnpm add --global . --ignore-scripts",
|
|
48
48
|
"cli:unlink": "pnpm rm --global starwind",
|
|
49
49
|
"cli:yalc:link": "yalc publish && yalc link @starwind-ui/core",
|
|
50
50
|
"cli:yalc:unlink": "yalc remove @starwind-ui/core && yalc remove starwind",
|
|
@@ -60,7 +60,7 @@ var package_default = {
|
|
|
60
60
|
},
|
|
61
61
|
dependencies: {
|
|
62
62
|
"@clack/prompts": "^0.11.0",
|
|
63
|
-
"@starwind-ui/core": "
|
|
63
|
+
"@starwind-ui/core": "2.0.0",
|
|
64
64
|
chalk: "^5.6.2",
|
|
65
65
|
commander: "^14.0.2",
|
|
66
66
|
execa: "^9.6.0",
|
|
@@ -76,7 +76,7 @@ var package_default = {
|
|
|
76
76
|
tsup: "^8.5.1"
|
|
77
77
|
},
|
|
78
78
|
engines: {
|
|
79
|
-
node: "
|
|
79
|
+
node: ">=22.12.0"
|
|
80
80
|
}
|
|
81
81
|
};
|
|
82
82
|
|
|
@@ -90,6 +90,7 @@ var PATHS = {
|
|
|
90
90
|
STARWIND_CORE: "@starwind-ui/core",
|
|
91
91
|
STARWIND_CORE_COMPONENTS: "src/components",
|
|
92
92
|
STARWIND_CORE_UTILS: "src/lib/utils",
|
|
93
|
+
STARWIND_DOCS_BASE_URL: "https://starwind.dev/docs/components",
|
|
93
94
|
STARWIND_REMOTE_COMPONENT_REGISTRY: "https://starwind.dev/registry.json",
|
|
94
95
|
STARWIND_PRO_REGISTRY: "https://pro.starwind.dev/r/{name}",
|
|
95
96
|
LOCAL_CSS_FILE: "src/styles/starwind.css",
|
|
@@ -724,7 +725,7 @@ async function getShadcnCommand() {
|
|
|
724
725
|
return ["bunx", ["shadcn@3"]];
|
|
725
726
|
case "npm":
|
|
726
727
|
default:
|
|
727
|
-
return ["npx", ["shadcn@3"]];
|
|
728
|
+
return ["npx", ["-y", "shadcn@3"]];
|
|
728
729
|
}
|
|
729
730
|
}
|
|
730
731
|
async function installDependencies(packages, pm, dev = false, force = false) {
|
|
@@ -909,7 +910,7 @@ async function installComponent(name, options) {
|
|
|
909
910
|
}
|
|
910
911
|
}
|
|
911
912
|
}
|
|
912
|
-
const result = await copyComponent(name);
|
|
913
|
+
const result = await copyComponent(name, options?.overwrite);
|
|
913
914
|
if (dependencyResults.length > 0) {
|
|
914
915
|
return {
|
|
915
916
|
...result,
|
|
@@ -2069,11 +2070,21 @@ async function add(components, options) {
|
|
|
2069
2070
|
};
|
|
2070
2071
|
for (const registryComponent of registryComponents) {
|
|
2071
2072
|
try {
|
|
2072
|
-
p9.log.info(`Installing ${highlighter.info(registryComponent)}
|
|
2073
|
-
await execa2(
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2073
|
+
p9.log.info(`Installing ${highlighter.info(registryComponent)}`);
|
|
2074
|
+
await execa2(
|
|
2075
|
+
command,
|
|
2076
|
+
[
|
|
2077
|
+
...baseArgs,
|
|
2078
|
+
"add",
|
|
2079
|
+
"--yes",
|
|
2080
|
+
...options?.overwrite ? ["--overwrite"] : [],
|
|
2081
|
+
registryComponent
|
|
2082
|
+
],
|
|
2083
|
+
{
|
|
2084
|
+
stdio: "inherit",
|
|
2085
|
+
cwd: process.cwd()
|
|
2086
|
+
}
|
|
2087
|
+
);
|
|
2077
2088
|
registryResults.success.push(registryComponent);
|
|
2078
2089
|
} catch (error) {
|
|
2079
2090
|
registryResults.failed.push(registryComponent);
|
|
@@ -2150,6 +2161,7 @@ ${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
|
2150
2161
|
}
|
|
2151
2162
|
const result = await installComponent(comp, {
|
|
2152
2163
|
skipPrompts: options?.yes,
|
|
2164
|
+
overwrite: options?.overwrite,
|
|
2153
2165
|
packageManager: options?.packageManager
|
|
2154
2166
|
});
|
|
2155
2167
|
if (result.dependencyResults) {
|
|
@@ -2216,32 +2228,67 @@ ${registryResults.success.map((name) => ` ${name}`).join("\n")}`
|
|
|
2216
2228
|
}
|
|
2217
2229
|
}
|
|
2218
2230
|
|
|
2219
|
-
// src/commands/
|
|
2231
|
+
// src/commands/docs.ts
|
|
2220
2232
|
import * as p10 from "@clack/prompts";
|
|
2233
|
+
var DOCS_BASE_URL = "https://starwind.dev/docs/components";
|
|
2234
|
+
async function docs(components, options) {
|
|
2235
|
+
if (!options?.json) {
|
|
2236
|
+
p10.intro(highlighter.title(" Starwind Docs "));
|
|
2237
|
+
}
|
|
2238
|
+
try {
|
|
2239
|
+
const registry = await getAllComponents();
|
|
2240
|
+
const results = [];
|
|
2241
|
+
for (const name of components) {
|
|
2242
|
+
const exists = registry.find((c) => c.name === name);
|
|
2243
|
+
if (!exists) {
|
|
2244
|
+
p10.log.error(`Component ${highlighter.info(name)} not found in the Starwind registry.`);
|
|
2245
|
+
process.exit(1);
|
|
2246
|
+
}
|
|
2247
|
+
results.push({ component: name, url: `${DOCS_BASE_URL}/${name}/` });
|
|
2248
|
+
}
|
|
2249
|
+
if (options?.json) {
|
|
2250
|
+
console.log(JSON.stringify(results, null, 2));
|
|
2251
|
+
return;
|
|
2252
|
+
}
|
|
2253
|
+
const maxNameLength = Math.max(...results.map((r) => r.component.length));
|
|
2254
|
+
p10.log.message(highlighter.underline("Documentation links"));
|
|
2255
|
+
for (const { component, url } of results) {
|
|
2256
|
+
p10.log.info(` ${highlighter.info(component.padEnd(maxNameLength + 2))}${url}`);
|
|
2257
|
+
}
|
|
2258
|
+
p10.outro(`Found docs for ${results.length} component${results.length === 1 ? "" : "s"}`);
|
|
2259
|
+
} catch (error) {
|
|
2260
|
+
p10.log.error(error instanceof Error ? error.message : "Failed to fetch documentation");
|
|
2261
|
+
p10.cancel("Operation cancelled");
|
|
2262
|
+
process.exit(1);
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
// src/commands/remove.ts
|
|
2267
|
+
import * as p11 from "@clack/prompts";
|
|
2221
2268
|
async function remove(components, options) {
|
|
2222
2269
|
try {
|
|
2223
|
-
|
|
2270
|
+
p11.intro(highlighter.title(" Welcome to the Starwind CLI "));
|
|
2224
2271
|
const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
|
|
2225
2272
|
if (!configExists) {
|
|
2226
|
-
|
|
2273
|
+
p11.log.error("No Starwind configuration found. Please run starwind init first.");
|
|
2227
2274
|
process.exit(1);
|
|
2228
2275
|
}
|
|
2229
2276
|
const config = await getConfig();
|
|
2230
2277
|
const installedComponents = config.components;
|
|
2231
2278
|
if (installedComponents.length === 0) {
|
|
2232
|
-
|
|
2279
|
+
p11.log.warn("No components are currently installed.");
|
|
2233
2280
|
process.exit(0);
|
|
2234
2281
|
}
|
|
2235
2282
|
let componentsToRemove = [];
|
|
2236
2283
|
if (options?.all) {
|
|
2237
2284
|
componentsToRemove = installedComponents.map((comp) => comp.name);
|
|
2238
|
-
|
|
2285
|
+
p11.log.info(`Removing all ${componentsToRemove.length} installed components...`);
|
|
2239
2286
|
} else if (components && components.length > 0) {
|
|
2240
2287
|
const invalid = components.filter(
|
|
2241
2288
|
(comp) => !installedComponents.some((ic) => ic.name === comp)
|
|
2242
2289
|
);
|
|
2243
2290
|
if (invalid.length > 0) {
|
|
2244
|
-
|
|
2291
|
+
p11.log.warn(
|
|
2245
2292
|
`${highlighter.warn("Components not found:")}
|
|
2246
2293
|
${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
2247
2294
|
);
|
|
@@ -2250,7 +2297,7 @@ ${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
|
2250
2297
|
(comp) => installedComponents.some((ic) => ic.name === comp)
|
|
2251
2298
|
);
|
|
2252
2299
|
if (componentsToRemove.length === 0) {
|
|
2253
|
-
|
|
2300
|
+
p11.log.warn("No valid components to remove");
|
|
2254
2301
|
process.exit(0);
|
|
2255
2302
|
}
|
|
2256
2303
|
} else {
|
|
@@ -2258,25 +2305,25 @@ ${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
|
2258
2305
|
value: comp.name,
|
|
2259
2306
|
label: comp.name
|
|
2260
2307
|
}));
|
|
2261
|
-
const selected = await
|
|
2308
|
+
const selected = await p11.multiselect({
|
|
2262
2309
|
message: "Select components to remove",
|
|
2263
2310
|
options: choices
|
|
2264
2311
|
});
|
|
2265
|
-
if (
|
|
2266
|
-
|
|
2312
|
+
if (p11.isCancel(selected)) {
|
|
2313
|
+
p11.cancel("Operation cancelled");
|
|
2267
2314
|
process.exit(0);
|
|
2268
2315
|
}
|
|
2269
2316
|
componentsToRemove = selected;
|
|
2270
2317
|
}
|
|
2271
2318
|
if (componentsToRemove.length === 0) {
|
|
2272
|
-
|
|
2319
|
+
p11.log.warn("No components selected for removal");
|
|
2273
2320
|
process.exit(0);
|
|
2274
2321
|
}
|
|
2275
|
-
const confirmed = await
|
|
2322
|
+
const confirmed = await p11.confirm({
|
|
2276
2323
|
message: `Remove ${componentsToRemove.map((comp) => highlighter.info(comp)).join(", ")} ${componentsToRemove.length > 1 ? "components" : "component"}?`
|
|
2277
2324
|
});
|
|
2278
|
-
if (!confirmed ||
|
|
2279
|
-
|
|
2325
|
+
if (!confirmed || p11.isCancel(confirmed)) {
|
|
2326
|
+
p11.cancel("Operation cancelled");
|
|
2280
2327
|
process.exit(0);
|
|
2281
2328
|
}
|
|
2282
2329
|
const results = {
|
|
@@ -2301,60 +2348,295 @@ ${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
|
2301
2348
|
},
|
|
2302
2349
|
{ appendComponents: false }
|
|
2303
2350
|
);
|
|
2304
|
-
|
|
2351
|
+
p11.log.message(`
|
|
2305
2352
|
|
|
2306
2353
|
${highlighter.underline("Removal Summary")}`);
|
|
2307
2354
|
if (results.failed.length > 0) {
|
|
2308
|
-
|
|
2355
|
+
p11.log.error(
|
|
2309
2356
|
`${highlighter.error("Failed to remove components:")}
|
|
2310
2357
|
${results.failed.map((r) => ` ${r.name} - ${r.error}`).join("\n")}`
|
|
2311
2358
|
);
|
|
2312
2359
|
}
|
|
2313
2360
|
if (results.removed.length > 0) {
|
|
2314
|
-
|
|
2361
|
+
p11.log.success(
|
|
2315
2362
|
`${highlighter.success("Successfully removed components:")}
|
|
2316
2363
|
${results.removed.map((r) => ` ${r.name}`).join("\n")}`
|
|
2317
2364
|
);
|
|
2318
2365
|
}
|
|
2319
2366
|
await sleep(1e3);
|
|
2320
2367
|
if (results.removed.length > 0) {
|
|
2321
|
-
|
|
2368
|
+
p11.outro("Components removed successfully \u{1F5D1}\uFE0F");
|
|
2322
2369
|
} else {
|
|
2323
|
-
|
|
2370
|
+
p11.cancel("Errors occurred while removing components");
|
|
2324
2371
|
process.exit(1);
|
|
2325
2372
|
}
|
|
2326
2373
|
} catch (error) {
|
|
2327
|
-
|
|
2328
|
-
|
|
2374
|
+
p11.log.error(error instanceof Error ? error.message : "Failed to remove components");
|
|
2375
|
+
p11.cancel("Operation cancelled");
|
|
2376
|
+
process.exit(1);
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
// src/commands/search.ts
|
|
2381
|
+
import * as p12 from "@clack/prompts";
|
|
2382
|
+
|
|
2383
|
+
// src/utils/pro-manifest.ts
|
|
2384
|
+
import { z as z2 } from "zod";
|
|
2385
|
+
var manifestBlockSchema = z2.object({
|
|
2386
|
+
id: z2.string(),
|
|
2387
|
+
name: z2.string(),
|
|
2388
|
+
description: z2.string(),
|
|
2389
|
+
categories: z2.array(z2.string()),
|
|
2390
|
+
keywords: z2.array(z2.string()),
|
|
2391
|
+
plan: z2.enum(["free", "pro"]),
|
|
2392
|
+
installCommand: z2.string(),
|
|
2393
|
+
previewUrl: z2.string()
|
|
2394
|
+
});
|
|
2395
|
+
var manifestSchema = z2.object({
|
|
2396
|
+
$schema: z2.string().optional(),
|
|
2397
|
+
name: z2.string(),
|
|
2398
|
+
version: z2.string(),
|
|
2399
|
+
generatedAt: z2.string(),
|
|
2400
|
+
baseUrl: z2.string(),
|
|
2401
|
+
totalBlocks: z2.number(),
|
|
2402
|
+
categories: z2.array(z2.string()),
|
|
2403
|
+
blocks: z2.array(manifestBlockSchema)
|
|
2404
|
+
});
|
|
2405
|
+
var MANIFEST_URL = "https://pro.starwind.dev/r/manifest.json";
|
|
2406
|
+
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
2407
|
+
var manifestCache = null;
|
|
2408
|
+
async function getProManifest() {
|
|
2409
|
+
if (manifestCache && Date.now() < manifestCache.expiresAt) {
|
|
2410
|
+
return { manifest: manifestCache.data, source: "cache" };
|
|
2411
|
+
}
|
|
2412
|
+
try {
|
|
2413
|
+
const response = await fetch(MANIFEST_URL);
|
|
2414
|
+
if (!response.ok) {
|
|
2415
|
+
throw new Error(`Failed to fetch manifest: ${response.status} ${response.statusText}`);
|
|
2416
|
+
}
|
|
2417
|
+
const raw = await response.json();
|
|
2418
|
+
const manifest = manifestSchema.parse(raw);
|
|
2419
|
+
manifestCache = {
|
|
2420
|
+
data: manifest,
|
|
2421
|
+
timestamp: Date.now(),
|
|
2422
|
+
expiresAt: Date.now() + CACHE_TTL_MS
|
|
2423
|
+
};
|
|
2424
|
+
return { manifest, source: "network" };
|
|
2425
|
+
} catch (error) {
|
|
2426
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
2427
|
+
throw new Error(`Error fetching Starwind Pro manifest: ${message}`);
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
function scoreBlockMatch(block, query) {
|
|
2431
|
+
const q = query.toLowerCase();
|
|
2432
|
+
let score = 0;
|
|
2433
|
+
if (block.name.toLowerCase() === q) score += 100;
|
|
2434
|
+
else if (block.name.toLowerCase().includes(q)) score += 50;
|
|
2435
|
+
if (block.id.toLowerCase().includes(q)) score += 40;
|
|
2436
|
+
if (block.keywords.some((k) => k.toLowerCase() === q)) score += 30;
|
|
2437
|
+
if (block.keywords.some((k) => k.toLowerCase().includes(q))) score += 20;
|
|
2438
|
+
if (block.description.toLowerCase().includes(q)) score += 10;
|
|
2439
|
+
if (block.categories.some((c) => c.toLowerCase().includes(q))) score += 15;
|
|
2440
|
+
return score;
|
|
2441
|
+
}
|
|
2442
|
+
async function searchProBlocks(options = {}) {
|
|
2443
|
+
const { query, category, plan, limit = 50, offset = 0 } = options;
|
|
2444
|
+
const { manifest } = await getProManifest();
|
|
2445
|
+
let results = [...manifest.blocks];
|
|
2446
|
+
if (category) {
|
|
2447
|
+
const catLower = category.toLowerCase();
|
|
2448
|
+
results = results.filter((b) => b.categories.some((c) => c.toLowerCase() === catLower));
|
|
2449
|
+
}
|
|
2450
|
+
if (plan) {
|
|
2451
|
+
results = results.filter((b) => b.plan === plan);
|
|
2452
|
+
}
|
|
2453
|
+
if (query) {
|
|
2454
|
+
const scored = results.map((block) => ({ block, score: scoreBlockMatch(block, query) })).filter(({ score }) => score > 0).sort((a, b) => b.score - a.score);
|
|
2455
|
+
results = scored.map(({ block }) => block);
|
|
2456
|
+
}
|
|
2457
|
+
const effectiveLimit = Math.min(Math.max(1, limit), 50);
|
|
2458
|
+
const effectiveOffset = Math.max(0, offset);
|
|
2459
|
+
return results.slice(effectiveOffset, effectiveOffset + effectiveLimit);
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
// src/commands/search.ts
|
|
2463
|
+
async function search(query, options) {
|
|
2464
|
+
if (!options?.json) {
|
|
2465
|
+
p12.intro(highlighter.title(" Starwind Search "));
|
|
2466
|
+
}
|
|
2467
|
+
try {
|
|
2468
|
+
const proOnly = !!(options?.category || options?.plan);
|
|
2469
|
+
let proBlocks = [];
|
|
2470
|
+
let matchedComponents = [];
|
|
2471
|
+
if (options?.json) {
|
|
2472
|
+
proBlocks = await searchProBlocks({
|
|
2473
|
+
query,
|
|
2474
|
+
category: options?.category,
|
|
2475
|
+
plan: options?.plan,
|
|
2476
|
+
limit: options?.limit ?? 20,
|
|
2477
|
+
offset: options?.offset ?? 0
|
|
2478
|
+
});
|
|
2479
|
+
if (!proOnly) {
|
|
2480
|
+
const coreComponents = await getAllComponents();
|
|
2481
|
+
if (query) {
|
|
2482
|
+
const q = query.toLowerCase();
|
|
2483
|
+
matchedComponents = coreComponents.filter(
|
|
2484
|
+
(c) => c.name.toLowerCase().includes(q) || (c.dependencies ?? []).some((dep) => dep.toLowerCase().includes(q))
|
|
2485
|
+
);
|
|
2486
|
+
} else {
|
|
2487
|
+
matchedComponents = coreComponents;
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
} else {
|
|
2491
|
+
const searchTasks = [
|
|
2492
|
+
{
|
|
2493
|
+
title: "Searching Starwind Pro blocks",
|
|
2494
|
+
task: async () => {
|
|
2495
|
+
proBlocks = await searchProBlocks({
|
|
2496
|
+
query,
|
|
2497
|
+
category: options?.category,
|
|
2498
|
+
plan: options?.plan,
|
|
2499
|
+
limit: options?.limit ?? 20,
|
|
2500
|
+
offset: options?.offset ?? 0
|
|
2501
|
+
});
|
|
2502
|
+
return `Found ${proBlocks.length} Pro block${proBlocks.length === 1 ? "" : "s"}`;
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
];
|
|
2506
|
+
if (!proOnly) {
|
|
2507
|
+
searchTasks.push({
|
|
2508
|
+
title: "Searching core components",
|
|
2509
|
+
task: async () => {
|
|
2510
|
+
const coreComponents = await getAllComponents();
|
|
2511
|
+
if (query) {
|
|
2512
|
+
const q = query.toLowerCase();
|
|
2513
|
+
matchedComponents = coreComponents.filter(
|
|
2514
|
+
(c) => c.name.toLowerCase().includes(q) || (c.dependencies ?? []).some((dep) => dep.toLowerCase().includes(q))
|
|
2515
|
+
);
|
|
2516
|
+
} else {
|
|
2517
|
+
matchedComponents = coreComponents;
|
|
2518
|
+
}
|
|
2519
|
+
return `Found ${matchedComponents.length} core component${matchedComponents.length === 1 ? "" : "s"}`;
|
|
2520
|
+
}
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2523
|
+
await p12.tasks(searchTasks);
|
|
2524
|
+
}
|
|
2525
|
+
if (options?.json) {
|
|
2526
|
+
console.log(
|
|
2527
|
+
JSON.stringify(
|
|
2528
|
+
{
|
|
2529
|
+
query: query || null,
|
|
2530
|
+
filters: {
|
|
2531
|
+
category: options?.category || null,
|
|
2532
|
+
plan: options?.plan || null,
|
|
2533
|
+
limit: options?.limit ?? 20
|
|
2534
|
+
},
|
|
2535
|
+
proBlocks: {
|
|
2536
|
+
total: proBlocks.length,
|
|
2537
|
+
results: proBlocks.map((b) => ({
|
|
2538
|
+
id: b.id,
|
|
2539
|
+
name: b.name,
|
|
2540
|
+
description: b.description,
|
|
2541
|
+
categories: b.categories,
|
|
2542
|
+
plan: b.plan,
|
|
2543
|
+
installCommand: b.installCommand + " --yes"
|
|
2544
|
+
}))
|
|
2545
|
+
},
|
|
2546
|
+
coreComponents: {
|
|
2547
|
+
total: matchedComponents.length,
|
|
2548
|
+
results: matchedComponents.map((c) => ({
|
|
2549
|
+
name: c.name,
|
|
2550
|
+
version: c.version,
|
|
2551
|
+
dependencies: c.dependencies,
|
|
2552
|
+
docsUrl: `${PATHS.STARWIND_DOCS_BASE_URL}/${c.name}/`
|
|
2553
|
+
}))
|
|
2554
|
+
},
|
|
2555
|
+
proSetupTip: "Run `starwind setup` to enable Starwind Pro blocks"
|
|
2556
|
+
},
|
|
2557
|
+
null,
|
|
2558
|
+
2
|
|
2559
|
+
)
|
|
2560
|
+
);
|
|
2561
|
+
return;
|
|
2562
|
+
}
|
|
2563
|
+
const hasPro = proBlocks.length > 0;
|
|
2564
|
+
const hasCore = matchedComponents.length > 0;
|
|
2565
|
+
if (!hasPro && !hasCore) {
|
|
2566
|
+
p12.log.warn("No results found for your search.");
|
|
2567
|
+
p12.outro("Try a different query or browse all categories.");
|
|
2568
|
+
return;
|
|
2569
|
+
}
|
|
2570
|
+
if (hasPro) {
|
|
2571
|
+
p12.log.message(highlighter.underline("Pro Blocks"));
|
|
2572
|
+
const maxNameLen = Math.max(...proBlocks.map((b) => b.name.length));
|
|
2573
|
+
for (const block of proBlocks) {
|
|
2574
|
+
const planBadge = block.plan === "pro" ? highlighter.info("[pro] ") : highlighter.success("[free]");
|
|
2575
|
+
const paddedName = block.name.padEnd(maxNameLen + 2);
|
|
2576
|
+
p12.log.info(` ${highlighter.info(paddedName)}${planBadge} ${block.installCommand}`);
|
|
2577
|
+
}
|
|
2578
|
+
console.log();
|
|
2579
|
+
}
|
|
2580
|
+
if (hasCore) {
|
|
2581
|
+
p12.log.message(highlighter.underline("Core Components"));
|
|
2582
|
+
const maxNameLen = Math.max(...matchedComponents.map((c) => c.name.length));
|
|
2583
|
+
for (const comp of matchedComponents) {
|
|
2584
|
+
const paddedName = comp.name.padEnd(maxNameLen + 2);
|
|
2585
|
+
p12.log.info(` ${highlighter.info(paddedName)}starwind add ${comp.name}`);
|
|
2586
|
+
}
|
|
2587
|
+
console.log();
|
|
2588
|
+
}
|
|
2589
|
+
if (proBlocks.length > 0) {
|
|
2590
|
+
const proConfigured = await hasStarwindProRegistry();
|
|
2591
|
+
const hasPaidBlocks = proBlocks.some((b) => b.plan === "pro");
|
|
2592
|
+
if (!proConfigured) {
|
|
2593
|
+
p12.note(
|
|
2594
|
+
`Pro blocks require Starwind Pro setup.
|
|
2595
|
+
Run ${highlighter.info("starwind setup")} to configure.`,
|
|
2596
|
+
"Pro Tip"
|
|
2597
|
+
);
|
|
2598
|
+
} else if (hasPaidBlocks) {
|
|
2599
|
+
p12.note(
|
|
2600
|
+
`Unlock premium blocks at ${highlighter.info("https://pro.starwind.dev/")}`,
|
|
2601
|
+
"Pro Tip"
|
|
2602
|
+
);
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
p12.outro(
|
|
2606
|
+
`Found ${proBlocks.length + matchedComponents.length} result${proBlocks.length + matchedComponents.length === 1 ? "" : "s"} \u{1F50E}`
|
|
2607
|
+
);
|
|
2608
|
+
} catch (error) {
|
|
2609
|
+
p12.log.error(error instanceof Error ? error.message : "Failed to search");
|
|
2610
|
+
p12.cancel("Operation cancelled");
|
|
2329
2611
|
process.exit(1);
|
|
2330
2612
|
}
|
|
2331
2613
|
}
|
|
2332
2614
|
|
|
2333
2615
|
// src/commands/setup.ts
|
|
2334
|
-
import * as
|
|
2616
|
+
import * as p13 from "@clack/prompts";
|
|
2335
2617
|
async function setup(options) {
|
|
2336
|
-
|
|
2618
|
+
p13.intro(highlighter.title(" Using Starwind Setup "));
|
|
2337
2619
|
try {
|
|
2338
2620
|
const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
|
|
2339
2621
|
if (!configExists) {
|
|
2340
|
-
const shouldInit = options?.yes ? true : await
|
|
2622
|
+
const shouldInit = options?.yes ? true : await p13.confirm({
|
|
2341
2623
|
message: `Starwind configuration not found. Would you like to run ${highlighter.info("starwind init")} now?`,
|
|
2342
2624
|
initialValue: true
|
|
2343
2625
|
});
|
|
2344
|
-
if (
|
|
2345
|
-
|
|
2626
|
+
if (p13.isCancel(shouldInit)) {
|
|
2627
|
+
p13.cancel("Operation cancelled");
|
|
2346
2628
|
process.exit(0);
|
|
2347
2629
|
}
|
|
2348
2630
|
if (shouldInit) {
|
|
2349
2631
|
await init(true, { defaults: options?.yes, packageManager: options?.packageManager });
|
|
2350
2632
|
} else {
|
|
2351
|
-
|
|
2633
|
+
p13.log.error(
|
|
2352
2634
|
`Please initialize starwind with ${highlighter.info("starwind init")} before running setup`
|
|
2353
2635
|
);
|
|
2354
2636
|
process.exit(1);
|
|
2355
2637
|
}
|
|
2356
2638
|
}
|
|
2357
|
-
const
|
|
2639
|
+
const tasks5 = [
|
|
2358
2640
|
{
|
|
2359
2641
|
name: "Starwind Pro",
|
|
2360
2642
|
value: "pro",
|
|
@@ -2366,32 +2648,32 @@ async function setup(options) {
|
|
|
2366
2648
|
];
|
|
2367
2649
|
const selectedTasks = [];
|
|
2368
2650
|
if (options?.pro) {
|
|
2369
|
-
const proTask =
|
|
2651
|
+
const proTask = tasks5.find((t) => t.value === "pro");
|
|
2370
2652
|
if (proTask) selectedTasks.push(proTask);
|
|
2371
2653
|
} else {
|
|
2372
|
-
const proTask =
|
|
2654
|
+
const proTask = tasks5.find((t) => t.value === "pro");
|
|
2373
2655
|
if (proTask) selectedTasks.push(proTask);
|
|
2374
2656
|
}
|
|
2375
2657
|
if (selectedTasks.length === 0) {
|
|
2376
|
-
|
|
2658
|
+
p13.log.warn("No setup tasks selected.");
|
|
2377
2659
|
process.exit(0);
|
|
2378
2660
|
}
|
|
2379
2661
|
for (const task of selectedTasks) {
|
|
2380
2662
|
await task.run();
|
|
2381
2663
|
}
|
|
2382
2664
|
} catch (error) {
|
|
2383
|
-
|
|
2384
|
-
|
|
2665
|
+
p13.log.error(error instanceof Error ? error.message : "Failed to run setup");
|
|
2666
|
+
p13.cancel("Operation cancelled");
|
|
2385
2667
|
process.exit(1);
|
|
2386
2668
|
}
|
|
2387
2669
|
}
|
|
2388
2670
|
async function runProSetup() {
|
|
2389
|
-
|
|
2671
|
+
p13.log.info(highlighter.info("Setting up Starwind Pro..."));
|
|
2390
2672
|
const configTasks = [];
|
|
2391
2673
|
const hasRegistry = await hasStarwindProRegistry();
|
|
2392
2674
|
const hasEnv = await checkStarwindProEnv();
|
|
2393
2675
|
if (hasRegistry && hasEnv) {
|
|
2394
|
-
|
|
2676
|
+
p13.log.info(highlighter.info("Starwind Pro registry and environment already configured"));
|
|
2395
2677
|
} else {
|
|
2396
2678
|
let cssFile = PATHS.LOCAL_CSS_FILE;
|
|
2397
2679
|
let baseColor = "neutral";
|
|
@@ -2425,7 +2707,7 @@ async function runProSetup() {
|
|
|
2425
2707
|
});
|
|
2426
2708
|
}
|
|
2427
2709
|
if (configTasks.length > 0) {
|
|
2428
|
-
await
|
|
2710
|
+
await p13.tasks(configTasks);
|
|
2429
2711
|
}
|
|
2430
2712
|
}
|
|
2431
2713
|
await sleep(250);
|
|
@@ -2433,37 +2715,37 @@ async function runProSetup() {
|
|
|
2433
2715
|
${highlighter.info("npx starwind@latest add @starwind-pro/component-name")}
|
|
2434
2716
|
|
|
2435
2717
|
Make sure to set your ${highlighter.infoBright("STARWIND_LICENSE_KEY")} environment variable in ${highlighter.infoBright(".env.local")}`;
|
|
2436
|
-
|
|
2718
|
+
p13.note(nextStepsMessage, "Next steps");
|
|
2437
2719
|
await sleep(1e3);
|
|
2438
|
-
|
|
2720
|
+
p13.outro("Enjoy using Starwind UI with Pro components! \u{1F680}");
|
|
2439
2721
|
}
|
|
2440
2722
|
|
|
2441
2723
|
// src/commands/update.ts
|
|
2442
|
-
import * as
|
|
2724
|
+
import * as p14 from "@clack/prompts";
|
|
2443
2725
|
async function update(components, options) {
|
|
2444
2726
|
try {
|
|
2445
|
-
|
|
2727
|
+
p14.intro(highlighter.title(" Welcome to the Starwind CLI "));
|
|
2446
2728
|
const configExists = await fileExists(PATHS.LOCAL_CONFIG_FILE);
|
|
2447
2729
|
if (!configExists) {
|
|
2448
|
-
|
|
2730
|
+
p14.log.error("No Starwind configuration found. Please run starwind init first.");
|
|
2449
2731
|
process.exit(1);
|
|
2450
2732
|
}
|
|
2451
2733
|
const config = await getConfig();
|
|
2452
2734
|
const installedComponents = config.components;
|
|
2453
2735
|
if (installedComponents.length === 0) {
|
|
2454
|
-
|
|
2736
|
+
p14.log.warn("No components are currently installed.");
|
|
2455
2737
|
process.exit(0);
|
|
2456
2738
|
}
|
|
2457
2739
|
let componentsToUpdate = [];
|
|
2458
2740
|
if (options?.all) {
|
|
2459
2741
|
componentsToUpdate = installedComponents.map((comp) => comp.name);
|
|
2460
|
-
|
|
2742
|
+
p14.log.info(`Checking updates for all ${componentsToUpdate.length} installed components...`);
|
|
2461
2743
|
} else if (components && components.length > 0) {
|
|
2462
2744
|
const invalid = components.filter(
|
|
2463
2745
|
(comp) => !installedComponents.some((ic) => ic.name === comp)
|
|
2464
2746
|
);
|
|
2465
2747
|
if (invalid.length > 0) {
|
|
2466
|
-
|
|
2748
|
+
p14.log.warn(
|
|
2467
2749
|
`${highlighter.warn("Components not found in project:")}
|
|
2468
2750
|
${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
2469
2751
|
);
|
|
@@ -2472,7 +2754,7 @@ ${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
|
2472
2754
|
(comp) => installedComponents.some((ic) => ic.name === comp)
|
|
2473
2755
|
);
|
|
2474
2756
|
if (componentsToUpdate.length === 0) {
|
|
2475
|
-
|
|
2757
|
+
p14.log.warn("No valid components to update");
|
|
2476
2758
|
process.exit(0);
|
|
2477
2759
|
}
|
|
2478
2760
|
} else {
|
|
@@ -2480,18 +2762,18 @@ ${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
|
2480
2762
|
value: comp.name,
|
|
2481
2763
|
label: comp.name
|
|
2482
2764
|
}));
|
|
2483
|
-
const selected = await
|
|
2765
|
+
const selected = await p14.multiselect({
|
|
2484
2766
|
message: "Select components to update",
|
|
2485
2767
|
options: choices
|
|
2486
2768
|
});
|
|
2487
|
-
if (
|
|
2488
|
-
|
|
2769
|
+
if (p14.isCancel(selected)) {
|
|
2770
|
+
p14.cancel("Operation cancelled");
|
|
2489
2771
|
process.exit(0);
|
|
2490
2772
|
}
|
|
2491
2773
|
componentsToUpdate = selected;
|
|
2492
2774
|
}
|
|
2493
2775
|
if (componentsToUpdate.length === 0) {
|
|
2494
|
-
|
|
2776
|
+
p14.log.warn("No components selected for update");
|
|
2495
2777
|
process.exit(0);
|
|
2496
2778
|
}
|
|
2497
2779
|
const results = {
|
|
@@ -2542,45 +2824,45 @@ ${invalid.map((name) => ` ${name}`).join("\n")}`
|
|
|
2542
2824
|
{ appendComponents: false }
|
|
2543
2825
|
);
|
|
2544
2826
|
} catch (error) {
|
|
2545
|
-
|
|
2827
|
+
p14.log.error(
|
|
2546
2828
|
`Failed to update config: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
2547
2829
|
);
|
|
2548
2830
|
process.exit(1);
|
|
2549
2831
|
}
|
|
2550
2832
|
}
|
|
2551
|
-
|
|
2833
|
+
p14.log.message(`
|
|
2552
2834
|
|
|
2553
2835
|
${highlighter.underline("Update Summary")}`);
|
|
2554
2836
|
if (results.failed.length > 0) {
|
|
2555
|
-
|
|
2837
|
+
p14.log.error(
|
|
2556
2838
|
`${highlighter.error("Failed to update components:")}
|
|
2557
2839
|
${results.failed.map((r) => ` ${r.name} - ${r.error}`).join("\n")}`
|
|
2558
2840
|
);
|
|
2559
2841
|
}
|
|
2560
2842
|
if (results.skipped.length > 0) {
|
|
2561
|
-
|
|
2843
|
+
p14.log.info(
|
|
2562
2844
|
`${highlighter.info("Components already up to date or skipped:")}
|
|
2563
2845
|
${results.skipped.map((r) => ` ${r.name} (${r.oldVersion})`).join("\n")}`
|
|
2564
2846
|
);
|
|
2565
2847
|
}
|
|
2566
2848
|
if (results.updated.length > 0) {
|
|
2567
|
-
|
|
2849
|
+
p14.log.success(
|
|
2568
2850
|
`${highlighter.success("Successfully updated components:")}
|
|
2569
2851
|
${results.updated.map((r) => ` ${r.name} (${r.oldVersion} \u2192 ${r.newVersion})`).join("\n")}`
|
|
2570
2852
|
);
|
|
2571
2853
|
}
|
|
2572
2854
|
await sleep(1e3);
|
|
2573
2855
|
if (results.updated.length > 0) {
|
|
2574
|
-
|
|
2856
|
+
p14.outro("Components updated successfully \u{1F680}");
|
|
2575
2857
|
} else if (results.skipped.length > 0 && results.failed.length === 0) {
|
|
2576
|
-
|
|
2858
|
+
p14.outro("Components already up to date or skipped \u2728");
|
|
2577
2859
|
} else {
|
|
2578
|
-
|
|
2860
|
+
p14.cancel("No components were updated");
|
|
2579
2861
|
process.exit(1);
|
|
2580
2862
|
}
|
|
2581
2863
|
} catch (error) {
|
|
2582
|
-
|
|
2583
|
-
|
|
2864
|
+
p14.log.error(error instanceof Error ? error.message : "Failed to update components");
|
|
2865
|
+
p14.cancel("Operation cancelled");
|
|
2584
2866
|
process.exit(1);
|
|
2585
2867
|
}
|
|
2586
2868
|
}
|
|
@@ -2588,13 +2870,30 @@ ${results.updated.map((r) => ` ${r.name} (${r.oldVersion} \u2192 ${r.newVersion
|
|
|
2588
2870
|
// src/index.ts
|
|
2589
2871
|
var program = new Command().name("starwind").description("Add beautifully designed components to your Astro applications").version(package_default.version);
|
|
2590
2872
|
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 }));
|
|
2591
|
-
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").option("-y, --yes", "Skip confirmation prompts").addOption(
|
|
2873
|
+
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").option("-y, --yes", "Skip confirmation prompts").option("-o, --overwrite", "Overwrite existing files").addOption(
|
|
2592
2874
|
new Option("-m, --package-manager <pm>", "Package manager to use").choices([
|
|
2593
2875
|
"npm",
|
|
2594
2876
|
"pnpm",
|
|
2595
2877
|
"yarn"
|
|
2596
2878
|
])
|
|
2597
2879
|
).action(add);
|
|
2880
|
+
program.command("docs").description("Open documentation for Starwind components").argument("[components...]", "The components to look up (space separated)").allowExcessArguments().option("--json", "Output as JSON").action(docs);
|
|
2881
|
+
program.command("search").description("Search Starwind components and Pro blocks").argument("[query]", "Search query string").allowExcessArguments().option("-p, --plan <plan>", "Filter Pro blocks by plan type (free or pro)").option("-c, --category <category>", "Filter Pro blocks by category").option("-l, --limit <number>", "Maximum number of Pro blocks to display", "20").option("-o, --offset <number>", "Offset for paginating Pro block results", "0").option("--json", "Output as JSON").action(
|
|
2882
|
+
async (query, opts) => {
|
|
2883
|
+
const parsedLimit = Math.min(Math.max(parseInt(opts.limit, 10) || 20, 1), 50);
|
|
2884
|
+
const parsedOffset = Math.max(parseInt(opts.offset, 10) || 0, 0);
|
|
2885
|
+
if (opts.plan && opts.plan !== "free" && opts.plan !== "pro") {
|
|
2886
|
+
program.error(`Invalid plan "${opts.plan}". Must be "free" or "pro".`);
|
|
2887
|
+
}
|
|
2888
|
+
await search(query, {
|
|
2889
|
+
plan: opts.plan,
|
|
2890
|
+
category: opts.category,
|
|
2891
|
+
limit: parsedLimit,
|
|
2892
|
+
offset: parsedOffset,
|
|
2893
|
+
json: opts.json
|
|
2894
|
+
});
|
|
2895
|
+
}
|
|
2896
|
+
);
|
|
2598
2897
|
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").addOption(
|
|
2599
2898
|
new Option("-m, --package-manager <pm>", "Package manager to use").choices([
|
|
2600
2899
|
"npm",
|