@lousy-agents/cli 1.1.0 → 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.
Files changed (32) hide show
  1. package/README.md +11 -12
  2. package/api/copilot-with-fastify/.devcontainer/devcontainer.json +90 -0
  3. package/api/copilot-with-fastify/.editorconfig +16 -0
  4. package/api/copilot-with-fastify/.github/ISSUE_TEMPLATE/feature-to-spec.yml +55 -0
  5. package/api/copilot-with-fastify/.github/copilot-instructions.md +387 -0
  6. package/api/copilot-with-fastify/.github/instructions/pipeline.instructions.md +149 -0
  7. package/api/copilot-with-fastify/.github/instructions/software-architecture.instructions.md +430 -0
  8. package/api/copilot-with-fastify/.github/instructions/spec.instructions.md +411 -0
  9. package/api/copilot-with-fastify/.github/instructions/test.instructions.md +268 -0
  10. package/api/copilot-with-fastify/.github/specs/README.md +84 -0
  11. package/api/copilot-with-fastify/.github/workflows/assign-copilot.yml +59 -0
  12. package/api/copilot-with-fastify/.github/workflows/ci.yml +88 -0
  13. package/api/copilot-with-fastify/.nvmrc +1 -0
  14. package/api/copilot-with-fastify/.vscode/extensions.json +14 -0
  15. package/api/copilot-with-fastify/.vscode/launch.json +30 -0
  16. package/api/copilot-with-fastify/.vscode/mcp.json +19 -0
  17. package/api/copilot-with-fastify/.yamllint +18 -0
  18. package/api/copilot-with-fastify/biome.json +31 -0
  19. package/api/copilot-with-fastify/package.json +37 -0
  20. package/api/copilot-with-fastify/tsconfig.json +34 -0
  21. package/api/copilot-with-fastify/vitest.config.ts +21 -0
  22. package/api/copilot-with-fastify/vitest.integration.config.ts +18 -0
  23. package/api/copilot-with-fastify/vitest.setup.ts +5 -0
  24. package/dist/commands/init.d.ts +2 -1
  25. package/dist/commands/init.d.ts.map +1 -1
  26. package/dist/commands/init.js +39 -45
  27. package/dist/commands/init.js.map +1 -1
  28. package/dist/lib/config.d.ts +6 -5
  29. package/dist/lib/config.d.ts.map +1 -1
  30. package/dist/lib/config.js +186 -6
  31. package/dist/lib/config.js.map +1 -1
  32. package/package.json +4 -3
