Skip to content

Commit

Permalink
Add type definition
Browse files Browse the repository at this point in the history
  • Loading branch information
ilikejames committed Mar 28, 2023
1 parent 86a5f76 commit 99dc6b0
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 3 deletions.
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,32 @@ jobs:
- name: Node.js 0.8
node-version: "0.8"
npm-i: mocha@2.5.3 supertest@1.1.0
npm-rm: nyc
npm-rm: nyc @types/node typescript

- name: Node.js 0.10
node-version: "0.10"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
npm-rm: typescript @types/node

- name: Node.js 0.12
node-version: "0.12"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
npm-rm: typescript @types/node

- name: io.js 1.x
node-version: "1.8"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
npm-rm: typescript @types/node

- name: io.js 2.x
node-version: "2.5"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
npm-rm: typescript @types/node

- name: io.js 3.x
node-version: "3.3"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
npm-rm: typescript @types/node

- name: Node.js 4.x
node-version: "4.9"
Expand Down Expand Up @@ -182,6 +187,10 @@ jobs:
npm test
fi
- name: Test type definition
if: steps.list_env.outputs.typescript != ''
run: npm run test-types

- name: Lint code
if: steps.list_env.outputs.eslint != ''
run: npm run lint
Expand Down
96 changes: 96 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import Methods from "methods";
import { OutgoingMessage } from "http";

export default Router;

type Method = typeof Methods[number];

type LowercaseMethods = Lowercase<Method>;

export interface RouterOptions {
strict?: boolean;
caseSensitive?: boolean;
mergeParams?: boolean;
}

export interface IncomingRequest {
url?: string;
method?: string;
originalUrl?: string;
params?: Record<string, unknown>;
}

export interface RoutedRequest extends IncomingRequest {
baseUrl: string;
next?: NextFunction;
route?: IRoute;
}

export interface NextFunction {
(err?: any): void;
}

type IRoute = Record<LowercaseMethods, IRouterHandler<IRoute>> & {
path: string;
stack: any;
all: IRouterHandler<IRoute>;
}

type RequestParamHandler = (
req: IncomingRequest,
res: OutgoingMessage,
next: NextFunction,
value: any,
name: string
) => any;

export interface RouteHandler {
(req: RoutedRequest, res: OutgoingMessage, next: NextFunction): any;
}

export interface RequestHandler {
(req: IncomingRequest, res: OutgoingMessage, next: NextFunction): any;
}

type ErrorRequestHandler = (
err: any,
req: IncomingRequest,
res: any,
next: NextFunction
) => any;

type PathParams = string | RegExp | Array<string | RegExp>;

type RequestHandlerParams =
| RouteHandler
| ErrorRequestHandler
| Array<RouteHandler | ErrorRequestHandler>;

interface IRouterMatcher<T> {
(path: PathParams, ...handlers: RouteHandler[]): T;
(path: PathParams, ...handlers: RequestHandlerParams[]): T;
}

interface IRouterHandler<T> {
(...handlers: RouteHandler[]): T;
(...handlers: RequestHandlerParams[]): T;
}

type IRouter = Record<LowercaseMethods, IRouterMatcher<IRouter>> & {
param(name: string, handler: RequestParamHandler): IRouter;
param(
callback: (name: string, matcher: RegExp) => RequestParamHandler
): IRouter;
all: IRouterMatcher<IRouter>;
use: IRouterHandler<IRouter> & IRouterMatcher<IRouter>;
handle: RequestHandler;
route(prefix: PathParams): IRoute;
stack: any[];
}

interface RouterConstructor {
new (options?: RouterOptions): IRouter & RequestHandler;
(options?: RouterOptions): IRouter & RequestHandler;
}

declare var Router: RouterConstructor;
10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"license": "MIT",
"repository": "pillarjs/router",
"dependencies": {
"@types/methods": "^1.1.1",
"array-flatten": "3.0.0",
"debug": "2.6.9",
"methods": "~1.1.2",
Expand All @@ -18,23 +19,27 @@
"utils-merge": "1.0.1"
},
"devDependencies": {
"@types/node": "^18.0.0",
"after": "0.8.2",
"eslint": "8.34.0",
"eslint-plugin-markdown": "3.0.0",
"finalhandler": "1.2.0",
"mocha": "10.2.0",
"nyc": "15.1.0",
"safe-buffer": "5.2.1",
"supertest": "6.3.3"
"supertest": "6.3.3",
"typescript": "^5.0.0"
},
"files": [
"lib/",
"LICENSE",
"HISTORY.md",
"README.md",
"SECURITY.md",
"index.js"
"index.js",
"index.d.ts"
],
"types": "index.d.ts",
"engines": {
"node": ">= 0.8"
},
Expand All @@ -43,6 +48,7 @@
"test": "mocha --reporter spec --bail --check-leaks test/",
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
"test-cov": "nyc --reporter=text npm test",
"test-types": "tsc --project tsconfig.json --noEmit",
"version": "node scripts/version-history.js && git add HISTORY.md"
}
}
81 changes: 81 additions & 0 deletions test/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { createServer, OutgoingMessage } from 'http';
import Router, {
RouterOptions,
RouteHandler,
NextFunction,
RoutedRequest
} from '..';

const options: RouterOptions = {
strict: false,
caseSensitive: false,
mergeParams: false
};

const r = new Router();
const r2 = Router()

const router = new Router(options);
const routerHandler: RouteHandler = (req, res, next) => {
res.setHeader('Content-Type', 'plain/text');
res.write('Hello')
res.end('world')
};

router.get('/', routerHandler);
router.post('/', routerHandler);
router.delete('/', routerHandler);
router.patch('/', routerHandler);
router.options('/', routerHandler);
router.head('/', routerHandler);
router.bind('/', routerHandler);
router.connect('/', routerHandler);
router.trace('/', routerHandler);
router['m-search']('/', routerHandler);


// param
router.param('user_id', (req, res, next, id) => {});

// middleware
router.use((req, res, next) => {
type TReq = Expect<Equal<typeof req, RoutedRequest>>
type TRes = Expect<Equal<typeof res, OutgoingMessage>>
type TNext = Expect<Equal<typeof next, NextFunction>>
next();
});

const api = router.route('/api/');

router.route('/')
.all((req, res, next) => {
type TReq = Expect<Equal<typeof req, RoutedRequest>>
type TRes = Expect<Equal<typeof res, OutgoingMessage>>
type TNext = Expect<Equal<typeof next, NextFunction>>
next();
})
.get((req, res, next) => {
type TReq = Expect<Equal<typeof req, RoutedRequest>>
type TRes = Expect<Equal<typeof res, OutgoingMessage>>
type TNext = Expect<Equal<typeof next, NextFunction>>
});


// test router handling

var server = createServer(function(req, res) {
router(req, res, (err) => {
//
})
router.handle(req, res, (err) => {
//
})
})


// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Compute<T> = T extends (...args: any[]) => any ? T : { [K in keyof T]: Compute<T[K]> }

export type Equal<X, Y> = (<T>() => T extends Compute<X> ? 1 : 2) extends <T>() => T extends Compute<Y> ? 1 : 2 ? true : false

export type Expect<T extends true> = T extends true ? true : never
22 changes: 22 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"esModuleInterop": true,
"noImplicitAny": false,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"types": ["node"],
"noEmit": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"test/**/*"
],
"files": [
"index.d.ts"
]
}

0 comments on commit 99dc6b0

Please sign in to comment.