npm package: @g1suite/api-cli
Description: CLI for scaffolding API Node servers and Cloudflare Worker apps, plus generating routes with paths and per-method handlers.
Latest version: 0.6.2

# @g1suite/api-cli

CLI for scaffolding API Node servers and Cloudflare Worker apps, plus generating routes with paths and per-method handlers.

## Quickstart

- Create an API project:

```bash
nx run api-cli:build
node dist/cli.js create --name my-api --template api --dir apps/my-api
```

- Create a Cloudflare Worker project:

```bash
node dist/cli.js create --name my-worker --template cloudflare-worker --dir apps/my-worker
```

## Generate Routes

- API route with dynamic params and methods:

```bash
node dist/cli.js generate route --name user --path "/users/:id" --methods "GET,DELETE" --dir apps/my-api
# Produces: apps/my-api/src/routes/v1/users/[id].ts (version auto-detected)
# Exports named methods: GET, DELETE
```

- Override target API version and use dry-run:

```bash
# Explicitly write under v2
node dist/cli.js generate route --name hello --dir apps/my-api --api-version v2
# Preview planned files without writing
node dist/cli.js generate route --name hello --dir apps/my-api --dry-run
```

- Scaffold a new API version module:

```bash
node dist/cli.js generate version --api-version v2 --dir apps/my-api
# Produces: apps/my-api/src/routes/v2/index.ts
```

- Create an aggregated routes index and optionally patch `app.ts`:

```bash
node dist/cli.js generate aggregated --dir apps/my-api --patch-app
# Writes: apps/my-api/src/routes/index.ts that imports all detected versions
# If --patch-app is set, adds import and calls registerAllVersions(app) in src/app.ts
```

- Worker route with dynamic params and method map:

```bash
node dist/cli.js generate route --name user --path "/users/:id" --methods "GET,DELETE" --dir apps/my-worker
# Registers in src/routes/index.ts as a method map for "/users/:id"
```

## Path Conventions

- API routes are versioned under `src/routes/<version>/...` (e.g., `src/routes/v1`).
- Detection order for target version:
  - `.g1api.json` `defaultApiVersion` (if present)
  - `src/app.ts` import/mount patterns (e.g., `from './routes/<ver>/index'` or `app.route('/<ver>', vApp)`)
  - Filesystem: existing `src/routes/<ver>/index.ts`
  - Fallback: `v1`
- You can override detection using `--api-version <ver>` on `generate route`.
- Aggregated index lives at `src/routes/index.ts` and mounts each version under its prefix.
- API filenames use bracket params: `src/routes/v1/users/[id].ts` maps to `/users/:id` at runtime.
- Worker paths accept either `/users/:id` or `/users/[id]` in the registry; both are supported by the template router.

## Method Handling

- API: Named exports (e.g., `export async function GET`) are registered per method by the framework loader. If only a default export exists, it is treated as GET.
- Worker: A single function is treated as GET-only. Method maps dispatch strictly per-method and return 405 for unsupported methods.

## Start Commands

- API dev server:

```bash
node dist/cli.js start --dir apps/my-api
# Runs: bunx tsx scripts/prepare-docs-assets.ts && bunx tsx watch src/server.ts
```

- Worker dev server:

```bash
node dist/cli.js start --dir apps/my-worker
# Prints: wrangler dev
```
## Nx Start Target

- Run via Nx (dry-run to preview):

```bash
nx run api-cli:start -- --dry-run --dir templates/project/api
# Outputs: Start command: bunx tsx watch src/server.ts
```

- Start an API project:

```bash
nx run api-cli:start -- --dir apps/my-api
```

- Start a Worker project:

```bash
nx run api-cli:start -- --dir apps/my-worker
```

- Notes:
- `--dir` is resolved relative to `packages/api-cli` when run via Nx.
- Use paths like `templates/project/api` or absolute paths for fixtures.
- The CLI auto-detects template type by presence of `src/server.ts` (API) or `wrangler.toml` (Worker).

### Dev Alias and Workspace Root

- Use the dev alias:

```bash
nx run api-cli:dev -- --dry-run --dir templates/project/cloudflare-worker
```

- Resolve `--dir` from workspace root:

```bash
nx run api-cli:start -- --dry-run --root --dir packages/api-cli/templates/project/api
nx run api-cli:dev   -- --dry-run --root --dir packages/api-cli/templates/project/cloudflare-worker
```

## Install & Usage

- Use the latest published CLI without local build:

```bash
npx @g1suite/api-cli@latest create --name my-api --template api --dir apps/my-api
npx @g1suite/api-cli@latest update --dir apps/my-api
npx @g1suite/api-cli@latest doctor --dir apps/my-api
npx @g1suite/api-cli@latest migrate --dir apps/my-api --dry-run
```

