diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 378e367..88114b0 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -22,7 +22,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- @@ -47,7 +47,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- @@ -69,7 +69,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- @@ -91,7 +91,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- @@ -182,7 +182,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- @@ -225,7 +225,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index b0023a2..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Publish to npm - -on: - release: - types: [created] - -jobs: - get-version: - name: Get Version - runs-on: ubuntu-latest - outputs: - version: ${{ steps.version.outputs.VERSION }} - steps: - - name: Extract version from tag - id: version - run: | - VERSION="${GITHUB_REF#refs/tags/}" - VERSION="${VERSION#v}" - VERSION="${VERSION#.}" - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - publish: - name: Publish to npm - runs-on: ubuntu-latest - needs: get-version - steps: - - uses: actions/checkout@v4 - - - uses: oven-sh/setup-bun@v2 - - - uses: actions/setup-node@v4 - with: - node-version: '20' - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - run: bun install - - - name: Update version - run: npm version ${{ needs.get-version.outputs.version }} --no-git-tag-version --allow-same-version - - - name: Build - run: bun run build - - - name: Run unit tests - run: bun run test - - - name: Run E2E tests - run: bun test src/cli.e2e.test.ts - - - name: Publish - run: npm publish - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - commit-version: - name: Commit Version to Repo - runs-on: ubuntu-latest - needs: [get-version, publish] - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - with: - ref: main - - - name: Update version - run: npm version ${{ needs.get-version.outputs.version }} --no-git-tag-version --allow-same-version - - - name: Commit and push - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add package.json - git commit -m "chore: bump version to ${{ needs.get-version.outputs.version }}" - git push origin main diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9805a56..b74720f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- @@ -79,7 +79,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} + key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- diff --git a/src/cli.test.ts b/src/cli.test.ts index a0451fa..e092c0a 100644 --- a/src/cli.test.ts +++ b/src/cli.test.ts @@ -9,6 +9,7 @@ import { formatFramework, formatLanguage, getVersion, + mapFormatter, parseArgs, promptNewProject, showBanner, @@ -350,21 +351,83 @@ describe("formatFramework", () => { }); // Swift/iOS frameworks - it("formats swiftui correctly", () => { - expect(formatFramework("swiftui")).toBe("swiftui"); + it("formats SwiftUI correctly", () => { + expect(formatFramework("swiftui")).toBe("SwiftUI"); }); - it("formats uikit correctly", () => { - expect(formatFramework("uikit")).toBe("uikit"); + it("formats UIKit correctly", () => { + expect(formatFramework("uikit")).toBe("UIKit"); + }); + + it("formats Vapor correctly", () => { + expect(formatFramework("vapor")).toBe("Vapor"); + }); + + it("formats SwiftData correctly", () => { + expect(formatFramework("swiftdata")).toBe("SwiftData"); + }); + + it("formats Combine correctly", () => { + expect(formatFramework("combine")).toBe("Combine"); }); // Android frameworks - it("formats jetpack-compose correctly", () => { - expect(formatFramework("jetpack-compose")).toBe("jetpack-compose"); + it("formats Jetpack Compose correctly", () => { + expect(formatFramework("jetpack-compose")).toBe("Jetpack Compose"); + }); + + it("formats Android Views correctly", () => { + expect(formatFramework("android-views")).toBe("Android Views"); + }); + + it("formats Room correctly", () => { + expect(formatFramework("room")).toBe("Room"); + }); + + it("formats Hilt correctly", () => { + expect(formatFramework("hilt")).toBe("Hilt"); + }); + + it("formats Ktor correctly", () => { + expect(formatFramework("ktor-android")).toBe("Ktor"); + }); +}); + +// ============================================================================ +// mapFormatter Tests +// ============================================================================ + +describe("mapFormatter", () => { + it("maps eslint to prettier", () => { + expect(mapFormatter("eslint")).toBe("prettier"); + }); + + it("maps biome to biome", () => { + expect(mapFormatter("biome")).toBe("biome"); + }); + + it("maps ruff to ruff", () => { + expect(mapFormatter("ruff")).toBe("ruff"); + }); + + it("maps flake8 to black", () => { + expect(mapFormatter("flake8")).toBe("black"); + }); + + it("maps clippy to rustfmt", () => { + expect(mapFormatter("clippy")).toBe("rustfmt"); + }); + + it("maps rubocop to rubocop", () => { + expect(mapFormatter("rubocop")).toBe("rubocop"); + }); + + it("maps golangci-lint to gofmt", () => { + expect(mapFormatter("golangci-lint")).toBe("gofmt"); }); - it("formats android-views correctly", () => { - expect(formatFramework("android-views")).toBe("android-views"); + it("maps null to null", () => { + expect(mapFormatter(null)).toBeNull(); }); }); diff --git a/src/cli.ts b/src/cli.ts index b6d9bc0..3d99bca 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -32,7 +32,15 @@ import prompts from "prompts"; import { analyzeRepository, summarizeTechStack } from "./analyzer.js"; import { ensureDirectories, writeSettings } from "./generator.js"; import { getAnalysisPrompt } from "./prompt.js"; -import type { Args, Framework, Language, NewProjectPreferences, ProjectInfo } from "./types.js"; +import type { + Args, + Formatter, + Framework, + Language, + Linter, + NewProjectPreferences, + ProjectInfo, +} from "./types.js"; // ============================================================================ // Constants @@ -330,7 +338,7 @@ export async function promptNewProject(args: Args): Promise> = { + eslint: "prettier", + biome: "biome", + ruff: "ruff", + flake8: "black", + pylint: "black", + "golangci-lint": "gofmt", + clippy: "rustfmt", + rubocop: "rubocop", + }; + return mapping[linter] ?? null; +} + export function createTaskFile( projectInfo: ProjectInfo, preferences: NewProjectPreferences | null @@ -535,7 +558,7 @@ export function formatLanguage(lang: Language): string { } export function formatFramework(fw: Framework): string { - const names: Record = { + const names: Partial> = { nextjs: "Next.js", react: "React", vue: "Vue.js", @@ -567,10 +590,24 @@ export function formatFramework(fw: Framework): string { sinatra: "Sinatra", spring: "Spring", quarkus: "Quarkus", + // Swift/iOS + swiftui: "SwiftUI", + uikit: "UIKit", + vapor: "Vapor", + swiftdata: "SwiftData", + combine: "Combine", + // Android + "jetpack-compose": "Jetpack Compose", + "android-views": "Android Views", + room: "Room", + hilt: "Hilt", + "ktor-android": "Ktor", + // CSS/UI tailwind: "Tailwind CSS", shadcn: "shadcn/ui", chakra: "Chakra UI", mui: "Material UI", + // Database/ORM prisma: "Prisma", drizzle: "Drizzle", typeorm: "TypeORM", @@ -615,7 +652,6 @@ export function runClaudeAnalysis(projectDir: string, projectInfo: ProjectInfo): "claude", [ "-p", - "--dangerously-skip-permissions", "--allowedTools", "Read", "--allowedTools",