@jwn-js/common 1.1.47 → 1.3.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/ApiError.d.ts +1 -1
- package/{Server-24c15b65.js → Server-77093d28.js} +0 -4
- package/Server.js +1 -1
- package/docs/assets/js/search.js +1 -1
- package/docs/classes/ApiError.html +26 -8
- package/docs/classes/Controller.html +996 -0
- package/docs/classes/Jwt.html +22 -4
- package/docs/classes/Memcached.html +22 -4
- package/docs/classes/Model.html +559 -0
- package/docs/classes/Server.html +22 -4
- package/docs/classes/Ssr.html +355 -0
- package/docs/classes/Web.html +485 -0
- package/docs/index.html +22 -4
- package/docs/interfaces/ApiErrorMessage.html +22 -4
- package/docs/interfaces/ServerHandler.html +22 -4
- package/docs/interfaces/ServerOptions.html +22 -4
- package/docs/interfaces/ServerWebsocket.html +22 -4
- package/docs/modules.html +149 -6
- package/index.d.ts +504 -1
- package/index.js +637 -2
- package/package.json +14 -12
package/index.js
CHANGED
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var ApiError = require('./ApiError.js');
|
|
6
|
-
var Server = require('./Server-
|
|
6
|
+
var Server = require('./Server-77093d28.js');
|
|
7
7
|
var Jwt = require('./Jwt.js');
|
|
8
8
|
var ApiError$1 = require('./ApiError-b517f53a.js');
|
|
9
|
-
var querystring = require('querystring');
|
|
10
9
|
var stream = require('stream');
|
|
10
|
+
var querystring = require('querystring');
|
|
11
11
|
var formidable = require('formidable');
|
|
12
12
|
var path = require('path');
|
|
13
13
|
var fs = require('fs');
|
|
14
14
|
require('dns');
|
|
15
15
|
require('uWebSockets.js');
|
|
16
|
+
var easyAsh = require('easy-ash');
|
|
17
|
+
var xmljs = require('xml-js');
|
|
16
18
|
require('crypto');
|
|
17
19
|
|
|
18
20
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -21,6 +23,7 @@ var querystring__default = /*#__PURE__*/_interopDefaultLegacy(querystring);
|
|
|
21
23
|
var formidable__default = /*#__PURE__*/_interopDefaultLegacy(formidable);
|
|
22
24
|
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
23
25
|
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
26
|
+
var xmljs__default = /*#__PURE__*/_interopDefaultLegacy(xmljs);
|
|
24
27
|
|
|
25
28
|
class Memcached {
|
|
26
29
|
constructor(memjs, specialHeaders = { "x-cache": "memcached-js" }, maxKeyLength = 160, debug = 0) {
|
|
@@ -105,6 +108,40 @@ function readJson(res, cb, err) {
|
|
|
105
108
|
res.onAborted(err);
|
|
106
109
|
}
|
|
107
110
|
|
|
111
|
+
const rawBody = (res, req) => new Promise((resolve, reject) => {
|
|
112
|
+
readRaw(res, (obj) => {
|
|
113
|
+
resolve(obj);
|
|
114
|
+
}, (e) => {
|
|
115
|
+
reject(new ApiError$1.ApiError({ message: "Can`t parse request", code: 1, statusCode: 404 }));
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
function readRaw(res, cb, err) {
|
|
119
|
+
let buffer = Buffer.from([]);
|
|
120
|
+
res.onData((ab, isLast) => {
|
|
121
|
+
buffer = Buffer.concat([buffer, Buffer.from(ab)]);
|
|
122
|
+
if (isLast) {
|
|
123
|
+
cb(buffer);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
res.onAborted(err);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const streamBody = (res, req) => {
|
|
130
|
+
const err = new ApiError$1.ApiError({ message: "Can`t parse body", code: 1, statusCode: 404 });
|
|
131
|
+
res.onAborted(() => err);
|
|
132
|
+
const stream$1 = new stream.PassThrough();
|
|
133
|
+
stream$1.headers = {};
|
|
134
|
+
req.forEach((key, val) => stream$1.headers[key] = val);
|
|
135
|
+
res.onData((chunk, isLast) => {
|
|
136
|
+
stream$1.write(Buffer.from(Buffer.from(chunk)));
|
|
137
|
+
stream$1.resume();
|
|
138
|
+
if (isLast) {
|
|
139
|
+
stream$1.end();
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return stream$1;
|
|
143
|
+
};
|
|
144
|
+
|
|
108
145
|
const urlencodedBody = (res, req) => new Promise((resolve, reject) => {
|
|
109
146
|
readBody(res, (obj) => {
|
|
110
147
|
resolve(obj);
|
|
@@ -375,10 +412,603 @@ async function staticBody(res, req, base) {
|
|
|
375
412
|
}
|
|
376
413
|
}
|
|
377
414
|
|
|
415
|
+
const status = {
|
|
416
|
+
100: "100 Continue",
|
|
417
|
+
101: "101 Switching Protocols",
|
|
418
|
+
200: "200 OK",
|
|
419
|
+
201: "201 Created",
|
|
420
|
+
202: "202 Accepted",
|
|
421
|
+
203: "203 Non-Authoritative Information",
|
|
422
|
+
204: "No Content",
|
|
423
|
+
205: "205 Reset Content",
|
|
424
|
+
206: "206 Partial Content",
|
|
425
|
+
300: "300 Multiple Choices",
|
|
426
|
+
301: "301 Moved Permanently",
|
|
427
|
+
302: "302 Found",
|
|
428
|
+
303: "303 See Other",
|
|
429
|
+
304: "304 Not Modified",
|
|
430
|
+
305: "305 Use Proxy",
|
|
431
|
+
306: "306 (Unused)",
|
|
432
|
+
307: "307 Temporary Redirect",
|
|
433
|
+
400: "400 Bad Request",
|
|
434
|
+
401: "401 Unauthorized",
|
|
435
|
+
402: "402 Payment Required",
|
|
436
|
+
403: "403 Forbidden",
|
|
437
|
+
404: "404 Not Found",
|
|
438
|
+
405: "405 Method Not Allowed",
|
|
439
|
+
406: "406 Not Acceptable",
|
|
440
|
+
407: "407 Proxy Authentication Required",
|
|
441
|
+
408: "408 Request Timeout",
|
|
442
|
+
409: "409 Conflict",
|
|
443
|
+
410: "410 Gone",
|
|
444
|
+
411: "411 Length Required",
|
|
445
|
+
412: "412 Precondition Failed",
|
|
446
|
+
413: "413 Request Entity Too Large",
|
|
447
|
+
414: "414 Request-URI Too Long",
|
|
448
|
+
415: "415 Unsupported Media Type",
|
|
449
|
+
416: "416 Requested Range Not Satisfiable",
|
|
450
|
+
417: "417 Expectation Failed",
|
|
451
|
+
500: "500 Internal Server Error",
|
|
452
|
+
501: "501 Not Implemented",
|
|
453
|
+
502: "502 Bad Gateway",
|
|
454
|
+
503: "503 Service Unavailable",
|
|
455
|
+
504: "504 Gateway Timeout",
|
|
456
|
+
505: "505 HTTP Version Not Supported"
|
|
457
|
+
};
|
|
458
|
+
const codeToStatus = (code) => {
|
|
459
|
+
return status.hasOwnProperty(code) ? status[code] : `${code}`;
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
class Ssr {
|
|
463
|
+
constructor(res, req, context, entry) {
|
|
464
|
+
this.res = res;
|
|
465
|
+
this.req = req;
|
|
466
|
+
this.context = context;
|
|
467
|
+
this.entry = entry;
|
|
468
|
+
}
|
|
469
|
+
async request(request = {}) {
|
|
470
|
+
this.res.onAborted(() => {
|
|
471
|
+
console.log("Abort is SSR handler");
|
|
472
|
+
});
|
|
473
|
+
const url = this.req.getUrl();
|
|
474
|
+
const extension = getExt(url);
|
|
475
|
+
if (extensions.includes(extension)) {
|
|
476
|
+
await staticBody(this.res, this.req, "./dist/client");
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
const contextSsr = {
|
|
480
|
+
hostname: this.req.getHeader("host"),
|
|
481
|
+
protocol: this.req.getHeader("x-forwarded-proto") || "http",
|
|
482
|
+
url: this.req.getUrl(),
|
|
483
|
+
cookies: Server.cookieParse(this.req.getHeader("cookie")),
|
|
484
|
+
ip: this.req.getHeader("x-forwarded-for")?.split(/,\s+/)?.[0],
|
|
485
|
+
memcache: null,
|
|
486
|
+
statusCode: 200,
|
|
487
|
+
headers: {},
|
|
488
|
+
responseHeaders: {
|
|
489
|
+
"content-type": "text/html; charset=utf-8"
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
this.req.forEach((key2, value) => contextSsr.headers[key2] = value);
|
|
493
|
+
const key = `${contextSsr.protocol}://${contextSsr.hostname}${contextSsr.url}`;
|
|
494
|
+
let html;
|
|
495
|
+
const page = await this.context.memcached.getPage(key);
|
|
496
|
+
if (page) {
|
|
497
|
+
html = page.data.toString();
|
|
498
|
+
contextSsr.headers = page.headers;
|
|
499
|
+
} else {
|
|
500
|
+
({ html } = await this.entry(url, {
|
|
501
|
+
manifest: this.context.manifest,
|
|
502
|
+
res: this.res,
|
|
503
|
+
req: this.req,
|
|
504
|
+
context: contextSsr
|
|
505
|
+
}));
|
|
506
|
+
if (contextSsr.statusCode === 200) {
|
|
507
|
+
await this.context.memcached.setPage(key, contextSsr.headers, html, contextSsr.memcache);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
this.res.writeStatus(codeToStatus(contextSsr.statusCode));
|
|
511
|
+
Object.keys(contextSsr.headers).map((key2) => this.res.writeHeader(key2, contextSsr.headers[key2]));
|
|
512
|
+
this.res.end(html);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const selectControllerParams = async (db, method, name, subaction) => {
|
|
517
|
+
const row = (await db.poolQuery({ sql: `
|
|
518
|
+
SELECT c.id AS controller_id,
|
|
519
|
+
c.name AS controller_name,
|
|
520
|
+
c.is_active AS controller_is_active,
|
|
521
|
+
c.is_sitemap AS controller_is_sitemap,
|
|
522
|
+
a.id AS action_id,
|
|
523
|
+
a.name AS action_name,
|
|
524
|
+
a.is_active AS action_is_active,
|
|
525
|
+
a.method AS action_method,
|
|
526
|
+
s.id AS subaction_id,
|
|
527
|
+
s.name AS subaction_name,
|
|
528
|
+
s.is_permission AS subaction_is_permission,
|
|
529
|
+
s.is_check_method AS subaction_is_check_method,
|
|
530
|
+
s.is_log AS subaction_is_log,
|
|
531
|
+
s.is_active AS subaction_is_active
|
|
532
|
+
FROM app_controllers c
|
|
533
|
+
LEFT JOIN app_subactions s ON s.app_controllers_id = c.id AND s.name = :subaction
|
|
534
|
+
LEFT JOIN app_actions a ON a.id = s.app_actions_id
|
|
535
|
+
WHERE c.name = :name
|
|
536
|
+
`, namedPlaceholders: true }, { name, subaction }))?.[0];
|
|
537
|
+
if (!row) {
|
|
538
|
+
throw new ApiError$1.ApiError({
|
|
539
|
+
statusCode: 404,
|
|
540
|
+
code: 11,
|
|
541
|
+
message: `Controller ${name} not found is site schema`
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
const allowMethods = (row?.action_method || "").split(",").map((method2) => method2.trim());
|
|
545
|
+
if (row.controller_is_active !== 1) {
|
|
546
|
+
throw new ApiError$1.ApiError({
|
|
547
|
+
statusCode: 404,
|
|
548
|
+
code: 11,
|
|
549
|
+
message: `Controller ${name} not active is site schema`
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
if (!row.action_id) {
|
|
553
|
+
throw new ApiError$1.ApiError({
|
|
554
|
+
statusCode: 404,
|
|
555
|
+
code: 11,
|
|
556
|
+
message: `Action not found is site schema`
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
if (row.action_is_active !== 1) {
|
|
560
|
+
throw new ApiError$1.ApiError({
|
|
561
|
+
statusCode: 404,
|
|
562
|
+
code: 11,
|
|
563
|
+
message: `Action ${row.action_name} not active is site schema`
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
if (!row.subaction_id) {
|
|
567
|
+
throw new ApiError$1.ApiError({
|
|
568
|
+
statusCode: 404,
|
|
569
|
+
code: 11,
|
|
570
|
+
message: `Subaction ${subaction} not found is site schema`
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
if (row.subaction_is_active !== 1) {
|
|
574
|
+
throw new ApiError$1.ApiError({
|
|
575
|
+
statusCode: 404,
|
|
576
|
+
code: 11,
|
|
577
|
+
message: `Subaction ${subaction} not active is site schema`
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
if (row.subaction_is_check_method !== 0) {
|
|
581
|
+
if (row.action_method !== "any" && !allowMethods.includes(method)) {
|
|
582
|
+
throw new ApiError$1.ApiError({
|
|
583
|
+
statusCode: 404,
|
|
584
|
+
code: 11,
|
|
585
|
+
message: `Controller ${name} action ${row.action_name} allow only ${row.action_method} method`
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return {
|
|
590
|
+
controller: {
|
|
591
|
+
id: +row.controller_id,
|
|
592
|
+
name: row.controller_name,
|
|
593
|
+
isActive: !!row.controller_is_active,
|
|
594
|
+
isSitemap: !!row.controller_is_sitemap
|
|
595
|
+
},
|
|
596
|
+
action: {
|
|
597
|
+
id: +row.action_id,
|
|
598
|
+
name: row.action_name,
|
|
599
|
+
isActive: !!row.action_is_active,
|
|
600
|
+
method: row.action_method
|
|
601
|
+
},
|
|
602
|
+
subaction: {
|
|
603
|
+
id: +row.subaction_id,
|
|
604
|
+
name: row.subaction_name,
|
|
605
|
+
isPermission: !!row.subaction_is_permission,
|
|
606
|
+
isCheckMethod: !!row.subaction_is_check_method,
|
|
607
|
+
isLog: !!row.subaction_is_log,
|
|
608
|
+
isActive: !!row.subaction_is_active
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
class Web {
|
|
614
|
+
constructor(res, req, context) {
|
|
615
|
+
this.defaultRequest = {
|
|
616
|
+
controller: "Index",
|
|
617
|
+
subaction: "index",
|
|
618
|
+
lang: "ru"
|
|
619
|
+
};
|
|
620
|
+
this.defaultResponse = {
|
|
621
|
+
statusCode: 200,
|
|
622
|
+
headers: { "content-type": "application/json" },
|
|
623
|
+
body: {}
|
|
624
|
+
};
|
|
625
|
+
this.res = res;
|
|
626
|
+
this.req = req;
|
|
627
|
+
this.context = context;
|
|
628
|
+
}
|
|
629
|
+
async request(request = {}) {
|
|
630
|
+
let response = {};
|
|
631
|
+
try {
|
|
632
|
+
this.contextWeb = {
|
|
633
|
+
config: this.context.config,
|
|
634
|
+
db: this.context.db,
|
|
635
|
+
method: this.req.getMethod(),
|
|
636
|
+
cookies: this.req.cookies,
|
|
637
|
+
hostname: this.req.getHeader("host"),
|
|
638
|
+
protocol: this.req.getHeader("x-forwarded-proto") || "http",
|
|
639
|
+
url: this.req.getUrl(),
|
|
640
|
+
headers: {}
|
|
641
|
+
};
|
|
642
|
+
this.req.forEach((key, value) => this.contextWeb.headers[key] = value);
|
|
643
|
+
const type = this.contextWeb.headers["content-type"] || "application/json";
|
|
644
|
+
request = Object.assign({}, this.defaultRequest, request, querystring__default['default'].parse(this.req.getQuery()));
|
|
645
|
+
if (type.indexOf("application/json") !== -1 || type.indexOf("text/json") !== -1) {
|
|
646
|
+
Object.assign(request, await jsonBody(this.res, this.req));
|
|
647
|
+
} else if (!["get", "head"].includes(this.contextWeb.method) && type.indexOf("multipart/form-data") !== -1) {
|
|
648
|
+
Object.assign(request, await multipartBody(this.res, this.req));
|
|
649
|
+
} else if (!["get", "head"].includes(this.contextWeb.method) && type.indexOf("application/x-www-form-urlencoded") !== -1) {
|
|
650
|
+
Object.assign(request, await urlencodedBody(this.res, this.req));
|
|
651
|
+
} else if (!["get", "head"].includes(this.contextWeb.method) && (type.indexOf("application/xml") !== -1 || type.indexOf("text/xml") !== -1)) {
|
|
652
|
+
const raw = (await rawBody(this.res, this.req)).toString();
|
|
653
|
+
const records = xmljs__default['default'].xml2js(raw, { compact: true, cdataKey: "_value", textKey: "_value" });
|
|
654
|
+
Object.assign(request, records || {});
|
|
655
|
+
} else if (!["get", "head"].includes(this.contextWeb.method) && type.indexOf("application/octet-stream") !== -1) {
|
|
656
|
+
Object.defineProperty(this.contextWeb, "$stream", {
|
|
657
|
+
enumerable: false,
|
|
658
|
+
configurable: false,
|
|
659
|
+
writable: false,
|
|
660
|
+
value: await streamBody(this.res, this.req)
|
|
661
|
+
});
|
|
662
|
+
} else {
|
|
663
|
+
Object.defineProperty(this.contextWeb, "$body", {
|
|
664
|
+
enumerable: false,
|
|
665
|
+
configurable: false,
|
|
666
|
+
writable: false,
|
|
667
|
+
value: await rawBody(this.res, this.req)
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
this.route = this.findRoute(request);
|
|
671
|
+
Object.assign(this.contextWeb, await selectControllerParams(this.contextWeb.db.home, this.contextWeb.method, this.route.name, request.subaction));
|
|
672
|
+
Object.defineProperty(this.contextWeb, "$route", {
|
|
673
|
+
enumerable: false,
|
|
674
|
+
configurable: false,
|
|
675
|
+
writable: false,
|
|
676
|
+
value: this.route
|
|
677
|
+
});
|
|
678
|
+
const controllerClass = await this.importController(request);
|
|
679
|
+
this.contextWeb.getRequest = () => request;
|
|
680
|
+
const controller = new controllerClass();
|
|
681
|
+
this.injectContext(controller);
|
|
682
|
+
const initResponse = await this.initComponent(controller);
|
|
683
|
+
if (typeof initResponse === "undefined") {
|
|
684
|
+
if (request.subaction in controller) {
|
|
685
|
+
response = await controller[request.subaction]();
|
|
686
|
+
} else {
|
|
687
|
+
throw new ApiError$1.ApiError({
|
|
688
|
+
statusCode: 404,
|
|
689
|
+
code: 13,
|
|
690
|
+
message: `Method ${request.subaction} not found in ${request.controller} route`
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
} else {
|
|
694
|
+
response = initResponse;
|
|
695
|
+
}
|
|
696
|
+
response = Object.assign({}, this.defaultResponse, response);
|
|
697
|
+
this.success(response);
|
|
698
|
+
} catch (e) {
|
|
699
|
+
this.error(e);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
async importController(request) {
|
|
703
|
+
let controllerClass = this.route.component.default || this.route.component;
|
|
704
|
+
if (!easyAsh.isClass(controllerClass)) {
|
|
705
|
+
controllerClass = (await this.route.component()).default;
|
|
706
|
+
}
|
|
707
|
+
if (typeof controllerClass !== "function") {
|
|
708
|
+
throw new ApiError$1.ApiError({
|
|
709
|
+
statusCode: 404,
|
|
710
|
+
code: 12,
|
|
711
|
+
message: `Class not found for ${request.controller} route`
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
return controllerClass;
|
|
715
|
+
}
|
|
716
|
+
findRoute(request) {
|
|
717
|
+
const route = this.context.routes.filter((v) => v.name === request.controller && (v.method === this.contextWeb.method || v.method === "any" || Array.isArray(v.method) && v.method.includes(this.contextWeb.method) || typeof v.method === "undefined"))?.[0];
|
|
718
|
+
if (!route) {
|
|
719
|
+
throw new ApiError$1.ApiError({
|
|
720
|
+
statusCode: 404,
|
|
721
|
+
code: 11,
|
|
722
|
+
message: `Route ${request.controller} not found`
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
return route;
|
|
726
|
+
}
|
|
727
|
+
injectContext(obj) {
|
|
728
|
+
if ("$inject" in obj) {
|
|
729
|
+
obj.$inject(this.contextWeb);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
async initComponent(obj) {
|
|
733
|
+
const inits = ["init", ...obj.$inits || []];
|
|
734
|
+
for (const method of inits) {
|
|
735
|
+
if (obj[method]) {
|
|
736
|
+
const out = await obj[method]();
|
|
737
|
+
if (out) {
|
|
738
|
+
return out;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
success(response) {
|
|
744
|
+
const status = codeToStatus(response.statusCode || 200);
|
|
745
|
+
const body = easyAsh.isObject(response.body) ? JSON.stringify(response.body) : response.body;
|
|
746
|
+
this.res.writeStatus(status);
|
|
747
|
+
Object.entries(response.headers).map(([key, value]) => this.res.writeHeader(key, value));
|
|
748
|
+
this.res.end(body);
|
|
749
|
+
}
|
|
750
|
+
error(e) {
|
|
751
|
+
let status = codeToStatus(404), headers = {}, body = e.message;
|
|
752
|
+
if (e instanceof ApiError$1.ApiError) {
|
|
753
|
+
const data = { message: e.getMessage() };
|
|
754
|
+
status = codeToStatus(e.getStatusCode());
|
|
755
|
+
headers = e.getHeaders();
|
|
756
|
+
body = easyAsh.isObject(e.getData()) && Object.keys(e.getData()).length > 0 ? JSON.stringify(e.getData()) : JSON.stringify(data);
|
|
757
|
+
}
|
|
758
|
+
this.res.writeStatus(status);
|
|
759
|
+
Object.entries(headers).map(([key, value]) => this.res.writeHeader(key, value));
|
|
760
|
+
this.res.end(body);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
const config = readConfigSync("./connect.json");
|
|
765
|
+
const mountWithContext = async ($class, $context, request = {}) => {
|
|
766
|
+
const initComponent = async (obj2) => {
|
|
767
|
+
let out;
|
|
768
|
+
if ("init" in obj2) {
|
|
769
|
+
out = await obj2.init();
|
|
770
|
+
}
|
|
771
|
+
return out;
|
|
772
|
+
};
|
|
773
|
+
const injectContext = (obj2, $context2) => {
|
|
774
|
+
if ("$inject" in obj2) {
|
|
775
|
+
obj2.$inject($context2);
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
$context = Object.assign({
|
|
779
|
+
config,
|
|
780
|
+
getRequest: () => request,
|
|
781
|
+
method: "get",
|
|
782
|
+
...request.controller && request.subaction && $context.db?.home ? await selectControllerParams($context.db.home, $context.method || "get", request.controller, request.subaction) : {},
|
|
783
|
+
cookies: {},
|
|
784
|
+
hostname: config.server?.development?.host,
|
|
785
|
+
protocol: "http",
|
|
786
|
+
headers: {}
|
|
787
|
+
}, $context);
|
|
788
|
+
const obj = new $class();
|
|
789
|
+
injectContext(obj, $context);
|
|
790
|
+
const initResponse = await initComponent(obj);
|
|
791
|
+
if (initResponse) {
|
|
792
|
+
throw new ApiError$1.ApiError({
|
|
793
|
+
statusCode: 404,
|
|
794
|
+
code: 13,
|
|
795
|
+
message: `init method response value`
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
return obj;
|
|
799
|
+
};
|
|
800
|
+
|
|
801
|
+
const xmlOptions = { compact: true, ignoreComment: true, spaces: 4 };
|
|
802
|
+
class Controller {
|
|
803
|
+
setCookieHeader(name, value, options = {}) {
|
|
804
|
+
return cookieString(name, value, options);
|
|
805
|
+
}
|
|
806
|
+
success(data = {}, options) {
|
|
807
|
+
return {
|
|
808
|
+
headers: options?.headers || { "content-type": "application/json" },
|
|
809
|
+
body: {
|
|
810
|
+
isError: false,
|
|
811
|
+
data
|
|
812
|
+
},
|
|
813
|
+
memcache: options?.memcache || null,
|
|
814
|
+
statusCode: options?.statusCode || 200
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
error(err) {
|
|
818
|
+
const e = err;
|
|
819
|
+
const code = e.code ? e.code : 0;
|
|
820
|
+
const message = e.message ? e.message : "Api request error";
|
|
821
|
+
const statusCode = e.statusCode ? e.statusCode : 404;
|
|
822
|
+
const data = e.data ? e.data : {};
|
|
823
|
+
const response = e.response ? {
|
|
824
|
+
status: e.response.status,
|
|
825
|
+
headers: e.response.headers,
|
|
826
|
+
config: {
|
|
827
|
+
url: e.response.url,
|
|
828
|
+
method: e.response.method,
|
|
829
|
+
params: e.response.params,
|
|
830
|
+
headers: e.response.headers
|
|
831
|
+
},
|
|
832
|
+
data: e.response.data
|
|
833
|
+
} : {};
|
|
834
|
+
const headers = Object.assign({ "content-type": "application/json" }, e.headers);
|
|
835
|
+
return {
|
|
836
|
+
headers,
|
|
837
|
+
body: {
|
|
838
|
+
isError: true,
|
|
839
|
+
error: message,
|
|
840
|
+
code,
|
|
841
|
+
data,
|
|
842
|
+
stack: process.env.NODE_ENV !== "production" ? e.stack : "",
|
|
843
|
+
response: process.env.NODE_ENV !== "production" ? response : {}
|
|
844
|
+
},
|
|
845
|
+
statusCode
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
successXml(data = {}, options) {
|
|
849
|
+
const defaultXml = {
|
|
850
|
+
_declaration: {
|
|
851
|
+
_attributes: {
|
|
852
|
+
version: "1.0",
|
|
853
|
+
encoding: "utf-8"
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
const response = this.success(data, options);
|
|
858
|
+
return {
|
|
859
|
+
headers: options?.headers || { "content-type": "application/xml" },
|
|
860
|
+
body: xmljs__default['default'].js2xml(Object.assign(defaultXml, { body: { ...response.body } }), xmlOptions),
|
|
861
|
+
memcache: response.memcache
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
errorXml(err) {
|
|
865
|
+
const e = err;
|
|
866
|
+
const defaultXml = {
|
|
867
|
+
_declaration: {
|
|
868
|
+
_attributes: {
|
|
869
|
+
version: "1.0",
|
|
870
|
+
encoding: "utf-8"
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
const response = this.error(e);
|
|
875
|
+
const headers = Object.assign({ "content-type": "application/json" }, e.headers);
|
|
876
|
+
return {
|
|
877
|
+
headers,
|
|
878
|
+
body: xmljs__default['default'].js2xml(Object.assign(defaultXml, { body: { ...response.body } }), xmlOptions),
|
|
879
|
+
statusCode: response.statusCode
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
async $create(model, ...args) {
|
|
883
|
+
const obj = new model(...args);
|
|
884
|
+
if ("$inject" in obj) {
|
|
885
|
+
obj.$inject({
|
|
886
|
+
method: this.$context.method,
|
|
887
|
+
getRequest: this.$context.getRequest,
|
|
888
|
+
config: this.$context.config,
|
|
889
|
+
db: this.$context.db,
|
|
890
|
+
headers: this.$context.headers,
|
|
891
|
+
controller: this.$context.controller,
|
|
892
|
+
action: this.$context.action,
|
|
893
|
+
subaction: this.$context.subaction
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
const inits = ["init", ...obj.$inits || []];
|
|
897
|
+
for (const method of inits) {
|
|
898
|
+
if (obj[method]) {
|
|
899
|
+
await obj[method]();
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
return obj;
|
|
903
|
+
}
|
|
904
|
+
$inject(context) {
|
|
905
|
+
this.$context = context;
|
|
906
|
+
}
|
|
907
|
+
getContext() {
|
|
908
|
+
return this.$context;
|
|
909
|
+
}
|
|
910
|
+
getRequest() {
|
|
911
|
+
return this.$context.getRequest();
|
|
912
|
+
}
|
|
913
|
+
getBody() {
|
|
914
|
+
return this.$context["$body"] || Buffer.from("");
|
|
915
|
+
}
|
|
916
|
+
getStream() {
|
|
917
|
+
return this.$context["$stream"] || new stream.PassThrough().end();
|
|
918
|
+
}
|
|
919
|
+
getConfig() {
|
|
920
|
+
return this.$context.config;
|
|
921
|
+
}
|
|
922
|
+
getMethod() {
|
|
923
|
+
return this.$context.method;
|
|
924
|
+
}
|
|
925
|
+
getCookies() {
|
|
926
|
+
return this.$context.cookies;
|
|
927
|
+
}
|
|
928
|
+
getHostname() {
|
|
929
|
+
return this.$context.hostname;
|
|
930
|
+
}
|
|
931
|
+
getUrl() {
|
|
932
|
+
return this.$context.url;
|
|
933
|
+
}
|
|
934
|
+
getProtocol() {
|
|
935
|
+
return this.$context.protocol;
|
|
936
|
+
}
|
|
937
|
+
getDb() {
|
|
938
|
+
return this.$context.db;
|
|
939
|
+
}
|
|
940
|
+
getHeaders() {
|
|
941
|
+
return this.$context.headers;
|
|
942
|
+
}
|
|
943
|
+
getController() {
|
|
944
|
+
return this.$context.controller;
|
|
945
|
+
}
|
|
946
|
+
getAction() {
|
|
947
|
+
return this.$context.action;
|
|
948
|
+
}
|
|
949
|
+
getSubaction() {
|
|
950
|
+
return this.$context.subaction;
|
|
951
|
+
}
|
|
952
|
+
getHome() {
|
|
953
|
+
return this.getDb().home;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
class Model {
|
|
958
|
+
async $create(model, ...args) {
|
|
959
|
+
const obj = new model(...args);
|
|
960
|
+
if ("$inject" in obj) {
|
|
961
|
+
obj.$inject({
|
|
962
|
+
method: this.$context.method,
|
|
963
|
+
getRequest: this.$context.getRequest,
|
|
964
|
+
config: this.$context.config,
|
|
965
|
+
db: this.$context.db,
|
|
966
|
+
headers: this.$context.headers,
|
|
967
|
+
controller: this.$context.controller,
|
|
968
|
+
action: this.$context.action,
|
|
969
|
+
subaction: this.$context.subaction
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
if ("init" in obj) {
|
|
973
|
+
await obj.init();
|
|
974
|
+
}
|
|
975
|
+
return obj;
|
|
976
|
+
}
|
|
977
|
+
$inject(context) {
|
|
978
|
+
this.$context = context;
|
|
979
|
+
}
|
|
980
|
+
getContext() {
|
|
981
|
+
return this.$context;
|
|
982
|
+
}
|
|
983
|
+
getRequest() {
|
|
984
|
+
return this.$context.getRequest();
|
|
985
|
+
}
|
|
986
|
+
getConfig() {
|
|
987
|
+
return this.$context.config;
|
|
988
|
+
}
|
|
989
|
+
getMethod() {
|
|
990
|
+
return this.$context.method;
|
|
991
|
+
}
|
|
992
|
+
getHeaders() {
|
|
993
|
+
return this.$context.headers;
|
|
994
|
+
}
|
|
995
|
+
getController() {
|
|
996
|
+
return this.$context.controller;
|
|
997
|
+
}
|
|
998
|
+
getAction() {
|
|
999
|
+
return this.$context.action;
|
|
1000
|
+
}
|
|
1001
|
+
getSubaction() {
|
|
1002
|
+
return this.$context.subaction;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
378
1006
|
const helpers = {
|
|
379
1007
|
cookieParse: Server.cookieParse,
|
|
380
1008
|
cookieString,
|
|
381
1009
|
jsonBody,
|
|
1010
|
+
rawBody,
|
|
1011
|
+
streamBody,
|
|
382
1012
|
urlencodedBody,
|
|
383
1013
|
multipartBody,
|
|
384
1014
|
readConfig,
|
|
@@ -392,5 +1022,10 @@ exports.ApiError = ApiError.ApiError;
|
|
|
392
1022
|
exports.Server = Server.Server;
|
|
393
1023
|
exports.codeToStatus = Server.codeToStatus;
|
|
394
1024
|
exports.Jwt = Jwt.Jwt;
|
|
1025
|
+
exports.Controller = Controller;
|
|
395
1026
|
exports.Memcached = Memcached;
|
|
1027
|
+
exports.Model = Model;
|
|
1028
|
+
exports.Ssr = Ssr;
|
|
1029
|
+
exports.Web = Web;
|
|
396
1030
|
exports.helpers = helpers;
|
|
1031
|
+
exports.mount = mountWithContext;
|