- Or via `bunx` if installed:

```bash
bunx @g1suite/api-cli create --name my-worker --template cloudflare-worker --dir apps/my-worker
```

Notes:
- `--root` resolves `--dir` relative to the Nx workspace root.
- Without `--root`, `--dir` resolves relative to the current working directory.

## Template Metadata

- Projects created with `create` include a `g1-template.json` file at the project root:

```json
{
  "template": "api",
  "templateVersion": "2.0.0",
  "files": {
    "src/server.ts": "<sha256>",
    "src/routes/index.ts": "<sha256>"
  }
}
```

- This metadata helps the CLI detect divergence and plan upgrades.

## Update & Doctor

- Analyze project divergence and dependency versions without changing files:

```bash
node dist/cli.js update --dir apps/my-api
# or
npx @g1suite/api-cli@latest update --dir apps/my-api
```

- Print a quick health report (CLI version, template version, file status):

```bash
node dist/cli.js doctor --dir apps/my-api
# or
npx @g1suite/api-cli@latest doctor --dir apps/my-api
```

## Migrate (Stub)

- Show a conceptual migration plan between template versions (no changes applied):

```bash
node dist/cli.js migrate --dir apps/my-api --dry-run
# or
npx @g1suite/api-cli@latest migrate --dir apps/my-api --dry-run
```

- Planned steps include:
- Update runtime dependencies (`bun update` / `npm update`).
- Apply codemods for template changes (coming soon).
- Re-run `doctor` to verify project health.

## Version Migration

- Scaffold and mount a new API version alongside the current one:

```bash
node dist/cli.js migrate-version --to v2 --dir apps/my-api
# Creates: src/routes/v2/index.ts, mounts at /v2 in src/app.ts, updates .g1api.json
```

Notes:
- Valid versions: `v<number>` (e.g., `v2`) or `vYYYY-MM` (e.g., `v2025-11`).
- `.g1api.json` is updated with `defaultApiVersion` and `multipleVersions: true` when migrating.

## API Configuration

- Projects include `.g1api.json` to track API versioning defaults:

```json
{
  "defaultApiVersion": "v1",
  "multipleVersions": false
}
```

- Route generation respects `defaultApiVersion` unless overridden by `--api-version`.

## Migrate Apply

- Align dependency ranges to match the template recommendations and bump template metadata:

```bash
npx @g1suite/api-cli@latest migrate --dir apps/my-api --apply
```

- What happens:
- Compares `dependencies` and `devDependencies` with the chosen template.
- Updates out-of-sync ranges and adds missing recommended deps.
- If `g1-template.json` exists, updates `templateVersion` to the CLI’s version.

## Doctor Enhancements

- Doctor reports more detail about project health:
- Prints CLI version, detected template, and metadata status.
- Lists unchanged/changed/missing files against `g1-template.json`.
- Reports dependency alignment: out-of-sync and missing template recommendations.

## Plugin System

- The CLI supports lightweight plugins to extend behavior for `doctor` and `migrate`.
- Plugins are discovered via either:
- `api-cli.config.json` at project root with `{ "plugins": ["<name>", "<name>"] }`.
- `package.json` fields `g1ApiCli.plugins` or names starting with `@g1suite/api-cli-plugin-`.

- Plugin interface (TypeScript):

```ts
export type ApiCliPluginContext = {
  root: string;
  template: string | null;
  cliVersion: string;
  metadata: any;
  log: (msg: string) => void;
};

export type ApiCliPlugin = {
  name?: string;
  doctor?: (ctx: ApiCliPluginContext) => Promise<void> | void;
  migratePlan?: (ctx: ApiCliPluginContext) => Promise<void> | void;
  migrateApply?: (ctx: ApiCliPluginContext) => Promise<void> | void;
};
```

- Example plugin module:

```js
// my-plugins/api-health-check.js
export default {
  name: "api-health-check",
  async doctor(ctx) {
    ctx.log("Plugin: running extra health checks...");
    // custom checks here
  },
  async migratePlan(ctx) {
    ctx.log("Plugin: suggesting additional steps for migration plan...");
  },
  async migrateApply(ctx) {
    ctx.log("Plugin: applying additional adjustments...");
  }
};
```

- Configure discovery via `api-cli.config.json`:

```json
{
  "plugins": [
    "./my-plugins/api-health-check.js",
    "@g1suite/api-cli-plugin-example"
  ]
}
```

- Behavior notes:
- Plugin import failures are isolated and do not break the CLI.
- Each hook runs at the end of the related command, after core diagnostics.
- Use `ctx.log` for consistent output.