@jwn-js/common 2.2.1 → 2.2.3

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.
Files changed (82) hide show
  1. package/ApiError.js +37 -1
  2. package/ApiError.mjs +35 -1
  3. package/Jwt-B4QZ2Ypb.js +80 -0
  4. package/Jwt-Be4GWrIO.js +75 -0
  5. package/Jwt.js +8 -1
  6. package/Jwt.mjs +2 -1
  7. package/Memcached.js +166 -9
  8. package/Memcached.mjs +164 -9
  9. package/Server.js +316 -1
  10. package/Server.mjs +313 -1
  11. package/cookieParse.js +25 -1
  12. package/cookieParse.mjs +23 -1
  13. package/cookieString.js +22 -1
  14. package/cookieString.mjs +20 -1
  15. package/docs/classes/ApiError.html +2 -2
  16. package/docs/classes/AsyncJwt.html +2 -2
  17. package/docs/classes/Controller.html +2 -2
  18. package/docs/classes/Jwt.html +2 -2
  19. package/docs/classes/Memcached.html +2 -2
  20. package/docs/classes/Model.html +2 -2
  21. package/docs/classes/Server.html +2 -2
  22. package/docs/classes/Ssr.html +2 -2
  23. package/docs/classes/Web.html +2 -2
  24. package/docs/functions/action.html +2 -2
  25. package/docs/functions/body.html +2 -2
  26. package/docs/functions/codeToStatus.html +2 -2
  27. package/docs/functions/config.html +2 -2
  28. package/docs/functions/connection.html +2 -2
  29. package/docs/functions/context.html +2 -2
  30. package/docs/functions/controller-1.html +2 -2
  31. package/docs/functions/cookies.html +2 -2
  32. package/docs/functions/db.html +2 -2
  33. package/docs/functions/headers.html +2 -2
  34. package/docs/functions/home.html +2 -2
  35. package/docs/functions/hostname.html +2 -2
  36. package/docs/functions/http.html +2 -2
  37. package/docs/functions/init.html +2 -2
  38. package/docs/functions/json.html +2 -2
  39. package/docs/functions/logerror.html +2 -2
  40. package/docs/functions/method.html +2 -2
  41. package/docs/functions/mixin.html +2 -2
  42. package/docs/functions/mount.html +2 -2
  43. package/docs/functions/pool.html +2 -2
  44. package/docs/functions/protocol.html +2 -2
  45. package/docs/functions/request.html +2 -2
  46. package/docs/functions/selectControllersSchema.html +1 -1
  47. package/docs/functions/stream.html +2 -2
  48. package/docs/functions/subaction.html +2 -2
  49. package/docs/functions/url.html +2 -2
  50. package/docs/functions/xml.html +2 -2
  51. package/docs/index.html +2 -2
  52. package/docs/interfaces/ApiErrorMessage.html +2 -2
  53. package/docs/interfaces/ContextSsr.html +2 -2
  54. package/docs/interfaces/ContextWeb.html +2 -2
  55. package/docs/interfaces/OptionsSsr.html +2 -2
  56. package/docs/interfaces/OptionsWeb.html +2 -2
  57. package/docs/interfaces/ResponseOptions.html +2 -2
  58. package/docs/interfaces/Route.html +2 -2
  59. package/docs/interfaces/Schema.html +2 -2
  60. package/docs/interfaces/ServerHandler.html +2 -2
  61. package/docs/interfaces/ServerOptions.html +2 -2
  62. package/docs/interfaces/ServerWebsocket.html +2 -2
  63. package/docs/modules.html +2 -2
  64. package/docs/types/ServerRoutes.html +1 -1
  65. package/docs/variables/helpers.html +2 -2
  66. package/index.js +1473 -4
  67. package/index.mjs +1417 -4
  68. package/jsonBody.js +25 -1
  69. package/jsonBody.mjs +23 -1
  70. package/multipartBody.js +42 -1
  71. package/multipartBody.mjs +40 -1
  72. package/package.json +1 -1
  73. package/readConfig.js +11 -1
  74. package/readConfig.mjs +9 -1
  75. package/readConfigSync.js +11 -1
  76. package/readConfigSync.mjs +9 -1
  77. package/staticBody.js +205 -1
  78. package/staticBody.mjs +200 -1
  79. package/urlencodedBody.js +26 -1
  80. package/urlencodedBody.mjs +24 -1
  81. package/Jwt-7tQL-rwa.js +0 -1
  82. package/Jwt-CDdbxwvH.js +0 -1
