create-better-t-stack 3.27.4 → 3.27.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +12 -6
- package/dist/index.mjs +1 -1
- package/dist/{src-nmBsmday.mjs → src-VGvTc2ik.mjs} +384 -283
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-
|
|
2
|
+
import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-VGvTc2ik.mjs";
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/dist/index.d.mts
CHANGED
|
@@ -225,6 +225,9 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
|
|
|
225
225
|
fumadocs?: {
|
|
226
226
|
template: "react-router" | "tanstack-start" | "next-mdx" | "next-mdx-static" | "waku" | "react-router-spa" | "tanstack-start-spa";
|
|
227
227
|
devPort?: number | undefined;
|
|
228
|
+
search?: "orama" | "orama-cloud" | undefined;
|
|
229
|
+
ogImage?: "next-og" | "takumi" | undefined;
|
|
230
|
+
aiChat?: "openrouter" | "inkeep" | undefined;
|
|
228
231
|
} | undefined;
|
|
229
232
|
opentui?: {
|
|
230
233
|
template: "solid" | "react" | "core";
|
|
@@ -244,9 +247,9 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
|
|
|
244
247
|
} | undefined;
|
|
245
248
|
ultracite?: {
|
|
246
249
|
linter?: "biome" | "oxlint" | "eslint" | undefined;
|
|
247
|
-
editors?: ("void" | "antigravity" | "cursor" | "vscode" | "zed" | "windsurf" | "trae" | "kiro")[] | undefined;
|
|
248
|
-
agents?: ("cline" | "codex" | "opencode" | "goose" | "amp" | "droid" | "claude" | "jules" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "junie" | "augmentcode" | "kilo-code" | "roo-code" | "warp" | "crush" | "qwen" | "amazon-q-cli" | "firebender" | "cursor-cli" | "mistral-vibe" | "vercel")[] | undefined;
|
|
249
|
-
hooks?: ("cursor" | "windsurf" | "claude")[] | undefined;
|
|
250
|
+
editors?: ("void" | "antigravity" | "cursor" | "vscode" | "zed" | "windsurf" | "trae" | "codebuddy" | "bob" | "kiro")[] | undefined;
|
|
251
|
+
agents?: ("cline" | "codex" | "opencode" | "goose" | "amp" | "pi" | "qoder" | "droid" | "zencoder" | "mcpjam" | "bob" | "universal" | "claude" | "jules" | "replit" | "devin" | "lovable" | "ona" | "openclaw" | "continue" | "snowflake-cortex" | "deepagents" | "kimi-cli" | "mux" | "adal" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "junie" | "augmentcode" | "kilo-code" | "roo-code" | "warp" | "crush" | "qwen" | "amazon-q-cli" | "firebender" | "cursor-cli" | "mistral-vibe" | "vercel")[] | undefined;
|
|
252
|
+
hooks?: ("cursor" | "windsurf" | "codebuddy" | "claude" | "copilot")[] | undefined;
|
|
250
253
|
} | undefined;
|
|
251
254
|
} | undefined;
|
|
252
255
|
dbSetupOptions?: {
|
|
@@ -332,6 +335,9 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
|
|
|
332
335
|
fumadocs?: {
|
|
333
336
|
template: "react-router" | "tanstack-start" | "next-mdx" | "next-mdx-static" | "waku" | "react-router-spa" | "tanstack-start-spa";
|
|
334
337
|
devPort?: number | undefined;
|
|
338
|
+
search?: "orama" | "orama-cloud" | undefined;
|
|
339
|
+
ogImage?: "next-og" | "takumi" | undefined;
|
|
340
|
+
aiChat?: "openrouter" | "inkeep" | undefined;
|
|
335
341
|
} | undefined;
|
|
336
342
|
opentui?: {
|
|
337
343
|
template: "solid" | "react" | "core";
|
|
@@ -351,9 +357,9 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
|
|
|
351
357
|
} | undefined;
|
|
352
358
|
ultracite?: {
|
|
353
359
|
linter?: "biome" | "oxlint" | "eslint" | undefined;
|
|
354
|
-
editors?: ("void" | "antigravity" | "cursor" | "vscode" | "zed" | "windsurf" | "trae" | "kiro")[] | undefined;
|
|
355
|
-
agents?: ("cline" | "codex" | "opencode" | "goose" | "amp" | "droid" | "claude" | "jules" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "junie" | "augmentcode" | "kilo-code" | "roo-code" | "warp" | "crush" | "qwen" | "amazon-q-cli" | "firebender" | "cursor-cli" | "mistral-vibe" | "vercel")[] | undefined;
|
|
356
|
-
hooks?: ("cursor" | "windsurf" | "claude")[] | undefined;
|
|
360
|
+
editors?: ("void" | "antigravity" | "cursor" | "vscode" | "zed" | "windsurf" | "trae" | "codebuddy" | "bob" | "kiro")[] | undefined;
|
|
361
|
+
agents?: ("cline" | "codex" | "opencode" | "goose" | "amp" | "pi" | "qoder" | "droid" | "zencoder" | "mcpjam" | "bob" | "universal" | "claude" | "jules" | "replit" | "devin" | "lovable" | "ona" | "openclaw" | "continue" | "snowflake-cortex" | "deepagents" | "kimi-cli" | "mux" | "adal" | "copilot" | "aider" | "firebase-studio" | "open-hands" | "gemini" | "junie" | "augmentcode" | "kilo-code" | "roo-code" | "warp" | "crush" | "qwen" | "amazon-q-cli" | "firebender" | "cursor-cli" | "mistral-vibe" | "vercel")[] | undefined;
|
|
362
|
+
hooks?: ("cursor" | "windsurf" | "codebuddy" | "claude" | "copilot")[] | undefined;
|
|
357
363
|
} | undefined;
|
|
358
364
|
} | undefined;
|
|
359
365
|
webDeploy?: "none" | "cloudflare" | undefined;
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-
|
|
2
|
+
import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-VGvTc2ik.mjs";
|
|
3
3
|
export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
|
|
@@ -5,7 +5,7 @@ import { initTRPC } from "@trpc/server";
|
|
|
5
5
|
import { Result, Result as Result$1, TaggedError } from "better-result";
|
|
6
6
|
import { createCli } from "trpc-cli";
|
|
7
7
|
import z from "zod";
|
|
8
|
-
import { cancel, confirm,
|
|
8
|
+
import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
|
|
9
9
|
import pc from "picocolors";
|
|
10
10
|
import path from "node:path";
|
|
11
11
|
import envPaths from "env-paths";
|
|
@@ -1381,6 +1381,62 @@ const addPackageDependency = async (opts) => {
|
|
|
1381
1381
|
await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
|
|
1382
1382
|
};
|
|
1383
1383
|
//#endregion
|
|
1384
|
+
//#region src/prompts/navigable-group.ts
|
|
1385
|
+
/**
|
|
1386
|
+
* Navigable group - a group of prompts that allows going back
|
|
1387
|
+
*/
|
|
1388
|
+
/**
|
|
1389
|
+
* Define a group of prompts that supports going back to previous prompts.
|
|
1390
|
+
* Returns a result object with all the values, or handles cancel/go-back navigation.
|
|
1391
|
+
*/
|
|
1392
|
+
async function navigableGroup(prompts, opts) {
|
|
1393
|
+
const results = {};
|
|
1394
|
+
const promptNames = Object.keys(prompts);
|
|
1395
|
+
let currentIndex = 0;
|
|
1396
|
+
let goingBack = false;
|
|
1397
|
+
while (currentIndex < promptNames.length) {
|
|
1398
|
+
const name = promptNames[currentIndex];
|
|
1399
|
+
const prompt = prompts[name];
|
|
1400
|
+
setIsFirstPrompt$1(currentIndex === 0);
|
|
1401
|
+
setLastPromptShownUI(false);
|
|
1402
|
+
const result = await prompt({ results })?.catch((e) => {
|
|
1403
|
+
throw e;
|
|
1404
|
+
});
|
|
1405
|
+
if (isGoBack(result)) {
|
|
1406
|
+
goingBack = true;
|
|
1407
|
+
if (currentIndex > 0) {
|
|
1408
|
+
const prevName = promptNames[currentIndex - 1];
|
|
1409
|
+
delete results[prevName];
|
|
1410
|
+
currentIndex--;
|
|
1411
|
+
continue;
|
|
1412
|
+
}
|
|
1413
|
+
goingBack = false;
|
|
1414
|
+
continue;
|
|
1415
|
+
}
|
|
1416
|
+
if (isCancel$1(result)) {
|
|
1417
|
+
if (typeof opts?.onCancel === "function") {
|
|
1418
|
+
results[name] = "canceled";
|
|
1419
|
+
opts.onCancel({ results });
|
|
1420
|
+
}
|
|
1421
|
+
setIsFirstPrompt$1(false);
|
|
1422
|
+
return results;
|
|
1423
|
+
}
|
|
1424
|
+
if (goingBack && !didLastPromptShowUI()) {
|
|
1425
|
+
if (currentIndex > 0) {
|
|
1426
|
+
const prevName = promptNames[currentIndex - 1];
|
|
1427
|
+
delete results[prevName];
|
|
1428
|
+
currentIndex--;
|
|
1429
|
+
continue;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
goingBack = false;
|
|
1433
|
+
results[name] = result;
|
|
1434
|
+
currentIndex++;
|
|
1435
|
+
}
|
|
1436
|
+
setIsFirstPrompt$1(false);
|
|
1437
|
+
return results;
|
|
1438
|
+
}
|
|
1439
|
+
//#endregion
|
|
1384
1440
|
//#region src/utils/external-commands.ts
|
|
1385
1441
|
function shouldSkipExternalCommands() {
|
|
1386
1442
|
return process.env.BTS_SKIP_EXTERNAL_COMMANDS === "1" || process.env.BTS_TEST_MODE === "1";
|
|
@@ -1484,64 +1540,143 @@ function getPackageRunnerPrefix(packageManager) {
|
|
|
1484
1540
|
const TEMPLATES$2 = {
|
|
1485
1541
|
"next-mdx": {
|
|
1486
1542
|
label: "Next.js: Fumadocs MDX",
|
|
1487
|
-
hint: "
|
|
1543
|
+
hint: "recommended",
|
|
1488
1544
|
value: "+next+fuma-docs-mdx"
|
|
1489
1545
|
},
|
|
1490
1546
|
"next-mdx-static": {
|
|
1491
|
-
label: "Next.js: Fumadocs MDX
|
|
1492
|
-
hint: "Static export template with MDX support",
|
|
1547
|
+
label: "Next.js Static: Fumadocs MDX",
|
|
1493
1548
|
value: "+next+fuma-docs-mdx+static"
|
|
1494
1549
|
},
|
|
1495
1550
|
waku: {
|
|
1496
|
-
label: "Waku:
|
|
1497
|
-
hint: "Template using Waku with content collections",
|
|
1551
|
+
label: "Waku: Fumadocs MDX",
|
|
1498
1552
|
value: "waku"
|
|
1499
1553
|
},
|
|
1500
1554
|
"react-router": {
|
|
1501
|
-
label: "React Router: MDX
|
|
1502
|
-
hint: "Template for React Router with MDX remote",
|
|
1555
|
+
label: "React Router: Fumadocs MDX (not RSC)",
|
|
1503
1556
|
value: "react-router"
|
|
1504
1557
|
},
|
|
1505
1558
|
"react-router-spa": {
|
|
1506
|
-
label: "React Router:
|
|
1507
|
-
hint: "
|
|
1559
|
+
label: "React Router SPA: Fumadocs MDX (not RSC)",
|
|
1560
|
+
hint: "SPA mode allows you to host the site statically, compatible with a CDN.",
|
|
1508
1561
|
value: "react-router-spa"
|
|
1509
1562
|
},
|
|
1510
1563
|
"tanstack-start": {
|
|
1511
|
-
label: "Tanstack Start: MDX
|
|
1512
|
-
hint: "Template for Tanstack Start with MDX remote",
|
|
1564
|
+
label: "Tanstack Start: Fumadocs MDX (not RSC)",
|
|
1513
1565
|
value: "tanstack-start"
|
|
1514
1566
|
},
|
|
1515
1567
|
"tanstack-start-spa": {
|
|
1516
|
-
label: "Tanstack Start:
|
|
1517
|
-
hint: "
|
|
1568
|
+
label: "Tanstack Start SPA: Fumadocs MDX (not RSC)",
|
|
1569
|
+
hint: "SPA mode allows you to host the site statically, compatible with a CDN.",
|
|
1518
1570
|
value: "tanstack-start-spa"
|
|
1519
1571
|
}
|
|
1520
1572
|
};
|
|
1521
1573
|
const DEFAULT_TEMPLATE$2 = "next-mdx";
|
|
1522
1574
|
const DEFAULT_DEV_PORT$1 = 4e3;
|
|
1575
|
+
function aiChatDisabledForTemplate(template) {
|
|
1576
|
+
return template === "next-mdx-static" || template.endsWith("-spa");
|
|
1577
|
+
}
|
|
1523
1578
|
async function setupFumadocs(config) {
|
|
1524
1579
|
if (shouldSkipExternalCommands()) return Result.ok(void 0);
|
|
1525
1580
|
const { packageManager, projectDir } = config;
|
|
1526
1581
|
cliLog.info("Setting up Fumadocs...");
|
|
1527
1582
|
const configuredOptions = config.addonOptions?.fumadocs;
|
|
1528
1583
|
let template = configuredOptions?.template;
|
|
1529
|
-
|
|
1584
|
+
let search = configuredOptions?.search;
|
|
1585
|
+
let ogImage = configuredOptions?.ogImage;
|
|
1586
|
+
let aiChat = configuredOptions?.aiChat;
|
|
1587
|
+
if (isSilent()) template = template ?? DEFAULT_TEMPLATE$2;
|
|
1530
1588
|
else {
|
|
1531
|
-
const
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1589
|
+
const promptResult = await Result.tryPromise({
|
|
1590
|
+
try: () => navigableGroup({
|
|
1591
|
+
template: async () => {
|
|
1592
|
+
if (template !== void 0) return template;
|
|
1593
|
+
return navigableSelect({
|
|
1594
|
+
message: "Choose a template",
|
|
1595
|
+
options: Object.entries(TEMPLATES$2).map(([key, t]) => ({
|
|
1596
|
+
value: key,
|
|
1597
|
+
label: t.label,
|
|
1598
|
+
hint: "hint" in t ? t.hint : void 0
|
|
1599
|
+
})),
|
|
1600
|
+
initialValue: DEFAULT_TEMPLATE$2
|
|
1601
|
+
});
|
|
1602
|
+
},
|
|
1603
|
+
search: async () => {
|
|
1604
|
+
if (search !== void 0) return search;
|
|
1605
|
+
return navigableSelect({
|
|
1606
|
+
message: "Choose a search solution?",
|
|
1607
|
+
options: [{
|
|
1608
|
+
value: "orama",
|
|
1609
|
+
label: "Default",
|
|
1610
|
+
hint: "local search powered by Orama, recommended"
|
|
1611
|
+
}, {
|
|
1612
|
+
value: "orama-cloud",
|
|
1613
|
+
label: "Orama Cloud",
|
|
1614
|
+
hint: "3rd party search solution, signup needed"
|
|
1615
|
+
}],
|
|
1616
|
+
initialValue: "orama"
|
|
1617
|
+
});
|
|
1618
|
+
},
|
|
1619
|
+
ogImage: async ({ results }) => {
|
|
1620
|
+
if (ogImage !== void 0) return ogImage;
|
|
1621
|
+
if (!(results.template ?? template ?? DEFAULT_TEMPLATE$2).startsWith("next-")) return "skip";
|
|
1622
|
+
return navigableSelect({
|
|
1623
|
+
message: "Configure Open Graph Image generation?",
|
|
1624
|
+
options: [{
|
|
1625
|
+
value: "next-og",
|
|
1626
|
+
label: "next/og",
|
|
1627
|
+
hint: "Next.js built-in solution"
|
|
1628
|
+
}, {
|
|
1629
|
+
value: "takumi",
|
|
1630
|
+
label: "Takumi",
|
|
1631
|
+
hint: "Output WebP format, framework-agnostic"
|
|
1632
|
+
}],
|
|
1633
|
+
initialValue: "next-og"
|
|
1634
|
+
});
|
|
1635
|
+
},
|
|
1636
|
+
aiChat: async ({ results }) => {
|
|
1637
|
+
if (aiChat !== void 0) return aiChat;
|
|
1638
|
+
if (aiChatDisabledForTemplate(results.template ?? template ?? DEFAULT_TEMPLATE$2)) return "none";
|
|
1639
|
+
return navigableSelect({
|
|
1640
|
+
message: "Configure AI Chat?",
|
|
1641
|
+
options: [
|
|
1642
|
+
{
|
|
1643
|
+
value: "none",
|
|
1644
|
+
label: "No"
|
|
1645
|
+
},
|
|
1646
|
+
{
|
|
1647
|
+
value: "openrouter",
|
|
1648
|
+
label: "AI SDK",
|
|
1649
|
+
hint: "default to OpenRouter"
|
|
1650
|
+
},
|
|
1651
|
+
{
|
|
1652
|
+
value: "inkeep",
|
|
1653
|
+
label: "Inkeep AI",
|
|
1654
|
+
hint: "API key required"
|
|
1655
|
+
}
|
|
1656
|
+
],
|
|
1657
|
+
initialValue: "none"
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
}),
|
|
1661
|
+
catch: (e) => new AddonSetupError({
|
|
1662
|
+
addon: "fumadocs",
|
|
1663
|
+
message: `Failed to run Fumadocs prompts: ${e instanceof Error ? e.message : String(e)}`,
|
|
1664
|
+
cause: e
|
|
1665
|
+
})
|
|
1539
1666
|
});
|
|
1540
|
-
if (
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1667
|
+
if (promptResult.isErr()) return Result.err(promptResult.error);
|
|
1668
|
+
const results = promptResult.value;
|
|
1669
|
+
if (results.template === void 0 || results.search === void 0 || results.ogImage === void 0 || results.aiChat === void 0) return userCancelled("Operation cancelled");
|
|
1670
|
+
template = results.template;
|
|
1671
|
+
search = results.search;
|
|
1672
|
+
ogImage = results.ogImage === "skip" ? void 0 : results.ogImage;
|
|
1673
|
+
aiChat = results.aiChat === "none" ? void 0 : results.aiChat;
|
|
1674
|
+
}
|
|
1675
|
+
if (!template) return userCancelled("Operation cancelled");
|
|
1544
1676
|
const isNextTemplate = template.startsWith("next-");
|
|
1677
|
+
if (!isNextTemplate) ogImage = void 0;
|
|
1678
|
+
if (aiChatDisabledForTemplate(template)) aiChat = void 0;
|
|
1679
|
+
const templateArg = TEMPLATES$2[template].value;
|
|
1545
1680
|
const devPort = configuredOptions?.devPort ?? DEFAULT_DEV_PORT$1;
|
|
1546
1681
|
const options = [
|
|
1547
1682
|
`--template ${templateArg}`,
|
|
@@ -1549,7 +1684,10 @@ async function setupFumadocs(config) {
|
|
|
1549
1684
|
"--no-git"
|
|
1550
1685
|
];
|
|
1551
1686
|
if (isNextTemplate) options.push("--src");
|
|
1552
|
-
if (config.addons.includes("biome")) options.push("--linter biome");
|
|
1687
|
+
if (config.addons.includes("biome") || config.addons.includes("ultracite")) options.push("--linter biome");
|
|
1688
|
+
if (search) options.push(`--search ${search}`);
|
|
1689
|
+
if (ogImage) options.push(`--og-image ${ogImage}`);
|
|
1690
|
+
if (aiChat) options.push(`--ai-chat ${aiChat}`);
|
|
1553
1691
|
const args = getPackageExecutionArgs(packageManager, `create-fumadocs-app@latest fumadocs ${options.join(" ")}`);
|
|
1554
1692
|
const appsDir = path.join(projectDir, "apps");
|
|
1555
1693
|
await fs.ensureDir(appsDir);
|
|
@@ -1812,67 +1950,84 @@ async function setupMcp(config) {
|
|
|
1812
1950
|
if (shouldSkipExternalCommands()) return Result.ok(void 0);
|
|
1813
1951
|
const { packageManager, projectDir } = config;
|
|
1814
1952
|
cliLog.info("Setting up MCP servers...");
|
|
1815
|
-
|
|
1816
|
-
if (!scope) if (isSilent()) scope = DEFAULT_SCOPE$1;
|
|
1817
|
-
else {
|
|
1818
|
-
const selectedScope = await select({
|
|
1819
|
-
message: "Where should MCP servers be installed?",
|
|
1820
|
-
options: [{
|
|
1821
|
-
value: "project",
|
|
1822
|
-
label: "Project",
|
|
1823
|
-
hint: "Writes to project config files (recommended for teams)"
|
|
1824
|
-
}, {
|
|
1825
|
-
value: "global",
|
|
1826
|
-
label: "Global",
|
|
1827
|
-
hint: "Writes to user-level config files (personal machine)"
|
|
1828
|
-
}],
|
|
1829
|
-
initialValue: DEFAULT_SCOPE$1
|
|
1830
|
-
});
|
|
1831
|
-
if (isCancel(selectedScope)) return Result.err(new UserCancelledError({ message: "Operation cancelled" }));
|
|
1832
|
-
scope = selectedScope;
|
|
1833
|
-
}
|
|
1834
|
-
const recommendedServers = getRecommendedMcpServers(config, scope);
|
|
1835
|
-
if (recommendedServers.length === 0) return Result.ok(void 0);
|
|
1836
|
-
const allServersByKey = new Map(getAllMcpServers(config).map((server) => [server.key, server]));
|
|
1837
|
-
const serverOptions = recommendedServers.map((s) => ({
|
|
1838
|
-
value: s.key,
|
|
1839
|
-
label: s.label,
|
|
1840
|
-
hint: s.target
|
|
1841
|
-
}));
|
|
1953
|
+
const configuredScope = config.addonOptions?.mcp?.scope;
|
|
1842
1954
|
const configuredServerKeys = config.addonOptions?.mcp?.servers;
|
|
1843
|
-
const availableServerKeys = new Set(allServersByKey.keys());
|
|
1844
|
-
let selectedServerKeys = configuredServerKeys?.filter((serverKey) => availableServerKeys.has(serverKey)) ?? [];
|
|
1845
|
-
if (selectedServerKeys.length === 0 && configuredServerKeys === void 0) if (isSilent()) selectedServerKeys = serverOptions.map((o) => o.value);
|
|
1846
|
-
else {
|
|
1847
|
-
const promptedServerKeys = await multiselect({
|
|
1848
|
-
message: "Select MCP servers to install",
|
|
1849
|
-
options: serverOptions,
|
|
1850
|
-
required: false,
|
|
1851
|
-
initialValues: serverOptions.map((o) => o.value)
|
|
1852
|
-
});
|
|
1853
|
-
if (isCancel(promptedServerKeys)) return Result.err(new UserCancelledError({ message: "Operation cancelled" }));
|
|
1854
|
-
selectedServerKeys = [...promptedServerKeys];
|
|
1855
|
-
}
|
|
1856
|
-
if (selectedServerKeys.length === 0) return Result.ok(void 0);
|
|
1857
|
-
const agentOptions = filterAgentsForScope(scope).map((a) => ({
|
|
1858
|
-
value: a.value,
|
|
1859
|
-
label: a.label
|
|
1860
|
-
}));
|
|
1861
|
-
const defaultAgents = uniqueValues$1(DEFAULT_AGENTS$2.filter((agent) => agentOptions.some((option) => option.value === agent)));
|
|
1862
1955
|
const configuredAgents = config.addonOptions?.mcp?.agents;
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1956
|
+
const allServersByKey = new Map(getAllMcpServers(config).map((server) => [server.key, server]));
|
|
1957
|
+
const availableServerKeys = new Set(allServersByKey.keys());
|
|
1958
|
+
let scope;
|
|
1959
|
+
let selectedServerKeys;
|
|
1960
|
+
let selectedAgents;
|
|
1961
|
+
if (isSilent()) {
|
|
1962
|
+
scope = configuredScope ?? DEFAULT_SCOPE$1;
|
|
1963
|
+
const recommendedServers = getRecommendedMcpServers(config, scope);
|
|
1964
|
+
if (recommendedServers.length === 0) return Result.ok(void 0);
|
|
1965
|
+
const serverOptions = recommendedServers.map((s) => s.key);
|
|
1966
|
+
selectedServerKeys = configuredServerKeys?.filter((k) => availableServerKeys.has(k)) ?? serverOptions;
|
|
1967
|
+
if (selectedServerKeys.length === 0) return Result.ok(void 0);
|
|
1968
|
+
const agentOptions = filterAgentsForScope(scope);
|
|
1969
|
+
const defaultAgents = uniqueValues$1(DEFAULT_AGENTS$2.filter((a) => agentOptions.some((o) => o.value === a)));
|
|
1970
|
+
selectedAgents = configuredAgents?.filter((a) => agentOptions.some((o) => o.value === a)) ?? defaultAgents;
|
|
1971
|
+
if (selectedAgents.length === 0) return Result.ok(void 0);
|
|
1972
|
+
} else {
|
|
1973
|
+
const results = await navigableGroup({
|
|
1974
|
+
scope: async () => {
|
|
1975
|
+
if (configuredScope !== void 0) return configuredScope;
|
|
1976
|
+
return navigableSelect({
|
|
1977
|
+
message: "Where should MCP servers be installed?",
|
|
1978
|
+
options: [{
|
|
1979
|
+
value: "project",
|
|
1980
|
+
label: "Project",
|
|
1981
|
+
hint: "Writes to project config files (recommended for teams)"
|
|
1982
|
+
}, {
|
|
1983
|
+
value: "global",
|
|
1984
|
+
label: "Global",
|
|
1985
|
+
hint: "Writes to user-level config files (personal machine)"
|
|
1986
|
+
}],
|
|
1987
|
+
initialValue: DEFAULT_SCOPE$1
|
|
1988
|
+
});
|
|
1989
|
+
},
|
|
1990
|
+
servers: async ({ results: r }) => {
|
|
1991
|
+
const recommended = getRecommendedMcpServers(config, r.scope ?? configuredScope ?? DEFAULT_SCOPE$1);
|
|
1992
|
+
if (recommended.length === 0) return [];
|
|
1993
|
+
const options = recommended.map((s) => ({
|
|
1994
|
+
value: s.key,
|
|
1995
|
+
label: s.label,
|
|
1996
|
+
hint: s.target
|
|
1997
|
+
}));
|
|
1998
|
+
if (configuredServerKeys !== void 0) return configuredServerKeys.filter((k) => availableServerKeys.has(k));
|
|
1999
|
+
return navigableMultiselect({
|
|
2000
|
+
message: "Select MCP servers to install",
|
|
2001
|
+
options,
|
|
2002
|
+
required: false,
|
|
2003
|
+
initialValues: options.map((o) => o.value)
|
|
2004
|
+
});
|
|
2005
|
+
},
|
|
2006
|
+
agents: async ({ results: r }) => {
|
|
2007
|
+
const currentScope = r.scope ?? configuredScope ?? DEFAULT_SCOPE$1;
|
|
2008
|
+
const currentServers = r.servers;
|
|
2009
|
+
if (currentServers !== void 0 && currentServers.length === 0) return [];
|
|
2010
|
+
const agentOpts = filterAgentsForScope(currentScope);
|
|
2011
|
+
if (agentOpts.length === 0) return [];
|
|
2012
|
+
const defaults = uniqueValues$1(DEFAULT_AGENTS$2.filter((a) => agentOpts.some((o) => o.value === a)));
|
|
2013
|
+
if (configuredAgents !== void 0) return configuredAgents.filter((a) => agentOpts.some((o) => o.value === a));
|
|
2014
|
+
return navigableMultiselect({
|
|
2015
|
+
message: "Select agents to install MCP servers to",
|
|
2016
|
+
options: agentOpts.map((a) => ({
|
|
2017
|
+
value: a.value,
|
|
2018
|
+
label: a.label
|
|
2019
|
+
})),
|
|
2020
|
+
required: false,
|
|
2021
|
+
initialValues: defaults
|
|
2022
|
+
});
|
|
2023
|
+
}
|
|
1871
2024
|
});
|
|
1872
|
-
if (
|
|
1873
|
-
|
|
2025
|
+
if (results.scope === void 0 || results.servers === void 0 || results.agents === void 0) return Result.err(new UserCancelledError({ message: "Operation cancelled" }));
|
|
2026
|
+
scope = results.scope;
|
|
2027
|
+
selectedServerKeys = results.servers;
|
|
2028
|
+
selectedAgents = results.agents;
|
|
2029
|
+
if (selectedServerKeys.length === 0 || selectedAgents.length === 0) return Result.ok(void 0);
|
|
1874
2030
|
}
|
|
1875
|
-
if (selectedAgents.length === 0) return Result.ok(void 0);
|
|
1876
2031
|
const selectedServers = [];
|
|
1877
2032
|
for (const key of selectedServerKeys) {
|
|
1878
2033
|
const server = allServersByKey.get(key);
|
|
@@ -2236,55 +2391,64 @@ async function setupSkills(config) {
|
|
|
2236
2391
|
}));
|
|
2237
2392
|
});
|
|
2238
2393
|
if (skillOptions.length === 0) return Result.ok(void 0);
|
|
2239
|
-
|
|
2240
|
-
if (!scope) if (isSilent()) scope = DEFAULT_SCOPE;
|
|
2241
|
-
else {
|
|
2242
|
-
const selectedScope = await select({
|
|
2243
|
-
message: "Where should skills be installed?",
|
|
2244
|
-
options: [{
|
|
2245
|
-
value: "project",
|
|
2246
|
-
label: "Project",
|
|
2247
|
-
hint: "Writes to project config files (recommended for teams)"
|
|
2248
|
-
}, {
|
|
2249
|
-
value: "global",
|
|
2250
|
-
label: "Global",
|
|
2251
|
-
hint: "Writes to user-level config files (personal machine)"
|
|
2252
|
-
}],
|
|
2253
|
-
initialValue: DEFAULT_SCOPE
|
|
2254
|
-
});
|
|
2255
|
-
if (isCancel(selectedScope)) return Result.err(new UserCancelledError({ message: "Operation cancelled" }));
|
|
2256
|
-
scope = selectedScope;
|
|
2257
|
-
}
|
|
2258
|
-
const allSkillValues = skillOptions.map((opt) => opt.value);
|
|
2394
|
+
const configuredScope = skillsOptions?.scope;
|
|
2259
2395
|
const configuredSelections = skillsOptions?.selections;
|
|
2260
|
-
let selectedSkills;
|
|
2261
|
-
if (configuredSelections !== void 0) selectedSkills = configuredSelections.flatMap((selection) => selection.skills.map((skill) => `${selection.source}::${skill}`));
|
|
2262
|
-
else if (isSilent()) selectedSkills = allSkillValues;
|
|
2263
|
-
else {
|
|
2264
|
-
const promptedSkills = await multiselect({
|
|
2265
|
-
message: "Select skills to install",
|
|
2266
|
-
options: skillOptions,
|
|
2267
|
-
required: false,
|
|
2268
|
-
initialValues: allSkillValues
|
|
2269
|
-
});
|
|
2270
|
-
if (isCancel(promptedSkills)) return Result.err(new UserCancelledError({ message: "Operation cancelled" }));
|
|
2271
|
-
selectedSkills = promptedSkills;
|
|
2272
|
-
}
|
|
2273
|
-
if (selectedSkills.length === 0) return Result.ok(void 0);
|
|
2274
2396
|
const configuredAgents = skillsOptions?.agents;
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2397
|
+
const allSkillValues = skillOptions.map((opt) => opt.value);
|
|
2398
|
+
let scope;
|
|
2399
|
+
let selectedSkills;
|
|
2400
|
+
let selectedAgents;
|
|
2401
|
+
if (isSilent()) {
|
|
2402
|
+
scope = configuredScope ?? DEFAULT_SCOPE;
|
|
2403
|
+
selectedSkills = configuredSelections !== void 0 ? configuredSelections.flatMap((selection) => selection.skills.map((skill) => `${selection.source}::${skill}`)) : allSkillValues;
|
|
2404
|
+
if (selectedSkills.length === 0) return Result.ok(void 0);
|
|
2405
|
+
selectedAgents = configuredAgents ? [...configuredAgents] : [...DEFAULT_AGENTS$1];
|
|
2406
|
+
if (selectedAgents.length === 0) return Result.ok(void 0);
|
|
2407
|
+
} else {
|
|
2408
|
+
const results = await navigableGroup({
|
|
2409
|
+
scope: async () => {
|
|
2410
|
+
if (configuredScope !== void 0) return configuredScope;
|
|
2411
|
+
return navigableSelect({
|
|
2412
|
+
message: "Where should skills be installed?",
|
|
2413
|
+
options: [{
|
|
2414
|
+
value: "project",
|
|
2415
|
+
label: "Project",
|
|
2416
|
+
hint: "Writes to project config files (recommended for teams)"
|
|
2417
|
+
}, {
|
|
2418
|
+
value: "global",
|
|
2419
|
+
label: "Global",
|
|
2420
|
+
hint: "Writes to user-level config files (personal machine)"
|
|
2421
|
+
}],
|
|
2422
|
+
initialValue: DEFAULT_SCOPE
|
|
2423
|
+
});
|
|
2424
|
+
},
|
|
2425
|
+
skills: async () => {
|
|
2426
|
+
if (configuredSelections !== void 0) return configuredSelections.flatMap((selection) => selection.skills.map((skill) => `${selection.source}::${skill}`));
|
|
2427
|
+
return navigableMultiselect({
|
|
2428
|
+
message: "Select skills to install",
|
|
2429
|
+
options: skillOptions,
|
|
2430
|
+
required: false,
|
|
2431
|
+
initialValues: allSkillValues
|
|
2432
|
+
});
|
|
2433
|
+
},
|
|
2434
|
+
agents: async ({ results: r }) => {
|
|
2435
|
+
const pickedSkills = r.skills;
|
|
2436
|
+
if (pickedSkills !== void 0 && pickedSkills.length === 0) return [];
|
|
2437
|
+
if (configuredAgents !== void 0) return [...configuredAgents];
|
|
2438
|
+
return navigableMultiselect({
|
|
2439
|
+
message: "Select agents to install skills to",
|
|
2440
|
+
options: AVAILABLE_AGENTS,
|
|
2441
|
+
required: false,
|
|
2442
|
+
initialValues: [...DEFAULT_AGENTS$1]
|
|
2443
|
+
});
|
|
2444
|
+
}
|
|
2283
2445
|
});
|
|
2284
|
-
if (
|
|
2285
|
-
|
|
2446
|
+
if (results.scope === void 0 || results.skills === void 0 || results.agents === void 0) return Result.err(new UserCancelledError({ message: "Operation cancelled" }));
|
|
2447
|
+
scope = results.scope;
|
|
2448
|
+
selectedSkills = results.skills;
|
|
2449
|
+
selectedAgents = results.agents;
|
|
2450
|
+
if (selectedSkills.length === 0 || selectedAgents.length === 0) return Result.ok(void 0);
|
|
2286
2451
|
}
|
|
2287
|
-
if (selectedAgents.length === 0) return Result.ok(void 0);
|
|
2288
2452
|
const skillsBySource = {};
|
|
2289
2453
|
for (const skillKey of selectedSkills) {
|
|
2290
2454
|
const [source, skillName] = skillKey.split("::");
|
|
@@ -2474,7 +2638,8 @@ async function setupTui(config) {
|
|
|
2474
2638
|
cliLog.info("Setting up OpenTUI...");
|
|
2475
2639
|
let template = resolveTuiTemplate(config);
|
|
2476
2640
|
if (!template) {
|
|
2477
|
-
|
|
2641
|
+
setIsFirstPrompt(true);
|
|
2642
|
+
const selectedTemplate = await navigableSelect({
|
|
2478
2643
|
message: "Choose a template",
|
|
2479
2644
|
options: Object.entries(TEMPLATES$1).map(([key, templateOption]) => ({
|
|
2480
2645
|
value: key,
|
|
@@ -2483,7 +2648,7 @@ async function setupTui(config) {
|
|
|
2483
2648
|
})),
|
|
2484
2649
|
initialValue: DEFAULT_TEMPLATE$1
|
|
2485
2650
|
});
|
|
2486
|
-
if (isCancel(selectedTemplate)) return userCancelled("Operation cancelled");
|
|
2651
|
+
if (isCancel$1(selectedTemplate)) return userCancelled("Operation cancelled");
|
|
2487
2652
|
template = selectedTemplate;
|
|
2488
2653
|
}
|
|
2489
2654
|
const args = getPackageExecutionArgs(packageManager, `create-tui@latest --template ${template} --no-git --no-install tui`);
|
|
@@ -2563,42 +2728,40 @@ async function postProcessTuiWorkspace(tuiDir) {
|
|
|
2563
2728
|
//#endregion
|
|
2564
2729
|
//#region src/helpers/addons/ultracite-setup.ts
|
|
2565
2730
|
const LINTERS = {
|
|
2566
|
-
biome: {
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
},
|
|
2570
|
-
eslint: {
|
|
2571
|
-
label: "ESLint",
|
|
2572
|
-
hint: "Traditional JavaScript linter"
|
|
2573
|
-
},
|
|
2574
|
-
oxlint: {
|
|
2575
|
-
label: "Oxlint",
|
|
2576
|
-
hint: "Oxidation compiler linter"
|
|
2577
|
-
}
|
|
2578
|
-
};
|
|
2579
|
-
const EDITORS = {
|
|
2580
|
-
vscode: { label: "VS Code" },
|
|
2581
|
-
cursor: { label: "Cursor" },
|
|
2582
|
-
windsurf: { label: "Windsurf" },
|
|
2583
|
-
antigravity: { label: "Antigravity" },
|
|
2584
|
-
kiro: { label: "Kiro" },
|
|
2585
|
-
trae: { label: "Trae" },
|
|
2586
|
-
void: { label: "Void" },
|
|
2587
|
-
zed: { label: "Zed" }
|
|
2731
|
+
biome: { label: "Biome (Recommended)" },
|
|
2732
|
+
eslint: { label: "ESLint + Prettier + Stylelint" },
|
|
2733
|
+
oxlint: { label: "Oxlint + Oxfmt" }
|
|
2588
2734
|
};
|
|
2589
2735
|
const AGENTS = {
|
|
2590
|
-
|
|
2736
|
+
universal: { label: "Universal (AGENTS.md — covers all agents)" },
|
|
2737
|
+
claude: { label: "Claude Code" },
|
|
2591
2738
|
codex: { label: "Codex" },
|
|
2592
2739
|
jules: { label: "Jules" },
|
|
2740
|
+
replit: { label: "Replit Agent" },
|
|
2741
|
+
devin: { label: "Devin" },
|
|
2742
|
+
lovable: { label: "Lovable" },
|
|
2743
|
+
zencoder: { label: "Zencoder" },
|
|
2744
|
+
ona: { label: "Ona" },
|
|
2745
|
+
openclaw: { label: "OpenClaw" },
|
|
2746
|
+
continue: { label: "Continue" },
|
|
2747
|
+
"snowflake-cortex": { label: "Snowflake Cortex" },
|
|
2748
|
+
deepagents: { label: "Deepagents" },
|
|
2749
|
+
qoder: { label: "Qoder" },
|
|
2750
|
+
"kimi-cli": { label: "Kimi CLI" },
|
|
2751
|
+
mcpjam: { label: "MCPJam" },
|
|
2752
|
+
mux: { label: "Mux" },
|
|
2753
|
+
pi: { label: "Pi" },
|
|
2754
|
+
adal: { label: "AdaL" },
|
|
2593
2755
|
copilot: { label: "GitHub Copilot" },
|
|
2594
2756
|
cline: { label: "Cline" },
|
|
2595
|
-
amp: { label: "
|
|
2757
|
+
amp: { label: "AMP" },
|
|
2596
2758
|
aider: { label: "Aider" },
|
|
2597
2759
|
"firebase-studio": { label: "Firebase Studio" },
|
|
2598
|
-
"open-hands": { label: "
|
|
2760
|
+
"open-hands": { label: "OpenHands" },
|
|
2599
2761
|
gemini: { label: "Gemini" },
|
|
2600
2762
|
junie: { label: "Junie" },
|
|
2601
|
-
augmentcode: { label: "
|
|
2763
|
+
augmentcode: { label: "Augment Code" },
|
|
2764
|
+
bob: { label: "IBM Bob" },
|
|
2602
2765
|
"kilo-code": { label: "Kilo Code" },
|
|
2603
2766
|
goose: { label: "Goose" },
|
|
2604
2767
|
"roo-code": { label: "Roo Code" },
|
|
@@ -2606,21 +2769,23 @@ const AGENTS = {
|
|
|
2606
2769
|
droid: { label: "Droid" },
|
|
2607
2770
|
opencode: { label: "OpenCode" },
|
|
2608
2771
|
crush: { label: "Crush" },
|
|
2609
|
-
qwen: { label: "Qwen" },
|
|
2772
|
+
qwen: { label: "Qwen Code" },
|
|
2610
2773
|
"amazon-q-cli": { label: "Amazon Q CLI" },
|
|
2611
2774
|
firebender: { label: "Firebender" },
|
|
2612
2775
|
"cursor-cli": { label: "Cursor CLI" },
|
|
2613
2776
|
"mistral-vibe": { label: "Mistral Vibe" },
|
|
2614
|
-
vercel: { label: "Vercel" }
|
|
2777
|
+
vercel: { label: "Vercel Agent" }
|
|
2615
2778
|
};
|
|
2616
2779
|
const HOOKS = {
|
|
2617
2780
|
cursor: { label: "Cursor" },
|
|
2618
2781
|
windsurf: { label: "Windsurf" },
|
|
2619
|
-
|
|
2782
|
+
codebuddy: { label: "CodeBuddy" },
|
|
2783
|
+
claude: { label: "Claude Code" },
|
|
2784
|
+
copilot: { label: "GitHub Copilot" }
|
|
2620
2785
|
};
|
|
2621
2786
|
const DEFAULT_LINTER = "biome";
|
|
2622
|
-
const DEFAULT_EDITORS = ["vscode"
|
|
2623
|
-
const DEFAULT_AGENTS = ["
|
|
2787
|
+
const DEFAULT_EDITORS = ["vscode"];
|
|
2788
|
+
const DEFAULT_AGENTS = ["universal"];
|
|
2624
2789
|
const DEFAULT_HOOKS = [];
|
|
2625
2790
|
function getFrameworksFromFrontend(frontend) {
|
|
2626
2791
|
const frameworkMap = {
|
|
@@ -2633,7 +2798,8 @@ function getFrameworksFromFrontend(frontend) {
|
|
|
2633
2798
|
"native-uniwind": "react",
|
|
2634
2799
|
"native-unistyles": "react",
|
|
2635
2800
|
svelte: "svelte",
|
|
2636
|
-
solid: "solid"
|
|
2801
|
+
solid: "solid",
|
|
2802
|
+
astro: "astro"
|
|
2637
2803
|
};
|
|
2638
2804
|
const frameworks = /* @__PURE__ */ new Set();
|
|
2639
2805
|
for (const f of frontend) if (f !== "none" && frameworkMap[f]) frameworks.add(frameworkMap[f]);
|
|
@@ -2651,10 +2817,7 @@ function buildUltraciteInitArgs({ packageManager, linter, frameworks, editors, a
|
|
|
2651
2817
|
if (editors.length > 0) ultraciteArgs.push("--editors", ...editors);
|
|
2652
2818
|
if (agents.length > 0) ultraciteArgs.push("--agents", ...agents);
|
|
2653
2819
|
if (hooks.length > 0) ultraciteArgs.push("--hooks", ...hooks);
|
|
2654
|
-
if (gitHooks.length > 0)
|
|
2655
|
-
const integrations = gitHooks.includes("husky") ? [...new Set([...gitHooks, "lint-staged"])] : gitHooks;
|
|
2656
|
-
ultraciteArgs.push("--integrations", ...integrations);
|
|
2657
|
-
}
|
|
2820
|
+
if (gitHooks.length > 0) ultraciteArgs.push("--integrations", ...gitHooks);
|
|
2658
2821
|
return [
|
|
2659
2822
|
...getPackageRunnerPrefix(packageManager),
|
|
2660
2823
|
"ultracite@latest",
|
|
@@ -2678,67 +2841,60 @@ async function setupUltracite(config, gitHooks) {
|
|
|
2678
2841
|
agents = agents ?? [...DEFAULT_AGENTS];
|
|
2679
2842
|
hooks = hooks ?? [...DEFAULT_HOOKS];
|
|
2680
2843
|
} else {
|
|
2681
|
-
const
|
|
2682
|
-
|
|
2683
|
-
return
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
}),
|
|
2693
|
-
editors: () => multiselect({
|
|
2694
|
-
message: "Choose editors",
|
|
2695
|
-
required: false,
|
|
2696
|
-
options: Object.entries(EDITORS).map(([key, editor]) => ({
|
|
2697
|
-
value: key,
|
|
2698
|
-
label: editor.label
|
|
2699
|
-
})),
|
|
2700
|
-
initialValues: editors ?? [...DEFAULT_EDITORS]
|
|
2701
|
-
}),
|
|
2702
|
-
agents: () => multiselect({
|
|
2703
|
-
message: "Choose agents",
|
|
2704
|
-
required: false,
|
|
2705
|
-
options: Object.entries(AGENTS).map(([key, agent]) => ({
|
|
2706
|
-
value: key,
|
|
2707
|
-
label: agent.label
|
|
2708
|
-
})),
|
|
2709
|
-
initialValues: agents ?? [...DEFAULT_AGENTS]
|
|
2710
|
-
}),
|
|
2711
|
-
hooks: () => multiselect({
|
|
2712
|
-
message: "Choose hooks",
|
|
2713
|
-
required: false,
|
|
2714
|
-
options: Object.entries(HOOKS).map(([key, hook]) => ({
|
|
2715
|
-
value: key,
|
|
2716
|
-
label: hook.label
|
|
2717
|
-
})),
|
|
2718
|
-
initialValues: hooks ?? [...DEFAULT_HOOKS]
|
|
2719
|
-
})
|
|
2720
|
-
}, { onCancel: () => {
|
|
2721
|
-
throw new UserCancelledError({ message: "Operation cancelled" });
|
|
2722
|
-
} });
|
|
2844
|
+
const results = await navigableGroup({
|
|
2845
|
+
linter: async () => {
|
|
2846
|
+
if (linter !== void 0) return linter;
|
|
2847
|
+
return navigableSelect({
|
|
2848
|
+
message: "Which linter do you want to use?",
|
|
2849
|
+
options: Object.entries(LINTERS).map(([key, linterOption]) => ({
|
|
2850
|
+
value: key,
|
|
2851
|
+
label: linterOption.label
|
|
2852
|
+
})),
|
|
2853
|
+
initialValue: linter ?? DEFAULT_LINTER
|
|
2854
|
+
});
|
|
2723
2855
|
},
|
|
2724
|
-
|
|
2725
|
-
if (
|
|
2726
|
-
return
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2856
|
+
editors: async () => {
|
|
2857
|
+
if (editors !== void 0) return editors;
|
|
2858
|
+
return navigableMultiselect({
|
|
2859
|
+
message: "Which editors do you want to configure (recommended)?",
|
|
2860
|
+
required: false,
|
|
2861
|
+
options: [{
|
|
2862
|
+
value: "vscode",
|
|
2863
|
+
label: "VSCode / Cursor / Windsurf"
|
|
2864
|
+
}, {
|
|
2865
|
+
value: "zed",
|
|
2866
|
+
label: "Zed"
|
|
2867
|
+
}]
|
|
2868
|
+
});
|
|
2869
|
+
},
|
|
2870
|
+
agents: async () => {
|
|
2871
|
+
if (agents !== void 0) return agents;
|
|
2872
|
+
return navigableMultiselect({
|
|
2873
|
+
message: "Which agent files do you want to add (optional)?",
|
|
2874
|
+
required: false,
|
|
2875
|
+
options: Object.entries(AGENTS).map(([key, agent]) => ({
|
|
2876
|
+
value: key,
|
|
2877
|
+
label: agent.label
|
|
2878
|
+
}))
|
|
2879
|
+
});
|
|
2880
|
+
},
|
|
2881
|
+
hooks: async () => {
|
|
2882
|
+
if (hooks !== void 0) return hooks;
|
|
2883
|
+
return navigableMultiselect({
|
|
2884
|
+
message: "Which agent hooks do you want to enable (optional)?",
|
|
2885
|
+
required: false,
|
|
2886
|
+
options: Object.entries(HOOKS).map(([key, hook]) => ({
|
|
2887
|
+
value: key,
|
|
2888
|
+
label: hook.label
|
|
2889
|
+
}))
|
|
2730
2890
|
});
|
|
2731
2891
|
}
|
|
2732
2892
|
});
|
|
2733
|
-
if (
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
linter = groupResult.value.linter;
|
|
2739
|
-
editors = groupResult.value.editors;
|
|
2740
|
-
agents = groupResult.value.agents;
|
|
2741
|
-
hooks = groupResult.value.hooks;
|
|
2893
|
+
if (results.linter === void 0 || results.editors === void 0 || results.agents === void 0 || results.hooks === void 0) return userCancelled("Operation cancelled");
|
|
2894
|
+
linter = results.linter;
|
|
2895
|
+
editors = results.editors;
|
|
2896
|
+
agents = results.agents;
|
|
2897
|
+
hooks = results.hooks;
|
|
2742
2898
|
}
|
|
2743
2899
|
const frameworks = getFrameworksFromFrontend(frontend);
|
|
2744
2900
|
const args = buildUltraciteInitArgs({
|
|
@@ -2809,7 +2965,8 @@ async function setupWxt(config) {
|
|
|
2809
2965
|
let template = configuredOptions?.template;
|
|
2810
2966
|
if (!template) if (isSilent()) template = DEFAULT_TEMPLATE;
|
|
2811
2967
|
else {
|
|
2812
|
-
|
|
2968
|
+
setIsFirstPrompt(true);
|
|
2969
|
+
const selectedTemplate = await navigableSelect({
|
|
2813
2970
|
message: "Choose a template",
|
|
2814
2971
|
options: Object.entries(TEMPLATES).map(([key, templateOption]) => ({
|
|
2815
2972
|
value: key,
|
|
@@ -2818,7 +2975,7 @@ async function setupWxt(config) {
|
|
|
2818
2975
|
})),
|
|
2819
2976
|
initialValue: DEFAULT_TEMPLATE
|
|
2820
2977
|
});
|
|
2821
|
-
if (isCancel(selectedTemplate)) return userCancelled("Operation cancelled");
|
|
2978
|
+
if (isCancel$1(selectedTemplate)) return userCancelled("Operation cancelled");
|
|
2822
2979
|
template = selectedTemplate;
|
|
2823
2980
|
}
|
|
2824
2981
|
const devPort = configuredOptions?.devPort ?? DEFAULT_DEV_PORT;
|
|
@@ -3648,62 +3805,6 @@ async function getinstallChoice(install) {
|
|
|
3648
3805
|
return response;
|
|
3649
3806
|
}
|
|
3650
3807
|
//#endregion
|
|
3651
|
-
//#region src/prompts/navigable-group.ts
|
|
3652
|
-
/**
|
|
3653
|
-
* Navigable group - a group of prompts that allows going back
|
|
3654
|
-
*/
|
|
3655
|
-
/**
|
|
3656
|
-
* Define a group of prompts that supports going back to previous prompts.
|
|
3657
|
-
* Returns a result object with all the values, or handles cancel/go-back navigation.
|
|
3658
|
-
*/
|
|
3659
|
-
async function navigableGroup(prompts, opts) {
|
|
3660
|
-
const results = {};
|
|
3661
|
-
const promptNames = Object.keys(prompts);
|
|
3662
|
-
let currentIndex = 0;
|
|
3663
|
-
let goingBack = false;
|
|
3664
|
-
while (currentIndex < promptNames.length) {
|
|
3665
|
-
const name = promptNames[currentIndex];
|
|
3666
|
-
const prompt = prompts[name];
|
|
3667
|
-
setIsFirstPrompt$1(currentIndex === 0);
|
|
3668
|
-
setLastPromptShownUI(false);
|
|
3669
|
-
const result = await prompt({ results })?.catch((e) => {
|
|
3670
|
-
throw e;
|
|
3671
|
-
});
|
|
3672
|
-
if (isGoBack(result)) {
|
|
3673
|
-
goingBack = true;
|
|
3674
|
-
if (currentIndex > 0) {
|
|
3675
|
-
const prevName = promptNames[currentIndex - 1];
|
|
3676
|
-
delete results[prevName];
|
|
3677
|
-
currentIndex--;
|
|
3678
|
-
continue;
|
|
3679
|
-
}
|
|
3680
|
-
goingBack = false;
|
|
3681
|
-
continue;
|
|
3682
|
-
}
|
|
3683
|
-
if (isCancel$1(result)) {
|
|
3684
|
-
if (typeof opts?.onCancel === "function") {
|
|
3685
|
-
results[name] = "canceled";
|
|
3686
|
-
opts.onCancel({ results });
|
|
3687
|
-
}
|
|
3688
|
-
setIsFirstPrompt$1(false);
|
|
3689
|
-
return results;
|
|
3690
|
-
}
|
|
3691
|
-
if (goingBack && !didLastPromptShowUI()) {
|
|
3692
|
-
if (currentIndex > 0) {
|
|
3693
|
-
const prevName = promptNames[currentIndex - 1];
|
|
3694
|
-
delete results[prevName];
|
|
3695
|
-
currentIndex--;
|
|
3696
|
-
continue;
|
|
3697
|
-
}
|
|
3698
|
-
}
|
|
3699
|
-
goingBack = false;
|
|
3700
|
-
results[name] = result;
|
|
3701
|
-
currentIndex++;
|
|
3702
|
-
}
|
|
3703
|
-
setIsFirstPrompt$1(false);
|
|
3704
|
-
return results;
|
|
3705
|
-
}
|
|
3706
|
-
//#endregion
|
|
3707
3808
|
//#region src/utils/config-validation.ts
|
|
3708
3809
|
function validationErr(message) {
|
|
3709
3810
|
return Result.err(new ValidationError({ message }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.27.
|
|
3
|
+
"version": "3.27.5",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-auth",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"prepublishOnly": "npm run build"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@better-t-stack/template-generator": "^3.27.
|
|
74
|
-
"@better-t-stack/types": "^3.27.
|
|
73
|
+
"@better-t-stack/template-generator": "^3.27.5",
|
|
74
|
+
"@better-t-stack/types": "^3.27.5",
|
|
75
75
|
"@clack/core": "^1.2.0",
|
|
76
76
|
"@clack/prompts": "^1.2.0",
|
|
77
77
|
"@modelcontextprotocol/sdk": "1.29.0",
|