# @ddadaal/next-typed-api-routes

> Make Next.js API Routes strongly typed with routes and clients type completion and auto-generated parameter validation

Latest version **0.2.12** (published 2021-11-19) · MIT license · 0 weekly downloads

> **Deprecated.** This package is deprecated.

## Install

```sh
npm install @ddadaal/next-typed-api-routes
pnpm add @ddadaal/next-typed-api-routes
yarn add @ddadaal/next-typed-api-routes
bun add @ddadaal/next-typed-api-routes
```

Provides the command `ntar`.

## Health

**Score 10/100 (F)** — status: deprecated.

Negative: deprecated.

## Facts

| | |
|---|---|
| Version | 0.2.12 |
| Published | 2021-11-19 |
| First published | 2021-09-29 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 8 |
| Unpacked size | 89 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Chen Junda |
| Maintainers | ddadaal |
| Keywords | next, typescript |

## Links

- npm: https://www.npmjs.com/package/@ddadaal/next-typed-api-routes
- Repository: https://github.com/ddadaal/next-typed-api-routes
- Homepage: https://github.com/ddadaal/next-typed-api-routes#readme
- Issues: https://github.com/ddadaal/next-typed-api-routes/issues
- npm.io page: https://npm.io/package/@ddadaal/next-typed-api-routes

## Dependencies (8)

