Skip to content

Commit 47d114f

Browse files
author
Harrison Ifeanyichukwu
committed
feat(components): simplified api, fixed http2 api, changed routing api parameters
this PR fixes error starting up http2 server, it simplifies routing method parameters BREAKING CHANGE: routhing method parameters changed, middleware and route callbacks now receive fourth and third arguments respectively, that contains a pathParams object containing the routes matched parameters
1 parent cdf4f91 commit 47d114f

23 files changed

+961
-1663
lines changed

.husky/commit-msg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
. "$(dirname "$0")/_/husky.sh"
3+
yarn commitlint --edit $1

.husky/pre-commit

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/sh
2+
. "$(dirname "$0")/_/husky.sh"
3+
4+
# run test:precommit when ready
5+
# npx lint-staged && yarn test:precommit
6+
7+
# npx lint-staged

.husky/prepare-commit-msg

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
. "$(dirname "$0")/_/husky.sh"
3+
4+
exec < /dev/tty && npx cz --hook || true

.server.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const { createConfig } = require('./build/cjs');
22
module.exports = createConfig({
33
https: {
44
enabled: false,
5-
enforce: true,
5+
enforce: false,
66
credentials: {
77
key: '.cert/server.key',
88
cert: '.cert/server.crt',

commitlint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = { extends: ['@commitlint/config-conventional'] }

package.json

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"build"
1717
],
1818
"scripts": {
19-
"commit": "git-cz",
19+
"prepare": "husky install",
2020
"pretest": "bash ./scripts/gen-ssl-cert.sh",
2121
"test": "cross-env BABEL_ENV=test jest --runInBand",
2222
"build": "yarn rollup-all",
@@ -50,19 +50,20 @@
5050
},
5151
"homepage": "https://github.com/teclone/r-server#readme",
5252
"devDependencies": {
53+
"@commitlint/cli": "^16.2.3",
54+
"@commitlint/config-conventional": "^16.2.1",
5355
"@semantic-release/github": "^8.0.7",
54-
"@teclone/rollup-all": "^1.26.0",
56+
"@teclone/rollup-all": "^1.29.1",
5557
"@types/jest": "24.0.11",
5658
"@types/request-promise": "^4.1.47",
5759
"@typescript-eslint/eslint-plugin": "^5.59.1",
5860
"@typescript-eslint/parser": "^5.59.1",
5961
"babel-jest": "^29.5.0",
60-
"commitizen": "4.0.3",
6162
"coveralls": "3.0.3",
6263
"cross-env": "^7.0.3",
63-
"cz-conventional-changelog": "2.1.0",
6464
"eslint": "^8.39.0",
6565
"eslint-config-prettier": "^8.8.0",
66+
"husky": "^8.0.3",
6667
"jest": "^29.5.0",
6768
"js-beautify": "1.7.5",
6869
"prettier": "^2.8.8",
@@ -72,11 +73,13 @@
7273
"semantic-release": "^17.4.2",
7374
"semantic-release-cli": "5.2.0",
7475
"source-map-support": "0.5.12",
75-
"typescript": "^4.2.3"
76+
"typescript": "^4.2.3",
77+
"commitizen": "^4.2.4",
78+
"cz-conventional-changelog": "3.3.0"
7679
},
7780
"config": {
7881
"commitizen": {
79-
"path": "cz-conventional-changelog"
82+
"path": "./node_modules/cz-conventional-changelog"
8083
}
8184
},
8285
"dependencies": {

src/@types/index.d.ts renamed to src/@types/index.ts

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { IncomingHttpHeaders } from 'http';
12
import { ServerRequest } from '../modules/Request';
23
import { ServerResponse } from '../modules/Response';
34

@@ -89,7 +90,7 @@ export type Method =
8990
| 'delete'
9091
| '*';
9192

92-
export type Url = string;
93+
export type Path = string;
9394

9495
export type RouteId = number;
9596

@@ -99,7 +100,7 @@ export type Parameter = string | number | boolean;
99100

100101
export interface Next {
101102
(): true;
102-
reset: () => boolean;
103+
reset: () => void;
103104
status: () => boolean;
104105
}
105106

@@ -109,8 +110,7 @@ export type Callback<
109110
> = (
110111
request: Rq,
111112
response: Rs,
112-
params: ObjectOfAny,
113-
options?: ObjectOfAny
113+
options: { pathParams: PathParameters } & Record<string, any>
114114
) => Promise<boolean>;
115115

116116
export type ErrorCallback<
@@ -130,44 +130,18 @@ export type Middleware<
130130
request: Rq,
131131
response: Rs,
132132
next: Next,
133-
params: ObjectOfAny,
134-
options?: ObjectOfAny
133+
options: { pathParams: PathParameters } & Record<string, any>
135134
) => Promise<boolean> | boolean;
136135

137136
export type ListenerCallback = () => void;
138137

139-
export interface CallbackOptions {
140-
use: Middleware | Middleware[];
141-
options?: ObjectOfAny;
142-
}
143-
144-
export interface MiddlewareOptions {
145-
method: Method | Method[];
146-
options?: ObjectOfAny;
147-
}
148-
149-
export interface ResolvedCallbackOptions {
150-
use: Middleware[];
151-
options?: ObjectOfAny;
152-
}
153-
154-
export interface ResolvedMiddlewareOptions {
155-
method: Method[];
156-
options?: ObjectOfAny;
157-
}
158-
159-
export type RouteInstance = [
160-
RouteId,
161-
Url,
162-
Callback,
163-
null | ResolvedCallbackOptions
164-
];
138+
export type RouteInstance = [RouteId, Path, Callback, Middleware[]];
165139

166140
export type MiddlewareInstance = [
167141
MiddlewareId,
168-
Url,
142+
Path,
169143
Middleware[],
170-
null | ResolvedMiddlewareOptions
144+
Set<Method>
171145
];
172146

173147
export interface FileEntry {
@@ -232,6 +206,11 @@ export interface Data {
232206
[propName: string]: string | string[];
233207
}
234208

209+
export type PathParameters<T extends string = string> = Record<
210+
T,
211+
string | number | boolean
212+
>;
213+
235214
export interface Headers {
236215
[propName: string]: string;
237216
}
@@ -256,11 +235,37 @@ export interface RouteParameter {
256235
value: string | number | boolean;
257236
}
258237

259-
export interface Routes {
260-
options: RouteInstance[];
261-
head: RouteInstance[];
262-
get: RouteInstance[];
263-
post: RouteInstance[];
264-
put: RouteInstance[];
265-
delete: RouteInstance[];
238+
export type Routes = Record<Exclude<Method, '*'>, RouteInstance[]>;
239+
240+
export interface RouteResponse<ResponseData = {}> {
241+
status?: 'success' | 'error';
242+
statusCode?: number;
243+
message?: string;
244+
data?: ResponseData;
245+
headers?: IncomingHttpHeaders;
246+
ttl?: number;
247+
}
248+
249+
export interface APIExecutor<RequestBody, ResponseData> {
250+
(arg: {
251+
/**
252+
* request body, should be a combination of parsed post body and url search params
253+
*/
254+
body: RequestBody;
255+
256+
/**
257+
* request http headers
258+
*/
259+
headers: IncomingHttpHeaders;
260+
261+
/**
262+
* request path parameters, as contained in the routing path
263+
*/
264+
pathParams: PathParameters;
265+
}): Promise<RouteResponse<ResponseData> | null>;
266+
267+
/**
268+
* assigned name of the handler
269+
*/
270+
apiName?: string;
266271
}

src/index.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ export { Server } from './modules/Server';
44
export { Router } from './modules/Router';
55

66
export { Http1Request, Http2Request } from './modules/Request';
7-
export {
8-
Http1Response,
9-
Http2Response,
10-
RouteResponse,
11-
APIExecutor,
12-
} from './modules/Response';
7+
export { Http1Response, Http2Response } from './modules/Response';
8+
9+
export * from './@types';
1310

1411
export const createConfig = (config: RServerConfig) => config;

src/modules/BodyParser.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,16 @@ export class BodyParser {
236236
}
237237

238238
/**
239-
* parse the query parameters in the given url
239+
* converts url search parameters to object
240+
* @param searchParams
241+
* @returns
240242
*/
241-
parseQueryString(url: string): Data {
242-
if (url.indexOf('?') > -1) {
243-
return this.parseUrlEncoded(url.split('?')[1]);
244-
} else {
245-
return {};
243+
urlSearchParamsToObject(searchParams: URLSearchParams) {
244+
const result: Data = {};
245+
for (const key of searchParams.keys()) {
246+
result[key] = searchParams.get(key);
246247
}
248+
return result;
247249
}
248250

249251
/**

src/modules/Constants.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
import { Routes } from '../@types';
1+
import { Method, Routes } from '../@types';
22

3+
// this matches a route token path in the form of {dataType:pathParameterName} or {pathParameterName}
34
const singleToken = '\\{((?:[a-z]+:)?[a-z]+)\\}';
45

6+
// single token regex
57
export const SINGLE_TOKEN_REGEX = new RegExp(singleToken, 'i');
8+
9+
// double token regex, helps capture routh tokens that targets two pairs of from and to values
10+
// eg {dataType:fromPathParameterName}-{dataType:toPathParameterName}
11+
// or {dataType:fromPathParameterName}.{dataType:toPathParameterName}
612
export const DOUBLE_TOKEN_REGEX = new RegExp(
713
singleToken + '([-.])' + singleToken,
814
'i'
@@ -26,7 +32,7 @@ export const assignRouteId = () => ++routeId;
2632

2733
export const assignMiddlewareId = () => ++middlewareId;
2834

29-
export const ROUTE_KEYS: Array<keyof Routes> = [
35+
export const ALL_METHODS: Method[] = [
3036
'options',
3137
'head',
3238
'get',

0 commit comments

Comments
 (0)