package/index.mjs CHANGED
@@ -1,4 +1,222 @@
1
- import{ApiError as h}from"./ApiError.mjs";import{codeToStatus as _}from"./Server.mjs";import{Server as pe}from"./Server.mjs";import{t as v,f as x,u as U}from"./Jwt-7tQL-rwa.js";import{J as ge}from"./Jwt-7tQL-rwa.js";import V,{webcrypto as X}from"crypto";import{TextEncoder as z}from"util";import{Memcached as $}from"./Memcached.mjs";import{jsonBody as O}from"./jsonBody.mjs";import{PassThrough as j,Stream as k}from"stream";import{urlencodedBody as H}from"./urlencodedBody.mjs";import{multipartBody as R}from"./multipartBody.mjs";import{readConfig as G}from"./readConfig.mjs";import{readConfigSync as Y}from"./readConfigSync.mjs";import{cookieParse as q}from"./cookieParse.mjs";import{cookieString as P}from"./cookieString.mjs";import{getExt as W,extensions as E,staticBody as N}from"./staticBody.mjs";import*as M from"fs";import*as Z from"path";import tt from"path";import{isClass as et,isObject as B,omit as st}from"easy-ash";import ot from"querystring";import S from"xml-js";import*as nt from"os";import"reflect-metadata";import"dns";import"uWebSockets.js";import"formidable";const{subtle:D}=X;class it{constructor(e,t){this.algorithm="SHA-256",this.secret=e,this.algorithm=t?.algorithm||this.algorithm,this.algorithm=this.algorithm.replace("-","").replace("SHA","SHA-")}async verify(e){if(!e)return!1;const t=e.split(".");return await this.signString(`${t[0]}.${t[1]}`)===t[2]}async sign(e){const t=v({alg:this.algorithm.replace("-","").replace("SHA","HS"),typ:"JWT"}),s=v(e),n=await this.signString(`${t}.${s}`);return`${t}.${s}.${n}`}decode(e){const t=(e||"").split("."),s=x(t[0]),n=x(t[1]);return{head:s,body:n}}async signString(e){const t=new z,s=await D.importKey("raw",t.encode(this.secret),{name:"HMAC",hash:{name:this.algorithm}},!1,["sign","verify"]);return U(Buffer.from(await D.sign("HMAC",s,t.encode(e))).toString("base64"))}}const rt=o=>{const e=(o||"").split("."),t=x(e[0]),s=x(e[1]);return{head:t,body:s}},C=o=>new Promise((e,t)=>{at(o,s=>e(s),()=>{t(new h({message:"Can`t parse request",code:1,statusCode:404}))})});function at(o,e,t){let s=Buffer.from([]);o.onData((n,i)=>{s=Buffer.concat([s,Buffer.from(n)]),i&&e(s)}),o.onAborted(t)}const w=(o,e,t=!0)=>{o.onAborted(()=>new h({message:"Connection aborted",code:1,statusCode:404}));const s=new j;return s.headers={},e.forEach((n,i)=>s.headers[n]=i),o.onData((n,i)=>{s.write(Buffer.from(Buffer.from(n))),t&&s.resume(),i&&s.end()}),s},ct=(o,e={})=>{for(const t of o){const s=Z.resolve(t);Object.assign(e,JSON.parse(M.readFileSync(s).toString()))}return e};class ht{constructor(e,t,s,n){this.res=e,this.req=t,this.context=s,this.entry=n}async request(e={}){this.res.onAborted(()=>{console.log("Abort is SSR handler")});const t=this.req.getQuery(),s=this.req.getUrl()+(t?`?${t}`:""),n=W(s);if(E.includes(n)){await N(this.res,this.req,"./dist/client");return}const i={hostname:this.req.getHeader("host"),protocol:this.req.getHeader("x-forwarded-proto")||"http",url:this.req.getUrl(),cookies:q(this.req.getHeader("cookie")),ip:this.req.getHeader("x-forwarded-for")?.split(/,\s+/)?.[0],memcache:null,statusCode:200,headers:{},responseHeaders:{"content-type":"text/html; charset=utf-8"}};this.req.forEach((c,l)=>i.headers[c]=l);const a=`${i.protocol}://${i.hostname}${i.url}`;let r,d=null;this.context.memcached&&(d=await this.context.memcached.getPage(a)),d?(r=d.data.toString(),i.headers=d.headers):({html:r}=await this.entry(s,{manifest:this.context.manifest,res:this.res,req:this.req,context:i}),i.statusCode===200&&this.context.memcached&&await this.context.memcached.setPage(a,i.headers,r,i.memcache)),this.res.writeStatus(_(i.statusCode)),Object.keys(i.headers).map(c=>this.res.writeHeader(c,i.headers[c])),this.res.end(r)}}const dt=async(o,e,t)=>(await o.poolQuery({sql:`
1
+ import { ApiError } from './ApiError.mjs';
2
+ import { codeToStatus } from './Server.mjs';
3
+ export { Server } from './Server.mjs';
4
+ import { t as toBase64url, f as fromBase64url, u as urlEncode } from './Jwt-Be4GWrIO.js';
5
+ export { J as Jwt } from './Jwt-Be4GWrIO.js';
6
+ import crypto, { webcrypto } from 'crypto';
7
+ import { TextEncoder } from 'util';
8
+ import { Memcached } from './Memcached.mjs';
9
+ import { jsonBody } from './jsonBody.mjs';
10
+ import { PassThrough, Stream } from 'stream';
11
+ import { urlencodedBody } from './urlencodedBody.mjs';
12
+ import { multipartBody } from './multipartBody.mjs';
13
+ import { readConfig } from './readConfig.mjs';
14
+ import { readConfigSync } from './readConfigSync.mjs';
15
+ import { cookieParse } from './cookieParse.mjs';
16
+ import { cookieString } from './cookieString.mjs';
17
+ import { getExt, extensions, staticBody } from './staticBody.mjs';
18
+ import * as fs from 'fs';
19
+ import * as path from 'path';
20
+ import path__default from 'path';
21
+ import { isClass, isObject, omit } from 'easy-ash';
22
+ import querystring from 'querystring';
23
+ import xmljs from 'xml-js';
24
+ import * as os from 'os';
25
+ import 'reflect-metadata';
26
+ import 'dns';
27
+ import 'uWebSockets.js';
28
+ import 'formidable';
29
+
30
+ const { subtle } = webcrypto;
31
+ class AsyncJwt {
32
+ /**
33
+ * @constructor
34
+ * @param secret
35
+ * @param opt addition options
36
+ */
37
+ constructor(secret, opt) {
38
+ this.algorithm = "SHA-256";
39
+ this.secret = secret;
40
+ this.algorithm = opt?.algorithm || this.algorithm;
41
+ this.algorithm = this.algorithm.replace("-", "").replace("SHA", "SHA-");
42
+ }
43
+ /**
44
+ * Verify jwt token
45
+ * @param jwt token
46
+ * @returns is token valid
47
+ */
48
+ async verify(jwt) {
49
+ if (!jwt) {
50
+ return false;
51
+ }
52
+ const parts = jwt.split(".");
53
+ const signature = await this.signString(`${parts[0]}.${parts[1]}`);
54
+ return signature === parts[2];
55
+ }
56
+ /**
57
+ * Get token
58
+ * @param data - user data
59
+ * @returns jwt
60
+ */
61
+ async sign(data) {
62
+ const head = toBase64url({
63
+ alg: this.algorithm.replace("-", "").replace("SHA", "HS"),
64
+ typ: "JWT"
65
+ });
66
+ const body = toBase64url(data);
67
+ const signature = await this.signString(`${head}.${body}`);
68
+ return `${head}.${body}.${signature}`;
69
+ }
70
+ /**
71
+ * Decode token
72
+ * @param jwt - jwt token
73
+ * @returns {head, body}
74
+ */
75
+ decode(jwt) {
76
+ const parts = (jwt || "").split(".");
77
+ const head = fromBase64url(parts[0]);
78
+ const body = fromBase64url(parts[1]);
79
+ return { head, body };
80
+ }
81
+ /**
82
+ * Sign
83
+ * @param str input string
84
+ * @returns base64 sign
85
+ * @private
86
+ */
87
+ async signString(str) {
88
+ const enc = new TextEncoder();
89
+ const key = await subtle.importKey(
90
+ "raw",
91
+ enc.encode(this.secret),
92
+ {
93
+ name: "HMAC",
94
+ hash: {
95
+ name: this.algorithm
96
+ }
97
+ },
98
+ false,
99
+ ["sign", "verify"]
100
+ );
101
+ return urlEncode(Buffer.from(await subtle.sign(
102
+ "HMAC",
103
+ key,
104
+ enc.encode(str)
105
+ )).toString("base64"));
106
+ }
107
+ }
108
+
109
+ const jwtDecode = (jwt) => {
110
+ const parts = (jwt || "").split(".");
111
+ const head = fromBase64url(parts[0]);
112
+ const body = fromBase64url(parts[1]);
113
+ return { head, body };
114
+ };
115
+
116
+ const rawBody = (res) => new Promise((resolve, reject) => {
117
+ readRaw(res, (obj) => resolve(obj), () => {
118
+ reject(new ApiError({ message: "Can`t parse request", code: 1, statusCode: 404 }));
119
+ });
120
+ });
121
+ function readRaw(res, cb, err) {
122
+ let buffer = Buffer.from([]);
123
+ res.onData((ab, isLast) => {
124
+ buffer = Buffer.concat([buffer, Buffer.from(ab)]);
125
+ isLast && cb(buffer);
126
+ });
127
+ res.onAborted(err);
128
+ }
129
+
130
+ const streamBody = (res, req, resume = true) => {
131
+ res.onAborted(() => new ApiError({ message: "Connection aborted", code: 1, statusCode: 404 }));
132
+ const stream = new PassThrough();
133
+ stream.headers = {};
134
+ req.forEach((key, val) => stream.headers[key] = val);
135
+ res.onData((chunk, isLast) => {
136
+ stream.write(Buffer.from(Buffer.from(chunk)));
137
+ resume && stream.resume();
138
+ isLast && stream.end();
139
+ });
140
+ return stream;
141
+ };
142
+
143
+ const readJsonConfigsSync = (configs, input = {}) => {
144
+ for (const config of configs) {
145
+ const filePath = path.resolve(config);
146
+ Object.assign(input, JSON.parse(fs.readFileSync(filePath).toString()));
147
+ }
148
+ return input;
149
+ };
150
+
151
+ class Ssr {
152
+ /**
153
+ * @constructor
154
+ * @param res response
155
+ * @param req request
156
+ * @param context params
157
+ * @param entry - entry point function
158
+ */
159
+ constructor(res, req, context, entry) {
160
+ this.res = res;
161
+ this.req = req;
162
+ this.context = context;
163
+ this.entry = entry;
164
+ }
165
+ /**
166
+ * @param request addition request params
167
+ */
168
+ async request(request = {}) {
169
+ this.res.onAborted(() => {
170
+ console.log("Abort is SSR handler");
171
+ });
172
+ const query = this.req.getQuery();
173
+ const url = this.req.getUrl() + (query ? `?${query}` : "");
174
+ const extension = getExt(url);
175
+ if (extensions.includes(extension)) {
176
+ await staticBody(this.res, this.req, "./dist/client");
177
+ return;
178
+ }
179
+ const contextSsr = {
180
+ hostname: this.req.getHeader("host"),
181
+ protocol: this.req.getHeader("x-forwarded-proto") || "http",
182
+ url: this.req.getUrl(),
183
+ cookies: cookieParse(this.req.getHeader("cookie")),
184
+ ip: this.req.getHeader("x-forwarded-for")?.split(/,\s+/)?.[0],
185
+ memcache: null,
186
+ statusCode: 200,
187
+ headers: {},
188
+ responseHeaders: {
189
+ "content-type": "text/html; charset=utf-8"
190
+ }
191
+ };
192
+ this.req.forEach((key2, value) => contextSsr.headers[key2] = value);
193
+ const key = `${contextSsr.protocol}://${contextSsr.hostname}${contextSsr.url}`;
194
+ let html, page = null;
195
+ if (this.context.memcached) {
196
+ page = await this.context.memcached.getPage(key);
197
+ }
198
+ if (page) {
199
+ html = page.data.toString();
200
+ contextSsr.headers = page.headers;
201
+ } else {
202
+ ({ html } = await this.entry(url, {
203
+ manifest: this.context.manifest,
204
+ res: this.res,
205
+ req: this.req,
206
+ context: contextSsr
207
+ }));
208
+ if (contextSsr.statusCode === 200 && this.context.memcached) {
209
+ await this.context.memcached.setPage(key, contextSsr.headers, html, contextSsr.memcache);
210
+ }
211
+ }
212
+ this.res.writeStatus(codeToStatus(contextSsr.statusCode));
213
+ Object.keys(contextSsr.headers).map((key2) => this.res.writeHeader(key2, contextSsr.headers[key2]));
214
+ this.res.end(html);
215
+ }
216
+ }
217
+
218
+ const selectRouteController = async (db, name, subaction) => {
219
+ return (await db.poolQuery({ sql: `
2
220
  SELECT c.id AS controller_id,
3
221
  c.name AS controller_name,
4
222
  c.is_active AS controller_is_active,
@@ -17,7 +235,10 @@ import{ApiError as h}from"./ApiError.mjs";import{codeToStatus as _}from"./Server
17
235
  INNER JOIN app_subactions s ON s.app_controllers_id = c.id
18
236
  LEFT JOIN app_actions a ON a.id = s.app_actions_id
19
237
  WHERE c.name = :name AND s.name = :subaction
20
- `,namedPlaceholders:!0},{name:e,subaction:t}))?.[0],ut=async o=>(await o.poolQuery(`
238
+ `, namedPlaceholders: true }, { name, subaction }))?.[0];
239
+ };
240
+ const selectAll = async (db) => {
241
+ const rows = await db.poolQuery(`
21
242
  SELECT c.id AS controller_id,
22
243
  c.name AS controller_name,
23
244
  c.is_active AS controller_is_active,
@@ -35,7 +256,113 @@ import{ApiError as h}from"./ApiError.mjs";import{codeToStatus as _}from"./Server
35
256
  FROM app_controllers c
36
257
  INNER JOIN app_subactions s ON s.app_controllers_id = c.id
37
258
  LEFT JOIN app_actions a ON a.id = s.app_actions_id;
38
- `)).reduce((e,t)=>(e[`${t.controller_name}::${t.subaction_name}`]=t,e),{}),mt=async(o,e,t,s,n="",i=3600)=>{const a=`${n}::routes::controllers`,r=`${e}::${t}`,d=await s.getValue(a);if(d){const c=JSON.parse(d.toString());return(c||{}).hasOwnProperty(r)?c[r]:void 0}else{const c=await ut(o);return await s.setValue(a,Buffer.from(JSON.stringify(c)),i),(c||{}).hasOwnProperty(r)?c[r]:void 0}},J=async(o,e,t,s,n,i="",a=3600)=>{let r;if(n&&n.isClient()&&n.isConnectedServers()?r=await mt(o,t,s,n,i,a):r=await dt(o,t,s),!r)throw new h({statusCode:404,code:11,message:`Controller ${t} not found in site schema`});const d=(r?.action_method||"").split(",").map(c=>c.trim());if(r.controller_is_active!==1)throw new h({statusCode:404,code:11,message:`Controller ${t} not active in site schema`});if(!r.action_id)throw new h({statusCode:404,code:11,message:"Action not found in site schema"});if(r.action_is_active!==1)throw new h({statusCode:404,code:11,message:`Action ${r.action_name} not active in site schema`});if(!r.subaction_id)throw new h({statusCode:404,code:11,message:`Subaction ${s} not found in site schema`});if(r.subaction_is_active!==1)throw new h({statusCode:404,code:11,message:`Subaction ${s} not active in site schema`});if(r.subaction_is_check_method!==0&&r.action_method!=="any"&&!d.includes(e))throw new h({statusCode:404,code:11,message:`Controller ${t} action ${r.action_name} allow only ${r.action_method} method`});return{controller:{id:+r.controller_id,name:r.controller_name,isActive:!!r.controller_is_active,isSitemap:!!r.controller_is_sitemap},action:{id:+r.action_id,name:r.action_name,isActive:!!r.action_is_active,method:r.action_method},subaction:{id:+r.subaction_id,name:r.subaction_name,isPermission:!!r.subaction_is_permission,isCheckMethod:!!r.subaction_is_check_method,isLog:!!r.subaction_is_log,isActive:!!r.subaction_is_active,isSync:!1}}},lt=async o=>{const e={},t={};return(await o.poolQuery(`
259
+ `);
260
+ return rows.reduce((ac, row) => {
261
+ ac[`${row.controller_name}::${row.subaction_name}`] = row;
262
+ return ac;
263
+ }, {});
264
+ };
265
+ const selectRouteControllerMemcached = async (db, name, subaction, memcached, memcachedPrefix = "", expires = 3600) => {
266
+ const key = `${memcachedPrefix}::routes::controllers`;
267
+ const index = `${name}::${subaction}`;
268
+ const schema = await memcached.getValue(key);
269
+ if (schema) {
270
+ const json = JSON.parse(schema.toString());
271
+ return (json || {}).hasOwnProperty(index) ? json[index] : void 0;
272
+ } else {
273
+ const all = await selectAll(db);
274
+ await memcached.setValue(key, Buffer.from(JSON.stringify(all)), expires);
275
+ return (all || {}).hasOwnProperty(index) ? all[index] : void 0;
276
+ }
277
+ };
278
+ const selectControllerParams = async (db, method, name, subaction, memcached, memcachedPrefix = "", expires = 3600) => {
279
+ let row;
280
+ if (memcached && memcached.isClient() && memcached.isConnectedServers()) {
281
+ row = await selectRouteControllerMemcached(db, name, subaction, memcached, memcachedPrefix, expires);
282
+ } else {
283
+ row = await selectRouteController(db, name, subaction);
284
+ }
285
+ if (!row) {
286
+ throw new ApiError({
287
+ statusCode: 404,
288
+ code: 11,
289
+ message: `Controller ${name} not found in site schema`
290
+ });
291
+ }
292
+ const allowMethods = (row?.action_method || "").split(",").map((method2) => method2.trim());
293
+ if (row.controller_is_active !== 1) {
294
+ throw new ApiError({
295
+ statusCode: 404,
296
+ code: 11,
297
+ message: `Controller ${name} not active in site schema`
298
+ });
299
+ }
300
+ if (!row.action_id) {
301
+ throw new ApiError({
302
+ statusCode: 404,
303
+ code: 11,
304
+ message: `Action not found in site schema`
305
+ });
306
+ }
307
+ if (row.action_is_active !== 1) {
308
+ throw new ApiError({
309
+ statusCode: 404,
310
+ code: 11,
311
+ message: `Action ${row.action_name} not active in site schema`
312
+ });
313
+ }
314
+ if (!row.subaction_id) {
315
+ throw new ApiError({
316
+ statusCode: 404,
317
+ code: 11,
318
+ message: `Subaction ${subaction} not found in site schema`
319
+ });
320
+ }
321
+ if (row.subaction_is_active !== 1) {
322
+ throw new ApiError({
323
+ statusCode: 404,
324
+ code: 11,
325
+ message: `Subaction ${subaction} not active in site schema`
326
+ });
327
+ }
328
+ if (row.subaction_is_check_method !== 0) {
329
+ if (row.action_method !== "any" && !allowMethods.includes(method)) {
330
+ throw new ApiError({
331
+ statusCode: 404,
332
+ code: 11,
333
+ message: `Controller ${name} action ${row.action_name} allow only ${row.action_method} method`
334
+ });
335
+ }
336
+ }
337
+ return {
338
+ controller: {
339
+ id: +row.controller_id,
340
+ name: row.controller_name,
341
+ isActive: !!row.controller_is_active,
342
+ isSitemap: !!row.controller_is_sitemap
343
+ },
344
+ action: {
345
+ id: +row.action_id,
346
+ name: row.action_name,
347
+ isActive: !!row.action_is_active,
348
+ method: row.action_method
349
+ },
350
+ subaction: {
351
+ id: +row.subaction_id,
352
+ name: row.subaction_name,
353
+ isPermission: !!row.subaction_is_permission,
354
+ isCheckMethod: !!row.subaction_is_check_method,
355
+ isLog: !!row.subaction_is_log,
356
+ isActive: !!row.subaction_is_active,
357
+ isSync: false
358
+ }
359
+ };
360
+ };
361
+
362
+ const selectControllersSchema = async (pool) => {
363
+ const actions = {};
364
+ const controllers = {};
365
+ const rows = await pool.poolQuery(`
39
366
  SELECT c.id AS controller_id,
40
367
  c.name AS controller_name,
41
368
  c.is_active AS controller_is_active,
@@ -54,4 +381,1090 @@ import{ApiError as h}from"./ApiError.mjs";import{codeToStatus as _}from"./Server
54
381
  FROM app_controllers c
55
382
  INNER JOIN app_subactions s ON s.app_controllers_id = c.id
56
383
  LEFT JOIN app_actions a ON a.id = s.app_actions_id;
57
- `)).forEach(s=>{e[s.action_name]={id:s.action_id,name:s.action_name,isActive:!!s.action_is_active,method:s.action_method},t[s.controller_name]=t[s.controller_name]||{id:s.controller_id,name:s.controller_name,isActive:!!s.controller_is_active,isSitemap:!!s.controller_is_sitemap,subactions:[]},t[s.controller_name].subactions.push({id:s.subaction_id,action:s.action_name,name:s.subaction_name,isPermission:!!s.subaction_is_permission,isCheckMethod:!!s.subaction_is_check_method,isLog:!!s.subaction_is_log,isActive:!!s.subaction_is_active,isSync:!!s.subaction_is_sync})}),{controllers:Object.values(t),actions:Object.values(e)}},I=(o,e,t,s)=>{let n=o.controllers.find(d=>d.name===t);if(!n)throw new h({statusCode:404,code:11,message:`Controller ${t} not found is site schema`});if(n=Object.assign({isActive:!0,isSitemap:!1},n),!n.isActive)throw new h({statusCode:404,code:11,message:`Controller ${t} not active is site schema`});let i=n.subactions.find(d=>d.name===s);if(!i)throw new h({statusCode:404,code:11,message:`Subaction ${s} not found is site schema`});if(i=Object.assign({isPermission:!1,isCheckMethod:!1,isLog:!1,isActive:!0},i),!i.isActive)throw new h({statusCode:404,code:11,message:`Subaction ${s} not active is site schema`});let a=o.actions.find(d=>d.name===i.action);if(!a)throw new h({statusCode:404,code:11,message:"Action not found is site schema"});if(a=Object.assign({isActive:!0,method:"any"},a),!a.isActive)throw new h({statusCode:404,code:11,message:`Action ${a.name} not active is site schema`});const r=(a?.method||"").split(",").map(d=>d.trim());if(i.isCheckMethod&&a.method!=="any"&&!r.includes(e))throw new h({statusCode:404,code:11,message:`Controller ${t} action ${a.name} allow only ${a.method} method`});return{controller:{id:n.id,name:n.name,isActive:n.isActive,isSitemap:n.isSitemap},subaction:{id:i.id,name:i.name,isPermission:i.isPermission,isCheckMethod:i.isCheckMethod,isLog:i.isLog,isActive:i.isActive,isSync:!!i.isSync},action:{id:a.id,name:a.name,isActive:a.isActive,method:a.method}}};class ft{constructor(e,t,s){this.defaultRequest={lang:"ru"},this.defaultResponse={statusCode:200,headers:{"content-type":"application/json"},body:{}},this.defaultControllerSubaction={controller:"Index",subaction:"index"},this.res=e,this.req=t,this.res.onAborted(()=>new h({message:"The connection was close",code:1,statusCode:404})),this.context=s}setDefaultRequest(e){return Object.assign(this.defaultRequest,e),this}async request(e={}){let t={};try{const s=this.req.getQuery(),n=Object.assign({},this.defaultRequest,e,ot.parse(this.req.getQuery()));this.contextWeb={config:this.context.config,db:this.context.db,method:this.req.getMethod(),cookies:this.req.cookies,hostname:this.req.getHeader("host"),protocol:this.req.getHeader("x-forwarded-proto")||"http",url:this.req.getUrl()+(s?`?${s}`:""),headers:{},stack:this.context.stack||{},getRequest:()=>n},this.memcachedKey=`${this.contextWeb.protocol}://${this.contextWeb.hostname}${this.contextWeb.url}`,this.req.forEach((c,l)=>this.contextWeb.headers[c]=l);const i=this.contextWeb.headers["content-type"]||"application/json";if(n.controller&&n.subaction&&this.context.schema&&(this.route=this.findRoute(n.controller),Object.defineProperty(this.contextWeb,"$route",{enumerable:!1,configurable:!1,writable:!1,value:this.route}),Object.assign(this.contextWeb,I(this.context.schema,this.contextWeb.method,this.route.name,n.subaction)),this.contextWeb.subaction.isSync)){["get","head"].includes(this.contextWeb.method)||Object.defineProperty(this.contextWeb,"$stream",{enumerable:!1,configurable:!1,writable:!1,value:w(this.res,this.req,!1)});const c=this.importControllerSync(n.controller),l=new c;if(this.injectContext(l),n.subaction in l)t=await l[n.subaction]();else throw new h({statusCode:404,code:13,message:`Method ${n.subaction} not found in ${n.controller} route`});t=Object.assign({},this.defaultResponse,t),this.success(t);return}if(["get","head"].includes(this.contextWeb.method)&&this.contextWeb?.stack?.memcached instanceof $){const c=this.contextWeb.stack.memcached;if(c.isConnectedServers()){const l=await c.getPage(this.memcachedKey);if(l){const{data:b,headers:g}=l;this.success({body:b.toString(),headers:g,statusCode:200})}}}if(n.controller=n.controller||this.defaultControllerSubaction.controller,n.subaction=n.subaction||this.defaultControllerSubaction.subaction,!["get","head"].includes(this.contextWeb.method))if(i.indexOf("application/json")!==-1||i.indexOf("text/json")!==-1)Object.assign(n,await O(this.res));else if(i.indexOf("multipart/form-data")!==-1)Object.assign(n,await R(this.res,this.req)),Object.defineProperty(this.contextWeb,"$files",{enumerable:!1,configurable:!1,writable:!1,value:n.files});else if(i.indexOf("application/x-www-form-urlencoded")!==-1)Object.assign(n,await H(this.res));else if(i.indexOf("application/xml")!==-1||i.indexOf("text/xml")!==-1){const c=(await C(this.res)).toString(),l=S.xml2js(c,{compact:!0,cdataKey:"_value",textKey:"_value"});Object.assign(n,l||{})}else i.indexOf("stream")!==-1?Object.defineProperty(this.contextWeb,"$stream",{enumerable:!1,configurable:!1,writable:!1,value:w(this.res,this.req,!1)}):i.indexOf("binary")!==-1?await new Promise(c=>{const l=w(this.res,this.req),b=nt.tmpdir(),g="./body_"+V.randomBytes(32).toString("hex"),u=tt.resolve(b,g),p=M.createWriteStream(u);l.pipe(p),Object.defineProperty(this.contextWeb,"$files",{enumerable:!1,configurable:!1,writable:!1,value:{body:{path:u}}}),l.on("end",()=>c(!0))}):Object.defineProperty(this.contextWeb,"$body",{enumerable:!1,configurable:!1,writable:!1,value:await C(this.res)});this.route=this.findRoute(n.controller),Object.assign(this.contextWeb,this.context.schema?I(this.context.schema,this.contextWeb.method,this.route.name,n.subaction):await J(this.contextWeb.db.home,this.contextWeb.method,this.route.name,n.subaction,this.context.stack?.memcached,this.context.stack?.memcachedPrefix,this.context.stack?.memcachedExpiry)),Object.defineProperty(this.contextWeb,"$route",{enumerable:!1,configurable:!1,writable:!1,value:this.route});const a=await this.importController(n.controller),r=new a;this.injectContext(r);const d=await this.initComponent(r);if(typeof d>"u")if(n.subaction in r)t=await r[n.subaction]();else throw new h({statusCode:404,code:13,message:`Method ${n.subaction} not found in ${n.controller} route`});else t=d;t=Object.assign({},this.defaultResponse,t),this.success(t)}catch(s){this.error(s)}}async importController(e){let t=this.route.component.default||this.route.component;if(et(t)||(t=(await this.route.component()).default),typeof t!="function")throw new h({statusCode:404,code:12,message:`Class not found for ${e} route`});return t}importControllerSync(e){const t=this.route.component.default||this.route.component;if(typeof t!="function")throw new h({statusCode:404,code:12,message:`Class not found for ${e} route`});return t}findRoute(e){const t=this.context.routes.filter(s=>s.name===e&&(s.method===this.contextWeb.method||s.method==="any"||Array.isArray(s.method)&&s.method.includes(this.contextWeb.method)||typeof s.method>"u"))?.[0];if(!t)throw new h({statusCode:404,code:11,message:`Route ${e} not found`});return t}injectContext(e){"$inject"in e&&e.$inject(this.contextWeb)}async initComponent(e){const t=[...new Set(["init",...e.$inits||[]])];for(const s of t)if(e[s]){const n=await e[s]();if(n)return n}}success(e){const t=e.body instanceof k,s=e.statusCode||200,n=_(s),i=!t&&B(e.body)?JSON.stringify(e.body):e.body;!t&&["get","head"].includes(this.contextWeb.method)&&s===200&&e.memcache&&this.contextWeb?.stack?.memcached instanceof $&&this.contextWeb.stack.memcached.setPage(this.memcachedKey,e.headers,i,e.memcache).then(),t?this.res.cork(()=>{this.res.writeStatus(n),this.writeHeaders(e.headers),i.on("data",a=>{this.res.write(a)}).on("end",()=>{this.res.end()})}):this.res.cork(()=>{this.res.writeStatus(n),this.writeHeaders(e.headers),this.res.end(i)})}error(e){const t=e instanceof h&&e.getData()instanceof k;let s=_(404),n=this.defaultResponse.headers,i=e.message;if(e instanceof h){const a={isError:!0,code:e.getCode(),error:e.getMessage()};s=_(e.getStatusCode()),n=e.getHeaders()||this.defaultResponse.headers,t?i=e.getData():i=B(e.getData())&&Object.keys(e.getData()).length>0?JSON.stringify(e.getData()):JSON.stringify(a)}t?this.res.cork(()=>{this.res.writeStatus(s),this.writeHeaders(n),i.on("data",a=>{this.res.write(a)}).on("end",()=>{this.res.end()})}):this.res.cork(()=>{this.res.writeStatus(s),this.writeHeaders(n),this.res.end(i)})}writeHeaders(e){Object.entries(e).forEach(([t,s])=>{Array.isArray(s)?s.forEach(n=>this.res.writeHeader(t,n)):this.res.writeHeader(t,s)})}}const pt=async(o,e,t={})=>{const s=async a=>{let r;return"init"in a&&(r=await a.init()),r},n=(a,r)=>{"$inject"in a&&a.$inject(r)};e=Object.assign({config:{},getRequest:()=>t,method:"get",...t.controller&&t.subaction&&e.db?.home?await J(e.db.home,e.method||"get",t.controller,t.subaction):{},cookies:{},hostname:e.config?.server?.development?.host,protocol:"http",headers:{}},e);const i=new o;if(n(i,e),await s(i))throw new h({statusCode:404,code:13,message:"init method response value"});return i},L={compact:!0,ignoreComment:!0,spaces:4};class bt{constructor(){this.responseHeaders={}}setCookieHeader(e,t,s={}){return P(e,t,s)}success(e={},t){return{headers:Object.assign({"content-type":"application/json"},this.responseHeaders,t?.headers||{}),body:{isError:!1,data:e},memcache:t?.memcache||null,statusCode:t?.statusCode||200}}error(e){const t=e,s=t.code?t.code:0,n=t.message?t.message:"Api request error",i=t.statusCode?t.statusCode:404,a=t.data?t.data:{},r=t.response?{status:t.response.status,headers:t.response.headers,config:{url:t.response.url,method:t.response.method,params:t.response.params,headers:t.response.headers},data:t.response.data}:{};return{headers:Object.assign({"content-type":"application/json"},t.headers),body:{isError:!0,error:n,code:s,data:a,stack:process.env.NODE_ENV!=="production"?t.stack:"",response:process.env.NODE_ENV!=="production"?r:{}},statusCode:i}}successXml(e={},t){const s={_declaration:{_attributes:{version:"1.0",encoding:"utf-8"}}},n=this.success(e,t);return{headers:Object.assign({"content-type":"application/xml"},this.responseHeaders,t?.headers||{}),body:S.js2xml(Object.assign(s,{body:{...n.body}}),L),memcache:n.memcache}}errorXml(e){const t=e,s={_declaration:{_attributes:{version:"1.0",encoding:"utf-8"}}},n=this.error(t);return{headers:Object.assign({"content-type":"application/json"},t.headers),body:S.js2xml(Object.assign(s,{body:{...n.body}}),L),statusCode:n.statusCode}}async $create(e,...t){const s=new e(...t);"$inject"in s&&s.$inject({method:this.$context.method,getRequest:this.$context.getRequest,config:this.$context.config,db:this.$context.db,stack:this.$context.stack,headers:this.$context.headers,cookies:this.$context.cookies,controller:this.$context.controller,action:this.$context.action,subaction:this.$context.subaction,setResponseHeader:(i,a)=>this.setResponseHeader(i,a),setCookieHeader:this.setCookieHeader});const n=["init",...s.$inits||[]];for(const i of n)s[i]&&await s[i]();return s}async $createAll(e){return Promise.all(e.map(t=>this.$create(...t)))}$inject(e){this.$context=e}getContext(){return this.$context}getRequest(){return this.$context.getRequest()}getBody(){return this.$context.$body||Buffer.from("")}getFiles(){return this.$context.$files||{}}getStream(){return this.$context.$stream||new j().end()}getConfig(){return this.$context.config}getMethod(){return this.$context.method}getCookies(){return this.$context.cookies}getHostname(){return this.$context.hostname}getUrl(){return this.$context.url}getProtocol(){return this.$context.protocol}getDb(){return this.$context.db}getHeaders(){return this.$context.headers}getController(){return this.$context.controller}getAction(){return this.$context.action}getSubaction(){return this.$context.subaction}getHome(){return this.getDb().home}getPool(e="home"){return this.getDb()[e]}getStack(){return this.$context.stack}setResponseHeader(e,t){this.responseHeaders.hasOwnProperty(e)?(this.responseHeaders[e]=Array.isArray(this.responseHeaders[e])?this.responseHeaders[e]:[this.responseHeaders[e]],this.responseHeaders[e].push(t)):this.responseHeaders[e]=t}}class gt{async $create(e,...t){const s=new e(...t);return"$inject"in s&&s.$inject({method:this.$context.method,getRequest:this.$context.getRequest,config:this.$context.config,db:this.$context.db,stack:this.$context.stack,headers:this.$context.headers,cookies:this.$context.cookies,controller:this.$context.controller,action:this.$context.action,subaction:this.$context.subaction,setResponseHeader:this.$context.setResponseHeader,setCookieHeader:this.$context.setCookieHeader}),"init"in s&&await s.init(),s}async $createAll(e){return Promise.all(e.map(t=>this.$create(...t)))}$inject(e){this.$context=e}getContext(){return this.$context}getRequest(){return this.$context.getRequest()}getConfig(){return this.$context.config}getMethod(){return this.$context.method}getHeaders(){return this.$context.headers}getCookies(){return this.$context.cookies}getController(){return this.$context.controller}getAction(){return this.$context.action}getSubaction(){return this.$context.subaction}getDb(){return this.$context.db}getHome(){return this.$context.db.home}getPool(e="home"){return this.getDb()[e]}getStack(){return this.$context.stack}setResponseHeader(e,t){return this.$context.setResponseHeader(e,t)}setCookieHeader(e,t,s={}){return this.$context.setCookieHeader(e,t,s)}}const f=Symbol("arguments"),T=Symbol("connections"),A=Symbol("response"),F=Symbol("init"),K=Symbol("logger"),_t=o=>o.charAt(0).toUpperCase()+o.slice(1);function yt(o,e={}){const t=Reflect.ownKeys(o),s=Reflect.ownKeys(e),n=Symbol("isa");function i(a){for(const r of t)Object.defineProperty(a.prototype,r,{value:o[r]});return Object.defineProperty(a.prototype,n,{value:!0}),a}for(const a of s)Object.defineProperty(i,a,{value:e[a],enumerable:e.propertyIsEnumerable(a)});return Object.defineProperty(i,Symbol.hasInstance,{value:a=>!!a[n]}),i}const m=(o,e,t,s,n,i)=>{const a=Reflect.getOwnMetadata(o,e,t)||{};a[s]={type:n,params:i},Reflect.defineMetadata(o,a,e,t)};function xt(){return function(o,e,t){m(f,o,e,t,"request")}}function wt(){return function(o,e,t){m(f,o,e,t,"context")}}function $t(){return function(o,e,t){m(f,o,e,t,"config")}}function St(){return function(o,e,t){m(f,o,e,t,"method")}}function Ct(){return function(o,e,t){m(f,o,e,t,"cookies")}}function At(){return function(o,e,t){m(f,o,e,t,"hostname")}}function vt(){return function(o,e,t){m(f,o,e,t,"url")}}function Ot(){return function(o,e,t){m(f,o,e,t,"protocol")}}function jt(){return function(o,e,t){m(f,o,e,t,"db")}}function kt(){return function(o,e,t){m(f,o,e,t,"headers")}}function Ht(){return function(o,e,t){m(f,o,e,t,"controller")}}function Rt(){return function(o,e,t){m(f,o,e,t,"action")}}function qt(){return function(o,e,t){m(f,o,e,t,"subaction")}}function Pt(){return function(o,e,t){m(f,o,e,t,"body")}}function Wt(){return function(o,e,t){m(f,o,e,t,"stream")}}function Et(){return function(o,e,t){m(f,o,e,t,"home")}}function Nt(o="home"){return function(e,t,s){m(f,e,t,s,"pool",o)}}function Mt(o="home"){return function(e,t,s){m(T,e,t,s,"connection",o)}}function Bt(o={}){return function(e,t,s){m(A,e,t,0,"json",o)}}function Dt(o={}){return function(e,t,s){m(A,e,t,0,"xml",o)}}function Jt(o){return function(e,t,s){m(K,e,t,o,"logger",o)}}function It(o){return function(e,t,s){const n={format:"json"},i=s.value;s.value=async function(){o&&Object.assign(n,await o.apply(this)||{});const a=[],r=[],d=Reflect.getOwnMetadata(f,e,t)||{},c=Reflect.getOwnMetadata(T,e,t)||{},l=Reflect.getOwnMetadata(K,e,t)||{},b=Reflect.getOwnMetadata(A,e,t)?.[0]||{type:"json",params:{}},g=Reflect.getOwnMetadata(F,e,t)?.[0]||{type:"",params:{}};for(const u in d){if(!d.hasOwnProperty(u))continue;const p=`get${_t(d[u].type)}`;a[+u]=this[p](d[u].params)}for(const u in c)c.hasOwnProperty(u)&&(c[u].type,a[+u]=await this.getDb()[c[u].params].getConnection(),r.push(a[+u]));try{let u=await i.apply(this,a),p;if(Array.isArray(u)&&([u,p]=u),g.type!=="init")return n.format==="xml"||b.type==="xml"?this.successXml(u,Object.assign(b.params,p||{})):this.success(u,Object.assign(b.params,p||{}))}catch(u){await Promise.all([...r.map(y=>y.rollback())]);let p;n.format==="xml"||b.type==="xml"?p=this.errorXml(u):p=this.error(u);for(const y in l){if(!l.hasOwnProperty(y))continue;const Q=l[y].params;await this[Q].error(u,{response:st(p?.body||{},["stack"])})}return p}finally{await Promise.all([...r.map(u=>u.release())])}}}}function Lt(){return function(o,e,t){m(F,o,e,0,"init"),t.value,"$inits"in o||Object.defineProperty(o,"$inits",{value:[]}),o.$inits.push(e)}}const Tt={cookieParse:q,cookieString:P,jsonBody:O,rawBody:C,streamBody:w,urlencodedBody:H,multipartBody:R,readConfig:G,readConfigSync:Y,staticBody:N,extensions:E,getExt:W,jwtDecode:rt,readJsonConfigsSync:ct};export{h as ApiError,it as AsyncJwt,bt as Controller,ge as Jwt,$ as Memcached,gt as Model,pe as Server,ht as Ssr,ft as Web,Rt as action,Pt as body,_ as codeToStatus,$t as config,Mt as connection,wt as context,Ht as controller,Ct as cookies,jt as db,kt as headers,Tt as helpers,Et as home,At as hostname,It as http,Lt as init,Bt as json,Jt as logerror,St as method,yt as mixin,pt as mount,Nt as pool,Ot as protocol,xt as request,lt as selectControllersSchema,Wt as stream,qt as subaction,vt as url,Dt as xml};
384
+ `);
385
+ rows.forEach((row) => {
386
+ actions[row.action_name] = {
387
+ id: row.action_id,
388
+ name: row.action_name,
389
+ isActive: !!row.action_is_active,
390
+ method: row.action_method
391
+ };
392
+ controllers[row.controller_name] = controllers[row.controller_name] || {
393
+ id: row.controller_id,
394
+ name: row.controller_name,
395
+ isActive: !!row.controller_is_active,
396
+ isSitemap: !!row.controller_is_sitemap,
397
+ subactions: []
398
+ };
399
+ controllers[row.controller_name].subactions.push({
400
+ id: row.subaction_id,
401
+ action: row.action_name,
402
+ name: row.subaction_name,
403
+ isPermission: !!row.subaction_is_permission,
404
+ isCheckMethod: !!row.subaction_is_check_method,
405
+ isLog: !!row.subaction_is_log,
406
+ isActive: !!row.subaction_is_active,
407
+ isSync: !!row.subaction_is_sync
408
+ });
409
+ });
410
+ return {
411
+ controllers: Object.values(controllers),
412
+ actions: Object.values(actions)
413
+ };
414
+ };
415
+ const schemaControllerParams = (schema, method, name, subaction) => {
416
+ let controllerRow = schema.controllers.find((row) => row.name === name);
417
+ if (!controllerRow) {
418
+ throw new ApiError({
419
+ statusCode: 404,
420
+ code: 11,
421
+ message: `Controller ${name} not found is site schema`
422
+ });
423
+ }
424
+ controllerRow = Object.assign({
425
+ isActive: true,
426
+ isSitemap: false
427
+ }, controllerRow);
428
+ if (!controllerRow.isActive) {
429
+ throw new ApiError({
430
+ statusCode: 404,
431
+ code: 11,
432
+ message: `Controller ${name} not active is site schema`
433
+ });
434
+ }
435
+ let subactionRow = controllerRow.subactions.find((row) => row.name === subaction);
436
+ if (!subactionRow) {
437
+ throw new ApiError({
438
+ statusCode: 404,
439
+ code: 11,
440
+ message: `Subaction ${subaction} not found is site schema`
441
+ });
442
+ }
443
+ subactionRow = Object.assign({
444
+ isPermission: false,
445
+ isCheckMethod: false,
446
+ isLog: false,
447
+ isActive: true
448
+ }, subactionRow);
449
+ if (!subactionRow.isActive) {
450
+ throw new ApiError({
451
+ statusCode: 404,
452
+ code: 11,
453
+ message: `Subaction ${subaction} not active is site schema`
454
+ });
455
+ }
456
+ let actionRow = schema.actions.find((row) => row.name === subactionRow.action);
457
+ if (!actionRow) {
458
+ throw new ApiError({
459
+ statusCode: 404,
460
+ code: 11,
461
+ message: `Action not found is site schema`
462
+ });
463
+ }
464
+ actionRow = Object.assign({
465
+ isActive: true,
466
+ method: "any"
467
+ }, actionRow);
468
+ if (!actionRow.isActive) {
469
+ throw new ApiError({
470
+ statusCode: 404,
471
+ code: 11,
472
+ message: `Action ${actionRow.name} not active is site schema`
473
+ });
474
+ }
475
+ const allowMethods = (actionRow?.method || "").split(",").map((method2) => method2.trim());
476
+ if (subactionRow.isCheckMethod) {
477
+ if (actionRow.method !== "any" && !allowMethods.includes(method)) {
478
+ throw new ApiError({
479
+ statusCode: 404,
480
+ code: 11,
481
+ message: `Controller ${name} action ${actionRow.name} allow only ${actionRow.method} method`
482
+ });
483
+ }
484
+ }
485
+ return {
486
+ controller: {
487
+ id: controllerRow.id,
488
+ name: controllerRow.name,
489
+ isActive: controllerRow.isActive,
490
+ isSitemap: controllerRow.isSitemap
491
+ },
492
+ subaction: {
493
+ id: subactionRow.id,
494
+ name: subactionRow.name,
495
+ isPermission: subactionRow.isPermission,
496
+ isCheckMethod: subactionRow.isCheckMethod,
497
+ isLog: subactionRow.isLog,
498
+ isActive: subactionRow.isActive,
499
+ isSync: !!subactionRow.isSync
500
+ },
501
+ action: {
502
+ id: actionRow.id,
503
+ name: actionRow.name,
504
+ isActive: actionRow.isActive,
505
+ method: actionRow.method
506
+ }
507
+ };
508
+ };
509
+
510
+ class Web {
511
+ constructor(res, req, context) {
512
+ this.defaultRequest = {
513
+ lang: "ru"
514
+ };
515
+ this.defaultResponse = {
516
+ statusCode: 200,
517
+ headers: { "content-type": "application/json" },
518
+ body: {}
519
+ };
520
+ this.defaultControllerSubaction = {
521
+ controller: "Index",
522
+ subaction: "index"
523
+ };
524
+ this.res = res;
525
+ this.req = req;
526
+ this.res.onAborted(() => new ApiError({ message: "The connection was close", code: 1, statusCode: 404 }));
527
+ this.context = context;
528
+ }
529
+ setDefaultRequest(params) {
530
+ Object.assign(this.defaultRequest, params);
531
+ return this;
532
+ }
533
+ async request(input = {}) {
534
+ let response = {};
535
+ try {
536
+ const query = this.req.getQuery();
537
+ const request = Object.assign(
538
+ {},
539
+ this.defaultRequest,
540
+ input,
541
+ querystring.parse(this.req.getQuery())
542
+ );
543
+ this.contextWeb = {
544
+ config: this.context.config,
545
+ db: this.context.db,
546
+ method: this.req.getMethod(),
547
+ cookies: this.req.cookies,
548
+ hostname: this.req.getHeader("host"),
549
+ protocol: this.req.getHeader("x-forwarded-proto") || "http",
550
+ url: this.req.getUrl() + (query ? `?${query}` : ""),
551
+ headers: {},
552
+ stack: this.context.stack || {},
553
+ getRequest: () => request
554
+ };
555
+ this.memcachedKey = `${this.contextWeb.protocol}://${this.contextWeb.hostname}${this.contextWeb.url}`;
556
+ this.req.forEach((key, value) => this.contextWeb.headers[key] = value);
557
+ const type = this.contextWeb.headers["content-type"] || "application/json";
558
+ if (request.controller && request.subaction && this.context.schema) {
559
+ this.route = this.findRoute(request.controller);
560
+ Object.defineProperty(this.contextWeb, "$route", {
561
+ enumerable: false,
562
+ configurable: false,
563
+ writable: false,
564
+ value: this.route
565
+ });
566
+ Object.assign(
567
+ this.contextWeb,
568
+ schemaControllerParams(
569
+ this.context.schema,
570
+ this.contextWeb.method,
571
+ this.route.name,
572
+ // Определяет контроллер
573
+ request.subaction
574
+ )
575
+ );
576
+ if (this.contextWeb.subaction.isSync) {
577
+ if (!["get", "head"].includes(this.contextWeb.method)) {
578
+ Object.defineProperty(this.contextWeb, "$stream", {
579
+ enumerable: false,
580
+ configurable: false,
581
+ writable: false,
582
+ value: streamBody(this.res, this.req, false)
583
+ });
584
+ }
585
+ const controllerClass2 = this.importControllerSync(request.controller);
586
+ const controller2 = new controllerClass2();
587
+ this.injectContext(controller2);
588
+ if (request.subaction in controller2) {
589
+ response = await controller2[request.subaction]();
590
+ } else {
591
+ throw new ApiError(
592
+ {
593
+ statusCode: 404,
594
+ code: 13,
595
+ message: `Method ${request.subaction} not found in ${request.controller} route`
596
+ }
597
+ );
598
+ }
599
+ response = Object.assign({}, this.defaultResponse, response);
600
+ this.success(response);
601
+ return;
602
+ }
603
+ }
604
+ if (["get", "head"].includes(this.contextWeb.method) && this.contextWeb?.stack?.memcached instanceof Memcached) {
605
+ const memcached = this.contextWeb.stack.memcached;
606
+ if (memcached.isConnectedServers()) {
607
+ const cache = await memcached.getPage(this.memcachedKey);
608
+ if (cache) {
609
+ const { data, headers } = cache;
610
+ this.success({
611
+ body: data.toString(),
612
+ headers,
613
+ statusCode: 200
614
+ });
615
+ }
616
+ }
617
+ }
618
+ request.controller = request.controller || this.defaultControllerSubaction.controller;
619
+ request.subaction = request.subaction || this.defaultControllerSubaction.subaction;
620
+ if (!["get", "head"].includes(this.contextWeb.method)) {
621
+ if (type.indexOf("application/json") !== -1 || type.indexOf("text/json") !== -1) {
622
+ Object.assign(request, await jsonBody(this.res));
623
+ } else if (type.indexOf("multipart/form-data") !== -1) {
624
+ Object.assign(request, await multipartBody(this.res, this.req));
625
+ Object.defineProperty(this.contextWeb, "$files", {
626
+ enumerable: false,
627
+ configurable: false,
628
+ writable: false,
629
+ value: request.files
630
+ });
631
+ } else if (type.indexOf("application/x-www-form-urlencoded") !== -1) {
632
+ Object.assign(request, await urlencodedBody(this.res));
633
+ } else if (type.indexOf("application/xml") !== -1 || type.indexOf("text/xml") !== -1) {
634
+ const raw = (await rawBody(this.res)).toString();
635
+ const records = xmljs.xml2js(raw, { compact: true, cdataKey: "_value", textKey: "_value" });
636
+ Object.assign(request, records || {});
637
+ } else if (type.indexOf("stream") !== -1) {
638
+ Object.defineProperty(this.contextWeb, "$stream", {
639
+ enumerable: false,
640
+ configurable: false,
641
+ writable: false,
642
+ value: streamBody(this.res, this.req, false)
643
+ });
644
+ } else if (type.indexOf("binary") !== -1) {
645
+ await new Promise((resolve) => {
646
+ const stream = streamBody(this.res, this.req);
647
+ const temp = os.tmpdir();
648
+ const name = "./body_" + crypto.randomBytes(32).toString("hex");
649
+ const pathToFile = path__default.resolve(temp, name);
650
+ const writer = fs.createWriteStream(pathToFile);
651
+ stream.pipe(writer);
652
+ Object.defineProperty(this.contextWeb, "$files", {
653
+ enumerable: false,
654
+ configurable: false,
655
+ writable: false,
656
+ value: { body: { path: pathToFile } }
657
+ });
658
+ stream.on("end", () => resolve(true));
659
+ });
660
+ } else {
661
+ Object.defineProperty(this.contextWeb, "$body", {
662
+ enumerable: false,
663
+ configurable: false,
664
+ writable: false,
665
+ value: await rawBody(this.res)
666
+ });
667
+ }
668
+ }
669
+ this.route = this.findRoute(request.controller);
670
+ Object.assign(
671
+ this.contextWeb,
672
+ this.context.schema ? schemaControllerParams(
673
+ this.context.schema,
674
+ this.contextWeb.method,
675
+ this.route.name,
676
+ // Определяет контроллер
677
+ request.subaction
678
+ ) : await selectControllerParams(
679
+ this.contextWeb.db.home,
680
+ this.contextWeb.method,
681
+ this.route.name,
682
+ request.subaction,
683
+ this.context.stack?.memcached,
684
+ this.context.stack?.memcachedPrefix,
685
+ this.context.stack?.memcachedExpiry
686
+ )
687
+ );
688
+ Object.defineProperty(this.contextWeb, "$route", {
689
+ enumerable: false,
690
+ configurable: false,
691
+ writable: false,
692
+ value: this.route
693
+ });
694
+ const controllerClass = await this.importController(request.controller);
695
+ const controller = new controllerClass();
696
+ this.injectContext(controller);
697
+ const initResponse = await this.initComponent(controller);
698
+ if (typeof initResponse === "undefined") {
699
+ if (request.subaction in controller) {
700
+ response = await controller[request.subaction]();
701
+ } else {
702
+ throw new ApiError(
703
+ {
704
+ statusCode: 404,
705
+ code: 13,
706
+ message: `Method ${request.subaction} not found in ${request.controller} route`
707
+ }
708
+ );
709
+ }
710
+ } else {
711
+ response = initResponse;
712
+ }
713
+ response = Object.assign({}, this.defaultResponse, response);
714
+ this.success(response);
715
+ } catch (e) {
716
+ this.error(e);
717
+ }
718
+ }
719
+ /**
720
+ * Import controller class
721
+ */
722
+ async importController(controllerName) {
723
+ let controllerClass = this.route.component.default || this.route.component;
724
+ if (!isClass(controllerClass)) {
725
+ controllerClass = (await this.route.component()).default;
726
+ }
727
+ if (typeof controllerClass !== "function") {
728
+ throw new ApiError(
729
+ {
730
+ statusCode: 404,
731
+ code: 12,
732
+ message: `Class not found for ${controllerName} route`
733
+ }
734
+ );
735
+ }
736
+ return controllerClass;
737
+ }
738
+ /**
739
+ * Sync controller
740
+ */
741
+ importControllerSync(controllerName) {
742
+ const controllerClass = this.route.component.default || this.route.component;
743
+ if (typeof controllerClass !== "function") {
744
+ throw new ApiError(
745
+ {
746
+ statusCode: 404,
747
+ code: 12,
748
+ message: `Class not found for ${controllerName} route`
749
+ }
750
+ );
751
+ }
752
+ return controllerClass;
753
+ }
754
+ /**
755
+ * Find route in api routers
756
+ */
757
+ findRoute(controllerName) {
758
+ const route = this.context.routes.filter(
759
+ (v) => v.name === controllerName && (v.method === this.contextWeb.method || v.method === "any" || Array.isArray(v.method) && v.method.includes(this.contextWeb.method) || typeof v.method === "undefined")
760
+ )?.[0];
761
+ if (!route) {
762
+ throw new ApiError(
763
+ {
764
+ statusCode: 404,
765
+ code: 11,
766
+ message: `Route ${controllerName} not found`
767
+ }
768
+ );
769
+ }
770
+ return route;
771
+ }
772
+ injectContext(obj) {
773
+ if ("$inject" in obj) {
774
+ obj.$inject(this.contextWeb);
775
+ }
776
+ }
777
+ async initComponent(obj) {
778
+ const inits = [.../* @__PURE__ */ new Set(["init", ...obj.$inits || []])];
779
+ for (const method of inits) {
780
+ if (obj[method]) {
781
+ const out = await obj[method]();
782
+ if (out) {
783
+ return out;
784
+ }
785
+ }
786
+ }
787
+ }
788
+ success(response) {
789
+ const isStream = response.body instanceof Stream;
790
+ const isBuffer = response.body instanceof Uint8Array;
791
+ const code = response.statusCode || 200;
792
+ const status = codeToStatus(code);
793
+ const body = !isBuffer && !isStream && isObject(response.body) ? JSON.stringify(response.body) : response.body;
794
+ if (!isStream && ["get", "head"].includes(this.contextWeb.method) && code === 200 && response.memcache && this.contextWeb?.stack?.memcached instanceof Memcached) {
795
+ const memcached = this.contextWeb.stack.memcached;
796
+ memcached.setPage(this.memcachedKey, response.headers, body, response.memcache).then();
797
+ }
798
+ if (!isStream) {
799
+ this.res.cork(() => {
800
+ this.res.writeStatus(status);
801
+ this.writeHeaders(response.headers);
802
+ this.res.end(body);
803
+ });
804
+ } else {
805
+ this.res.cork(() => {
806
+ this.res.writeStatus(status);
807
+ this.writeHeaders(response.headers);
808
+ body.on("data", (chunk) => {
809
+ this.res.write(chunk);
810
+ }).on("end", () => {
811
+ this.res.end();
812
+ });
813
+ });
814
+ }
815
+ }
816
+ /**
817
+ * Error response
818
+ */
819
+ error(e) {
820
+ const isStream = e instanceof ApiError && e.getData() instanceof Stream;
821
+ let status = codeToStatus(404), headers = this.defaultResponse.headers, body = e.message;
822
+ if (e instanceof ApiError) {
823
+ const data = { isError: true, code: e.getCode(), error: e.getMessage() };
824
+ status = codeToStatus(e.getStatusCode());
825
+ headers = e.getHeaders() || this.defaultResponse.headers;
826
+ if (isStream) {
827
+ body = e.getData();
828
+ } else {
829
+ body = isObject(e.getData()) && Object.keys(e.getData()).length > 0 ? JSON.stringify(e.getData()) : JSON.stringify(data);
830
+ }
831
+ }
832
+ if (!isStream) {
833
+ this.res.cork(() => {
834
+ this.res.writeStatus(status);
835
+ this.writeHeaders(headers);
836
+ this.res.end(body);
837
+ });
838
+ } else {
839
+ this.res.cork(() => {
840
+ this.res.writeStatus(status);
841
+ this.writeHeaders(headers);
842
+ body.on("data", (chunk) => {
843
+ this.res.write(chunk);
844
+ }).on("end", () => {
845
+ this.res.end();
846
+ });
847
+ });
848
+ }
849
+ }
850
+ writeHeaders(headers) {
851
+ Object.entries(headers).forEach(([key, value]) => {
852
+ if (Array.isArray(value)) {
853
+ value.forEach((v) => this.res.writeHeader(key, v));
854
+ } else {
855
+ this.res.writeHeader(key, value);
856
+ }
857
+ });
858
+ }
859
+ }
860
+
861
+ const mountWithContext = async ($class, $context, request = {}) => {
862
+ const initComponent = async (obj2) => {
863
+ let out;
864
+ if ("init" in obj2) {
865
+ out = await obj2.init();
866
+ }
867
+ return out;
868
+ };
869
+ const injectContext = (obj2, $context2) => {
870
+ if ("$inject" in obj2) {
871
+ obj2.$inject($context2);
872
+ }
873
+ };
874
+ $context = Object.assign({
875
+ config: {},
876
+ getRequest: () => request,
877
+ method: "get",
878
+ ...request.controller && request.subaction && $context.db?.home ? await selectControllerParams(
879
+ $context.db.home,
880
+ $context.method || "get",
881
+ request.controller,
882
+ request.subaction
883
+ ) : {},
884
+ cookies: {},
885
+ hostname: $context.config?.server?.development?.host,
886
+ protocol: "http",
887
+ headers: {}
888
+ }, $context);
889
+ const obj = new $class();
890
+ injectContext(obj, $context);
891
+ const initResponse = await initComponent(obj);
892
+ if (initResponse) {
893
+ throw new ApiError(
894
+ {
895
+ statusCode: 404,
896
+ code: 13,
897
+ message: `init method response value`
898
+ }
899
+ );
900
+ }
901
+ return obj;
902
+ };
903
+
904
+ const xmlOptions = { compact: true, ignoreComment: true, spaces: 4 };
905
+ class Controller {
906
+ constructor() {
907
+ // Addition headers that can be add in any place
908
+ this.responseHeaders = {};
909
+ }
910
+ /**
911
+ * Set cookies
912
+ * @param name
913
+ * @param value
914
+ * @param options
915
+ */
916
+ setCookieHeader(name, value, options = {}) {
917
+ return cookieString(name, value, options);
918
+ }
919
+ /**
920
+ * Success request
921
+ * @param data response params
922
+ * @param options
923
+ * @returns
924
+ */
925
+ success(data = {}, options) {
926
+ return {
927
+ headers: Object.assign({ "content-type": "application/json" }, this.responseHeaders, options?.headers || {}),
928
+ body: {
929
+ isError: false,
930
+ data
931
+ },
932
+ memcache: options?.memcache || null,
933
+ statusCode: options?.statusCode || 200
934
+ };
935
+ }
936
+ /**
937
+ * Error response
938
+ * @param err
939
+ */
940
+ error(err) {
941
+ const e = err;
942
+ const code = e.code ? e.code : 0;
943
+ const message = e.message ? e.message : "Api request error";
944
+ const statusCode = e.statusCode ? e.statusCode : 404;
945
+ const data = e.data ? e.data : {};
946
+ const response = e.response ? {
947
+ // @ts-ignore
948
+ status: e.response.status,
949
+ // @ts-ignore
950
+ headers: e.response.headers,
951
+ config: {
952
+ // @ts-ignore
953
+ url: e.response.url,
954
+ // @ts-ignore
955
+ method: e.response.method,
956
+ // @ts-ignore
957
+ params: e.response.params,
958
+ // @ts-ignore
959
+ headers: e.response.headers
960
+ },
961
+ // @ts-ignore
962
+ data: e.response.data
963
+ } : {};
964
+ const headers = Object.assign({ "content-type": "application/json" }, e.headers);
965
+ return {
966
+ headers,
967
+ body: {
968
+ isError: true,
969
+ error: message,
970
+ code,
971
+ data,
972
+ stack: process.env.NODE_ENV !== "production" ? e.stack : "",
973
+ response: process.env.NODE_ENV !== "production" ? response : {}
974
+ },
975
+ statusCode
976
+ };
977
+ }
978
+ /**
979
+ * Xml response
980
+ * @param data response params
981
+ * @param options addition options
982
+ */
983
+ successXml(data = {}, options) {
984
+ const defaultXml = {
985
+ _declaration: {
986
+ _attributes: {
987
+ version: "1.0",
988
+ encoding: "utf-8"
989
+ }
990
+ }
991
+ };
992
+ const response = this.success(data, options);
993
+ return {
994
+ headers: Object.assign({ "content-type": "application/xml" }, this.responseHeaders, options?.headers || {}),
995
+ body: xmljs.js2xml(Object.assign(defaultXml, { body: { ...response.body } }), xmlOptions),
996
+ memcache: response.memcache
997
+ };
998
+ }
999
+ /**
1000
+ * Error xml response
1001
+ * @param err error object
1002
+ */
1003
+ errorXml(err) {
1004
+ const e = err;
1005
+ const defaultXml = {
1006
+ _declaration: {
1007
+ _attributes: {
1008
+ version: "1.0",
1009
+ encoding: "utf-8"
1010
+ }
1011
+ }
1012
+ };
1013
+ const response = this.error(e);
1014
+ const headers = Object.assign({ "content-type": "application/xml" }, e.headers);
1015
+ return {
1016
+ headers,
1017
+ body: xmljs.js2xml(Object.assign(defaultXml, { body: { ...response.body } }), xmlOptions),
1018
+ statusCode: response.statusCode
1019
+ };
1020
+ }
1021
+ // Create model
1022
+ async $create(model, ...args) {
1023
+ const obj = new model(...args);
1024
+ if ("$inject" in obj) {
1025
+ obj.$inject({
1026
+ method: this.$context.method,
1027
+ getRequest: this.$context.getRequest,
1028
+ config: this.$context.config,
1029
+ db: this.$context.db,
1030
+ stack: this.$context.stack,
1031
+ headers: this.$context.headers,
1032
+ cookies: this.$context.cookies,
1033
+ controller: this.$context.controller,
1034
+ action: this.$context.action,
1035
+ subaction: this.$context.subaction,
1036
+ setResponseHeader: (key, value) => this.setResponseHeader(key, value),
1037
+ setCookieHeader: this.setCookieHeader
1038
+ });
1039
+ }
1040
+ const inits = ["init", ...obj.$inits || []];
1041
+ for (const method of inits) {
1042
+ if (obj[method]) {
1043
+ await obj[method]();
1044
+ }
1045
+ }
1046
+ return obj;
1047
+ }
1048
+ // Create group of libs
1049
+ async $createAll(models) {
1050
+ return Promise.all(models.map((params) => this.$create(...params)));
1051
+ }
1052
+ /**
1053
+ * Inject app context
1054
+ * @param context
1055
+ */
1056
+ $inject(context) {
1057
+ this.$context = context;
1058
+ }
1059
+ getContext() {
1060
+ return this.$context;
1061
+ }
1062
+ getRequest() {
1063
+ return this.$context.getRequest();
1064
+ }
1065
+ getBody() {
1066
+ return this.$context["$body"] || Buffer.from("");
1067
+ }
1068
+ getFiles() {
1069
+ return this.$context["$files"] || {};
1070
+ }
1071
+ getStream() {
1072
+ return this.$context["$stream"] || new PassThrough().end();
1073
+ }
1074
+ getConfig() {
1075
+ return this.$context.config;
1076
+ }
1077
+ getMethod() {
1078
+ return this.$context.method;
1079
+ }
1080
+ getCookies() {
1081
+ return this.$context.cookies;
1082
+ }
1083
+ getHostname() {
1084
+ return this.$context.hostname;
1085
+ }
1086
+ getUrl() {
1087
+ return this.$context.url;
1088
+ }
1089
+ getProtocol() {
1090
+ return this.$context.protocol;
1091
+ }
1092
+ getDb() {
1093
+ return this.$context.db;
1094
+ }
1095
+ getHeaders() {
1096
+ return this.$context.headers;
1097
+ }
1098
+ getController() {
1099
+ return this.$context.controller;
1100
+ }
1101
+ getAction() {
1102
+ return this.$context.action;
1103
+ }
1104
+ getSubaction() {
1105
+ return this.$context.subaction;
1106
+ }
1107
+ getHome() {
1108
+ return this.getDb().home;
1109
+ }
1110
+ getPool(key = "home") {
1111
+ return this.getDb()[key];
1112
+ }
1113
+ getStack() {
1114
+ return this.$context.stack;
1115
+ }
1116
+ setResponseHeader(key, value) {
1117
+ if (this.responseHeaders.hasOwnProperty(key)) {
1118
+ this.responseHeaders[key] = Array.isArray(this.responseHeaders[key]) ? this.responseHeaders[key] : [this.responseHeaders[key]];
1119
+ this.responseHeaders[key].push(value);
1120
+ } else {
1121
+ this.responseHeaders[key] = value;
1122
+ }
1123
+ }
1124
+ }
1125
+
1126
+ class Model {
1127
+ /**
1128
+ * Create model
1129
+ * @param model
1130
+ * @param args
1131
+ */
1132
+ async $create(model, ...args) {
1133
+ const obj = new model(...args);
1134
+ if ("$inject" in obj) {
1135
+ obj.$inject({
1136
+ method: this.$context.method,
1137
+ getRequest: this.$context.getRequest,
1138
+ config: this.$context.config,
1139
+ db: this.$context.db,
1140
+ stack: this.$context.stack,
1141
+ headers: this.$context.headers,
1142
+ cookies: this.$context.cookies,
1143
+ controller: this.$context.controller,
1144
+ action: this.$context.action,
1145
+ subaction: this.$context.subaction,
1146
+ setResponseHeader: this.$context.setResponseHeader,
1147
+ setCookieHeader: this.$context.setCookieHeader
1148
+ });
1149
+ }
1150
+ if ("init" in obj) {
1151
+ await obj.init();
1152
+ }
1153
+ return obj;
1154
+ }
1155
+ // Create group of libs
1156
+ async $createAll(models) {
1157
+ return Promise.all(models.map((params) => this.$create(...params)));
1158
+ }
1159
+ /**
1160
+ * Inject app context
1161
+ * @param context
1162
+ */
1163
+ $inject(context) {
1164
+ this.$context = context;
1165
+ }
1166
+ getContext() {
1167
+ return this.$context;
1168
+ }
1169
+ getRequest() {
1170
+ return this.$context.getRequest();
1171
+ }
1172
+ getConfig() {
1173
+ return this.$context.config;
1174
+ }
1175
+ getMethod() {
1176
+ return this.$context.method;
1177
+ }
1178
+ getHeaders() {
1179
+ return this.$context.headers;
1180
+ }
1181
+ getCookies() {
1182
+ return this.$context.cookies;
1183
+ }
1184
+ getController() {
1185
+ return this.$context.controller;
1186
+ }
1187
+ getAction() {
1188
+ return this.$context.action;
1189
+ }
1190
+ getSubaction() {
1191
+ return this.$context.subaction;
1192
+ }
1193
+ getDb() {
1194
+ return this.$context.db;
1195
+ }
1196
+ getHome() {
1197
+ return this.$context.db.home;
1198
+ }
1199
+ getPool(key = "home") {
1200
+ return this.getDb()[key];
1201
+ }
1202
+ getStack() {
1203
+ return this.$context.stack;
1204
+ }
1205
+ setResponseHeader(key, value) {
1206
+ return this.$context.setResponseHeader(key, value);
1207
+ }
1208
+ setCookieHeader(name, value, options = {}) {
1209
+ return this.$context.setCookieHeader(name, value, options);
1210
+ }
1211
+ }
1212
+
1213
+ const argumentsSubactionsKey = Symbol("arguments");
1214
+ const argumentsConnectionsKey = Symbol("connections");
1215
+ const responseSubactionsKey = Symbol("response");
1216
+ const responseInitKey = Symbol("init");
1217
+ const responseLoggerKey = Symbol("logger");
1218
+ const upperCaseFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1);
1219
+ function mixin(behaviour, sharedBehaviour = {}) {
1220
+ const instanceKeys = Reflect.ownKeys(behaviour);
1221
+ const sharedKeys = Reflect.ownKeys(sharedBehaviour);
1222
+ const typeTag = Symbol("isa");
1223
+ function _mixin(clazz) {
1224
+ for (const property of instanceKeys) {
1225
+ Object.defineProperty(clazz.prototype, property, { value: behaviour[property] });
1226
+ }
1227
+ Object.defineProperty(clazz.prototype, typeTag, { value: true });
1228
+ return clazz;
1229
+ }
1230
+ for (const property of sharedKeys) {
1231
+ Object.defineProperty(_mixin, property, {
1232
+ //@ts-ignore
1233
+ value: sharedBehaviour[property],
1234
+ enumerable: sharedBehaviour.propertyIsEnumerable(property)
1235
+ });
1236
+ }
1237
+ Object.defineProperty(_mixin, Symbol.hasInstance, {
1238
+ value: (i) => !!i[typeTag]
1239
+ });
1240
+ return _mixin;
1241
+ }
1242
+ const defineMetadataArgument = (key, target, propertyKey, parameterIndex, argumentType, params) => {
1243
+ const existingArguments = Reflect.getOwnMetadata(
1244
+ key,
1245
+ target,
1246
+ propertyKey
1247
+ ) || {};
1248
+ existingArguments[parameterIndex] = {
1249
+ type: argumentType,
1250
+ params
1251
+ };
1252
+ Reflect.defineMetadata(key, existingArguments, target, propertyKey);
1253
+ };
1254
+ function request() {
1255
+ return function(target, propertyKey, parameterIndex) {
1256
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "request");
1257
+ };
1258
+ }
1259
+ function context() {
1260
+ return function(target, propertyKey, parameterIndex) {
1261
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "context");
1262
+ };
1263
+ }
1264
+ function config() {
1265
+ return function(target, propertyKey, parameterIndex) {
1266
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "config");
1267
+ };
1268
+ }
1269
+ function method() {
1270
+ return function(target, propertyKey, parameterIndex) {
1271
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "method");
1272
+ };
1273
+ }
1274
+ function cookies() {
1275
+ return function(target, propertyKey, parameterIndex) {
1276
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "cookies");
1277
+ };
1278
+ }
1279
+ function hostname() {
1280
+ return function(target, propertyKey, parameterIndex) {
1281
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "hostname");
1282
+ };
1283
+ }
1284
+ function url() {
1285
+ return function(target, propertyKey, parameterIndex) {
1286
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "url");
1287
+ };
1288
+ }
1289
+ function protocol() {
1290
+ return function(target, propertyKey, parameterIndex) {
1291
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "protocol");
1292
+ };
1293
+ }
1294
+ function db() {
1295
+ return function(target, propertyKey, parameterIndex) {
1296
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "db");
1297
+ };
1298
+ }
1299
+ function headers() {
1300
+ return function(target, propertyKey, parameterIndex) {
1301
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "headers");
1302
+ };
1303
+ }
1304
+ function controller() {
1305
+ return function(target, propertyKey, parameterIndex) {
1306
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "controller");
1307
+ };
1308
+ }
1309
+ function action() {
1310
+ return function(target, propertyKey, parameterIndex) {
1311
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "action");
1312
+ };
1313
+ }
1314
+ function subaction() {
1315
+ return function(target, propertyKey, parameterIndex) {
1316
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "subaction");
1317
+ };
1318
+ }
1319
+ function body() {
1320
+ return function(target, propertyKey, parameterIndex) {
1321
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "body");
1322
+ };
1323
+ }
1324
+ function stream() {
1325
+ return function(target, propertyKey, parameterIndex) {
1326
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "stream");
1327
+ };
1328
+ }
1329
+ function home() {
1330
+ return function(target, propertyKey, parameterIndex) {
1331
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "home");
1332
+ };
1333
+ }
1334
+ function pool(name = "home") {
1335
+ return function(target, propertyKey, parameterIndex) {
1336
+ defineMetadataArgument(argumentsSubactionsKey, target, propertyKey, parameterIndex, "pool", name);
1337
+ };
1338
+ }
1339
+ function connection(name = "home") {
1340
+ return function(target, propertyKey, parameterIndex) {
1341
+ defineMetadataArgument(argumentsConnectionsKey, target, propertyKey, parameterIndex, "connection", name);
1342
+ };
1343
+ }
1344
+ function json(opt = {}) {
1345
+ return function(target, propertyKey, descriptor) {
1346
+ defineMetadataArgument(responseSubactionsKey, target, propertyKey, 0, "json", opt);
1347
+ };
1348
+ }
1349
+ function xml(opt = {}) {
1350
+ return function(target, propertyKey, descriptor) {
1351
+ defineMetadataArgument(responseSubactionsKey, target, propertyKey, 0, "xml", opt);
1352
+ };
1353
+ }
1354
+ function logerror(name) {
1355
+ return function(target, propertyKey, descriptor) {
1356
+ defineMetadataArgument(responseLoggerKey, target, propertyKey, name, "logger", name);
1357
+ };
1358
+ }
1359
+ function http(beforeCreate) {
1360
+ return function(target, propertyKey, descriptor) {
1361
+ const opts = {
1362
+ format: "json"
1363
+ };
1364
+ const method2 = descriptor.value;
1365
+ descriptor.value = async function() {
1366
+ if (beforeCreate) {
1367
+ Object.assign(opts, await beforeCreate.apply(this) || {});
1368
+ }
1369
+ const args = [];
1370
+ const connections = [];
1371
+ const existingArguments = Reflect.getOwnMetadata(
1372
+ argumentsSubactionsKey,
1373
+ target,
1374
+ propertyKey
1375
+ ) || {};
1376
+ const existingConnections = Reflect.getOwnMetadata(
1377
+ argumentsConnectionsKey,
1378
+ target,
1379
+ propertyKey
1380
+ ) || {};
1381
+ const existingLoggers = Reflect.getOwnMetadata(
1382
+ responseLoggerKey,
1383
+ target,
1384
+ propertyKey
1385
+ ) || {};
1386
+ const response = Reflect.getOwnMetadata(
1387
+ responseSubactionsKey,
1388
+ target,
1389
+ propertyKey
1390
+ )?.[0] || { type: "json", params: {} };
1391
+ const responseInit = Reflect.getOwnMetadata(
1392
+ responseInitKey,
1393
+ target,
1394
+ propertyKey
1395
+ )?.[0] || { type: "", params: {} };
1396
+ for (const key in existingArguments) {
1397
+ if (!existingArguments.hasOwnProperty(key)) {
1398
+ continue;
1399
+ }
1400
+ const getterName = `get${upperCaseFirstLetter(existingArguments[key].type)}`;
1401
+ args[+key] = this[getterName](existingArguments[key].params);
1402
+ }
1403
+ for (const key in existingConnections) {
1404
+ if (!existingConnections.hasOwnProperty(key)) {
1405
+ continue;
1406
+ }
1407
+ existingConnections[key].type;
1408
+ args[+key] = await this.getDb()[existingConnections[key].params].getConnection();
1409
+ connections.push(args[+key]);
1410
+ }
1411
+ try {
1412
+ let out = await method2.apply(this, args), opt;
1413
+ Array.isArray(out) && ([out, opt] = out);
1414
+ if (responseInit.type !== "init") {
1415
+ if (opts.format === "xml" || response.type === "xml") {
1416
+ return this.successXml(out, Object.assign(response.params, opt || {}));
1417
+ }
1418
+ return this.success(out, Object.assign(response.params, opt || {}));
1419
+ }
1420
+ } catch (e) {
1421
+ await Promise.all([...connections.map((connection2) => connection2.rollback())]);
1422
+ let output;
1423
+ if (opts.format === "xml" || response.type === "xml") {
1424
+ output = this.errorXml(e);
1425
+ } else {
1426
+ output = this.error(e);
1427
+ }
1428
+ for (const key in existingLoggers) {
1429
+ if (!existingLoggers.hasOwnProperty(key)) {
1430
+ continue;
1431
+ }
1432
+ const logger = existingLoggers[key].params;
1433
+ await this[logger].error(e, { response: omit(output?.body || {}, ["stack"]) });
1434
+ }
1435
+ return output;
1436
+ } finally {
1437
+ await Promise.all([...connections.map((connection2) => connection2.release())]);
1438
+ }
1439
+ };
1440
+ };
1441
+ }
1442
+ function init() {
1443
+ return function(target, propertyKey, descriptor) {
1444
+ defineMetadataArgument(responseInitKey, target, propertyKey, 0, "init");
1445
+ descriptor.value;
1446
+ if (!("$inits" in target)) {
1447
+ Object.defineProperty(target, "$inits", { value: [] });
1448
+ }
1449
+ target.$inits.push(propertyKey);
1450
+ };
1451
+ }
1452
+
1453
+ const helpers = {
1454
+ cookieParse,
1455
+ cookieString,
1456
+ jsonBody,
1457
+ rawBody,
1458
+ streamBody,
1459
+ urlencodedBody,
1460
+ multipartBody,
1461
+ readConfig,
1462
+ readConfigSync,
1463
+ staticBody,
1464
+ extensions,
1465
+ getExt,
1466
+ jwtDecode,
1467
+ readJsonConfigsSync
1468
+ };
1469
+
1470
+ export { ApiError, AsyncJwt, Controller, Memcached, Model, Ssr, Web, action, body, codeToStatus, config, connection, context, controller, cookies, db, headers, helpers, home, hostname, http, init, json, logerror, method, mixin, mountWithContext as mount, pool, protocol, request, selectControllersSchema, stream, subaction, url, xml };