@technomoron/api-server-base 1.0.23 → 1.0.25
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/dist/cjs/api-server-base.d.ts +35 -20
- package/dist/cjs/api-server-base.js +56 -50
- package/dist/esm/api-server-base.d.ts +35 -20
- package/dist/esm/api-server-base.js +56 -50
- package/package.json +1 -1
|
@@ -49,13 +49,15 @@ export type ApiRoute = {
|
|
|
49
49
|
req: ApiAuthClass;
|
|
50
50
|
};
|
|
51
51
|
};
|
|
52
|
-
export
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
export declare class ApiModule<T> {
|
|
53
|
+
server: T;
|
|
54
|
+
namespace: string;
|
|
55
|
+
mountpath: string;
|
|
56
|
+
static defaultNamespace: string;
|
|
57
|
+
constructor(opts?: {
|
|
58
|
+
namespace?: string;
|
|
59
|
+
});
|
|
60
|
+
defineRoutes(): ApiRoute[];
|
|
59
61
|
}
|
|
60
62
|
export interface ApiErrorParams {
|
|
61
63
|
code?: number;
|
|
@@ -70,21 +72,28 @@ export declare class ApiError extends Error {
|
|
|
70
72
|
constructor({ code, message, data, errors }: ApiErrorParams);
|
|
71
73
|
}
|
|
72
74
|
export interface ApiServerConf {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
apiPort: number;
|
|
76
|
+
apiHost: string;
|
|
77
|
+
uploadPath: string;
|
|
78
|
+
uploadMax: number;
|
|
79
|
+
origins: string[];
|
|
80
|
+
debug: boolean;
|
|
81
|
+
apiBasePath: string;
|
|
82
|
+
accessSecret: string;
|
|
83
|
+
refreshSecret: string;
|
|
84
|
+
cookieDomain: string;
|
|
85
|
+
accessCookie: string;
|
|
86
|
+
refreshCookie: string;
|
|
87
|
+
accessExpiry: number;
|
|
88
|
+
refreshExpiry: number;
|
|
89
|
+
authApi: boolean;
|
|
90
|
+
devMode: boolean;
|
|
82
91
|
}
|
|
83
92
|
export declare class ApiServer {
|
|
84
93
|
app: Application;
|
|
85
94
|
currReq: ApiRequest | null;
|
|
86
|
-
private routerV1;
|
|
87
95
|
readonly config: ApiServerConf;
|
|
96
|
+
constructor(config?: Partial<ApiServerConf>);
|
|
88
97
|
jwtSign(payload: any, secret: string, expiresInSeconds: number, options?: SignOptions): JwtSignResult;
|
|
89
98
|
jwtVerify<T>(token: string, secret: string, options?: VerifyOptions): JwtVerifyResult<T>;
|
|
90
99
|
jwtDecode<T>(token: string, options?: jwt.DecodeOptions): JwtDecodeResult<T>;
|
|
@@ -95,6 +104,9 @@ export declare class ApiServer {
|
|
|
95
104
|
access: string;
|
|
96
105
|
refresh: string;
|
|
97
106
|
userId: unknown;
|
|
107
|
+
domain?: string;
|
|
108
|
+
fingerprint?: string;
|
|
109
|
+
label?: string;
|
|
98
110
|
}): Promise<void>;
|
|
99
111
|
getToken(params: {
|
|
100
112
|
accessToken?: string;
|
|
@@ -110,8 +122,12 @@ export declare class ApiServer {
|
|
|
110
122
|
refreshToken?: string;
|
|
111
123
|
accessToken?: string;
|
|
112
124
|
userId?: unknown;
|
|
125
|
+
domain?: string;
|
|
126
|
+
fingerprint?: string;
|
|
127
|
+
label?: string;
|
|
113
128
|
}): Promise<number>;
|
|
114
|
-
|
|
129
|
+
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
130
|
+
filterUser<T = any, U = any>(fullUser: T): U;
|
|
115
131
|
guessExceptionText(error: any, defMsg?: string): string;
|
|
116
132
|
protected authorize(apiReq: ApiRequest, requiredClass: ApiAuthClass): Promise<void>;
|
|
117
133
|
private middlewares;
|
|
@@ -119,8 +135,7 @@ export declare class ApiServer {
|
|
|
119
135
|
private verifyJWT;
|
|
120
136
|
private authenticate;
|
|
121
137
|
private handle_request;
|
|
122
|
-
|
|
123
|
-
api<T extends ApiModule<IApiServer>>(ApiModuleClass: new () => T): this;
|
|
138
|
+
api<T extends ApiModule<any>>(module: T): this;
|
|
124
139
|
dumpRequest(apiReq: ApiRequest): void;
|
|
125
140
|
}
|
|
126
141
|
export default ApiServer;
|
|
@@ -16,16 +16,16 @@ const express_1 = __importDefault(require("express"));
|
|
|
16
16
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
17
17
|
const multer_1 = __importDefault(require("multer"));
|
|
18
18
|
class ApiModule {
|
|
19
|
-
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
return this;
|
|
19
|
+
constructor(opts = {}) {
|
|
20
|
+
this.mountpath = '';
|
|
21
|
+
this.namespace = opts.namespace ?? this.constructor.defaultNamespace ?? '';
|
|
23
22
|
}
|
|
24
|
-
|
|
23
|
+
defineRoutes() {
|
|
25
24
|
return [];
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
exports.ApiModule = ApiModule;
|
|
28
|
+
ApiModule.defaultNamespace = '';
|
|
29
29
|
function guess_exception_text(error, defMsg = 'Unknown Error') {
|
|
30
30
|
const msg = [];
|
|
31
31
|
if (typeof error === 'string' && error.trim() !== '') {
|
|
@@ -52,7 +52,38 @@ class ApiError extends Error {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
exports.ApiError = ApiError;
|
|
55
|
+
function fillConfig(config) {
|
|
56
|
+
return {
|
|
57
|
+
apiPort: config.apiPort ?? 3101,
|
|
58
|
+
apiHost: config.apiHost ?? 'localhost',
|
|
59
|
+
uploadPath: config.uploadPath ?? '',
|
|
60
|
+
uploadMax: config.uploadMax ?? 30 * 1024 * 1024,
|
|
61
|
+
origins: config.origins ?? [],
|
|
62
|
+
debug: config.debug ?? false,
|
|
63
|
+
apiBasePath: config.apiBasePath ?? '/api',
|
|
64
|
+
accessSecret: config.accessSecret ?? '',
|
|
65
|
+
refreshSecret: config.refreshSecret ?? '',
|
|
66
|
+
cookieDomain: config.cookieDomain ?? '.somewhere-over-the-rainbow.com',
|
|
67
|
+
accessCookie: config.accessCookie ?? 'dat',
|
|
68
|
+
refreshCookie: config.refreshCookie ?? 'drt',
|
|
69
|
+
accessExpiry: config.accessExpiry ?? 60 * 15,
|
|
70
|
+
refreshExpiry: config.refreshExpiry ?? 30 * 24 * 60 * 60 * 1000,
|
|
71
|
+
authApi: config.authApi ?? false,
|
|
72
|
+
devMode: config.devMode ?? false
|
|
73
|
+
};
|
|
74
|
+
}
|
|
55
75
|
class ApiServer {
|
|
76
|
+
constructor(config = {}) {
|
|
77
|
+
this.currReq = null;
|
|
78
|
+
this.config = fillConfig(config);
|
|
79
|
+
this.app = (0, express_1.default)();
|
|
80
|
+
if (config.uploadPath) {
|
|
81
|
+
const upload = (0, multer_1.default)({ dest: config.uploadPath });
|
|
82
|
+
this.app.use(upload.any());
|
|
83
|
+
}
|
|
84
|
+
this.middlewares();
|
|
85
|
+
// addSwaggerUi(this.app);
|
|
86
|
+
}
|
|
56
87
|
jwtSign(payload, secret, expiresInSeconds, options) {
|
|
57
88
|
options || (options = {});
|
|
58
89
|
const opts = { ...options, expiresIn: expiresInSeconds };
|
|
@@ -141,27 +172,11 @@ class ApiServer {
|
|
|
141
172
|
async deleteToken(params) {
|
|
142
173
|
throw new Error('deleteToken() not implemented');
|
|
143
174
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
config.origins || (config.origins = []);
|
|
150
|
-
config.debug || (config.debug = false);
|
|
151
|
-
config.apiHost || (config.apiHost = 'localhost');
|
|
152
|
-
config.apiPort || (config.apiPort = 3101);
|
|
153
|
-
config.accessExpire || (config.accessExpire = 60 * 15); // 15 minutes default
|
|
154
|
-
config.refreshExpire || (config.refreshExpire = 30 * 24 * 60 * 60); // 30 days
|
|
155
|
-
this.config = config;
|
|
156
|
-
this.routerV1 = express_1.default.Router();
|
|
157
|
-
this.app = (0, express_1.default)();
|
|
158
|
-
if (config.uploadPath) {
|
|
159
|
-
const upload = (0, multer_1.default)({ dest: config.uploadPath });
|
|
160
|
-
this.app.use(upload.any());
|
|
161
|
-
}
|
|
162
|
-
this.middlewares();
|
|
163
|
-
this.app.use('/api/v1', this.routerV1);
|
|
164
|
-
// addSwaggerUi(this.app);
|
|
175
|
+
async verifyPassword(password, hash) {
|
|
176
|
+
throw new Error('verifyPassword() not implemented');
|
|
177
|
+
}
|
|
178
|
+
filterUser(fullUser) {
|
|
179
|
+
return fullUser;
|
|
165
180
|
}
|
|
166
181
|
guessExceptionText(error, defMsg = 'Unkown Error') {
|
|
167
182
|
return guess_exception_text(error, defMsg);
|
|
@@ -214,10 +229,10 @@ class ApiServer {
|
|
|
214
229
|
return this;
|
|
215
230
|
}
|
|
216
231
|
async verifyJWT(token) {
|
|
217
|
-
if (!this.config.
|
|
232
|
+
if (!this.config.accessSecret) {
|
|
218
233
|
return { tokenData: undefined, error: 'JWT authentication disabled; no jwtSecret set' };
|
|
219
234
|
}
|
|
220
|
-
const result = this.jwtVerify(token, this.config.
|
|
235
|
+
const result = this.jwtVerify(token, this.config.accessSecret);
|
|
221
236
|
if (!result.success) {
|
|
222
237
|
return { tokenData: undefined, error: result.error };
|
|
223
238
|
}
|
|
@@ -319,30 +334,21 @@ class ApiServer {
|
|
|
319
334
|
}
|
|
320
335
|
};
|
|
321
336
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
break;
|
|
335
|
-
case 'delete':
|
|
336
|
-
this.routerV1.delete(route.path, handler);
|
|
337
|
-
break;
|
|
338
|
-
default:
|
|
339
|
-
throw new Error(`Unsupported method: ${route.method}`);
|
|
337
|
+
api(module) {
|
|
338
|
+
const router = express_1.default.Router();
|
|
339
|
+
module.server = this;
|
|
340
|
+
const base = this.config.apiBasePath ?? '/api';
|
|
341
|
+
const ns = module.namespace;
|
|
342
|
+
const mountPath = `${base}${ns}`;
|
|
343
|
+
module.mountpath = mountPath;
|
|
344
|
+
module.defineRoutes().forEach((r) => {
|
|
345
|
+
const handler = this.handle_request(r.handler, r.auth);
|
|
346
|
+
router[r.method](r.path, handler);
|
|
347
|
+
if (this.config.debug) {
|
|
348
|
+
console.log(`Adding ${mountPath}${r.path} (${r.method.toUpperCase()})`);
|
|
340
349
|
}
|
|
341
350
|
});
|
|
342
|
-
|
|
343
|
-
api(ApiModuleClass) {
|
|
344
|
-
const moduleInstance = new ApiModuleClass();
|
|
345
|
-
moduleInstance.init(this); // docServer should be a valid IApiServer.
|
|
351
|
+
this.app.use(mountPath, router);
|
|
346
352
|
return this;
|
|
347
353
|
}
|
|
348
354
|
dumpRequest(apiReq) {
|
|
@@ -49,13 +49,15 @@ export type ApiRoute = {
|
|
|
49
49
|
req: ApiAuthClass;
|
|
50
50
|
};
|
|
51
51
|
};
|
|
52
|
-
export
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
export declare class ApiModule<T> {
|
|
53
|
+
server: T;
|
|
54
|
+
namespace: string;
|
|
55
|
+
mountpath: string;
|
|
56
|
+
static defaultNamespace: string;
|
|
57
|
+
constructor(opts?: {
|
|
58
|
+
namespace?: string;
|
|
59
|
+
});
|
|
60
|
+
defineRoutes(): ApiRoute[];
|
|
59
61
|
}
|
|
60
62
|
export interface ApiErrorParams {
|
|
61
63
|
code?: number;
|
|
@@ -70,21 +72,28 @@ export declare class ApiError extends Error {
|
|
|
70
72
|
constructor({ code, message, data, errors }: ApiErrorParams);
|
|
71
73
|
}
|
|
72
74
|
export interface ApiServerConf {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
apiPort: number;
|
|
76
|
+
apiHost: string;
|
|
77
|
+
uploadPath: string;
|
|
78
|
+
uploadMax: number;
|
|
79
|
+
origins: string[];
|
|
80
|
+
debug: boolean;
|
|
81
|
+
apiBasePath: string;
|
|
82
|
+
accessSecret: string;
|
|
83
|
+
refreshSecret: string;
|
|
84
|
+
cookieDomain: string;
|
|
85
|
+
accessCookie: string;
|
|
86
|
+
refreshCookie: string;
|
|
87
|
+
accessExpiry: number;
|
|
88
|
+
refreshExpiry: number;
|
|
89
|
+
authApi: boolean;
|
|
90
|
+
devMode: boolean;
|
|
82
91
|
}
|
|
83
92
|
export declare class ApiServer {
|
|
84
93
|
app: Application;
|
|
85
94
|
currReq: ApiRequest | null;
|
|
86
|
-
private routerV1;
|
|
87
95
|
readonly config: ApiServerConf;
|
|
96
|
+
constructor(config?: Partial<ApiServerConf>);
|
|
88
97
|
jwtSign(payload: any, secret: string, expiresInSeconds: number, options?: SignOptions): JwtSignResult;
|
|
89
98
|
jwtVerify<T>(token: string, secret: string, options?: VerifyOptions): JwtVerifyResult<T>;
|
|
90
99
|
jwtDecode<T>(token: string, options?: jwt.DecodeOptions): JwtDecodeResult<T>;
|
|
@@ -95,6 +104,9 @@ export declare class ApiServer {
|
|
|
95
104
|
access: string;
|
|
96
105
|
refresh: string;
|
|
97
106
|
userId: unknown;
|
|
107
|
+
domain?: string;
|
|
108
|
+
fingerprint?: string;
|
|
109
|
+
label?: string;
|
|
98
110
|
}): Promise<void>;
|
|
99
111
|
getToken(params: {
|
|
100
112
|
accessToken?: string;
|
|
@@ -110,8 +122,12 @@ export declare class ApiServer {
|
|
|
110
122
|
refreshToken?: string;
|
|
111
123
|
accessToken?: string;
|
|
112
124
|
userId?: unknown;
|
|
125
|
+
domain?: string;
|
|
126
|
+
fingerprint?: string;
|
|
127
|
+
label?: string;
|
|
113
128
|
}): Promise<number>;
|
|
114
|
-
|
|
129
|
+
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
130
|
+
filterUser<T = any, U = any>(fullUser: T): U;
|
|
115
131
|
guessExceptionText(error: any, defMsg?: string): string;
|
|
116
132
|
protected authorize(apiReq: ApiRequest, requiredClass: ApiAuthClass): Promise<void>;
|
|
117
133
|
private middlewares;
|
|
@@ -119,8 +135,7 @@ export declare class ApiServer {
|
|
|
119
135
|
private verifyJWT;
|
|
120
136
|
private authenticate;
|
|
121
137
|
private handle_request;
|
|
122
|
-
|
|
123
|
-
api<T extends ApiModule<IApiServer>>(ApiModuleClass: new () => T): this;
|
|
138
|
+
api<T extends ApiModule<any>>(module: T): this;
|
|
124
139
|
dumpRequest(apiReq: ApiRequest): void;
|
|
125
140
|
}
|
|
126
141
|
export default ApiServer;
|
|
@@ -10,15 +10,15 @@ import express from 'express';
|
|
|
10
10
|
import jwt from 'jsonwebtoken';
|
|
11
11
|
import multer from 'multer';
|
|
12
12
|
export class ApiModule {
|
|
13
|
-
|
|
14
|
-
this.
|
|
15
|
-
|
|
16
|
-
return this;
|
|
13
|
+
constructor(opts = {}) {
|
|
14
|
+
this.mountpath = '';
|
|
15
|
+
this.namespace = opts.namespace ?? this.constructor.defaultNamespace ?? '';
|
|
17
16
|
}
|
|
18
|
-
|
|
17
|
+
defineRoutes() {
|
|
19
18
|
return [];
|
|
20
19
|
}
|
|
21
20
|
}
|
|
21
|
+
ApiModule.defaultNamespace = '';
|
|
22
22
|
function guess_exception_text(error, defMsg = 'Unknown Error') {
|
|
23
23
|
const msg = [];
|
|
24
24
|
if (typeof error === 'string' && error.trim() !== '') {
|
|
@@ -44,7 +44,38 @@ export class ApiError extends Error {
|
|
|
44
44
|
this.errors = errors !== undefined ? errors : {};
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
function fillConfig(config) {
|
|
48
|
+
return {
|
|
49
|
+
apiPort: config.apiPort ?? 3101,
|
|
50
|
+
apiHost: config.apiHost ?? 'localhost',
|
|
51
|
+
uploadPath: config.uploadPath ?? '',
|
|
52
|
+
uploadMax: config.uploadMax ?? 30 * 1024 * 1024,
|
|
53
|
+
origins: config.origins ?? [],
|
|
54
|
+
debug: config.debug ?? false,
|
|
55
|
+
apiBasePath: config.apiBasePath ?? '/api',
|
|
56
|
+
accessSecret: config.accessSecret ?? '',
|
|
57
|
+
refreshSecret: config.refreshSecret ?? '',
|
|
58
|
+
cookieDomain: config.cookieDomain ?? '.somewhere-over-the-rainbow.com',
|
|
59
|
+
accessCookie: config.accessCookie ?? 'dat',
|
|
60
|
+
refreshCookie: config.refreshCookie ?? 'drt',
|
|
61
|
+
accessExpiry: config.accessExpiry ?? 60 * 15,
|
|
62
|
+
refreshExpiry: config.refreshExpiry ?? 30 * 24 * 60 * 60 * 1000,
|
|
63
|
+
authApi: config.authApi ?? false,
|
|
64
|
+
devMode: config.devMode ?? false
|
|
65
|
+
};
|
|
66
|
+
}
|
|
47
67
|
export class ApiServer {
|
|
68
|
+
constructor(config = {}) {
|
|
69
|
+
this.currReq = null;
|
|
70
|
+
this.config = fillConfig(config);
|
|
71
|
+
this.app = express();
|
|
72
|
+
if (config.uploadPath) {
|
|
73
|
+
const upload = multer({ dest: config.uploadPath });
|
|
74
|
+
this.app.use(upload.any());
|
|
75
|
+
}
|
|
76
|
+
this.middlewares();
|
|
77
|
+
// addSwaggerUi(this.app);
|
|
78
|
+
}
|
|
48
79
|
jwtSign(payload, secret, expiresInSeconds, options) {
|
|
49
80
|
options || (options = {});
|
|
50
81
|
const opts = { ...options, expiresIn: expiresInSeconds };
|
|
@@ -133,27 +164,11 @@ export class ApiServer {
|
|
|
133
164
|
async deleteToken(params) {
|
|
134
165
|
throw new Error('deleteToken() not implemented');
|
|
135
166
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
config.origins || (config.origins = []);
|
|
142
|
-
config.debug || (config.debug = false);
|
|
143
|
-
config.apiHost || (config.apiHost = 'localhost');
|
|
144
|
-
config.apiPort || (config.apiPort = 3101);
|
|
145
|
-
config.accessExpire || (config.accessExpire = 60 * 15); // 15 minutes default
|
|
146
|
-
config.refreshExpire || (config.refreshExpire = 30 * 24 * 60 * 60); // 30 days
|
|
147
|
-
this.config = config;
|
|
148
|
-
this.routerV1 = express.Router();
|
|
149
|
-
this.app = express();
|
|
150
|
-
if (config.uploadPath) {
|
|
151
|
-
const upload = multer({ dest: config.uploadPath });
|
|
152
|
-
this.app.use(upload.any());
|
|
153
|
-
}
|
|
154
|
-
this.middlewares();
|
|
155
|
-
this.app.use('/api/v1', this.routerV1);
|
|
156
|
-
// addSwaggerUi(this.app);
|
|
167
|
+
async verifyPassword(password, hash) {
|
|
168
|
+
throw new Error('verifyPassword() not implemented');
|
|
169
|
+
}
|
|
170
|
+
filterUser(fullUser) {
|
|
171
|
+
return fullUser;
|
|
157
172
|
}
|
|
158
173
|
guessExceptionText(error, defMsg = 'Unkown Error') {
|
|
159
174
|
return guess_exception_text(error, defMsg);
|
|
@@ -206,10 +221,10 @@ export class ApiServer {
|
|
|
206
221
|
return this;
|
|
207
222
|
}
|
|
208
223
|
async verifyJWT(token) {
|
|
209
|
-
if (!this.config.
|
|
224
|
+
if (!this.config.accessSecret) {
|
|
210
225
|
return { tokenData: undefined, error: 'JWT authentication disabled; no jwtSecret set' };
|
|
211
226
|
}
|
|
212
|
-
const result = this.jwtVerify(token, this.config.
|
|
227
|
+
const result = this.jwtVerify(token, this.config.accessSecret);
|
|
213
228
|
if (!result.success) {
|
|
214
229
|
return { tokenData: undefined, error: result.error };
|
|
215
230
|
}
|
|
@@ -311,30 +326,21 @@ export class ApiServer {
|
|
|
311
326
|
}
|
|
312
327
|
};
|
|
313
328
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
break;
|
|
327
|
-
case 'delete':
|
|
328
|
-
this.routerV1.delete(route.path, handler);
|
|
329
|
-
break;
|
|
330
|
-
default:
|
|
331
|
-
throw new Error(`Unsupported method: ${route.method}`);
|
|
329
|
+
api(module) {
|
|
330
|
+
const router = express.Router();
|
|
331
|
+
module.server = this;
|
|
332
|
+
const base = this.config.apiBasePath ?? '/api';
|
|
333
|
+
const ns = module.namespace;
|
|
334
|
+
const mountPath = `${base}${ns}`;
|
|
335
|
+
module.mountpath = mountPath;
|
|
336
|
+
module.defineRoutes().forEach((r) => {
|
|
337
|
+
const handler = this.handle_request(r.handler, r.auth);
|
|
338
|
+
router[r.method](r.path, handler);
|
|
339
|
+
if (this.config.debug) {
|
|
340
|
+
console.log(`Adding ${mountPath}${r.path} (${r.method.toUpperCase()})`);
|
|
332
341
|
}
|
|
333
342
|
});
|
|
334
|
-
|
|
335
|
-
api(ApiModuleClass) {
|
|
336
|
-
const moduleInstance = new ApiModuleClass();
|
|
337
|
-
moduleInstance.init(this); // docServer should be a valid IApiServer.
|
|
343
|
+
this.app.use(mountPath, router);
|
|
338
344
|
return this;
|
|
339
345
|
}
|
|
340
346
|
dumpRequest(apiReq) {
|