mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
feat(cli): update ultracite rules and add autocomplete multiselect in ultracite and ruler
This commit is contained in:
@@ -66,7 +66,7 @@
|
||||
"dependencies": {
|
||||
"@biomejs/js-api": "^3.0.0",
|
||||
"@biomejs/wasm-nodejs": "^2.2.0",
|
||||
"@clack/prompts": "^0.11.0",
|
||||
"@clack/prompts": "^1.0.0-alpha.4",
|
||||
"consola": "^3.4.2",
|
||||
"execa": "^9.6.0",
|
||||
"fs-extra": "^11.3.1",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import path from "node:path";
|
||||
import { isCancel, log, multiselect, spinner } from "@clack/prompts";
|
||||
import {
|
||||
isCancel,
|
||||
log,
|
||||
autocompleteMultiselect,
|
||||
spinner,
|
||||
} from "@clack/prompts";
|
||||
import { execa } from "execa";
|
||||
import fs from "fs-extra";
|
||||
import pc from "picocolors";
|
||||
@@ -61,14 +66,16 @@ export async function setupVibeRules(config: ProjectConfig) {
|
||||
opencode: { label: "OpenCode" },
|
||||
} as const;
|
||||
|
||||
const selectedEditors = await multiselect<keyof typeof EDITORS>({
|
||||
message: "Select AI assistants for Ruler",
|
||||
options: Object.entries(EDITORS).map(([key, v]) => ({
|
||||
value: key as keyof typeof EDITORS,
|
||||
label: v.label,
|
||||
})),
|
||||
required: false,
|
||||
});
|
||||
const selectedEditors = await autocompleteMultiselect<keyof typeof EDITORS>(
|
||||
{
|
||||
message: "Select AI assistants for Ruler",
|
||||
options: Object.entries(EDITORS).map(([key, v]) => ({
|
||||
value: key as keyof typeof EDITORS,
|
||||
label: v.label,
|
||||
})),
|
||||
required: false,
|
||||
},
|
||||
);
|
||||
|
||||
if (isCancel(selectedEditors)) return exitCancelled("Operation cancelled");
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { isCancel, log, multiselect } from "@clack/prompts";
|
||||
import {
|
||||
autocompleteMultiselect,
|
||||
group,
|
||||
log,
|
||||
multiselect,
|
||||
} from "@clack/prompts";
|
||||
import { execa } from "execa";
|
||||
import pc from "picocolors";
|
||||
import type { ProjectConfig } from "../../types";
|
||||
@@ -14,43 +19,79 @@ type UltraciteRule =
|
||||
| "windsurf"
|
||||
| "zed"
|
||||
| "claude"
|
||||
| "codex";
|
||||
| "codex"
|
||||
| "kiro"
|
||||
| "cline"
|
||||
| "amp"
|
||||
| "aider"
|
||||
| "firebase-studio"
|
||||
| "open-hands"
|
||||
| "gemini-cli"
|
||||
| "junie"
|
||||
| "augmentcode"
|
||||
| "kilo-code"
|
||||
| "goose";
|
||||
|
||||
const EDITORS = {
|
||||
vscode: {
|
||||
label: "VSCode / Cursor / Windsurf",
|
||||
hint: "Visual Studio Code editor configuration",
|
||||
},
|
||||
zed: {
|
||||
label: "Zed",
|
||||
hint: "Zed editor configuration",
|
||||
},
|
||||
} as const;
|
||||
|
||||
const RULES = {
|
||||
"vscode-copilot": {
|
||||
label: "VS Code Copilot",
|
||||
hint: "GitHub Copilot integration for VS Code",
|
||||
},
|
||||
cursor: {
|
||||
label: "Cursor",
|
||||
hint: "Cursor AI editor configuration",
|
||||
},
|
||||
windsurf: {
|
||||
label: "Windsurf",
|
||||
hint: "Windsurf editor configuration",
|
||||
},
|
||||
zed: {
|
||||
label: "Zed",
|
||||
hint: "Zed editor rules",
|
||||
},
|
||||
claude: {
|
||||
label: "Claude",
|
||||
hint: "Claude AI integration",
|
||||
},
|
||||
codex: {
|
||||
label: "Codex",
|
||||
hint: "Codex AI integration",
|
||||
},
|
||||
kiro: {
|
||||
label: "Kiro",
|
||||
},
|
||||
cline: {
|
||||
label: "Cline",
|
||||
},
|
||||
amp: {
|
||||
label: "Amp",
|
||||
},
|
||||
aider: {
|
||||
label: "Aider",
|
||||
},
|
||||
"firebase-studio": {
|
||||
label: "Firebase Studio",
|
||||
},
|
||||
"open-hands": {
|
||||
label: "Open Hands",
|
||||
},
|
||||
"gemini-cli": {
|
||||
label: "Gemini CLI",
|
||||
},
|
||||
junie: {
|
||||
label: "Junie",
|
||||
},
|
||||
augmentcode: {
|
||||
label: "AugmentCode",
|
||||
},
|
||||
"kilo-code": {
|
||||
label: "Kilo Code",
|
||||
},
|
||||
goose: {
|
||||
label: "Goose",
|
||||
},
|
||||
} as const;
|
||||
|
||||
@@ -62,29 +103,36 @@ export async function setupUltracite(config: ProjectConfig, hasHusky: boolean) {
|
||||
|
||||
await setupBiome(projectDir);
|
||||
|
||||
const editors = await multiselect<UltraciteEditor>({
|
||||
message: "Choose editors",
|
||||
options: Object.entries(EDITORS).map(([key, editor]) => ({
|
||||
value: key as UltraciteEditor,
|
||||
label: editor.label,
|
||||
hint: editor.hint,
|
||||
})),
|
||||
required: true,
|
||||
});
|
||||
const result = await group(
|
||||
{
|
||||
editors: () =>
|
||||
multiselect<UltraciteEditor>({
|
||||
message: "Choose editors",
|
||||
options: Object.entries(EDITORS).map(([key, editor]) => ({
|
||||
value: key as UltraciteEditor,
|
||||
label: editor.label,
|
||||
})),
|
||||
required: true,
|
||||
}),
|
||||
rules: () =>
|
||||
autocompleteMultiselect<UltraciteRule>({
|
||||
message: "Choose rules",
|
||||
options: Object.entries(RULES).map(([key, rule]) => ({
|
||||
value: key as UltraciteRule,
|
||||
label: rule.label,
|
||||
})),
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
exitCancelled("Operation cancelled");
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (isCancel(editors)) return exitCancelled("Operation cancelled");
|
||||
|
||||
const rules = await multiselect<UltraciteRule>({
|
||||
message: "Choose rules",
|
||||
options: Object.entries(RULES).map(([key, rule]) => ({
|
||||
value: key as UltraciteRule,
|
||||
label: rule.label,
|
||||
hint: rule.hint,
|
||||
})),
|
||||
required: true,
|
||||
});
|
||||
|
||||
if (isCancel(rules)) return exitCancelled("Operation cancelled");
|
||||
const editors = result.editors as UltraciteEditor[];
|
||||
const rules = result.rules as UltraciteRule[];
|
||||
|
||||
const ultraciteArgs = ["init", "--pm", packageManager];
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ export async function getProjectName(initialName?: string): Promise<string> {
|
||||
initialValue: initialName,
|
||||
defaultValue: defaultName,
|
||||
validate: (value) => {
|
||||
const nameToUse = value.trim() || defaultName;
|
||||
const nameToUse = String(value ?? "").trim() || defaultName;
|
||||
|
||||
const finalDirName = path.basename(nameToUse);
|
||||
const validationError = validateDirectoryName(finalDirName);
|
||||
|
||||
6
bun.lock
6
bun.lock
@@ -22,7 +22,7 @@
|
||||
"dependencies": {
|
||||
"@biomejs/js-api": "^3.0.0",
|
||||
"@biomejs/wasm-nodejs": "^2.2.0",
|
||||
"@clack/prompts": "^0.11.0",
|
||||
"@clack/prompts": "^1.0.0-alpha.4",
|
||||
"consola": "^3.4.2",
|
||||
"execa": "^9.6.0",
|
||||
"fs-extra": "^11.3.1",
|
||||
@@ -273,9 +273,9 @@
|
||||
|
||||
"@biomejs/wasm-nodejs": ["@biomejs/wasm-nodejs@2.2.0", "", {}, "sha512-jTN0IdKqt8EOPAzMGYKzeNykOKljZBRwABO2N6rEaC5CzJEhS3CuApdjqWpK/TMsVfw694gA3qhNNRhyFI2mWg=="],
|
||||
|
||||
"@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="],
|
||||
"@clack/core": ["@clack/core@1.0.0-alpha.4", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-VCtU+vjyKPMSakVrB9q1bOnXN7QW/w4+YQDQCOF59GrzydW+169i0fVx/qzRRXJgt8KGj/pZZ/JxXroFZIDByg=="],
|
||||
|
||||
"@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="],
|
||||
"@clack/prompts": ["@clack/prompts@1.0.0-alpha.4", "", { "dependencies": { "@clack/core": "1.0.0-alpha.4", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-KnmtDF2xQGoI5AlBme9akHtvCRV0RKAARUXHBQO2tMwnY8B08/4zPWigT7uLK25UPrMCEqnyQPkKRjNdhPbf8g=="],
|
||||
|
||||
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="],
|
||||
|
||||
|
||||
Reference in New Issue
Block a user