@@ -0,0 +1,84 @@
1
+ # Specifications Directory
2
+
3
+ This directory contains feature specifications created through the spec-driven development workflow.
4
+
5
+ ## Workflow Overview
6
+
7
+ 1. **Create a Spec Issue** — Use the "Copilot Feature To Spec" issue template to define your feature
8
+ 2. **Auto-Assignment** — Issues with the `copilot-ready` label automatically trigger Copilot assignment
9
+ 3. **Spec Creation** — Copilot creates a structured specification in this directory
10
+ 4. **Implementation** — Follow the tasks in the spec to implement the feature
11
+
12
+ ## Spec File Structure
13
+
14
+ Each spec follows this structure:
15
+
16
+ ```markdown
17
+ # Feature: <name>
18
+
19
+ ## Problem Statement
20
+ <2-3 sentences describing the problem>
21
+
22
+ ## Personas
23
+ | Persona | Impact | Notes |
24
+ |---------|--------|-------|
25
+
26
+ ## Value Assessment
27
+ - **Primary value**: <type> — <explanation>
28
+
29
+ ## User Stories
30
+
31
+ ### Story 1: <Title>
32
+ As a **<persona>**,
33
+ I want **<capability>**,
34
+ so that I can **<outcome>**.
35
+
36
+ #### Acceptance Criteria
37
+ - When <trigger>, the <system> shall <response>
38
+
39
+ ---
40
+
41
+ ## Design
42
+
43
+ ### Components Affected
44
+ ### Dependencies
45
+ ### Open Questions
46
+
47
+ ---
48
+
49
+ ## Tasks
50
+
51
+ ### Task 1: <Title>
52
+ **Objective**: ...
53
+ **Verification**: ...
54
+ ```
55
+
56
+ ## EARS Syntax for Acceptance Criteria
57
+
58
+ Use EARS (Easy Approach to Requirements Syntax) patterns:
59
+
60
+ | Pattern | Template | Use When |
61
+ |---------|----------|----------|
62
+ | Ubiquitous | The `<system>` shall `<response>` | Always true |
63
+ | Event-driven | When `<trigger>`, the `<system>` shall `<response>` | Responding to event |
64
+ | State-driven | While `<state>`, the `<system>` shall `<response>` | During a condition |
65
+ | Optional | Where `<feature>` is enabled, the `<system>` shall `<response>` | Configurable capability |
66
+ | Unwanted | If `<condition>`, then the `<system>` shall `<response>` | Error handling |
67
+ | Complex | While `<state>`, when `<trigger>`, the `<system>` shall `<response>` | Combining conditions |
68
+
69
+ ### Examples
70
+
71
+ ```markdown
72
+ - The API shall validate all input parameters
73
+ - When a user submits a form, the system shall display a success message
74
+ - While the server is under high load, the system shall queue requests
75
+ - Where manual approval is configured, the system shall pause deployment until approved
76
+ - If the request body is malformed, then the system shall return a 400 error
77
+ - While branch protection is enabled, when a push is attempted, the system shall reject unauthorized changes
78
+ ```
79
+
80
+ ## Related Files
81
+
82
+ - `.github/ISSUE_TEMPLATE/feature-to-spec.yml` — Issue template for creating specs
83
+ - `.github/workflows/assign-copilot.yml` — Workflow for auto-assigning Copilot
84
+ - `.github/instructions/spec.instructions.md` — Detailed instructions for spec writing
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: Auto-Assign Copilot on Spec Issues
3
+
4
+ on:
5
+ issues:
6
+ types: [opened, edited]
7
+
8
+ permissions:
9
+ issues: write
10
+
11
+ jobs:
12
+ assign-agent:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Assign and Instruct Copilot
16
+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
17
+ with:
18
+ script: |
19
+ const issue = context.payload.issue;
20
+
21
+ // Check if issue has the copilot-ready label
22
+ const hasCopilotLabel = issue.labels.some(label => label.name === 'copilot-ready');
23
+
24
+ if (!hasCopilotLabel) {
25
+ console.log("Issue does not have 'copilot-ready' label. Skipping.");
26
+ return;
27
+ }
28
+
29
+ const body = issue.body || "";
30
+ const pattern = /### Extra Instructions\s+([\s\S]*?)(?=\n###|$)/;
31
+ const match = body.match(pattern);
32
+
33
+ // Always mention @copilot to trigger assignment and provide context
34
+ let comment = "@copilot";
35
+
36
+ if (match && match[1].trim().length > 0) {
37
+ let instructions = match[1].trim();
38
+
39
+ // Basic sanitization: limit length to prevent overly long comments
40
+ const MAX_LENGTH = 2000;
41
+ if (instructions.length > MAX_LENGTH) {
42
+ instructions = instructions.slice(0, MAX_LENGTH) + "\n\n[Instructions truncated]";
43
+ }
44
+
45
+ comment = `@copilot ${instructions}`;
46
+ console.log("Found extra instructions, mentioning Copilot with instructions.");
47
+ } else {
48
+ comment = "@copilot Please work on this issue according to the specification provided.";
49
+ console.log("No extra instructions found, mentioning Copilot with default message.");
50
+ }
51
+
52
+ await github.rest.issues.createComment({
53
+ owner: context.repo.owner,
54
+ repo: context.repo.repo,
55
+ issue_number: issue.number,
56
+ body: comment
57
+ });
58
+
59
+ console.log("Successfully mentioned Copilot in issue comment.");
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches: [main]
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ lint:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
19
+
20
+ - name: Setup Node.js
21
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
22
+ with:
23
+ node-version-file: '.nvmrc'
24
+ cache: 'npm'
25
+
26
+ - name: Install dependencies
27
+ run: npm ci
28
+
29
+ - name: Lint
30
+ run: npx biome check
31
+
32
+ unit-tests:
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - name: Checkout
36
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
37
+
38
+ - name: Setup Node.js
39
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
40
+ with:
41
+ node-version-file: '.nvmrc'
42
+ cache: 'npm'
43
+
44
+ - name: Install dependencies
45
+ run: npm ci
46
+
47
+ - name: Run unit tests
48
+ run: npm test
49
+
50
+ integration-tests:
51
+ runs-on: ubuntu-latest
52
+ steps:
53
+ - name: Checkout
54
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
55
+
56
+ - name: Setup Node.js
57
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
58
+ with:
59
+ node-version-file: '.nvmrc'
60
+ cache: 'npm'
61
+
62
+ - name: Install dependencies
63
+ run: npm ci
64
+
65
+ - name: Run integration tests
66
+ run: npm run test:integration
67
+ env:
68
+ # Testcontainers will pull and manage PostgreSQL container
69
+ TESTCONTAINERS_RYUK_DISABLED: false
70
+
71
+ build:
72
+ runs-on: ubuntu-latest
73
+ needs: [lint, unit-tests, integration-tests]
74
+ steps:
75
+ - name: Checkout
76
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
77
+
78
+ - name: Setup Node.js
79
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
80
+ with:
81
+ node-version-file: '.nvmrc'
82
+ cache: 'npm'
83
+
84
+ - name: Install dependencies
85
+ run: npm ci
86
+
87
+ - name: Build
88
+ run: npm run build
@@ -0,0 +1 @@
1
+ v24.12.0
@@ -0,0 +1,14 @@
1
+ {
2
+ "recommendations": [
3
+ "biomejs.biome",
4
+ "editorconfig.editorconfig",
5
+ "vitest.explorer",
6
+ "ms-vscode-remote.remote-containers",
7
+ "GitHub.codespaces",
8
+ "GitHub.Copilot",
9
+ "GitHub.Copilot-Chat",
10
+ "GitHub.github-vscode-theme",
11
+ "redhat.vscode-yaml",
12
+ "ms-azuretools.vscode-docker"
13
+ ]
14
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Start API Locally",
6
+ "type": "node",
7
+ "request": "launch",
8
+ "runtimeExecutable": "npm",
9
+ "runtimeArgs": ["run", "dev"],
10
+ "console": "integratedTerminal",
11
+ "cwd": "${workspaceFolder}",
12
+ "serverReadyAction": {
13
+ "pattern": "Server listening on port ([0-9]+)",
14
+ "uriFormat": "http://localhost:%s/health",
15
+ "action": "openExternally"
16
+ }
17
+ },
18
+ {
19
+ "name": "Debug Current Test File",
20
+ "type": "node",
21
+ "request": "launch",
22
+ "autoAttachChildProcesses": true,
23
+ "skipFiles": ["<node_internals>/**", "**/node_modules/**"],
24
+ "program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
25
+ "args": ["run", "${relativeFile}"],
26
+ "smartStep": true,
27
+ "console": "integratedTerminal"
28
+ }
29
+ ]
30
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "servers": {
3
+ "context7": {
4
+ "type": "stdio",
5
+ "command": "npx",
6
+ "args": ["-y", "@upstash/context7-mcp"]
7
+ },
8
+ "sequential-thinking": {
9
+ "type": "stdio",
10
+ "command": "npx",
11
+ "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
12
+ },
13
+ "lousy-agents": {
14
+ "type": "stdio",
15
+ "command": "npx",
16
+ "args": ["-y", "@lousy-agents/cli", "mcp"]
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,18 @@
1
+ extends: default
2
+
3
+ ignore: |
4
+ node_modules/
5
+ dist/
6
+
7
+ rules:
8
+ indentation:
9
+ spaces: 2
10
+ indent-sequences: true
11
+ line-length:
12
+ max: 120
13
+ level: warning
14
+
15
+ document-start: disable
16
+ truthy: disable
17
+ comments:
18
+ min-spaces-from-content: 1
@@ -0,0 +1,31 @@
1
+ {
2
+ "root": false,
3
+ "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
4
+ "vcs": {
5
+ "enabled": true,
6
+ "clientKind": "git",
7
+ "useIgnoreFile": true
8
+ },
9
+ "files": {
10
+ "ignoreUnknown": false
11
+ },
12
+ "formatter": {
13
+ "enabled": true,
14
+ "indentStyle": "space",
15
+ "indentWidth": 4
16
+ },
17
+ "linter": {
18
+ "enabled": true,
19
+ "rules": {
20
+ "recommended": true,
21
+ "style": {
22
+ "useConsistentCurlyBraces": "error"
23
+ }
24
+ }
25
+ },
26
+ "javascript": {
27
+ "formatter": {
28
+ "quoteStyle": "double"
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "<%= it.projectName %>",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "tsx watch src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "test": "vitest run",
11
+ "test:integration": "vitest run --config vitest.integration.config.ts",
12
+ "lint": "biome check .",
13
+ "lint:fix": "biome check --write .",
14
+ "lint:workflows": "actionlint",
15
+ "lint:yaml": "yamllint .",
16
+ "db:migrate": "tsx src/db/migrate.ts"
17
+ },
18
+ "dependencies": {
19
+ "@fastify/cors": "11.0.1",
20
+ "@fastify/sensible": "6.0.3",
21
+ "fastify": "5.4.0",
22
+ "kysely": "0.28.2",
23
+ "pino": "9.6.0",
24
+ "postgres": "3.4.7",
25
+ "zod": "3.25.56"
26
+ },
27
+ "devDependencies": {
28
+ "@biomejs/biome": "2.3.8",
29
+ "@testcontainers/postgresql": "10.25.0",
30
+ "@types/node": "22.16.4",
31
+ "chance": "1.1.12",
32
+ "testcontainers": "10.25.0",
33
+ "tsx": "4.20.3",
34
+ "typescript": "5.8.3",
35
+ "vitest": "4.0.15"
36
+ }
37
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022"],
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "outDir": "./dist",
12
+ "rootDir": "./src",
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "resolveJsonModule": true,
17
+ "noEmit": false,
18
+ "isolatedModules": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+ "exactOptionalPropertyTypes": true,
23
+ "noImplicitReturns": true,
24
+ "noUncheckedIndexedAccess": true
25
+ },
26
+ "include": ["src/**/*.ts"],
27
+ "exclude": [
28
+ "node_modules",
29
+ "dist",
30
+ "**/*.test.ts",
31
+ "**/*.spec.ts",
32
+ "**/*.integration.ts"
33
+ ]
34
+ }
@@ -0,0 +1,21 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: "node",
7
+ setupFiles: ["./vitest.setup.ts"],
8
+ include: ["src/**/*.test.ts"],
9
+ exclude: ["**/*.integration.ts"],
10
+ coverage: {
11
+ provider: "v8",
12
+ reporter: ["text", "json", "html"],
13
+ exclude: [
14
+ "node_modules/",
15
+ "dist/",
16
+ "**/*.test.ts",
17
+ "**/*.integration.ts",
18
+ ],
19
+ },
20
+ },
21
+ });
@@ -0,0 +1,18 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: "node",
7
+ setupFiles: ["./vitest.setup.ts"],
8
+ include: ["src/**/*.integration.ts"],
9
+ testTimeout: 60000,
10
+ hookTimeout: 60000,
11
+ pool: "forks",
12
+ poolOptions: {
13
+ forks: {
14
+ singleFork: true,
15
+ },
16
+ },
17
+ },
18
+ });
@@ -0,0 +1,5 @@
1
+ // Vitest setup file for REST API tests
2
+ // Add any global test setup here
3
+
4
+ // Extend timeout for integration tests with Testcontainers
5
+ // Individual test files can override with their own timeouts
@@ -1,4 +1,5 @@
1
- export declare const PROJECT_TYPE_OPTIONS: ("CLI" | "webapp" | "REST API" | "GraphQL API")[];
1
+ export declare const PROJECT_TYPE_OPTIONS: ("api" | "cli" | "webapp" | "graphql")[];
2
+ export declare const SUPPORTED_PROJECT_TYPES: readonly ["webapp", "api"];
2
3
  export declare const initCommand: import("citty").CommandDef<{
3
4
  kind: {
4
5
  type: "string";
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,oBAAoB,mDAA4B,CAAC;AAmE9D,eAAO,MAAM,WAAW;;;;;;;;;EAoFtB,CAAC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,oBAAoB,0CAA4B,CAAC;AAC9D,eAAO,MAAM,uBAAuB,4BAA6B,CAAC;AAoGlE,eAAO,MAAM,WAAW;;;;;;;;;EAyEtB,CAAC"}
@@ -4,8 +4,9 @@ import { z } from "zod";
4
4
  import { getProjectStructure } from "../lib/config.js";
5
5
  import { createFilesystemStructure, } from "../lib/filesystem-structure.js";
6
6
  import { getProjectNameError, isValidProjectName, } from "../lib/project-name-validation.js";
7
- const ProjectTypeSchema = z.enum(["CLI", "webapp", "REST API", "GraphQL API"]);
7
+ const ProjectTypeSchema = z.enum(["cli", "webapp", "api", "graphql"]);
8
8
  export const PROJECT_TYPE_OPTIONS = ProjectTypeSchema.options;
9
+ export const SUPPORTED_PROJECT_TYPES = ["webapp", "api"];
9
10
  const initArgs = {
10
11
  kind: {
11
12
  type: "string",
@@ -19,29 +20,28 @@ const initArgs = {
19
20
  function formatErrorMessage(error) {
20
21
  return error instanceof Error ? error.message : String(error);
21
22
  }
22
- async function createCliScaffolding(targetDir) {
23
- try {
24
- // Load the CLI structure from configuration
25
- const cliStructure = await getProjectStructure("CLI");
26
- if (!cliStructure) {
27
- consola.warn("No CLI project structure defined in configuration");
28
- return;
29
- }
30
- await createFilesystemStructure(cliStructure, targetDir);
23
+ async function getValidatedProjectName(promptFn, existingName, projectTypeLabel, placeholder) {
24
+ const rawProjectName = existingName
25
+ ? existingName
26
+ : await promptFn("What is your project name?", {
27
+ type: "text",
28
+ placeholder,
29
+ });
30
+ const projectName = typeof rawProjectName === "string" ? rawProjectName.trim() : "";
31
+ if (!projectName) {
32
+ consola.error(`Project name is required for ${projectTypeLabel} projects`);
33
+ throw new Error("Project name is required");
31
34
  }
32
- catch (error) {
33
- consola.error(`Failed to create CLI scaffolding: ${formatErrorMessage(error)}`);
34
- throw error;
35
+ if (!isValidProjectName(projectName)) {
36
+ const errorMessage = getProjectNameError(projectName) || "Invalid npm package name";
37
+ consola.error(`Invalid project name: "${projectName}". ${errorMessage}`);
38
+ throw new Error(`Invalid project name. ${errorMessage}`);
35
39
  }
40
+ return { projectName };
36
41
  }
37
42
  async function createWebappScaffolding(targetDir, templateContext) {
38
43
  try {
39
- // Load the webapp structure from configuration
40
44
  const webappStructure = await getProjectStructure("webapp");
41
- if (!webappStructure) {
42
- consola.warn("No webapp project structure defined in configuration");
43
- return;
44
- }
45
45
  await createFilesystemStructure(webappStructure, targetDir, templateContext);
46
46
  }
47
47
  catch (error) {
@@ -49,6 +49,16 @@ async function createWebappScaffolding(targetDir, templateContext) {
49
49
  throw error;
50
50
  }
51
51
  }
52
+ async function createRestApiScaffolding(targetDir, templateContext) {
53
+ try {
54
+ const restApiStructure = await getProjectStructure("api");
55
+ await createFilesystemStructure(restApiStructure, targetDir, templateContext);
56
+ }
57
+ catch (error) {
58
+ consola.error(`Failed to create REST API scaffolding: ${formatErrorMessage(error)}`);
59
+ throw error;
60
+ }
61
+ }
52
62
  export const initCommand = defineCommand({
53
63
  meta: {
54
64
  name: "init",
@@ -56,22 +66,18 @@ export const initCommand = defineCommand({
56
66
  },
57
67
  args: initArgs,
58
68
  run: async (context) => {
59
- // Support dependency injection for testing via context.data
60
- // Runtime checks for type safety
61
69
  const targetDir = typeof context.data?.targetDir === "string"
62
70
  ? context.data.targetDir
63
71
  : process.cwd();
64
72
  const promptFn = typeof context.data?.prompt === "function"
65
73
  ? context.data.prompt
66
74
  : consola.prompt.bind(consola);
67
- // Use CLI argument if provided, otherwise prompt
68
75
  const rawProjectType = context.args.kind
69
76
  ? context.args.kind
70
77
  : await promptFn("What type of project are you initializing?", {
71
78
  type: "select",
72
- options: PROJECT_TYPE_OPTIONS,
79
+ options: SUPPORTED_PROJECT_TYPES,
73
80
  });
74
- // Validate the user input at runtime
75
81
  const parseResult = ProjectTypeSchema.safeParse(rawProjectType);
76
82
  if (!parseResult.success) {
77
83
  const validOptions = PROJECT_TYPE_OPTIONS.join(", ");
@@ -80,35 +86,23 @@ export const initCommand = defineCommand({
80
86
  }
81
87
  const projectType = parseResult.data;
82
88
  consola.success(`Selected project type: ${projectType}`);
83
- if (projectType === "CLI") {
84
- await createCliScaffolding(targetDir);
85
- consola.info("CLI project scaffolding complete. Check the .github directory for instructions.");
89
+ if (projectType === "cli") {
90
+ throw new Error('Project type "cli" is not yet supported. Supported types: webapp, api');
86
91
  }
87
92
  else if (projectType === "webapp") {
88
- // Get project name from CLI argument or prompt
89
- const rawProjectName = context.args.name
90
- ? context.args.name
91
- : await promptFn("What is your project name?", {
92
- type: "text",
93
- placeholder: "my-webapp",
94
- });
95
- const projectName = typeof rawProjectName === "string" ? rawProjectName.trim() : "";
96
- if (!projectName) {
97
- consola.error("Project name is required for webapp projects");
98
- throw new Error("Project name is required");
99
- }
100
- if (!isValidProjectName(projectName)) {
101
- const errorMessage = getProjectNameError(projectName) ||
102
- "Invalid npm package name";
103
- consola.error(`Invalid project name: "${projectName}". ${errorMessage}`);
104
- throw new Error(`Invalid project name. ${errorMessage}`);
105
- }
93
+ const { projectName } = await getValidatedProjectName(promptFn, context.args.name, "webapp", "my-webapp");
106
94
  const templateContext = { projectName };
107
95
  await createWebappScaffolding(targetDir, templateContext);
108
96
  consola.info("Webapp project scaffolding complete. Run 'npm install' to install dependencies.");
109
97
  }
98
+ else if (projectType === "api") {
99
+ const { projectName } = await getValidatedProjectName(promptFn, context.args.name, "REST API", "my-rest-api");
100
+ const templateContext = { projectName };
101
+ await createRestApiScaffolding(targetDir, templateContext);
102
+ consola.info("REST API project scaffolding complete. Run 'npm install' to install dependencies.");
103
+ }
110
104
  else {
111
- consola.info(`Scaffolding for ${projectType} projects will be implemented in a future release.`);
105
+ throw new Error('Project type "graphql" is not yet supported. Supported types: webapp, api');
112
106
  }
113
107
  },
114
108
  });
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}