diff --git a/apps/example/app/new/api/simple/route.ts b/apps/example/app/new/api/simple/route.ts new file mode 100644 index 0000000..c77c2c9 --- /dev/null +++ b/apps/example/app/new/api/simple/route.ts @@ -0,0 +1,15 @@ +import { BadRequestException, handler } from 'next-api-handler/beta'; + +import { getDataById } from '@/server/service'; + +export const GET = handler(async (req) => { + const searchParams = new URL(req.url).searchParams; + const id = searchParams.get('id'); + + if (typeof id !== 'string') + // can throw status code related errors + throw new BadRequestException('Id is required'); + + // automatically handle errors + return getDataById(id); +}); diff --git a/apps/example/next-env.d.ts b/apps/example/next-env.d.ts index 4f11a03..fd36f94 100644 --- a/apps/example/next-env.d.ts +++ b/apps/example/next-env.d.ts @@ -1,5 +1,6 @@ /// /// +/// // NOTE: This file should not be edited // see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/apps/example/tsconfig.json b/apps/example/tsconfig.json index 5b46601..28ca683 100644 --- a/apps/example/tsconfig.json +++ b/apps/example/tsconfig.json @@ -1,6 +1,6 @@ { "extends": "tsconfig/nextjs.json", - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "compilerOptions": { "rootDir": ".", "baseUrl": ".", @@ -9,7 +9,13 @@ // Fixes TypesCript infeered type error for pnpm morenorpos // Refernce: https://github.com/microsoft/TypeScript/issues/42873 "next": ["node_modules/next"] - } + }, + "plugins": [ + { + "name": "next" + } + ], + "strictNullChecks": true }, "exclude": ["node_modules"] } diff --git a/packages/next-api-handler/package.json b/packages/next-api-handler/package.json index 0587af6..6c9b740 100644 --- a/packages/next-api-handler/package.json +++ b/packages/next-api-handler/package.json @@ -12,12 +12,26 @@ "serverless" ], "main": "dist/index.js", - "typings": "dist/index.d.ts", + "types": "dist/index.d.ts", "module": "dist/index.js", + "typesVersions": { + "*": { + ".": [ + "dist/index.d.ts" + ], + "beta": [ + "dist/beta/index.d.ts" + ] + } + }, "exports": { ".": { "import": "./dist/index.js", "require": "./dist/index.cjs" + }, + "./beta": { + "import": "./dist/beta/index.js", + "require": "./dist/beta/index.cjs" } }, "type": "module", @@ -44,6 +58,7 @@ "license": "MIT", "scripts": { "clean": "rm -rf .turbo node_modules build dist coverage", + "dev": "pnpm watch:build", "build": "tsup", "fix": "run-s fix:*", "fix:prettier": "prettier \"src/**/*.ts\" --write --list-different", @@ -92,9 +107,9 @@ "typescript": "^5.2.2" }, "peerDependencies": { - "next": ">= 9.0.0" + "next": ">=13.0.0" }, "engines": { - "node": ">=8.10" + "node": ">=18" } } diff --git a/packages/next-api-handler/src/lib/beta/handler.ts b/packages/next-api-handler/src/lib/beta/handler.ts new file mode 100644 index 0000000..f8abd0c --- /dev/null +++ b/packages/next-api-handler/src/lib/beta/handler.ts @@ -0,0 +1,38 @@ +import { NextRequest } from 'next/server'; + +import { HttpException } from '../http-exceptions'; + +export type MaybePromise = T | Promise; + +export type HandlerParams = (req: NextRequest) => MaybePromise; + +export const handler = + (params: HandlerParams) => + async (req: NextRequest): Promise => { + try { + const data = await params(req); + return Response.json({ success: true, data }, { status: 200 }); + } catch (error) { + if (error instanceof HttpException) { + return Response.json( + { + success: false, + message: + process.env.NODE_ENV === 'production' + ? error.defaultMessage + : error.message, + }, + { status: error.status } + ); + } + + console.error('Unexpected Error', error); + return Response.json( + { + success: false, + message: 'Internal Server Error', + }, + { status: 500 } + ); + } + }; diff --git a/packages/next-api-handler/src/lib/beta/index.ts b/packages/next-api-handler/src/lib/beta/index.ts new file mode 100644 index 0000000..d2eea6c --- /dev/null +++ b/packages/next-api-handler/src/lib/beta/index.ts @@ -0,0 +1,3 @@ +export * from './handler'; +export * from '../http-exceptions'; +export * from '../type'; diff --git a/packages/next-api-handler/tsconfig.json b/packages/next-api-handler/tsconfig.json index 0b66529..1c46e75 100644 --- a/packages/next-api-handler/tsconfig.json +++ b/packages/next-api-handler/tsconfig.json @@ -1,14 +1,14 @@ { "extends": "tsconfig/base.json", "compilerOptions": { - "target": "es2017", + "target": "ES2017", "noUnusedLocals": true /* Report errors on unused locals. */, "noUnusedParameters": true /* Report errors on unused parameters. */, "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, - "lib": ["es2017"] + "lib": ["ES2017", "DOM"] }, "include": ["src/**/*.ts"], - "exclude": ["dist", "build", "node_modules"], + "exclude": ["dist", "build"], "compileOnSave": false } diff --git a/packages/next-api-handler/tsup.config.ts b/packages/next-api-handler/tsup.config.ts index ee56bad..00038f4 100644 --- a/packages/next-api-handler/tsup.config.ts +++ b/packages/next-api-handler/tsup.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'tsup'; export default defineConfig((options) => ({ - entry: ['src/lib/*.ts'], + entry: ['src/lib/*.ts', 'src/lib/beta/index.ts'], format: ['cjs', 'esm'], splitting: true, treeshake: true,