Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type definition #109

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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: @types/node typescript

- 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: @types/node typescript

- 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: @types/node typescript

- 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: @types/node typescript

- 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: @types/node typescript

- 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"
]
}