- [ajv](https://npm.io/package/ajv.md) ^8.8.1
- [tslib](https://npm.io/package/tslib.md) ^2.3.1
- [yargs](https://npm.io/package/yargs.md) ^17.2.1
- [typescript](https://npm.io/package/typescript.md) ~4.4.3
- [ajv-formats](https://npm.io/package/ajv-formats.md) ^2.1.1
- [fast-json-stringify](https://npm.io/package/fast-json-stringify.md) ^2.7.12
- [ajv-formats-draft2019](https://npm.io/package/ajv-formats-draft2019.md) ^1.6.1
- [ts-json-schema-generator](https://npm.io/package/ts-json-schema-generator.md) ^0.97.0

## Alternatives

- [@openai/codex-sdk](https://npm.io/package/@openai/codex-sdk.md) — 731.4K weekly downloads
- [babel-plugin-transform-react-jsx](https://npm.io/package/babel-plugin-transform-react-jsx.md) — 565.0K weekly downloads
- [babel-helper-remove-or-void](https://npm.io/package/babel-helper-remove-or-void.md) — 508.5K weekly downloads
- [@pnpm/store-controller-types](https://npm.io/package/@pnpm/store-controller-types.md) — 186.9K weekly downloads
- [react-native-signature-canvas](https://npm.io/package/react-native-signature-canvas.md) — 155.6K weekly downloads

## Recent versions

- 0.2.12 (latest) — 2021-11-19
- 0.2.11 — 2021-11-19
- 0.2.10 — 2021-11-11
- 0.2.9 — 2021-11-11
- 0.2.8 — 2021-11-11
- 0.2.7 — 2021-11-11
- 0.2.6 — 2021-11-11
- 0.2.5 — 2021-11-11
- 0.2.4 — 2021-11-09
- 0.2.3 — 2021-11-09
- 0.2.2 — 2021-11-09
- 0.2.1 — 2021-11-09
- 0.2.0 — 2021-11-06
- 0.1.10 — 2021-11-04
- 0.1.9 — 2021-11-04
- … 9 more at https://npm.io/package/@ddadaal/next-typed-api-routes/versions

## README

# next-typed-api-routes

![npm](https://img.shields.io/npm/v/@ddadaal/next-typed-api-routes)

Write a `Schema` interface in your API route file, and you get

- route parameters validation and type completion
- typed API clients
- faster JSON response serialization

all at one command!

# Requirement for the target Next.js Project

1. Use [TypeScript](https://nextjs.org/docs/basic-features/typescript)
2. Set `"baseUrl": "."` in `tsconfig.json` `compilerOptions` part

```json
{
  "compilerOptions": {
    "baseUrl": "."
  }
}
```
3. All codes should live in `src` dir [next.js src directory](https://nextjs.org/docs/advanced-features/src-directory)

# Get Started

1. Install the package in your Next.js TypeScript project

```bash
npm install --save @ddadaal/next-typed-api-routes
```

2. Create a API route `src/pages/api/test.ts` with the following content

```ts
import { route } from "@ddadaal/next-typed-api-routes";

interface Value {
  articleId: number;
}

export interface TestApiSchema {
  method: "POST";

  query: {
    a?: string | number;
  };

  body: {
    test: string;
  };

  responses: {
    200: { test: string; }
    403: { message: string; }
  }
}

export default route<TestApiSchema>("TestApiSchema", async (req) => {
  const { a } = req.query;
  const { test } = req.body;

  return { 200: { test: test + "" + a } };
});
```

3. Run `npx ntar schema && npx ntar client`

`schemas.json` will be generated at the module folder under `node_modules`. You should never edit it directly. The project cannot start without this file.

`src/apis/api.ts` will be generated at `src/apis`.

4. Import the `api` variable from `src/apis/api.ts` to use the client.

```ts
import { api } from "src/apis/api";

api.testApi({ query: {}, body: { test: "123" } })
  .httpError(403, ({ message }) => { console.log(403, message); })
  .then(({ test }) => { console.log(test); });
```

5. **Important** Add `ntar schema` to `postinstall` script in your `package.json`

so that `schemas.json` will be generated every time your project is `npm install`ed. 

```json
{
  "scripts": {
    "postinstall": "ntar schema"
  }
}
```

# Updating existing API Routes

To convert a normal API Routes to a type checked one, all you need to do is

1. Write a valid `Schema` interface
2. Wrap the handler function with `route` function, specify the name of Schema interface as the type argument and first argument

The Get Started part provides an example of a correctly formatted API route file. `ntar` will report errors if Incorrect route file is found.

Run `ntar schema` when the `Schema` interface is changed.

Run `ntar client` when the HTTP method or URL or the name of schema is changed.

# Schema Interface Specification

The shape of Schema interface is defined as follows:

```ts
// The name of the schema must be unique across the whole project
interface TestSchema {
  // Required. Must be a valid CAPITALIZED string literal type of HTTP method (GET, POST, PATCH)
  method: "POST";

  // Optional. Define the path param and query (to align with next.js)
  query: {
    // Supports most type constructs
    property?: string | number | AnotherInterface | Pick<{ number: string }, "number">;
    
    /**
     * You can also use jsdoc for more specific limits
     * You can use keywords and values from JSON Schema Draft-07
     * @format email
     * @maxLength 50
     */
    anotherProperty: string;
  }

  // Optional. Define the body
  body: {
    // Supports most type constructs
    property?: string | number | AnotherInterface | Pick<{ number: string }, "number">;
  } 

  // Required. Define the responses
  responses: {
    // Key as response code. 
    // Only one [200, 300) response should exist. It will be considered by clients as the success response
    // If the success response has no payload, the status code must be 204.
    200: {
      // Supports most type constructs
      property?: string | number | AnotherInterface | Pick<{ number: string }, "number">;
    };

    // If the code has no payload, set the type to null
    404: null;
  }
}
```

# Tips

- All schemas and used models must have globally unique name
- Return a `{ [statusCode]: payload }` object in a route to take advantages of response body type check and faster JSON serialization
- To ensure that client bundle doesn't include unnecessary packages (e.g. `ajv`, `fast-json-stringify`, which are only used in server side), 
    - import packages only from `@ddadaal/next-typed-api-routes/lib/client` in client files, 
    - import types with `import type` clause

# Thanks

- [`Ajv`](https://ajv.js.org/) for JSON Schema validation
- [`vega/ts-json-schema-generator`](https://github.com/vega/ts-json-schema-generator) for generating json schema from typescript
- [`fast-json-stringify`](https://github.com/fastify/fast-json-stringify) for faster JSON response serialization
- [`fastify`](https://github.com/fastify/fastify) for inspiration or unified validation and serialization using JSON schema

# Roadmap

- [ ] More configurations

# Development

```
npm install
npm install --no-save next
```

# License

MIT

---
_Source: https://npm.io/package/@ddadaal/next-typed-api-routes · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
