@autofleet/node-common 4.0.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -5
- package/.nvmrc +0 -1
- package/src/consts/index.test.ts +0 -26
- package/src/consts/index.ts +0 -5
- package/src/index.test.ts +0 -18
- package/src/index.ts +0 -6
- package/src/router/index.test.ts +0 -149
- package/src/router/index.ts +0 -45
- package/tsconfig.json +0 -15
- package/tsup.config.ts +0 -13
- package/vitest.config.ts +0 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/node-common",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -8,14 +8,17 @@
|
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
"import": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"require": {
|
|
15
|
-
"
|
|
16
|
-
"
|
|
15
|
+
"types": "./dist/index.d.cts",
|
|
16
|
+
"default": "./dist/index.cjs"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
19
22
|
"scripts": {
|
|
20
23
|
"coverage": "vitest --coverage",
|
|
21
24
|
"test": "vitest",
|
package/.nvmrc
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
22.9.0
|
package/src/consts/index.test.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { consts } from '.';
|
|
3
|
-
|
|
4
|
-
describe('consts', () => {
|
|
5
|
-
it('should be an object', () => {
|
|
6
|
-
expect(typeof consts).toBe('object');
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
it('should have ok', () => {
|
|
10
|
-
expect('ok' in consts).toBeTruthy();
|
|
11
|
-
expect(typeof consts.ok).toBe('string');
|
|
12
|
-
expect(consts.ok).toBe('OK');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('should have error', () => {
|
|
16
|
-
expect('error' in consts).toBeTruthy();
|
|
17
|
-
expect(typeof consts.error).toBe('string');
|
|
18
|
-
expect(consts.error).toBe('ERROR');
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('should have fail', () => {
|
|
22
|
-
expect('fail' in consts).toBeTruthy();
|
|
23
|
-
expect(typeof consts.fail).toBe('string');
|
|
24
|
-
expect(consts.fail).toBe('FAIL');
|
|
25
|
-
});
|
|
26
|
-
});
|
package/src/consts/index.ts
DELETED
package/src/index.test.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import * as nodeCommon from '.';
|
|
3
|
-
import { consts } from './consts';
|
|
4
|
-
import { AfRouter } from './router';
|
|
5
|
-
|
|
6
|
-
describe('node-common', () => {
|
|
7
|
-
it('exports consts', () => {
|
|
8
|
-
expect(nodeCommon.consts).toBe(consts);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('exports AfRouter', () => {
|
|
12
|
-
expect(nodeCommon.AfRouter).toBe(AfRouter);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('exports AFRouter aliased as Router', () => {
|
|
16
|
-
expect(nodeCommon.Router).toBe(AfRouter);
|
|
17
|
-
});
|
|
18
|
-
});
|
package/src/index.ts
DELETED
package/src/router/index.test.ts
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import Logger from '@autofleet/logger';
|
|
2
|
-
import type { Request, Response, NextFunction } from 'express';
|
|
3
|
-
import {
|
|
4
|
-
describe, expect, it, vi,
|
|
5
|
-
} from 'vitest';
|
|
6
|
-
import { AfRouter, METHODS } from '.';
|
|
7
|
-
|
|
8
|
-
const logger = Logger();
|
|
9
|
-
const noop = () => null;
|
|
10
|
-
|
|
11
|
-
describe('Router', () => {
|
|
12
|
-
it('is a function', () => {
|
|
13
|
-
expect(typeof AfRouter).toBe('function');
|
|
14
|
-
expect(AfRouter.length).toBe(1);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('returns a Router instance', () => {
|
|
18
|
-
const router = AfRouter({ logger });
|
|
19
|
-
expect(typeof router).toBe('function');
|
|
20
|
-
expect(typeof router.use).toBe('function');
|
|
21
|
-
expect(typeof router.get).toBe('function');
|
|
22
|
-
expect(typeof router.post).toBe('function');
|
|
23
|
-
expect(typeof router.put).toBe('function');
|
|
24
|
-
expect(typeof router.delete).toBe('function');
|
|
25
|
-
expect(typeof router.patch).toBe('function');
|
|
26
|
-
expect(typeof router.options).toBe('function');
|
|
27
|
-
expect(typeof router.head).toBe('function');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe.each(METHODS)('Route method %s', { timeout: 1000 }, (method) => {
|
|
31
|
-
it('handles sync routes', async () => {
|
|
32
|
-
const router = AfRouter({ logger });
|
|
33
|
-
router[method]('/test', (_req, res) => {
|
|
34
|
-
res.send('ok');
|
|
35
|
-
});
|
|
36
|
-
const { promise, resolve } = Promise.withResolvers<string>();
|
|
37
|
-
const req = { method, url: '/test', baseUrl: '' };
|
|
38
|
-
const res = { send: (data: string) => resolve(data) };
|
|
39
|
-
// @ts-expect-error handle is not typed for an unclear reason.
|
|
40
|
-
router.handle(req, res, noop);
|
|
41
|
-
expect(await promise).toBe('ok');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('handles async routes', async () => {
|
|
45
|
-
const router = AfRouter({ logger });
|
|
46
|
-
router[method]('/test', async (req, res) => {
|
|
47
|
-
res.send('ok');
|
|
48
|
-
});
|
|
49
|
-
const { promise, resolve } = Promise.withResolvers<string>();
|
|
50
|
-
const req = { method, url: '/test', baseUrl: '' };
|
|
51
|
-
const res = { send: (data: string) => resolve(data) };
|
|
52
|
-
// @ts-expect-error handle is not typed for an unclear reason.
|
|
53
|
-
router.handle(req, res, noop);
|
|
54
|
-
expect(await promise).toBe('ok');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('handles arrays of handlers', async () => {
|
|
58
|
-
const router = AfRouter({ logger });
|
|
59
|
-
router[method]('/test', [
|
|
60
|
-
(_req: Request, _res: Response, next: NextFunction) => next(),
|
|
61
|
-
(_req: Request, res: Response) => res.send('ok'),
|
|
62
|
-
]);
|
|
63
|
-
const { promise, resolve } = Promise.withResolvers<string>();
|
|
64
|
-
const req = { method, url: '/test', baseUrl: '' };
|
|
65
|
-
const res = { send: (data: string) => resolve(data) };
|
|
66
|
-
// @ts-expect-error handle is not typed for an unclear reason.
|
|
67
|
-
router.handle(req, res, noop);
|
|
68
|
-
expect(await promise).toBe('ok');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('handles errors', async () => {
|
|
72
|
-
const router = AfRouter({ logger });
|
|
73
|
-
const error = new Error('test error');
|
|
74
|
-
router[method]('/test', () => {
|
|
75
|
-
throw error;
|
|
76
|
-
});
|
|
77
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
78
|
-
const next = vi.fn(resolve);
|
|
79
|
-
const req = { method, url: '/test', baseUrl: '' };
|
|
80
|
-
const res = {};
|
|
81
|
-
// @ts-expect-error handle is not typed for an unclear reason.
|
|
82
|
-
router.handle(req, res, next);
|
|
83
|
-
await promise;
|
|
84
|
-
expect(next).toHaveBeenCalledExactlyOnceWith(error);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('handles rejections', async () => {
|
|
88
|
-
const router = AfRouter({ logger });
|
|
89
|
-
const error = new Error('test error');
|
|
90
|
-
router[method]('/test', () => Promise.reject(error));
|
|
91
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
92
|
-
const next = vi.fn(resolve);
|
|
93
|
-
const req = { method, url: '/test', baseUrl: '' };
|
|
94
|
-
const res = {};
|
|
95
|
-
// @ts-expect-error handle is not typed for an unclear reason.
|
|
96
|
-
router.handle(req, res, next);
|
|
97
|
-
await promise;
|
|
98
|
-
// expect(await promise).toBe({ error: 'test error', status: "ERROR" });
|
|
99
|
-
expect(next).toHaveBeenCalledExactlyOnceWith(error);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('forces errors with status code 400 if not 500', async () => {
|
|
103
|
-
const router = AfRouter({ logger });
|
|
104
|
-
const error = Object.assign(new Error('test error'), { statusCode: 418 });
|
|
105
|
-
router[method]('/test', () => Promise.reject(error));
|
|
106
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
107
|
-
const status = vi.fn(() => ({ json: resolve }));
|
|
108
|
-
const req = { method, url: '/test', baseUrl: '' };
|
|
109
|
-
const res = { status };
|
|
110
|
-
// @ts-expect-error handle is not typed for an unclear reason.
|
|
111
|
-
router.handle(req, res, noop);
|
|
112
|
-
await promise;
|
|
113
|
-
expect(await promise).toEqual({ error: 'test error', status: 'ERROR' });
|
|
114
|
-
expect(status).toHaveBeenCalledExactlyOnceWith(400);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('keeps original errors when status code is 500', async () => {
|
|
118
|
-
const router = AfRouter({ logger });
|
|
119
|
-
const error = Object.assign(new Error('test error'), { statusCode: 500 });
|
|
120
|
-
router[method]('/test', () => Promise.reject(error));
|
|
121
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
122
|
-
const next = vi.fn(resolve);
|
|
123
|
-
const req = { method, url: '/test', baseUrl: '' };
|
|
124
|
-
const res = {};
|
|
125
|
-
// @ts-expect-error handle is not typed for an unclear reason.
|
|
126
|
-
router.handle(req, res, next);
|
|
127
|
-
await promise;
|
|
128
|
-
expect(next).toHaveBeenCalledExactlyOnceWith(error);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('defaults to mergeParams true', async () => {
|
|
132
|
-
const router = AfRouter({ mergeParams: false, logger });
|
|
133
|
-
const childRouter = AfRouter({ logger });
|
|
134
|
-
router.use('/:parentParam', childRouter);
|
|
135
|
-
childRouter[method]<{ parentParam: string; param: string; }>('/:param', (req, res) => res.send({ param: req.params.param, parentParam: req.params.parentParam }));
|
|
136
|
-
|
|
137
|
-
const { promise, resolve } = Promise.withResolvers<string>();
|
|
138
|
-
const req = { method, url: '/foo/bar', baseUrl: '' };
|
|
139
|
-
const res = { send: (data: string) => resolve(data) };
|
|
140
|
-
// @ts-expect-error handle is not typed for an unclear reason.
|
|
141
|
-
router.handle(req, res, noop);
|
|
142
|
-
expect(await promise).toEqual({ parentParam: 'foo', param: 'bar' });
|
|
143
|
-
// @ts-expect-error mergeParams is a private field
|
|
144
|
-
expect(router.mergeParams).toBeFalsy();
|
|
145
|
-
// @ts-expect-error mergeParams is a private field
|
|
146
|
-
expect(childRouter.mergeParams).toBeTruthy();
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
});
|
package/src/router/index.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Router, type Request, type Response, type NextFunction, type Handler, type RouterOptions, type IRouterMatcher,
|
|
3
|
-
} from 'express';
|
|
4
|
-
import Logger, { type LoggerInstanceManager } from '@autofleet/logger';
|
|
5
|
-
|
|
6
|
-
export const METHODS = [
|
|
7
|
-
'all',
|
|
8
|
-
'get',
|
|
9
|
-
'post',
|
|
10
|
-
'put',
|
|
11
|
-
'delete',
|
|
12
|
-
'patch',
|
|
13
|
-
'options',
|
|
14
|
-
'head',
|
|
15
|
-
] as const;
|
|
16
|
-
|
|
17
|
-
const AfEntryPoint = (logger: LoggerInstanceManager, func: (req: Request, res: Response, nextFn: NextFunction) => void | PromiseLike<void>): Handler => async (req, res, next) => {
|
|
18
|
-
try {
|
|
19
|
-
await func(req, res, next);
|
|
20
|
-
} catch (err) {
|
|
21
|
-
const e = err as Error & { statusCode?: number };
|
|
22
|
-
logger.error(e.message);
|
|
23
|
-
if (e.statusCode && e.statusCode < 500) {
|
|
24
|
-
res.status(400).json({ error: e.message, status: 'ERROR' });
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
next(e);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/** @returns a monkey-patched express router that will handle async routes (and force a 400 status for codes <500) */
|
|
32
|
-
export const AfRouter = ({ logger = Logger(), ...options }: RouterOptions & { logger: LoggerInstanceManager }): Router => {
|
|
33
|
-
const myRouter = Router({ mergeParams: true, ...options });
|
|
34
|
-
METHODS.forEach((method) => {
|
|
35
|
-
const internalMethod = myRouter[method].bind(myRouter);
|
|
36
|
-
const newMethodHandler: IRouterMatcher<Router> = (...args: [...unknown[]]) => internalMethod(...args.map(argMapper) as [string]);
|
|
37
|
-
myRouter[method] = newMethodHandler;
|
|
38
|
-
});
|
|
39
|
-
return myRouter;
|
|
40
|
-
|
|
41
|
-
function argMapper(args: unknown): unknown {
|
|
42
|
-
if (Array.isArray(args)) return args.map(argMapper);
|
|
43
|
-
return typeof args === 'function' ? AfEntryPoint(logger, args as Handler) : args;
|
|
44
|
-
}
|
|
45
|
-
};
|
package/tsconfig.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
"strict": true,
|
|
8
|
-
"esModuleInterop": true,
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"lib": [
|
|
11
|
-
"ESNext"
|
|
12
|
-
]
|
|
13
|
-
},
|
|
14
|
-
"include": ["src", "tsup.config.ts", "vitest.config.ts"],
|
|
15
|
-
}
|
package/tsup.config.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'tsup';
|
|
2
|
-
|
|
3
|
-
export default defineConfig((options) => ({
|
|
4
|
-
entry: ['src/index.ts'],
|
|
5
|
-
target: 'node18.0',
|
|
6
|
-
dts: true,
|
|
7
|
-
format: ['esm', 'cjs'],
|
|
8
|
-
clean: !options.watch,
|
|
9
|
-
minify: !options.watch,
|
|
10
|
-
removeNodeProtocol: false,
|
|
11
|
-
treeshake: true,
|
|
12
|
-
sourcemap: true,
|
|
13
|
-
}));
|
package/vitest.config.ts
DELETED