equipped 5.0.29 → 5.0.31

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 (84) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cjs/audit/events.cjs +96 -0
  3. package/dist/cjs/audit/events.cjs.map +1 -0
  4. package/dist/cjs/audit/events.min.cjs +2 -0
  5. package/dist/cjs/audit/events.min.cjs.map +1 -0
  6. package/dist/cjs/audit/index.cjs +5 -0
  7. package/dist/cjs/audit/index.cjs.map +1 -0
  8. package/dist/cjs/audit/index.min.cjs +2 -0
  9. package/dist/cjs/audit/index.min.cjs.map +1 -0
  10. package/dist/cjs/server/impls/base.cjs +8 -2
  11. package/dist/cjs/server/impls/base.cjs.map +1 -1
  12. package/dist/cjs/server/impls/base.min.cjs +1 -1
  13. package/dist/cjs/server/impls/base.min.cjs.map +1 -1
  14. package/dist/cjs/server/impls/express.cjs +1 -0
  15. package/dist/cjs/server/impls/express.cjs.map +1 -1
  16. package/dist/cjs/server/impls/express.min.cjs +1 -1
  17. package/dist/cjs/server/impls/express.min.cjs.map +1 -1
  18. package/dist/cjs/server/impls/fastify.cjs +1 -0
  19. package/dist/cjs/server/impls/fastify.cjs.map +1 -1
  20. package/dist/cjs/server/impls/fastify.min.cjs +1 -1
  21. package/dist/cjs/server/impls/fastify.min.cjs.map +1 -1
  22. package/dist/cjs/server/requests.cjs +18 -1
  23. package/dist/cjs/server/requests.cjs.map +1 -1
  24. package/dist/cjs/server/requests.min.cjs +1 -1
  25. package/dist/cjs/server/requests.min.cjs.map +1 -1
  26. package/dist/cjs/server/routes.cjs +2 -0
  27. package/dist/cjs/server/routes.cjs.map +1 -1
  28. package/dist/cjs/server/routes.min.cjs +1 -1
  29. package/dist/cjs/server/routes.min.cjs.map +1 -1
  30. package/dist/cjs/server/types.cjs.map +1 -1
  31. package/dist/cjs/server/types.min.cjs +1 -1
  32. package/dist/cjs/server/types.min.cjs.map +1 -1
  33. package/dist/esm/audit/events.min.mjs +2 -0
  34. package/dist/esm/audit/events.min.mjs.map +1 -0
  35. package/dist/esm/audit/events.mjs +96 -0
  36. package/dist/esm/audit/events.mjs.map +1 -0
  37. package/dist/esm/audit/index.min.mjs +2 -0
  38. package/dist/esm/audit/index.min.mjs.map +1 -0
  39. package/dist/esm/audit/index.mjs +5 -0
  40. package/dist/esm/audit/index.mjs.map +1 -0
  41. package/dist/esm/server/impls/base.min.mjs +1 -1
  42. package/dist/esm/server/impls/base.min.mjs.map +1 -1
  43. package/dist/esm/server/impls/base.mjs +8 -2
  44. package/dist/esm/server/impls/base.mjs.map +1 -1
  45. package/dist/esm/server/impls/express.min.mjs +1 -1
  46. package/dist/esm/server/impls/express.min.mjs.map +1 -1
  47. package/dist/esm/server/impls/express.mjs +1 -0
  48. package/dist/esm/server/impls/express.mjs.map +1 -1
  49. package/dist/esm/server/impls/fastify.min.mjs +1 -1
  50. package/dist/esm/server/impls/fastify.min.mjs.map +1 -1
  51. package/dist/esm/server/impls/fastify.mjs +1 -0
  52. package/dist/esm/server/impls/fastify.mjs.map +1 -1
  53. package/dist/esm/server/requests.min.mjs +1 -1
  54. package/dist/esm/server/requests.min.mjs.map +1 -1
  55. package/dist/esm/server/requests.mjs +18 -1
  56. package/dist/esm/server/requests.mjs.map +1 -1
  57. package/dist/esm/server/routes.min.mjs +1 -1
  58. package/dist/esm/server/routes.min.mjs.map +1 -1
  59. package/dist/esm/server/routes.mjs +2 -0
  60. package/dist/esm/server/routes.mjs.map +1 -1
  61. package/dist/esm/server/types.min.mjs +1 -1
  62. package/dist/esm/server/types.min.mjs.map +1 -1
  63. package/dist/esm/server/types.mjs.map +1 -1
  64. package/dist/types/audit/events.js +95 -0
  65. package/dist/types/audit/index.d.ts +30 -0
  66. package/dist/types/audit/index.js +4 -0
  67. package/dist/types/db-B3v890eW.d.ts +24 -0
  68. package/dist/types/db-Bh0mF2ja.d.ts +14 -0
  69. package/dist/types/dbs/index.d.ts +2 -1
  70. package/dist/types/errors/index.d.ts +5 -4
  71. package/dist/types/{fastify-B7DQ55s8.d.ts → fastify-fV8eHFNl.d.ts} +1 -1
  72. package/dist/types/index.d.ts +6 -4
  73. package/dist/types/instance/index.d.ts +6 -4
  74. package/dist/types/{requests-DblEBsI-.d.ts → requests-HlupG2_s.d.ts} +29 -8
  75. package/dist/types/server/impls/base.js +8 -2
  76. package/dist/types/server/impls/express.js +1 -0
  77. package/dist/types/server/impls/fastify.js +1 -0
  78. package/dist/types/server/index.d.ts +5 -4
  79. package/dist/types/server/requests.js +18 -1
  80. package/dist/types/server/routes.js +2 -0
  81. package/dist/types/{validationError-xXVMlhsc.d.ts → validationError-Ztplzq8d.d.ts} +1 -1
  82. package/dist/types/validations/index.d.ts +16 -3
  83. package/package.json +13 -1
  84. package/dist/types/db-Gck93XBL.d.ts +0 -34
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [5.0.31](https://github.com/kevinand11/equipped/compare/v5.0.30...v5.0.31) (2025-10-02)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * type errors ([c945f0b](https://github.com/kevinand11/equipped/commit/c945f0b0e2324c74748214eb9ad8262eb8d9e4e5))
11
+
12
+ ### [5.0.30](https://github.com/kevinand11/equipped/compare/v5.0.29...v5.0.30) (2025-10-02)
13
+
14
+
15
+ ### Features
16
+
17
+ * events auditing ([4f7eb59](https://github.com/kevinand11/equipped/commit/4f7eb59c75cd8b2809084c798d4ce3e0bc500ead))
18
+ * response cookies and cookies validations ([a500adb](https://github.com/kevinand11/equipped/commit/a500adbd937efa1bd4d320836ba3671414bbe0f3))
19
+
5
20
  ### [5.0.29](https://github.com/kevinand11/equipped/compare/v5.0.28...v5.0.29) (2025-08-28)
6
21
 
7
22
 
@@ -0,0 +1,96 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _ulid = require('ulid');
2
+ var _valleyed = require('valleyed');
3
+ var _indexcjs = require('../dbs/index.cjs');
4
+ var _indexcjs3 = require('../errors/index.cjs');
5
+ class EventAudit {
6
+ constructor(db, dbName, handlers) {
7
+ this.db = db;
8
+ this.handlers = handlers;
9
+ this.table = db.use({
10
+ db: dbName,
11
+ col: "__audits",
12
+ mapper: (model) => ({ ...model, toJSON: () => model }),
13
+ options: { skipAudit: true }
14
+ });
15
+ for (const key in handlers) _valleyed.v.compile(handlers[key].pipe);
16
+ }
17
+
18
+ async #createEvent(type, payload, mode) {
19
+ const handler = this.handlers[type];
20
+ if (!handler) throw new (0, _indexcjs3.EquippedError)("audit handler not found", { type, payload, mode });
21
+ const validPayload = _valleyed.v.assert(handler.pipe, payload);
22
+ const key = this.createId();
23
+ const now = /* @__PURE__ */ new Date();
24
+ const audit = await this.table.insertOne(
25
+ {
26
+ key,
27
+ type,
28
+ mode,
29
+ ts: now.getTime(),
30
+ payload: validPayload,
31
+ status: "pending",
32
+ error: null,
33
+ startedAt: null,
34
+ completedAt: null
35
+ },
36
+ { getTime: () => now, makeId: () => key }
37
+ );
38
+ return audit;
39
+ }
40
+ async #processEvent(event) {
41
+ return this.db.session(async () => {
42
+ const handler = this.handlers[event.type];
43
+ if (!handler) throw new (0, _indexcjs3.EquippedError)("audit handler not found", { event });
44
+ try {
45
+ await this.table.updateOne(
46
+ { key: event.key },
47
+ { $set: { status: "processing", startedAt: Date.now(), completedAt: null, error: null } }
48
+ );
49
+ const result = await handler.handle(event.payload, {
50
+ idempotencyKey: event.key.toString(),
51
+ idempotencyDate: new Date(event.ts)
52
+ });
53
+ await this.table.updateOne({ key: event.key }, { $set: { status: "done", completedAt: Date.now() } });
54
+ return result;
55
+ } catch (err) {
56
+ const message = err instanceof Error ? err.message : String(err);
57
+ await this.table.updateOne({ key: event.key }, { $set: { status: "failed", error: message, completedAt: Date.now() } });
58
+ throw err;
59
+ }
60
+ });
61
+ }
62
+ async createSync(type, payload) {
63
+ const event = await this.#createEvent(type, payload, "sync");
64
+ return this.#processEvent(event);
65
+ }
66
+ async createAsync(type, payload) {
67
+ const event = await this.#createEvent(type, payload, "async");
68
+ this.#processEvent(event).catch(() => {
69
+ });
70
+ }
71
+ async replay(from) {
72
+ const { results: events } = await this.table.query(
73
+ _indexcjs.wrapQueryParams.call(void 0, {
74
+ where: [...from ? [{ field: "ts", value: from.getTime(), condition: _indexcjs.Conditions.gte }] : []],
75
+ sort: [{ field: "ts", desc: false }],
76
+ all: true
77
+ })
78
+ );
79
+ for (const event of events) await this.#processEvent(event);
80
+ }
81
+ async rerun(key) {
82
+ const event = await this.table.findOne({ key });
83
+ if (!event) throw new (0, _indexcjs3.EquippedError)("audit event not found", { key });
84
+ await this.#processEvent(event);
85
+ }
86
+ createId() {
87
+ return _ulid.ulid.call(void 0, );
88
+ }
89
+ static defineHandler(def) {
90
+ return def;
91
+ }
92
+ }
93
+
94
+
95
+ exports.EventAudit = EventAudit;
96
+ //# sourceMappingURL=events.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/audit/events.ts","/home/runner/work/equipped/equipped/dist/cjs/audit/events.cjs"],"names":[],"mappings":"AAAA,qGAAqB;AACrB,oCAA+C;AAE/C,4CAAuD;AACvD,gDAA8B;AAmBvB,MAAM,WAAgE;AAAA,EAG5E,WAAA,CACS,EAAA,EACR,MAAA,EACQ,QAAA,EACP;AAHO,IAAA,IAAA,CAAA,GAAA,EAAA,EAAA;AAEA,IAAA,IAAA,CAAA,SAAA,EAAA,QAAA;AAER,IAAA,IAAA,CAAK,MAAA,EAAQ,EAAA,CAAG,GAAA,CAAI;AAAA,MACnB,EAAA,EAAI,MAAA;AAAA,MACJ,GAAA,EAAK,UAAA;AAAA,MACL,MAAA,EAAQ,CAAC,KAAA,EAAA,GAAA,CAAW,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,CAAA,EAAA,GAAM,MAAiC,CAAA,CAAA;AAAA,MAC/E,OAAA,EAAS,EAAE,SAAA,EAAW,KAAK;AAAA,IAC5B,CAAC,CAAA;AACD,IAAA,IAAA,CAAA,MAAW,IAAA,GAAO,QAAA,EAAU,WAAA,CAAE,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,CAAG,IAAI,CAAA;AAAA,EAC1D;AAAA,EAdQ;AAAA,EAgBR,MAAM,CAAA,WAAA,CAAyC,IAAA,EAAS,OAAA,EAAkC,IAAA,EAAwB;AACjH,IAAA,MAAM,QAAA,EAAU,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA;AAClC,IAAA,GAAA,CAAI,CAAC,OAAA,EAAS,MAAM,IAAI,6BAAA,CAAc,yBAAA,EAA2B,EAAE,IAAA,EAAM,OAAA,EAAS,KAAK,CAAC,CAAA;AAExF,IAAA,MAAM,aAAA,EAAe,WAAA,CAAE,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AACnD,IAAA,MAAM,IAAA,EAAM,IAAA,CAAK,QAAA,CAAS,CAAA;AAC1B,IAAA,MAAM,IAAA,kBAAM,IAAI,IAAA,CAAK,CAAA;AAErB,IAAA,MAAM,MAAA,EAAQ,MAAM,IAAA,CAAK,KAAA,CAAM,SAAA;AAAA,MAC9B;AAAA,QACC,GAAA;AAAA,QACA,IAAA;AAAA,QACA,IAAA;AAAA,QACA,EAAA,EAAI,GAAA,CAAI,OAAA,CAAQ,CAAA;AAAA,QAChB,OAAA,EAAS,YAAA;AAAA,QACT,MAAA,EAAQ,SAAA;AAAA,QACR,KAAA,EAAO,IAAA;AAAA,QACP,SAAA,EAAW,IAAA;AAAA,QACX,WAAA,EAAa;AAAA,MACd,CAAA;AAAA,MACA,EAAE,OAAA,EAAS,CAAA,EAAA,GAAM,GAAA,EAAK,MAAA,EAAQ,CAAA,EAAA,GAAM,IAAI;AAAA,IACzC,CAAA;AACA,IAAA,OAAO,KAAA;AAAA,EACR;AAAA,EAEA,MAAM,CAAA,YAAA,CAA0C,KAAA,EAA8C;AAE7F,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,OAAA,CAAQ,MAAA,CAAA,EAAA,GAAY;AAClC,MAAA,MAAM,QAAA,EAAU,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA;AACxC,MAAA,GAAA,CAAI,CAAC,OAAA,EAAS,MAAM,IAAI,6BAAA,CAAc,yBAAA,EAA2B,EAAE,MAAM,CAAC,CAAA;AAC1E,MAAA,IAAI;AACH,QAAA,MAAM,IAAA,CAAK,KAAA,CAAM,SAAA;AAAA,UAChB,EAAE,GAAA,EAAK,KAAA,CAAM,IAAI,CAAA;AAAA,UACjB,EAAE,IAAA,EAAM,EAAE,MAAA,EAAQ,YAAA,EAAc,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,WAAA,EAAa,IAAA,EAAM,KAAA,EAAO,KAAK,EAAE;AAAA,QACzF,CAAA;AACA,QAAA,MAAM,OAAA,EAAS,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS;AAAA,UAClD,cAAA,EAAgB,KAAA,CAAM,GAAA,CAAI,QAAA,CAAS,CAAA;AAAA,UACnC,eAAA,EAAiB,IAAI,IAAA,CAAK,KAAA,CAAM,EAAE;AAAA,QACnC,CAAC,CAAA;AACD,QAAA,MAAM,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,EAAE,GAAA,EAAK,KAAA,CAAM,IAAI,CAAA,EAAG,EAAE,IAAA,EAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,WAAA,EAAa,IAAA,CAAK,GAAA,CAAI,EAAE,EAAE,CAAC,CAAA;AACpG,QAAA,OAAO,MAAA;AAAA,MACR,EAAA,MAAA,CAAS,GAAA,EAAK;AACb,QAAA,MAAM,QAAA,EAAU,IAAA,WAAe,MAAA,EAAQ,GAAA,CAAI,QAAA,EAAU,MAAA,CAAO,GAAG,CAAA;AAC/D,QAAA,MAAM,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,EAAE,GAAA,EAAK,KAAA,CAAM,IAAI,CAAA,EAAG,EAAE,IAAA,EAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,KAAA,EAAO,OAAA,EAAS,WAAA,EAAa,IAAA,CAAK,GAAA,CAAI,EAAE,EAAE,CAAC,CAAA;AACtH,QAAA,MAAM,GAAA;AAAA,MACP;AAAA,IACD,CAAC,CAAA;AAAA,EACF;AAAA,EAEA,MAAM,UAAA,CAAuC,IAAA,EAAS,OAAA,EAAkC;AACvF,IAAA,MAAM,MAAA,EAAQ,MAAM,IAAA,CAAK,CAAA,WAAA,CAAa,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAC3D,IAAA,OAAO,IAAA,CAAK,CAAA,YAAA,CAAc,KAAK,CAAA;AAAA,EAChC;AAAA,EAEA,MAAM,WAAA,CAAwC,IAAA,EAAS,OAAA,EAAkC;AACxF,IAAA,MAAM,MAAA,EAAQ,MAAM,IAAA,CAAK,CAAA,WAAA,CAAa,IAAA,EAAM,OAAA,EAAS,OAAO,CAAA;AAC5D,IAAA,IAAA,CAAK,CAAA,YAAA,CAAc,KAAK,CAAA,CAAE,KAAA,CAAM,CAAA,EAAA,GAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EACzC;AAAA,EAEA,MAAM,MAAA,CAAO,IAAA,EAAa;AACzB,IAAA,MAAM,EAAE,OAAA,EAAS,OAAO,EAAA,EAAI,MAAM,IAAA,CAAK,KAAA,CAAM,KAAA;AAAA,MAC5C,uCAAA;AAAgB,QACf,KAAA,EAAO,CAAC,GAAI,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,EAAG,SAAA,EAAW,oBAAA,CAAW,IAAI,CAAC,EAAA,EAAI,CAAC,CAAE,CAAA;AAAA,QAC5F,IAAA,EAAM,CAAC,EAAE,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,MAAM,CAAC,CAAA;AAAA,QACnC,GAAA,EAAK;AAAA,MACN,CAAC;AAAA,IACF,CAAA;AACA,IAAA,IAAA,CAAA,MAAW,MAAA,GAAS,MAAA,EAAQ,MAAM,IAAA,CAAK,CAAA,YAAA,CAAc,KAAK,CAAA;AAAA,EAC3D;AAAA,EAEA,MAAM,KAAA,CAAM,GAAA,EAAa;AACxB,IAAA,MAAM,MAAA,EAAQ,MAAM,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,EAAE,IAAI,CAAC,CAAA;AAC9C,IAAA,GAAA,CAAI,CAAC,KAAA,EAAO,MAAM,IAAI,6BAAA,CAAc,uBAAA,EAAyB,EAAE,IAAI,CAAC,CAAA;AACpE,IAAA,MAAM,IAAA,CAAK,CAAA,YAAA,CAAc,KAAK,CAAA;AAAA,EAC/B;AAAA,EAEA,QAAA,CAAA,EAAW;AACV,IAAA,OAAO,wBAAA,CAAK;AAAA,EACb;AAAA,EAEA,OAAO,aAAA,CAAoB,GAAA,EAA4B;AACtD,IAAA,OAAO,GAAA;AAAA,EACR;AACD;AC/BA;AACE;AACF,gCAAC","file":"/home/runner/work/equipped/equipped/dist/cjs/audit/events.cjs","sourcesContent":["import { ulid } from 'ulid'\nimport { Pipe, PipeInput, PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\n\nexport type EventDefinition<P, R> = {\n\tpipe: Pipe<any, P>\n\thandle: (payload: P, context: { idempotencyKey: string; idempotencyDate: Date }) => Promise<R>\n}\n\ntype EventDoc<K extends string, P> = {\n\tkey: string\n\ttype: K\n\tts: number\n\tpayload: P\n\tmode: 'sync' | 'async'\n\tstatus: 'pending' | 'processing' | 'done' | 'failed'\n\terror: string | null\n\tstartedAt: number | null\n\tcompletedAt: number | null\n}\n\nexport class EventAudit<E extends Record<string, EventDefinition<any, any>>> {\n\tprivate table: Table<any, EventDoc<string, any>, EventDoc<string, any> & { toJSON: () => Record<string, unknown> }, any>\n\n\tconstructor(\n\t\tprivate db: Db<any>,\n\t\tdbName: string,\n\t\tprivate handlers: E,\n\t) {\n\t\tthis.table = db.use({\n\t\t\tdb: dbName,\n\t\t\tcol: '__audits',\n\t\t\tmapper: (model) => ({ ...model, toJSON: () => model as Record<string, unknown> }),\n\t\t\toptions: { skipAudit: true },\n\t\t})\n\t\tfor (const key in handlers) v.compile(handlers[key]!.pipe)\n\t}\n\n\tasync #createEvent<K extends keyof E & string>(type: K, payload: PipeInput<E[K]['pipe']>, mode: 'sync' | 'async') {\n\t\tconst handler = this.handlers[type]\n\t\tif (!handler) throw new EquippedError('audit handler not found', { type, payload, mode })\n\n\t\tconst validPayload = v.assert(handler.pipe, payload)\n\t\tconst key = this.createId()\n\t\tconst now = new Date()\n\n\t\tconst audit = await this.table.insertOne(\n\t\t\t{\n\t\t\t\tkey,\n\t\t\t\ttype,\n\t\t\t\tmode,\n\t\t\t\tts: now.getTime(),\n\t\t\t\tpayload: validPayload,\n\t\t\t\tstatus: 'pending',\n\t\t\t\terror: null,\n\t\t\t\tstartedAt: null,\n\t\t\t\tcompletedAt: null,\n\t\t\t},\n\t\t\t{ getTime: () => now, makeId: () => key },\n\t\t)\n\t\treturn audit as unknown as EventDoc<K, PipeOutput<E[K]['pipe']>>\n\t}\n\n\tasync #processEvent<K extends keyof E & string>(event: EventDoc<K, PipeOutput<E[K]['pipe']>>) {\n\t\ttype HandlerResult = E[K] extends EventDefinition<any, infer R> ? R : never\n\t\treturn this.db.session(async () => {\n\t\t\tconst handler = this.handlers[event.type]\n\t\t\tif (!handler) throw new EquippedError('audit handler not found', { event })\n\t\t\ttry {\n\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t{ $set: { status: 'processing', startedAt: Date.now(), completedAt: null, error: null } },\n\t\t\t\t)\n\t\t\t\tconst result = await handler.handle(event.payload, {\n\t\t\t\t\tidempotencyKey: event.key.toString(),\n\t\t\t\t\tidempotencyDate: new Date(event.ts),\n\t\t\t\t})\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $set: { status: 'done', completedAt: Date.now() } })\n\t\t\t\treturn result as HandlerResult\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $set: { status: 'failed', error: message, completedAt: Date.now() } })\n\t\t\t\tthrow err\n\t\t\t}\n\t\t})\n\t}\n\n\tasync createSync<K extends keyof E & string>(type: K, payload: PipeInput<E[K]['pipe']>) {\n\t\tconst event = await this.#createEvent(type, payload, 'sync')\n\t\treturn this.#processEvent(event)\n\t}\n\n\tasync createAsync<K extends keyof E & string>(type: K, payload: PipeInput<E[K]['pipe']>) {\n\t\tconst event = await this.#createEvent(type, payload, 'async')\n\t\tthis.#processEvent(event).catch(() => {})\n\t}\n\n\tasync replay(from?: Date) {\n\t\tconst { results: events } = await this.table.query(\n\t\t\twrapQueryParams({\n\t\t\t\twhere: [...(from ? [{ field: 'ts', value: from.getTime(), condition: Conditions.gte }] : [])],\n\t\t\t\tsort: [{ field: 'ts', desc: false }],\n\t\t\t\tall: true,\n\t\t\t}),\n\t\t)\n\t\tfor (const event of events) await this.#processEvent(event)\n\t}\n\n\tasync rerun(key: string) {\n\t\tconst event = await this.table.findOne({ key })\n\t\tif (!event) throw new EquippedError('audit event not found', { key })\n\t\tawait this.#processEvent(event)\n\t}\n\n\tcreateId() {\n\t\treturn ulid()\n\t}\n\n\tstatic defineHandler<P, R>(def: EventDefinition<P, R>) {\n\t\treturn def\n\t}\n}\n",null]}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _ulid = require('ulid');var _valleyed = require('valleyed');var _indexmincjs = require('../dbs/index.min.cjs');var _indexmincjs3 = require('../errors/index.min.cjs');class k{constructor(t,n,e){this.db=t;this.handlers=e;this.table=t.use({db:n,col:"__audits",mapper:s=>({...s,toJSON:()=>s}),options:{skipAudit:!0}});for(const s in e)_valleyed.v.compile(e[s].pipe)}async#e(t,n,e){const s=this.handlers[t];if(!s)throw new (0, _indexmincjs3.EquippedError)("audit handler not found",{type:t,payload:n,mode:e});const p=_valleyed.v.assert(s.pipe,n),i=this.createId(),r=new Date;return await this.table.insertOne({key:i,type:t,mode:e,ts:r.getTime(),payload:p,status:"pending",error:null,startedAt:null,completedAt:null},{getTime:()=>r,makeId:()=>i})}async#t(t){return this.db.session(async()=>{const n=this.handlers[t.type];if(!n)throw new (0, _indexmincjs3.EquippedError)("audit handler not found",{event:t});try{await this.table.updateOne({key:t.key},{$set:{status:"processing",startedAt:Date.now(),completedAt:null,error:null}});const e=await n.handle(t.payload,{idempotencyKey:t.key.toString(),idempotencyDate:new Date(t.ts)});return await this.table.updateOne({key:t.key},{$set:{status:"done",completedAt:Date.now()}}),e}catch(e){const s=e instanceof Error?e.message:String(e);throw await this.table.updateOne({key:t.key},{$set:{status:"failed",error:s,completedAt:Date.now()}}),e}})}async createSync(t,n){const e=await this.#e(t,n,"sync");return this.#t(e)}async createAsync(t,n){const e=await this.#e(t,n,"async");this.#t(e).catch(()=>{})}async replay(t){const{results:n}=await this.table.query(_indexmincjs.wrapQueryParams.call(void 0, {where:[...t?[{field:"ts",value:t.getTime(),condition:_indexmincjs.Conditions.gte}]:[]],sort:[{field:"ts",desc:!1}],all:!0}));for(const e of n)await this.#t(e)}async rerun(t){const n=await this.table.findOne({key:t});if(!n)throw new (0, _indexmincjs3.EquippedError)("audit event not found",{key:t});await this.#t(n)}createId(){return _ulid.ulid.call(void 0, )}static defineHandler(t){return t}}exports.EventAudit = k;
2
+ //# sourceMappingURL=events.min.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/audit/events.ts"],"names":["db","handlers","model","key","#createEvent","mode","handler","type","EquippedError","v","now","validPayload","event","err","message","payload","#processEvent","from","events","Conditions","ulid"],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/audit/events.min.cjs","sourcesContent":["import { ulid } from 'ulid'\nimport { Pipe, PipeInput, PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\n\nexport type EventDefinition<P, R> = {\n\tpipe: Pipe<any, P>\n\thandle: (payload: P, context: { idempotencyKey: string; idempotencyDate: Date }) => Promise<R>\n}\n\ntype EventDoc<K extends string, P> = {\n\tkey: string\n\ttype: K\n\tts: number\n\tpayload: P\n\tmode: 'sync' | 'async'\n\tstatus: 'pending' | 'processing' | 'done' | 'failed'\n\terror: string | null\n\tstartedAt: number | null\n\tcompletedAt: number | null\n}\n\nexport class EventAudit<E extends Record<string, EventDefinition<any, any>>> {\n\tprivate table: Table<any, EventDoc<string, any>, EventDoc<string, any> & { toJSON: () => Record<string, unknown> }, any>\n\n\tconstructor(\n\t\tprivate db: Db<any>,\n\t\tdbName: string,\n\t\tprivate handlers: E,\n\t) {\n\t\tthis.table = db.use({\n\t\t\tdb: dbName,\n\t\t\tcol: '__audits',\n\t\t\tmapper: (model) => ({ ...model, toJSON: () => model as Record<string, unknown> }),\n\t\t\toptions: { skipAudit: true },\n\t\t})\n\t\tfor (const key in handlers) v.compile(handlers[key]!.pipe)\n\t}\n\n\tasync #createEvent<K extends keyof E & string>(type: K, payload: PipeInput<E[K]['pipe']>, mode: 'sync' | 'async') {\n\t\tconst handler = this.handlers[type]\n\t\tif (!handler) throw new EquippedError('audit handler not found', { type, payload, mode })\n\n\t\tconst validPayload = v.assert(handler.pipe, payload)\n\t\tconst key = this.createId()\n\t\tconst now = new Date()\n\n\t\tconst audit = await this.table.insertOne(\n\t\t\t{\n\t\t\t\tkey,\n\t\t\t\ttype,\n\t\t\t\tmode,\n\t\t\t\tts: now.getTime(),\n\t\t\t\tpayload: validPayload,\n\t\t\t\tstatus: 'pending',\n\t\t\t\terror: null,\n\t\t\t\tstartedAt: null,\n\t\t\t\tcompletedAt: null,\n\t\t\t},\n\t\t\t{ getTime: () => now, makeId: () => key },\n\t\t)\n\t\treturn audit as unknown as EventDoc<K, PipeOutput<E[K]['pipe']>>\n\t}\n\n\tasync #processEvent<K extends keyof E & string>(event: EventDoc<K, PipeOutput<E[K]['pipe']>>) {\n\t\ttype HandlerResult = E[K] extends EventDefinition<any, infer R> ? R : never\n\t\treturn this.db.session(async () => {\n\t\t\tconst handler = this.handlers[event.type]\n\t\t\tif (!handler) throw new EquippedError('audit handler not found', { event })\n\t\t\ttry {\n\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t{ $set: { status: 'processing', startedAt: Date.now(), completedAt: null, error: null } },\n\t\t\t\t)\n\t\t\t\tconst result = await handler.handle(event.payload, {\n\t\t\t\t\tidempotencyKey: event.key.toString(),\n\t\t\t\t\tidempotencyDate: new Date(event.ts),\n\t\t\t\t})\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $set: { status: 'done', completedAt: Date.now() } })\n\t\t\t\treturn result as HandlerResult\n\t\t\t} catch (err) {\n\t\t\t\tconst message = err instanceof Error ? err.message : String(err)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $set: { status: 'failed', error: message, completedAt: Date.now() } })\n\t\t\t\tthrow err\n\t\t\t}\n\t\t})\n\t}\n\n\tasync createSync<K extends keyof E & string>(type: K, payload: PipeInput<E[K]['pipe']>) {\n\t\tconst event = await this.#createEvent(type, payload, 'sync')\n\t\treturn this.#processEvent(event)\n\t}\n\n\tasync createAsync<K extends keyof E & string>(type: K, payload: PipeInput<E[K]['pipe']>) {\n\t\tconst event = await this.#createEvent(type, payload, 'async')\n\t\tthis.#processEvent(event).catch(() => {})\n\t}\n\n\tasync replay(from?: Date) {\n\t\tconst { results: events } = await this.table.query(\n\t\t\twrapQueryParams({\n\t\t\t\twhere: [...(from ? [{ field: 'ts', value: from.getTime(), condition: Conditions.gte }] : [])],\n\t\t\t\tsort: [{ field: 'ts', desc: false }],\n\t\t\t\tall: true,\n\t\t\t}),\n\t\t)\n\t\tfor (const event of events) await this.#processEvent(event)\n\t}\n\n\tasync rerun(key: string) {\n\t\tconst event = await this.table.findOne({ key })\n\t\tif (!event) throw new EquippedError('audit event not found', { key })\n\t\tawait this.#processEvent(event)\n\t}\n\n\tcreateId() {\n\t\treturn ulid()\n\t}\n\n\tstatic defineHandler<P, R>(def: EventDefinition<P, R>) {\n\t\treturn def\n\t}\n}\n"]}
@@ -0,0 +1,5 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _eventscjs = require('./events.cjs');
2
+
3
+
4
+ exports.EventAudit = _eventscjs.EventAudit;
5
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/audit/index.ts","/home/runner/work/equipped/equipped/dist/cjs/audit/index.cjs"],"names":[],"mappings":"AAAA,kHAA2B;ACC3B;AACE;AACF,2CAAC","file":"/home/runner/work/equipped/equipped/dist/cjs/audit/index.cjs","sourcesContent":["export { EventAudit } from './events'\n",null]}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _eventsmincjs = require('./events.min.cjs');exports.EventAudit = _eventsmincjs.EventAudit;
2
+ //# sourceMappingURL=index.min.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/audit/index.ts"],"names":[],"mappings":"AAAA,yHAA2B,8CAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/audit/index.min.cjs","sourcesContent":["export { EventAudit } from './events'\n"]}
@@ -83,10 +83,12 @@ class Server {
83
83
  const defs = [
84
84
  { key: "params", type: "request" },
85
85
  { key: "headers", type: "request" },
86
+ { key: "cookies", type: "request" },
86
87
  { key: "query", type: "request" },
87
88
  { key: "body", type: "request", skip: ![_typescjs.Methods.post, _typescjs.Methods.put, _typescjs.Methods.patch].includes(method) },
88
89
  { key: "response", type: "response" },
89
- { key: "responseHeaders", type: "response" }
90
+ { key: "responseHeaders", type: "response" },
91
+ { key: "responseCookies", type: "response" }
90
92
  ];
91
93
  defs.forEach((def) => {
92
94
  const pipe = _nullishCoalesce(schema[def.key], () => ( _valleyed.v.any()));
@@ -123,7 +125,8 @@ class Server {
123
125
  params: request.params,
124
126
  headers: request.headers,
125
127
  query: request.query,
126
- body: request.body
128
+ body: request.body,
129
+ cookies: request.cookies
127
130
  })
128
131
  );
129
132
  if (!validity.valid) throw _indexcjs5.pipeErrorToValidationError.call(void 0, validity.error);
@@ -131,6 +134,7 @@ class Server {
131
134
  request.headers = validity.value.headers;
132
135
  request.query = validity.value.query;
133
136
  request.body = validity.value.body;
137
+ request.cookies = validity.value.cookies;
134
138
  return request;
135
139
  };
136
140
  const validateResponse = async (response) => {
@@ -141,12 +145,14 @@ class Server {
141
145
  response,
142
146
  () => _valleyed.v.validate(responsePipe, {
143
147
  responseHeaders: response.headers,
148
+ responseCookies: response.cookies,
144
149
  response: response.body
145
150
  })
146
151
  );
147
152
  if (!validity.valid) throw _indexcjs5.pipeErrorToValidationError.call(void 0, validity.error);
148
153
  response.body = validity.value.response;
149
154
  response.headers = validity.value.responseHeaders;
155
+ response.cookieValues = validity.value.responseCookies;
150
156
  return response;
151
157
  };
152
158
  return {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/base.ts","/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.cjs"],"names":[],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.cjs","sourcesContent":["import type http from 'http'\n\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { parseAuthUser } from '../middlewares/parseAuthUser'\nimport { OpenApi, OpenApiSchemaDef } from '../openapi'\nimport { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, MethodsEnum, RouteDef, StatusCodes, type Route } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected cors = {\n\t\torigin: '*',\n\t\tmethods: Object.values(Methods)\n\t\t\t.filter((m) => m !== Methods.options)\n\t\t\t.map((m) => m.toUpperCase()),\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.unshift(parseAuthUser as any)\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst context = schema.context ? await schema.context(request) : {}\n\t\t\trequest.context = context\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params\n\t\t\trequest.headers = validity.value.headers\n\t\t\trequest.query = validity.value.query\n\t\t\trequest.body = validity.value.body\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response\n\t\t\tresponse.headers = validity.value.responseHeaders\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tInstance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n",null]}
1
+ {"version":3,"sources":["../../../../src/server/impls/base.ts","/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.cjs"],"names":[],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.cjs","sourcesContent":["import type http from 'http'\n\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { parseAuthUser } from '../middlewares/parseAuthUser'\nimport { OpenApi, OpenApiSchemaDef } from '../openapi'\nimport { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, MethodsEnum, RouteDef, StatusCodes, type Route } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected cors = {\n\t\torigin: '*',\n\t\tmethods: Object.values(Methods)\n\t\t\t.filter((m) => m !== Methods.options)\n\t\t\t.map((m) => m.toUpperCase()),\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.unshift(parseAuthUser as any)\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst context = schema.context ? await schema.context(request) : {}\n\t\t\trequest.context = context\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: response.cookies,\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tInstance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n",null]}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _socketio = require('socket.io');var _supertest = require('supertest'); var _supertest2 = _interopRequireDefault(_supertest);var _valleyed = require('valleyed');var _indexmincjs = require('../../errors/index.min.cjs');var _indexmincjs3 = require('../../instance/index.min.cjs');var _indexmincjs5 = require('../../validations/index.min.cjs');var _valleyedmincjs = require('../../validations/valleyed.min.cjs');var _parseAuthUsermincjs = require('../middlewares/parseAuthUser.min.cjs');var _openapimincjs = require('../openapi.min.cjs');var _requestsmincjs = require('../requests.min.cjs');var _socketsmincjs = require('../sockets.min.cjs');var _typesmincjs = require('../types.min.cjs');const U=Object.entries(_typesmincjs.StatusCodes).filter(([,f])=>f>399).map(([f,s])=>({status:s,contentType:"application/json",pipe:_valleyed.v.meta(_valleyed.v.array(_valleyed.v.object({message:_valleyed.v.string(),field:_valleyed.v.optional(_valleyed.v.string())})),{$refId:`Errors.${f}Response`,description:`${f} Response`})}));class ae{constructor(s,t,i){;ae.prototype.__init.call(this);this.config=t;this.implementations=i;this.server=s,this.#e=new (0, _openapimincjs.OpenApi)(t);const c=new (0, _socketio.Server)(s,{cors:this.cors});this.socket=new (0, _socketsmincjs.SocketEmitter)(c,t),this.addRouter(this.#e.router())}#t=[];#s=new Map;#e;__init() {this.cors={origin:"*",methods:Object.values(_typesmincjs.Methods).filter(s=>s!==_typesmincjs.Methods.options).map(s=>s.toUpperCase())}}addRouter(...s){s.map(t=>t.routes).forEach(t=>this.addRoute(...t))}addRoute(...s){s.forEach(t=>{this.#t.push(async()=>{const{method:i,path:c,schema:o={},onError:d,middlewares:u=[]}=t,p=`(${i.toUpperCase()}) ${this.#e.cleanPath(c)}`;if(this.#s.get(p))throw new (0, _indexmincjs.EquippedError)(`Route key ${p} already registered. All route keys must be unique`,{route:t,key:p});u.unshift(_parseAuthUsermincjs.parseAuthUser),u.forEach(m=>_optionalChain([m, 'access', _ => _.onSetup, 'optionalCall', _2 => _2(t)])),_optionalChain([d, 'optionalAccess', _3 => _3.onSetup, 'optionalCall', _4 => _4(t)]);const{validateRequest:R,validateResponse:q,jsonSchema:g}=this.#o(i,o);this.#s.set(p,!0),await this.#e.register(t,g),this.implementations.registerRoute(i,this.#e.cleanPath(c),async(m,k)=>{const w=await R(await this.implementations.parseRequest(m));try{for(const n of u)await n.cb(w,this.config);const e=await t.handler(w,this.config),a=e instanceof _requestsmincjs.Response?e:new (0, _requestsmincjs.Response)({body:e,status:_typesmincjs.StatusCodes.Ok,headers:{},piped:!1});return await this.implementations.handleResponse(k,await q(a))}catch(e){if(_optionalChain([d, 'optionalAccess', _5 => _5.cb])){const a=await d.cb(w,this.config,e),n=a instanceof _requestsmincjs.Response?a:new (0, _requestsmincjs.Response)({body:a,status:_typesmincjs.StatusCodes.BadRequest,headers:{}});return await this.implementations.handleResponse(k,await q(n))}throw e}})})})}#o(s,t){const i=_nullishCoalesce(_optionalChain([t, 'optionalAccess', _6 => _6.defaultStatusCode]), () => (_typesmincjs.StatusCodes.Ok)),c=_nullishCoalesce(_optionalChain([t, 'optionalAccess', _7 => _7.defaultContentType]), () => ("application/json"));let o=i,d=c;const u={response:{},request:{}},p={},R={};[{key:"params",type:"request"},{key:"headers",type:"request"},{key:"query",type:"request"},{key:"body",type:"request",skip:![_typesmincjs.Methods.post,_typesmincjs.Methods.put,_typesmincjs.Methods.patch].includes(s)},{key:"response",type:"response"},{key:"responseHeaders",type:"response"}].forEach(e=>{const a=_nullishCoalesce(t[e.key], () => (_valleyed.v.any()));if(!e.skip&&(e.type==="request"&&(p[e.key]=a,u.request[e.key]=_valleyed.v.schema(a)),e.type==="response")){const n=U.concat({status:i,contentType:d,pipe:a});R[e.key]=_valleyed.v.any().pipe(h=>{const E=_optionalChain([n, 'access', _8 => _8.find, 'call', _9 => _9(P=>P.status===o), 'optionalAccess', _10 => _10.pipe]);if(!E)throw _valleyed.PipeError.root(`schema not defined for status code: ${o}`,h);return _valleyed.v.assert(E,h)}),u.response[e.key]=n.map(h=>({status:h.status,contentType:h.contentType,schema:_valleyed.v.schema(h.pipe)}))}});const g=_valleyed.v.object(p);_valleyed.v.compile(g,{allErrors:!0});const m=_valleyed.v.object(R);return _valleyed.v.compile(m,{allErrors:!0}),{jsonSchema:u,validateRequest:async e=>{if(!Object.keys(p))return e;const a=t.context?await t.context(e):{};e.context=a;const n=_valleyedmincjs.requestLocalStorage.run(e,()=>_valleyed.v.validate(g,{params:e.params,headers:e.headers,query:e.query,body:e.body}));if(!n.valid)throw _indexmincjs5.pipeErrorToValidationError.call(void 0, n.error);return e.params=n.value.params,e.headers=n.value.headers,e.query=n.value.query,e.body=n.value.body,e},validateResponse:async e=>{if(!Object.keys(R))return e;o=e.status,d=e.contentType;const a=_valleyedmincjs.responseLocalStorage.run(e,()=>_valleyed.v.validate(m,{responseHeaders:e.headers,response:e.body}));if(!a.valid)throw _indexmincjs5.pipeErrorToValidationError.call(void 0, a.error);return e.body=a.value.response,e.headers=a.value.responseHeaders,e}}}test(){return _supertest2.default.call(void 0, this.server)}async start(){const s=this.config.port,t=_indexmincjs3.Instance.get(),{app:i}=t.settings;this.config.healthPath&&this.addRoute({method:_typesmincjs.Methods.get,path:this.config.healthPath,handler:async o=>o.res({body:`${t.id}(${i.name}) service running`,contentType:"text/plain"})}),this.implementations.registerNotFoundHandler(async o=>{const d=await this.implementations.parseRequest(o);throw new (0, _indexmincjs.NotFoundError)(`Route ${d.path} not found`)}),this.implementations.registerErrorHandler(async(o,d,u)=>{_indexmincjs3.Instance.get().log.error({error:o},"Uncaught error in route handler");const p=o instanceof _indexmincjs.RequestError?new (0, _requestsmincjs.Response)({body:o.serializedErrors,status:o.statusCode}):new (0, _requestsmincjs.Response)({body:[{message:"Something went wrong",data:o.message}],status:_typesmincjs.StatusCodes.BadRequest});return await this.implementations.handleResponse(u,p)}),await Promise.all(this.#t.map(o=>o()));const c=await this.implementations.start(s);return c&&_indexmincjs3.Instance.get().log.info(`${t.id}(${i.name}) service listening on port ${s}`),c}}exports.Server = ae;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _socketio = require('socket.io');var _supertest = require('supertest'); var _supertest2 = _interopRequireDefault(_supertest);var _valleyed = require('valleyed');var _indexmincjs = require('../../errors/index.min.cjs');var _indexmincjs3 = require('../../instance/index.min.cjs');var _indexmincjs5 = require('../../validations/index.min.cjs');var _valleyedmincjs = require('../../validations/valleyed.min.cjs');var _parseAuthUsermincjs = require('../middlewares/parseAuthUser.min.cjs');var _openapimincjs = require('../openapi.min.cjs');var _requestsmincjs = require('../requests.min.cjs');var _socketsmincjs = require('../sockets.min.cjs');var _typesmincjs = require('../types.min.cjs');const U=Object.entries(_typesmincjs.StatusCodes).filter(([,f])=>f>399).map(([f,s])=>({status:s,contentType:"application/json",pipe:_valleyed.v.meta(_valleyed.v.array(_valleyed.v.object({message:_valleyed.v.string(),field:_valleyed.v.optional(_valleyed.v.string())})),{$refId:`Errors.${f}Response`,description:`${f} Response`})}));class ae{constructor(s,t,i){;ae.prototype.__init.call(this);this.config=t;this.implementations=i;this.server=s,this.#e=new (0, _openapimincjs.OpenApi)(t);const c=new (0, _socketio.Server)(s,{cors:this.cors});this.socket=new (0, _socketsmincjs.SocketEmitter)(c,t),this.addRouter(this.#e.router())}#t=[];#s=new Map;#e;__init() {this.cors={origin:"*",methods:Object.values(_typesmincjs.Methods).filter(s=>s!==_typesmincjs.Methods.options).map(s=>s.toUpperCase())}}addRouter(...s){s.map(t=>t.routes).forEach(t=>this.addRoute(...t))}addRoute(...s){s.forEach(t=>{this.#t.push(async()=>{const{method:i,path:c,schema:o={},onError:d,middlewares:u=[]}=t,p=`(${i.toUpperCase()}) ${this.#e.cleanPath(c)}`;if(this.#s.get(p))throw new (0, _indexmincjs.EquippedError)(`Route key ${p} already registered. All route keys must be unique`,{route:t,key:p});u.unshift(_parseAuthUsermincjs.parseAuthUser),u.forEach(m=>_optionalChain([m, 'access', _ => _.onSetup, 'optionalCall', _2 => _2(t)])),_optionalChain([d, 'optionalAccess', _3 => _3.onSetup, 'optionalCall', _4 => _4(t)]);const{validateRequest:R,validateResponse:w,jsonSchema:v}=this.#o(i,o);this.#s.set(p,!0),await this.#e.register(t,v),this.implementations.registerRoute(i,this.#e.cleanPath(c),async(m,q)=>{const g=await R(await this.implementations.parseRequest(m));try{for(const n of u)await n.cb(g,this.config);const e=await t.handler(g,this.config),r=e instanceof _requestsmincjs.Response?e:new (0, _requestsmincjs.Response)({body:e,status:_typesmincjs.StatusCodes.Ok,headers:{},piped:!1});return await this.implementations.handleResponse(q,await w(r))}catch(e){if(_optionalChain([d, 'optionalAccess', _5 => _5.cb])){const r=await d.cb(g,this.config,e),n=r instanceof _requestsmincjs.Response?r:new (0, _requestsmincjs.Response)({body:r,status:_typesmincjs.StatusCodes.BadRequest,headers:{}});return await this.implementations.handleResponse(q,await w(n))}throw e}})})})}#o(s,t){const i=_nullishCoalesce(_optionalChain([t, 'optionalAccess', _6 => _6.defaultStatusCode]), () => (_typesmincjs.StatusCodes.Ok)),c=_nullishCoalesce(_optionalChain([t, 'optionalAccess', _7 => _7.defaultContentType]), () => ("application/json"));let o=i,d=c;const u={response:{},request:{}},p={},R={};[{key:"params",type:"request"},{key:"headers",type:"request"},{key:"cookies",type:"request"},{key:"query",type:"request"},{key:"body",type:"request",skip:![_typesmincjs.Methods.post,_typesmincjs.Methods.put,_typesmincjs.Methods.patch].includes(s)},{key:"response",type:"response"},{key:"responseHeaders",type:"response"},{key:"responseCookies",type:"response"}].forEach(e=>{const r=_nullishCoalesce(t[e.key], () => (_valleyed.v.any()));if(!e.skip&&(e.type==="request"&&(p[e.key]=r,u.request[e.key]=_valleyed.v.schema(r)),e.type==="response")){const n=U.concat({status:i,contentType:d,pipe:r});R[e.key]=_valleyed.v.any().pipe(h=>{const E=_optionalChain([n, 'access', _8 => _8.find, 'call', _9 => _9(P=>P.status===o), 'optionalAccess', _10 => _10.pipe]);if(!E)throw _valleyed.PipeError.root(`schema not defined for status code: ${o}`,h);return _valleyed.v.assert(E,h)}),u.response[e.key]=n.map(h=>({status:h.status,contentType:h.contentType,schema:_valleyed.v.schema(h.pipe)}))}});const v=_valleyed.v.object(p);_valleyed.v.compile(v,{allErrors:!0});const m=_valleyed.v.object(R);return _valleyed.v.compile(m,{allErrors:!0}),{jsonSchema:u,validateRequest:async e=>{if(!Object.keys(p))return e;const r=t.context?await t.context(e):{};e.context=r;const n=_valleyedmincjs.requestLocalStorage.run(e,()=>_valleyed.v.validate(v,{params:e.params,headers:e.headers,query:e.query,body:e.body,cookies:e.cookies}));if(!n.valid)throw _indexmincjs5.pipeErrorToValidationError.call(void 0, n.error);return e.params=n.value.params,e.headers=n.value.headers,e.query=n.value.query,e.body=n.value.body,e.cookies=n.value.cookies,e},validateResponse:async e=>{if(!Object.keys(R))return e;o=e.status,d=e.contentType;const r=_valleyedmincjs.responseLocalStorage.run(e,()=>_valleyed.v.validate(m,{responseHeaders:e.headers,responseCookies:e.cookies,response:e.body}));if(!r.valid)throw _indexmincjs5.pipeErrorToValidationError.call(void 0, r.error);return e.body=r.value.response,e.headers=r.value.responseHeaders,e.cookieValues=r.value.responseCookies,e}}}test(){return _supertest2.default.call(void 0, this.server)}async start(){const s=this.config.port,t=_indexmincjs3.Instance.get(),{app:i}=t.settings;this.config.healthPath&&this.addRoute({method:_typesmincjs.Methods.get,path:this.config.healthPath,handler:async o=>o.res({body:`${t.id}(${i.name}) service running`,contentType:"text/plain"})}),this.implementations.registerNotFoundHandler(async o=>{const d=await this.implementations.parseRequest(o);throw new (0, _indexmincjs.NotFoundError)(`Route ${d.path} not found`)}),this.implementations.registerErrorHandler(async(o,d,u)=>{_indexmincjs3.Instance.get().log.error({error:o},"Uncaught error in route handler");const p=o instanceof _indexmincjs.RequestError?new (0, _requestsmincjs.Response)({body:o.serializedErrors,status:o.statusCode}):new (0, _requestsmincjs.Response)({body:[{message:"Something went wrong",data:o.message}],status:_typesmincjs.StatusCodes.BadRequest});return await this.implementations.handleResponse(u,p)}),await Promise.all(this.#t.map(o=>o()));const c=await this.implementations.start(s);return c&&_indexmincjs3.Instance.get().log.info(`${t.id}(${i.name}) service listening on port ${s}`),c}}exports.Server = ae;
2
2
  //# sourceMappingURL=base.min.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/base.ts"],"names":["StatusCodes","v","key","server","config","implementations"],"mappings":"AAEA,szBAAuC,4FACjB,oCACa,yDAG1B,4DACA,+DACqB,oEACA,2EAGS,mDAET,qDACWA,mDAMvB,+CAGH,MACb,CAAA,CAAA,MAAQ,CAAA,OAAO,CAAA,wBAAMC,CAAAA,CAAE,MAAA,CAAO,CAAE,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,CAASA,CAAAA,GAAE,CAAA,CAAA,GAAO,CAAA,CAAG,CAAA,CAAA,CAAA,CAAA,CAAA,CAAOA,EAAE,CAAA,CAAA,MAAA,CAASA,CAAAA,CAAE,WAAY,CAAA,kBAC5E,CAAUC,IAAG,CAAA,WAAA,CAAA,IAAA,CACrB,WAAA,CAAA,KAAA,CAAA,WAAA,CAAA,MAAmB,CAAA,CAAA,OAAA,CAAA,WACpB,CAAC,MAGI,CAAA,CAAA,CAAA,KAaN,CAAA,WAAA,CAAA,QAAA,CACCC,WAAAA,CACQC,MAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,MACA,CAAA,CAAA,OAAA,EAAA,CAAA,CAAA,QAAAC,CASR,CAAA,WAAcF,CAAAA,CACd,EAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.min.cjs","sourcesContent":["import type http from 'http'\n\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { parseAuthUser } from '../middlewares/parseAuthUser'\nimport { OpenApi, OpenApiSchemaDef } from '../openapi'\nimport { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, MethodsEnum, RouteDef, StatusCodes, type Route } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected cors = {\n\t\torigin: '*',\n\t\tmethods: Object.values(Methods)\n\t\t\t.filter((m) => m !== Methods.options)\n\t\t\t.map((m) => m.toUpperCase()),\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.unshift(parseAuthUser as any)\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst context = schema.context ? await schema.context(request) : {}\n\t\t\trequest.context = context\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params\n\t\t\trequest.headers = validity.value.headers\n\t\t\trequest.query = validity.value.query\n\t\t\trequest.body = validity.value.body\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response\n\t\t\tresponse.headers = validity.value.responseHeaders\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tInstance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/server/impls/base.ts"],"names":["StatusCodes","v","key","server","config","implementations"],"mappings":"AAEA,szBAAuC,4FACjB,oCACa,yDAG1B,4DACA,+DACqB,oEACA,2EAGS,mDAET,qDACWA,mDAMvB,+CAGH,MACb,CAAA,CAAA,MAAQ,CAAA,OAAO,CAAA,wBAAMC,CAAAA,CAAE,MAAA,CAAO,CAAE,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,CAASA,CAAAA,GAAE,CAAA,CAAA,GAAO,CAAA,CAAG,CAAA,CAAA,CAAA,CAAA,CAAA,CAAOA,EAAE,CAAA,CAAA,MAAA,CAASA,CAAAA,CAAE,WAAY,CAAA,kBAC5E,CAAUC,IAAG,CAAA,WAAA,CAAA,IAAA,CACrB,WAAA,CAAA,KAAA,CAAA,WAAA,CAAA,MAAmB,CAAA,CAAA,OAAA,CAAA,WACpB,CAAC,MAGI,CAAA,CAAA,CAAA,KAaN,CAAA,WAAA,CAAA,QAAA,CACCC,WAAAA,CACQC,MAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,MACA,CAAA,CAAA,OAAA,EAAA,CAAA,CAAA,QAAAC,CASR,CAAA,WAAcF,CAAAA,CACd,EAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.min.cjs","sourcesContent":["import type http from 'http'\n\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { parseAuthUser } from '../middlewares/parseAuthUser'\nimport { OpenApi, OpenApiSchemaDef } from '../openapi'\nimport { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, MethodsEnum, RouteDef, StatusCodes, type Route } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected cors = {\n\t\torigin: '*',\n\t\tmethods: Object.values(Methods)\n\t\t\t.filter((m) => m !== Methods.options)\n\t\t\t.map((m) => m.toUpperCase()),\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.unshift(parseAuthUser as any)\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst context = schema.context ? await schema.context(request) : {}\n\t\t\trequest.context = context\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: response.cookies,\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tInstance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n"]}
@@ -62,6 +62,7 @@ class ExpressServer extends _basecjs.Server {
62
62
  handleResponse: async (res, response) => {
63
63
  if (!response.piped) {
64
64
  Object.entries(response.headers).forEach(([key, value]) => res.header(key, value));
65
+ Object.entries(response.cookies).forEach(([key, { value, ...opts }]) => res.cookie(key, value, opts));
65
66
  const type = response.body === null || response.body === void 0 ? "json" : "send";
66
67
  res.status(response.status)[type](response.body).end();
67
68
  } else {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/express.ts","/home/runner/work/equipped/equipped/dist/cjs/server/impls/express.cjs"],"names":["app"],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/express.cjs","sourcesContent":["import http from 'http'\n\nimport cookie from 'cookie-parser'\nimport cors from 'cors'\nimport express from 'express'\nimport fileUpload from 'express-fileupload'\nimport { rateLimit } from 'express-rate-limit'\n// import slowDown from 'express-slow-down'\nimport helmet from 'helmet'\nimport { pinoHttp } from 'pino-http'\n\nimport { Instance } from '../../instance'\nimport { getMediaDuration } from '../../utilities'\nimport { ServerConfig } from '../pipes'\nimport { Request } from '../requests'\nimport { IncomingFile, StatusCodes } from '../types'\nimport { Server } from './base'\n\nexport class ExpressServer extends Server<express.Request, express.Response> {\n\t#expressApp: express.Express\n\n\tconstructor(config: ServerConfig) {\n\t\tconst app = express()\n\t\tconst instance = Instance.get()\n\t\tsuper(http.createServer(app), config, {\n\t\t\tparseRequest: async (req) => {\n\t\t\t\tconst allHeaders = Object.fromEntries(Object.entries(req.headers).map(([key, val]) => [key, val ?? null]))\n\t\t\t\tconst headers = {\n\t\t\t\t\t...allHeaders,\n\t\t\t\t\tAuthorization: req.get('authorization'),\n\t\t\t\t\tRefreshToken: req.get('x-refresh-token'),\n\t\t\t\t\tApiKey: req.get('x-api-key'),\n\t\t\t\t\tContentType: req.get('content-type'),\n\t\t\t\t\tReferer: req.get('referer'),\n\t\t\t\t\tUserAgent: req.get('user-agent'),\n\t\t\t\t}\n\t\t\t\tconst files = Object.fromEntries(\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tObject.entries(req.files ?? {}).map(async ([key, file]) => {\n\t\t\t\t\t\t\tconst uploads = Array.isArray(file) ? file : [file]\n\t\t\t\t\t\t\tconst fileArray: IncomingFile[] = await Promise.all(\n\t\t\t\t\t\t\t\tuploads.map(async (f) => ({\n\t\t\t\t\t\t\t\t\tname: f.name,\n\t\t\t\t\t\t\t\t\ttype: f.mimetype,\n\t\t\t\t\t\t\t\t\tsize: f.size,\n\t\t\t\t\t\t\t\t\tisTruncated: f.truncated,\n\t\t\t\t\t\t\t\t\tdata: f.data,\n\t\t\t\t\t\t\t\t\tduration: await getMediaDuration(f.data),\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn <const>[key, fileArray]\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\n\t\t\t\treturn new Request<any>({\n\t\t\t\t\tip: req.ip,\n\t\t\t\t\tbody: req.body ?? {},\n\t\t\t\t\tcookies: req.cookies ?? {},\n\t\t\t\t\tparams: req.params ?? {},\n\t\t\t\t\tquery: req.query ?? {},\n\t\t\t\t\tmethod: <any>req.method,\n\t\t\t\t\tpath: req.path,\n\t\t\t\t\theaders,\n\t\t\t\t\tfiles,\n\t\t\t\t\tcontext: {},\n\t\t\t\t})\n\t\t\t},\n\t\t\thandleResponse: async (res, response) => {\n\t\t\t\tif (!response.piped) {\n\t\t\t\t\tObject.entries(<object>response.headers).forEach(([key, value]) => res.header(key, value))\n\t\t\t\t\tconst type = response.body === null || response.body === undefined ? 'json' : 'send'\n\t\t\t\t\tres.status(response.status)[type](response.body).end()\n\t\t\t\t} else {\n\t\t\t\t\tresponse.body.pipe(res)\n\t\t\t\t}\n\t\t\t},\n\t\t\tregisterRoute: (method, path, cb) => {\n\t\t\t\tthis.#expressApp[method]?.(path, cb)\n\t\t\t},\n\t\t\tregisterErrorHandler: (cb) => {\n\t\t\t\tthis.#expressApp.use(async (err, req, res, _next) => cb(err, req, res))\n\t\t\t},\n\t\t\tregisterNotFoundHandler: (cb) => {\n\t\t\t\tthis.#expressApp.use(cb)\n\t\t\t},\n\t\t\tstart: async (port) =>\n\t\t\t\tnew Promise((resolve: (s: boolean) => void, reject: (e: Error) => void) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst app = this.server.listen({ host: '0.0.0.0', port }, async () => resolve(true))\n\t\t\t\t\t\tInstance.on('close', app.close, 1)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treject(<Error>err)\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t})\n\t\tthis.#expressApp = app\n\n\t\tapp.disable('x-powered-by')\n\t\tif (config.requests.log) app.use(pinoHttp({ logger: instance.log }))\n\t\tapp.use(express.json())\n\t\tapp.use(express.text())\n\t\tapp.use(cookie())\n\t\tapp.use(\n\t\t\thelmet({\n\t\t\t\tcrossOriginResourcePolicy: { policy: 'cross-origin' },\n\t\t\t\tcontentSecurityPolicy: false,\n\t\t\t}),\n\t\t)\n\t\tapp.use(cors(this.cors))\n\t\tapp.use(express.urlencoded({ extended: false }))\n\t\tif (config.publicPath) app.use(express.static(config.publicPath))\n\t\tapp.use(\n\t\t\tfileUpload({\n\t\t\t\tlimits: { fileSize: instance.settings.utils.maxFileUploadSizeInMb * 1024 * 1024 },\n\t\t\t\tuseTempFiles: false,\n\t\t\t}),\n\t\t)\n\t\tif (config.requests.rateLimit.enabled)\n\t\t\tapp.use(\n\t\t\t\trateLimit({\n\t\t\t\t\twindowMs: config.requests.rateLimit.periodInMs,\n\t\t\t\t\tlimit: config.requests.rateLimit.limit,\n\t\t\t\t\thandler: (_: express.Request, res: express.Response) =>\n\t\t\t\t\t\tres.status(StatusCodes.TooManyRequests).json([{ message: 'Too Many Requests' }]),\n\t\t\t\t}),\n\t\t\t)\n\t\t/* if (this.settings.slowdown.enabled) app.use(slowDown({\n\t\t\twindowMs: this.settings.slowdown.periodInMs,\n\t\t\tdelayAfter: this.settings.slowdown.delayAfter,\n\t\t\tdelayMs: this.settings.slowdown.delayInMs\n\t\t})) */\n\t}\n}\n",null]}
1
+ {"version":3,"sources":["../../../../src/server/impls/express.ts","/home/runner/work/equipped/equipped/dist/cjs/server/impls/express.cjs"],"names":["app"],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/express.cjs","sourcesContent":["import http from 'http'\n\nimport cookie from 'cookie-parser'\nimport cors from 'cors'\nimport express from 'express'\nimport fileUpload from 'express-fileupload'\nimport { rateLimit } from 'express-rate-limit'\n// import slowDown from 'express-slow-down'\nimport helmet from 'helmet'\nimport { pinoHttp } from 'pino-http'\n\nimport { Instance } from '../../instance'\nimport { getMediaDuration } from '../../utilities'\nimport { ServerConfig } from '../pipes'\nimport { Request } from '../requests'\nimport { IncomingFile, StatusCodes } from '../types'\nimport { Server } from './base'\n\nexport class ExpressServer extends Server<express.Request, express.Response> {\n\t#expressApp: express.Express\n\n\tconstructor(config: ServerConfig) {\n\t\tconst app = express()\n\t\tconst instance = Instance.get()\n\t\tsuper(http.createServer(app), config, {\n\t\t\tparseRequest: async (req) => {\n\t\t\t\tconst allHeaders = Object.fromEntries(Object.entries(req.headers).map(([key, val]) => [key, val ?? null]))\n\t\t\t\tconst headers = {\n\t\t\t\t\t...allHeaders,\n\t\t\t\t\tAuthorization: req.get('authorization'),\n\t\t\t\t\tRefreshToken: req.get('x-refresh-token'),\n\t\t\t\t\tApiKey: req.get('x-api-key'),\n\t\t\t\t\tContentType: req.get('content-type'),\n\t\t\t\t\tReferer: req.get('referer'),\n\t\t\t\t\tUserAgent: req.get('user-agent'),\n\t\t\t\t}\n\t\t\t\tconst files = Object.fromEntries(\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tObject.entries(req.files ?? {}).map(async ([key, file]) => {\n\t\t\t\t\t\t\tconst uploads = Array.isArray(file) ? file : [file]\n\t\t\t\t\t\t\tconst fileArray: IncomingFile[] = await Promise.all(\n\t\t\t\t\t\t\t\tuploads.map(async (f) => ({\n\t\t\t\t\t\t\t\t\tname: f.name,\n\t\t\t\t\t\t\t\t\ttype: f.mimetype,\n\t\t\t\t\t\t\t\t\tsize: f.size,\n\t\t\t\t\t\t\t\t\tisTruncated: f.truncated,\n\t\t\t\t\t\t\t\t\tdata: f.data,\n\t\t\t\t\t\t\t\t\tduration: await getMediaDuration(f.data),\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn <const>[key, fileArray]\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\n\t\t\t\treturn new Request<any>({\n\t\t\t\t\tip: req.ip,\n\t\t\t\t\tbody: req.body ?? {},\n\t\t\t\t\tcookies: req.cookies ?? {},\n\t\t\t\t\tparams: req.params ?? {},\n\t\t\t\t\tquery: req.query ?? {},\n\t\t\t\t\tmethod: <any>req.method,\n\t\t\t\t\tpath: req.path,\n\t\t\t\t\theaders,\n\t\t\t\t\tfiles,\n\t\t\t\t\tcontext: {},\n\t\t\t\t})\n\t\t\t},\n\t\t\thandleResponse: async (res, response) => {\n\t\t\t\tif (!response.piped) {\n\t\t\t\t\tObject.entries(response.headers).forEach(([key, value]) => res.header(key, value as string))\n\t\t\t\t\tObject.entries(response.cookies).forEach(([key, { value, ...opts }]) => res.cookie(key, value, opts))\n\t\t\t\t\tconst type = response.body === null || response.body === undefined ? 'json' : 'send'\n\t\t\t\t\tres.status(response.status)[type](response.body).end()\n\t\t\t\t} else {\n\t\t\t\t\tresponse.body.pipe(res)\n\t\t\t\t}\n\t\t\t},\n\t\t\tregisterRoute: (method, path, cb) => {\n\t\t\t\tthis.#expressApp[method]?.(path, cb)\n\t\t\t},\n\t\t\tregisterErrorHandler: (cb) => {\n\t\t\t\tthis.#expressApp.use(async (err, req, res, _next) => cb(err, req, res))\n\t\t\t},\n\t\t\tregisterNotFoundHandler: (cb) => {\n\t\t\t\tthis.#expressApp.use(cb)\n\t\t\t},\n\t\t\tstart: async (port) =>\n\t\t\t\tnew Promise((resolve: (s: boolean) => void, reject: (e: Error) => void) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst app = this.server.listen({ host: '0.0.0.0', port }, async () => resolve(true))\n\t\t\t\t\t\tInstance.on('close', app.close, 1)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treject(<Error>err)\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t})\n\t\tthis.#expressApp = app\n\n\t\tapp.disable('x-powered-by')\n\t\tif (config.requests.log) app.use(pinoHttp({ logger: instance.log }))\n\t\tapp.use(express.json())\n\t\tapp.use(express.text())\n\t\tapp.use(cookie())\n\t\tapp.use(\n\t\t\thelmet({\n\t\t\t\tcrossOriginResourcePolicy: { policy: 'cross-origin' },\n\t\t\t\tcontentSecurityPolicy: false,\n\t\t\t}),\n\t\t)\n\t\tapp.use(cors(this.cors))\n\t\tapp.use(express.urlencoded({ extended: false }))\n\t\tif (config.publicPath) app.use(express.static(config.publicPath))\n\t\tapp.use(\n\t\t\tfileUpload({\n\t\t\t\tlimits: { fileSize: instance.settings.utils.maxFileUploadSizeInMb * 1024 * 1024 },\n\t\t\t\tuseTempFiles: false,\n\t\t\t}),\n\t\t)\n\t\tif (config.requests.rateLimit.enabled)\n\t\t\tapp.use(\n\t\t\t\trateLimit({\n\t\t\t\t\twindowMs: config.requests.rateLimit.periodInMs,\n\t\t\t\t\tlimit: config.requests.rateLimit.limit,\n\t\t\t\t\thandler: (_: express.Request, res: express.Response) =>\n\t\t\t\t\t\tres.status(StatusCodes.TooManyRequests).json([{ message: 'Too Many Requests' }]),\n\t\t\t\t}),\n\t\t\t)\n\t\t/* if (this.settings.slowdown.enabled) app.use(slowDown({\n\t\t\twindowMs: this.settings.slowdown.periodInMs,\n\t\t\tdelayAfter: this.settings.slowdown.delayAfter,\n\t\t\tdelayMs: this.settings.slowdown.delayInMs\n\t\t})) */\n\t}\n}\n",null]}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _http = require('http'); var _http2 = _interopRequireDefault(_http);var _cookieparser = require('cookie-parser'); var _cookieparser2 = _interopRequireDefault(_cookieparser);var _cors = require('cors'); var _cors2 = _interopRequireDefault(_cors);var _express = require('express'); var _express2 = _interopRequireDefault(_express);var _expressfileupload = require('express-fileupload'); var _expressfileupload2 = _interopRequireDefault(_expressfileupload);var _expressratelimit = require('express-rate-limit');var _helmet = require('helmet'); var _helmet2 = _interopRequireDefault(_helmet);var _pinohttp = require('pino-http');var _indexmincjs = require('../../instance/index.min.cjs');var _indexmincjs3 = require('../../utilities/index.min.cjs');var _requestsmincjs = require('../requests.min.cjs');var _typesmincjs = require('../types.min.cjs');var _basemincjs = require('./base.min.cjs');class N extends _basemincjs.Server{#e;constructor(i){const s=_express2.default.call(void 0, ),u=_indexmincjs.Instance.get();super(_http2.default.createServer(s),i,{parseRequest:async e=>{const r={...Object.fromEntries(Object.entries(e.headers).map(([a,p])=>[a,_nullishCoalesce(p, () => (null))])),Authorization:e.get("authorization"),RefreshToken:e.get("x-refresh-token"),ApiKey:e.get("x-api-key"),ContentType:e.get("content-type"),Referer:e.get("referer"),UserAgent:e.get("user-agent")},o=Object.fromEntries(await Promise.all(Object.entries(_nullishCoalesce(e.files, () => ({}))).map(async([a,p])=>{const l=Array.isArray(p)?p:[p],d=await Promise.all(l.map(async n=>({name:n.name,type:n.mimetype,size:n.size,isTruncated:n.truncated,data:n.data,duration:await _indexmincjs3.getMediaDuration.call(void 0, n.data)})));return[a,d]})));return new (0, _requestsmincjs.Request)({ip:e.ip,body:_nullishCoalesce(e.body, () => ({})),cookies:_nullishCoalesce(e.cookies, () => ({})),params:_nullishCoalesce(e.params, () => ({})),query:_nullishCoalesce(e.query, () => ({})),method:e.method,path:e.path,headers:r,files:o,context:{}})},handleResponse:async(e,t)=>{if(t.piped)t.body.pipe(e);else{Object.entries(t.headers).forEach(([o,a])=>e.header(o,a));const r=t.body===null||t.body===void 0?"json":"send";e.status(t.status)[r](t.body).end()}},registerRoute:(e,t,r)=>{_optionalChain([this, 'access', _ => _.#e, 'access', _2 => _2[e], 'optionalCall', _3 => _3(t,r)])},registerErrorHandler:e=>{this.#e.use(async(t,r,o,a)=>e(t,r,o))},registerNotFoundHandler:e=>{this.#e.use(e)},start:async e=>new Promise((t,r)=>{try{const o=this.server.listen({host:"0.0.0.0",port:e},async()=>t(!0));_indexmincjs.Instance.on("close",o.close,1)}catch(o){r(o)}})}),this.#e=s,s.disable("x-powered-by"),i.requests.log&&s.use(_pinohttp.pinoHttp.call(void 0, {logger:u.log})),s.use(_express2.default.json()),s.use(_express2.default.text()),s.use(_cookieparser2.default.call(void 0, )),s.use(_helmet2.default.call(void 0, {crossOriginResourcePolicy:{policy:"cross-origin"},contentSecurityPolicy:!1})),s.use(_cors2.default.call(void 0, this.cors)),s.use(_express2.default.urlencoded({extended:!1})),i.publicPath&&s.use(_express2.default.static(i.publicPath)),s.use(_expressfileupload2.default.call(void 0, {limits:{fileSize:u.settings.utils.maxFileUploadSizeInMb*1024*1024},useTempFiles:!1})),i.requests.rateLimit.enabled&&s.use(_expressratelimit.rateLimit.call(void 0, {windowMs:i.requests.rateLimit.periodInMs,limit:i.requests.rateLimit.limit,handler:(e,t)=>t.status(_typesmincjs.StatusCodes.TooManyRequests).json([{message:"Too Many Requests"}])}))}}exports.ExpressServer = N;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _http = require('http'); var _http2 = _interopRequireDefault(_http);var _cookieparser = require('cookie-parser'); var _cookieparser2 = _interopRequireDefault(_cookieparser);var _cors = require('cors'); var _cors2 = _interopRequireDefault(_cors);var _express = require('express'); var _express2 = _interopRequireDefault(_express);var _expressfileupload = require('express-fileupload'); var _expressfileupload2 = _interopRequireDefault(_expressfileupload);var _expressratelimit = require('express-rate-limit');var _helmet = require('helmet'); var _helmet2 = _interopRequireDefault(_helmet);var _pinohttp = require('pino-http');var _indexmincjs = require('../../instance/index.min.cjs');var _indexmincjs3 = require('../../utilities/index.min.cjs');var _requestsmincjs = require('../requests.min.cjs');var _typesmincjs = require('../types.min.cjs');var _basemincjs = require('./base.min.cjs');class N extends _basemincjs.Server{#e;constructor(a){const s=_express2.default.call(void 0, ),c=_indexmincjs.Instance.get();super(_http2.default.createServer(s),a,{parseRequest:async e=>{const o={...Object.fromEntries(Object.entries(e.headers).map(([i,n])=>[i,_nullishCoalesce(n, () => (null))])),Authorization:e.get("authorization"),RefreshToken:e.get("x-refresh-token"),ApiKey:e.get("x-api-key"),ContentType:e.get("content-type"),Referer:e.get("referer"),UserAgent:e.get("user-agent")},r=Object.fromEntries(await Promise.all(Object.entries(_nullishCoalesce(e.files, () => ({}))).map(async([i,n])=>{const l=Array.isArray(n)?n:[n],d=await Promise.all(l.map(async p=>({name:p.name,type:p.mimetype,size:p.size,isTruncated:p.truncated,data:p.data,duration:await _indexmincjs3.getMediaDuration.call(void 0, p.data)})));return[i,d]})));return new (0, _requestsmincjs.Request)({ip:e.ip,body:_nullishCoalesce(e.body, () => ({})),cookies:_nullishCoalesce(e.cookies, () => ({})),params:_nullishCoalesce(e.params, () => ({})),query:_nullishCoalesce(e.query, () => ({})),method:e.method,path:e.path,headers:o,files:r,context:{}})},handleResponse:async(e,t)=>{if(t.piped)t.body.pipe(e);else{Object.entries(t.headers).forEach(([r,i])=>e.header(r,i)),Object.entries(t.cookies).forEach(([r,{value:i,...n}])=>e.cookie(r,i,n));const o=t.body===null||t.body===void 0?"json":"send";e.status(t.status)[o](t.body).end()}},registerRoute:(e,t,o)=>{_optionalChain([this, 'access', _ => _.#e, 'access', _2 => _2[e], 'optionalCall', _3 => _3(t,o)])},registerErrorHandler:e=>{this.#e.use(async(t,o,r,i)=>e(t,o,r))},registerNotFoundHandler:e=>{this.#e.use(e)},start:async e=>new Promise((t,o)=>{try{const r=this.server.listen({host:"0.0.0.0",port:e},async()=>t(!0));_indexmincjs.Instance.on("close",r.close,1)}catch(r){o(r)}})}),this.#e=s,s.disable("x-powered-by"),a.requests.log&&s.use(_pinohttp.pinoHttp.call(void 0, {logger:c.log})),s.use(_express2.default.json()),s.use(_express2.default.text()),s.use(_cookieparser2.default.call(void 0, )),s.use(_helmet2.default.call(void 0, {crossOriginResourcePolicy:{policy:"cross-origin"},contentSecurityPolicy:!1})),s.use(_cors2.default.call(void 0, this.cors)),s.use(_express2.default.urlencoded({extended:!1})),a.publicPath&&s.use(_express2.default.static(a.publicPath)),s.use(_expressfileupload2.default.call(void 0, {limits:{fileSize:c.settings.utils.maxFileUploadSizeInMb*1024*1024},useTempFiles:!1})),a.requests.rateLimit.enabled&&s.use(_expressratelimit.rateLimit.call(void 0, {windowMs:a.requests.rateLimit.periodInMs,limit:a.requests.rateLimit.limit,handler:(e,t)=>t.status(_typesmincjs.StatusCodes.TooManyRequests).json([{message:"Too Many Requests"}])}))}}exports.ExpressServer = N;
2
2
  //# sourceMappingURL=express.min.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/express.ts"],"names":["ExpressServer","http","req","headers","key","val","files","uploads","file","fileArray","f","getMediaDuration","Request","response","res","value","type","path","cb","#expressApp","err","_next","port","app","reject","config","instance","cookie","helmet","cors","express","fileUpload","rateLimit","StatusCodes"],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/express.min.cjs","sourcesContent":["import http from 'http'\n\nimport cookie from 'cookie-parser'\nimport cors from 'cors'\nimport express from 'express'\nimport fileUpload from 'express-fileupload'\nimport { rateLimit } from 'express-rate-limit'\n// import slowDown from 'express-slow-down'\nimport helmet from 'helmet'\nimport { pinoHttp } from 'pino-http'\n\nimport { Instance } from '../../instance'\nimport { getMediaDuration } from '../../utilities'\nimport { ServerConfig } from '../pipes'\nimport { Request } from '../requests'\nimport { IncomingFile, StatusCodes } from '../types'\nimport { Server } from './base'\n\nexport class ExpressServer extends Server<express.Request, express.Response> {\n\t#expressApp: express.Express\n\n\tconstructor(config: ServerConfig) {\n\t\tconst app = express()\n\t\tconst instance = Instance.get()\n\t\tsuper(http.createServer(app), config, {\n\t\t\tparseRequest: async (req) => {\n\t\t\t\tconst allHeaders = Object.fromEntries(Object.entries(req.headers).map(([key, val]) => [key, val ?? null]))\n\t\t\t\tconst headers = {\n\t\t\t\t\t...allHeaders,\n\t\t\t\t\tAuthorization: req.get('authorization'),\n\t\t\t\t\tRefreshToken: req.get('x-refresh-token'),\n\t\t\t\t\tApiKey: req.get('x-api-key'),\n\t\t\t\t\tContentType: req.get('content-type'),\n\t\t\t\t\tReferer: req.get('referer'),\n\t\t\t\t\tUserAgent: req.get('user-agent'),\n\t\t\t\t}\n\t\t\t\tconst files = Object.fromEntries(\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tObject.entries(req.files ?? {}).map(async ([key, file]) => {\n\t\t\t\t\t\t\tconst uploads = Array.isArray(file) ? file : [file]\n\t\t\t\t\t\t\tconst fileArray: IncomingFile[] = await Promise.all(\n\t\t\t\t\t\t\t\tuploads.map(async (f) => ({\n\t\t\t\t\t\t\t\t\tname: f.name,\n\t\t\t\t\t\t\t\t\ttype: f.mimetype,\n\t\t\t\t\t\t\t\t\tsize: f.size,\n\t\t\t\t\t\t\t\t\tisTruncated: f.truncated,\n\t\t\t\t\t\t\t\t\tdata: f.data,\n\t\t\t\t\t\t\t\t\tduration: await getMediaDuration(f.data),\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn <const>[key, fileArray]\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\n\t\t\t\treturn new Request<any>({\n\t\t\t\t\tip: req.ip,\n\t\t\t\t\tbody: req.body ?? {},\n\t\t\t\t\tcookies: req.cookies ?? {},\n\t\t\t\t\tparams: req.params ?? {},\n\t\t\t\t\tquery: req.query ?? {},\n\t\t\t\t\tmethod: <any>req.method,\n\t\t\t\t\tpath: req.path,\n\t\t\t\t\theaders,\n\t\t\t\t\tfiles,\n\t\t\t\t\tcontext: {},\n\t\t\t\t})\n\t\t\t},\n\t\t\thandleResponse: async (res, response) => {\n\t\t\t\tif (!response.piped) {\n\t\t\t\t\tObject.entries(<object>response.headers).forEach(([key, value]) => res.header(key, value))\n\t\t\t\t\tconst type = response.body === null || response.body === undefined ? 'json' : 'send'\n\t\t\t\t\tres.status(response.status)[type](response.body).end()\n\t\t\t\t} else {\n\t\t\t\t\tresponse.body.pipe(res)\n\t\t\t\t}\n\t\t\t},\n\t\t\tregisterRoute: (method, path, cb) => {\n\t\t\t\tthis.#expressApp[method]?.(path, cb)\n\t\t\t},\n\t\t\tregisterErrorHandler: (cb) => {\n\t\t\t\tthis.#expressApp.use(async (err, req, res, _next) => cb(err, req, res))\n\t\t\t},\n\t\t\tregisterNotFoundHandler: (cb) => {\n\t\t\t\tthis.#expressApp.use(cb)\n\t\t\t},\n\t\t\tstart: async (port) =>\n\t\t\t\tnew Promise((resolve: (s: boolean) => void, reject: (e: Error) => void) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst app = this.server.listen({ host: '0.0.0.0', port }, async () => resolve(true))\n\t\t\t\t\t\tInstance.on('close', app.close, 1)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treject(<Error>err)\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t})\n\t\tthis.#expressApp = app\n\n\t\tapp.disable('x-powered-by')\n\t\tif (config.requests.log) app.use(pinoHttp({ logger: instance.log }))\n\t\tapp.use(express.json())\n\t\tapp.use(express.text())\n\t\tapp.use(cookie())\n\t\tapp.use(\n\t\t\thelmet({\n\t\t\t\tcrossOriginResourcePolicy: { policy: 'cross-origin' },\n\t\t\t\tcontentSecurityPolicy: false,\n\t\t\t}),\n\t\t)\n\t\tapp.use(cors(this.cors))\n\t\tapp.use(express.urlencoded({ extended: false }))\n\t\tif (config.publicPath) app.use(express.static(config.publicPath))\n\t\tapp.use(\n\t\t\tfileUpload({\n\t\t\t\tlimits: { fileSize: instance.settings.utils.maxFileUploadSizeInMb * 1024 * 1024 },\n\t\t\t\tuseTempFiles: false,\n\t\t\t}),\n\t\t)\n\t\tif (config.requests.rateLimit.enabled)\n\t\t\tapp.use(\n\t\t\t\trateLimit({\n\t\t\t\t\twindowMs: config.requests.rateLimit.periodInMs,\n\t\t\t\t\tlimit: config.requests.rateLimit.limit,\n\t\t\t\t\thandler: (_: express.Request, res: express.Response) =>\n\t\t\t\t\t\tres.status(StatusCodes.TooManyRequests).json([{ message: 'Too Many Requests' }]),\n\t\t\t\t}),\n\t\t\t)\n\t\t/* if (this.settings.slowdown.enabled) app.use(slowDown({\n\t\t\twindowMs: this.settings.slowdown.periodInMs,\n\t\t\tdelayAfter: this.settings.slowdown.delayAfter,\n\t\t\tdelayMs: this.settings.slowdown.delayInMs\n\t\t})) */\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/server/impls/express.ts"],"names":["ExpressServer","http","req","headers","key","val","files","uploads","file","fileArray","f","getMediaDuration","Request","response","res","value","opts","path","cb","#expressApp","err","_next","port","app","reject","config","instance","cookie","helmet","cors","express","fileUpload","rateLimit","StatusCodes"],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/express.min.cjs","sourcesContent":["import http from 'http'\n\nimport cookie from 'cookie-parser'\nimport cors from 'cors'\nimport express from 'express'\nimport fileUpload from 'express-fileupload'\nimport { rateLimit } from 'express-rate-limit'\n// import slowDown from 'express-slow-down'\nimport helmet from 'helmet'\nimport { pinoHttp } from 'pino-http'\n\nimport { Instance } from '../../instance'\nimport { getMediaDuration } from '../../utilities'\nimport { ServerConfig } from '../pipes'\nimport { Request } from '../requests'\nimport { IncomingFile, StatusCodes } from '../types'\nimport { Server } from './base'\n\nexport class ExpressServer extends Server<express.Request, express.Response> {\n\t#expressApp: express.Express\n\n\tconstructor(config: ServerConfig) {\n\t\tconst app = express()\n\t\tconst instance = Instance.get()\n\t\tsuper(http.createServer(app), config, {\n\t\t\tparseRequest: async (req) => {\n\t\t\t\tconst allHeaders = Object.fromEntries(Object.entries(req.headers).map(([key, val]) => [key, val ?? null]))\n\t\t\t\tconst headers = {\n\t\t\t\t\t...allHeaders,\n\t\t\t\t\tAuthorization: req.get('authorization'),\n\t\t\t\t\tRefreshToken: req.get('x-refresh-token'),\n\t\t\t\t\tApiKey: req.get('x-api-key'),\n\t\t\t\t\tContentType: req.get('content-type'),\n\t\t\t\t\tReferer: req.get('referer'),\n\t\t\t\t\tUserAgent: req.get('user-agent'),\n\t\t\t\t}\n\t\t\t\tconst files = Object.fromEntries(\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tObject.entries(req.files ?? {}).map(async ([key, file]) => {\n\t\t\t\t\t\t\tconst uploads = Array.isArray(file) ? file : [file]\n\t\t\t\t\t\t\tconst fileArray: IncomingFile[] = await Promise.all(\n\t\t\t\t\t\t\t\tuploads.map(async (f) => ({\n\t\t\t\t\t\t\t\t\tname: f.name,\n\t\t\t\t\t\t\t\t\ttype: f.mimetype,\n\t\t\t\t\t\t\t\t\tsize: f.size,\n\t\t\t\t\t\t\t\t\tisTruncated: f.truncated,\n\t\t\t\t\t\t\t\t\tdata: f.data,\n\t\t\t\t\t\t\t\t\tduration: await getMediaDuration(f.data),\n\t\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn <const>[key, fileArray]\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\n\t\t\t\treturn new Request<any>({\n\t\t\t\t\tip: req.ip,\n\t\t\t\t\tbody: req.body ?? {},\n\t\t\t\t\tcookies: req.cookies ?? {},\n\t\t\t\t\tparams: req.params ?? {},\n\t\t\t\t\tquery: req.query ?? {},\n\t\t\t\t\tmethod: <any>req.method,\n\t\t\t\t\tpath: req.path,\n\t\t\t\t\theaders,\n\t\t\t\t\tfiles,\n\t\t\t\t\tcontext: {},\n\t\t\t\t})\n\t\t\t},\n\t\t\thandleResponse: async (res, response) => {\n\t\t\t\tif (!response.piped) {\n\t\t\t\t\tObject.entries(response.headers).forEach(([key, value]) => res.header(key, value as string))\n\t\t\t\t\tObject.entries(response.cookies).forEach(([key, { value, ...opts }]) => res.cookie(key, value, opts))\n\t\t\t\t\tconst type = response.body === null || response.body === undefined ? 'json' : 'send'\n\t\t\t\t\tres.status(response.status)[type](response.body).end()\n\t\t\t\t} else {\n\t\t\t\t\tresponse.body.pipe(res)\n\t\t\t\t}\n\t\t\t},\n\t\t\tregisterRoute: (method, path, cb) => {\n\t\t\t\tthis.#expressApp[method]?.(path, cb)\n\t\t\t},\n\t\t\tregisterErrorHandler: (cb) => {\n\t\t\t\tthis.#expressApp.use(async (err, req, res, _next) => cb(err, req, res))\n\t\t\t},\n\t\t\tregisterNotFoundHandler: (cb) => {\n\t\t\t\tthis.#expressApp.use(cb)\n\t\t\t},\n\t\t\tstart: async (port) =>\n\t\t\t\tnew Promise((resolve: (s: boolean) => void, reject: (e: Error) => void) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst app = this.server.listen({ host: '0.0.0.0', port }, async () => resolve(true))\n\t\t\t\t\t\tInstance.on('close', app.close, 1)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treject(<Error>err)\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t})\n\t\tthis.#expressApp = app\n\n\t\tapp.disable('x-powered-by')\n\t\tif (config.requests.log) app.use(pinoHttp({ logger: instance.log }))\n\t\tapp.use(express.json())\n\t\tapp.use(express.text())\n\t\tapp.use(cookie())\n\t\tapp.use(\n\t\t\thelmet({\n\t\t\t\tcrossOriginResourcePolicy: { policy: 'cross-origin' },\n\t\t\t\tcontentSecurityPolicy: false,\n\t\t\t}),\n\t\t)\n\t\tapp.use(cors(this.cors))\n\t\tapp.use(express.urlencoded({ extended: false }))\n\t\tif (config.publicPath) app.use(express.static(config.publicPath))\n\t\tapp.use(\n\t\t\tfileUpload({\n\t\t\t\tlimits: { fileSize: instance.settings.utils.maxFileUploadSizeInMb * 1024 * 1024 },\n\t\t\t\tuseTempFiles: false,\n\t\t\t}),\n\t\t)\n\t\tif (config.requests.rateLimit.enabled)\n\t\t\tapp.use(\n\t\t\t\trateLimit({\n\t\t\t\t\twindowMs: config.requests.rateLimit.periodInMs,\n\t\t\t\t\tlimit: config.requests.rateLimit.limit,\n\t\t\t\t\thandler: (_: express.Request, res: express.Response) =>\n\t\t\t\t\t\tres.status(StatusCodes.TooManyRequests).json([{ message: 'Too Many Requests' }]),\n\t\t\t\t}),\n\t\t\t)\n\t\t/* if (this.settings.slowdown.enabled) app.use(slowDown({\n\t\t\twindowMs: this.settings.slowdown.periodInMs,\n\t\t\tdelayAfter: this.settings.slowdown.delayAfter,\n\t\t\tdelayMs: this.settings.slowdown.delayInMs\n\t\t})) */\n\t}\n}\n"]}
@@ -56,6 +56,7 @@ class FastifyServer extends _basecjs.Server {
56
56
  });
57
57
  },
58
58
  handleResponse: async (res, response) => {
59
+ for (const [key, { value, ...opts }] of Object.entries(response.cookies)) res = res.setCookie(key, value, opts);
59
60
  await res.status(response.status).headers(response.headers).send(response.body);
60
61
  },
61
62
  registerRoute: (method, path, cb) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/fastify.ts","/home/runner/work/equipped/equipped/dist/cjs/server/impls/fastify.cjs"],"names":[],"mappings":"AAAA,02BAA0B;AAC1B,iFAAwB;AACxB,iGAA4B;AAC5B,yFAA0B;AAC1B,qGAA6B;AAC7B,sGAA6B;AAC7B,yFAA0B;AAE1B,oFAAoB;AAEpB,gEAAe;AAEf,kDAAgC;AAChC,qDAAyB;AACzB,sDAAiC;AAEjC,8CAAwB;AACxB,wCAA0C;AAC1C,qCAAuB;AAEhB,MAAM,cAAA,QAAsB,gBAAqC;AAAA,EACvE,WAAA,CAAY,MAAA,EAAsB;AACjC,IAAA,MAAM,SAAA,EAAW,mBAAA,CAAS,GAAA,CAAI,CAAA;AAC9B,IAAA,MAAM,IAAA,EAAM,+BAAA;AAAQ,MACnB,mBAAA,EAAqB,IAAA;AAAA,MACrB,aAAA,EAAe,KAAA;AAAA,MACf,qBAAA,EAAuB,CAAC,MAAA,CAAO,QAAA,CAAS,GAAA;AAAA,MACxC,cAAA,EAAgB,MAAA,CAAO,QAAA,CAAS,IAAA,EAAM,QAAA,CAAS,IAAA,EAAM,KAAA,CAAA;AAAA,MACrD,GAAA,EAAK,EAAE,aAAA,EAAe,EAAE,WAAA,EAAa,MAAM,EAAE,CAAA;AAAA,MAC7C,oBAAA,EAAsB,CAAC,MAAA,EAAQ,IAAA,EAAA,GAC9B,IAAI,8BAAA;AAAA,QACH,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAA,GAAA,CAAW;AAAA,UACtB,QAAA,EAAU,kBAAC,KAAA,CAAM,OAAA,UAAW,IAAE,CAAA;AAAA,UAC9B,KAAA,EAAO,CAAA,EAAA;AACN,QAAA;AACH,MAAA;AACD,IAAA;AACS,IAAA;AACT,MAAA;AACO,QAAA;AACA,QAAA;AACF,UAAA;AACH,UAAA;AACA,UAAA;AACQ,UAAA;AACR,UAAA;AACA,UAAA;AACA,UAAA;AACD,QAAA;AACQ,QAAA;AAED,QAAA;AACE,UAAA;AACR,UAAA;AACA,UAAA;AACQ,UAAA;AACD,UAAA;AACM,UAAA;AACP,UAAA;AACN,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACW,QAAA;AACX,MAAA;AACA,MAAA;AACK,QAAA;AACE,UAAA;AACL,QAAA;AACF,MAAA;AACA,MAAA;AACK,QAAA;AACL,MAAA;AACA,MAAA;AACK,QAAA;AACL,MAAA;AACO,MAAA;AACI,QAAA;AACA,QAAA;AACD,QAAA;AACF,QAAA;AACR,MAAA;AACA,IAAA;AAEG,IAAA;AACA,IAAA;AACA,IAAA;AACO,IAAA;AACE,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACZ,MAAA;AACA,MAAA;AACU,MAAA;AACF,MAAA;AACD,QAAA;AACA,QAAA;AACG,UAAA;AACA,UAAA;AACF,UAAA;AACN,UAAA;AACM,UAAA;AACN,UAAA;AACD,QAAA;AAEU,QAAA;AACX,MAAA;AACA,IAAA;AAMU,IAAA;AACN,MAAA;AACE,QAAA;AACL,QAAA;AACA,QAAA;AACC,UAAA;AACA,UAAA;AACD,QAAA;AACA,MAAA;AACH,EAAA;AACD;AAES;AACG,EAAA;AACK,EAAA;AACA,EAAA;AACV,EAAA;AACA,EAAA;AACC,EAAA;AACU,IAAA;AAC8B,IAAA;AAC/C,EAAA;AACD;ACdkB;AACA;AACA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/fastify.cjs","sourcesContent":["import fastifyCookie from '@fastify/cookie'\nimport fastifyCors from '@fastify/cors'\nimport fastifyFormBody from '@fastify/formbody'\nimport fastifyHelmet from '@fastify/helmet'\nimport fastifyMultipart from '@fastify/multipart'\nimport fastifyRateLimit from '@fastify/rate-limit'\nimport fastifyStatic from '@fastify/static'\nimport type { FastifyReply, FastifyRequest } from 'fastify'\nimport Fastify from 'fastify'\n// import fastifySlowDown from 'fastify-slow-down'\nimport qs from 'qs'\n\nimport { ValidationError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { getMediaDuration } from '../../utilities'\nimport { ServerConfig } from '../pipes'\nimport { Request } from '../requests'\nimport { IncomingFile, StatusCodes } from '../types'\nimport { Server } from './base'\n\nexport class FastifyServer extends Server<FastifyRequest, FastifyReply> {\n\tconstructor(config: ServerConfig) {\n\t\tconst instance = Instance.get()\n\t\tconst app = Fastify({\n\t\t\tignoreTrailingSlash: true,\n\t\t\tcaseSensitive: false,\n\t\t\tdisableRequestLogging: !config.requests.log,\n\t\t\tloggerInstance: config.requests.log ? instance.log : undefined,\n\t\t\tajv: { customOptions: { coerceTypes: false } },\n\t\t\tschemaErrorFormatter: (errors, data) =>\n\t\t\t\tnew ValidationError(\n\t\t\t\t\terrors.map((error) => ({\n\t\t\t\t\t\tmessages: [error.message ?? ''],\n\t\t\t\t\t\tfield: `${data}${error.instancePath}`.replaceAll('/', '.'),\n\t\t\t\t\t})),\n\t\t\t\t),\n\t\t})\n\t\tsuper(app.server, config, {\n\t\t\tparseRequest: async (req) => {\n\t\t\t\tconst allHeaders = Object.fromEntries(Object.entries(req.headers).map(([key, val]) => [key, val ?? null]))\n\t\t\t\tconst headers = {\n\t\t\t\t\t...allHeaders,\n\t\t\t\t\tAuthorization: req.headers['authorization']?.toString(),\n\t\t\t\t\tRefreshToken: req.headers['x-refresh-token']?.toString(),\n\t\t\t\t\tApiKey: req.headers['x-api-key']?.toString(),\n\t\t\t\t\tContentType: req.headers['content-type']?.toString(),\n\t\t\t\t\tReferer: req.headers['referer']?.toString(),\n\t\t\t\t\tUserAgent: req.headers['user-agent']?.toString(),\n\t\t\t\t}\n\t\t\t\tconst { body, files } = excludeBufferKeys(req.body ?? {})\n\n\t\t\t\treturn new Request({\n\t\t\t\t\tip: req.ip,\n\t\t\t\t\tbody,\n\t\t\t\t\tcookies: req.cookies ?? {},\n\t\t\t\t\tparams: req.params ?? <any>{},\n\t\t\t\t\tquery: req.query ?? {},\n\t\t\t\t\tmethod: <any>req.method,\n\t\t\t\t\tpath: req.url,\n\t\t\t\t\theaders,\n\t\t\t\t\tfiles,\n\t\t\t\t\tcontext: {},\n\t\t\t\t})\n\t\t\t},\n\t\t\thandleResponse: async (res, response) => {\n\t\t\t\tawait res.status(response.status).headers(response.headers).send(response.body)\n\t\t\t},\n\t\t\tregisterRoute: (method, path, cb) => {\n\t\t\t\tapp.register(async (inst) => {\n\t\t\t\t\tinst.route({ url: path, method, handler: cb })\n\t\t\t\t})\n\t\t\t},\n\t\t\tregisterErrorHandler: (cb) => {\n\t\t\t\tapp.setErrorHandler(cb)\n\t\t\t},\n\t\t\tregisterNotFoundHandler: (cb) => {\n\t\t\t\tapp.setNotFoundHandler(cb)\n\t\t\t},\n\t\t\tstart: async (port) => {\n\t\t\t\tawait app.ready()\n\t\t\t\tawait app.listen({ port, host: '0.0.0.0' })\n\t\t\t\tInstance.on('close', app.close, 1)\n\t\t\t\treturn true\n\t\t\t},\n\t\t})\n\n\t\tapp.decorateRequest('savedReq', null)\n\t\tapp.setValidatorCompiler(() => () => true)\n\t\tapp.setSerializerCompiler(() => (data) => JSON.stringify(data))\n\t\tif (config.publicPath) app.register(fastifyStatic, { root: config.publicPath })\n\t\tapp.register(fastifyCookie, {})\n\t\tapp.register(fastifyCors, this.cors)\n\t\tapp.register(fastifyFormBody, { parser: (str) => qs.parse(str) })\n\t\tapp.register(fastifyHelmet, { crossOriginResourcePolicy: { policy: 'cross-origin' }, contentSecurityPolicy: false })\n\t\tapp.register(fastifyMultipart, {\n\t\t\tattachFieldsToBody: 'keyValues',\n\t\t\tthrowFileSizeLimit: false,\n\t\t\tlimits: { fileSize: instance.settings.utils.maxFileUploadSizeInMb * 1024 * 1024 },\n\t\t\tonFile: async (f) => {\n\t\t\t\tconst buffer = await f.toBuffer()\n\t\t\t\tconst parsed: IncomingFile = {\n\t\t\t\t\tname: f.filename,\n\t\t\t\t\ttype: f.mimetype,\n\t\t\t\t\tsize: buffer.byteLength,\n\t\t\t\t\tisTruncated: f.file.truncated,\n\t\t\t\t\tdata: buffer,\n\t\t\t\t\tduration: await getMediaDuration(buffer),\n\t\t\t\t}\n\t\t\t\t// @ts-ignore\n\t\t\t\tf.value = parsed\n\t\t\t},\n\t\t})\n\t\t/* if (this.settings.slowdown.enabled) app.register(fastifySlowDown, {\n\t\t\ttimeWindow: this.settings.slowdown.periodInMs,\n\t\t\tdelayAfter: this.settings.slowdown.delayAfter,\n\t\t\tdelay: this.settings.slowdown.delayInMs\n\t\t}) */\n\t\tif (config.requests.rateLimit.enabled)\n\t\t\tapp.register(fastifyRateLimit, {\n\t\t\t\tmax: config.requests.rateLimit.limit,\n\t\t\t\ttimeWindow: config.requests.rateLimit.periodInMs,\n\t\t\t\terrorResponseBuilder: (_, context) => ({\n\t\t\t\t\tstatusCode: StatusCodes.TooManyRequests,\n\t\t\t\t\tmessage: JSON.stringify([{ message: `Too Many Requests. Retry in ${context.after}` }]),\n\t\t\t\t}),\n\t\t\t})\n\t}\n}\n\nfunction excludeBufferKeys<T>(body: T) {\n\tif (typeof body !== 'object') return { body, files: {} }\n\tconst entries = Object.entries(body ?? {})\n\tconst isFile = (val: any) => (Array.isArray(val) ? isFile(val.at(0)) : Buffer.isBuffer(val?.data))\n\tconst fileEntries = entries.filter(([_, value]) => isFile(value)).map(([key, value]) => [key, Array.isArray(value) ? value : [value]])\n\tconst nonFileEntries = entries.filter(([_, value]) => !isFile(value))\n\treturn {\n\t\tbody: <T>Object.fromEntries(nonFileEntries),\n\t\tfiles: <Record<string, IncomingFile[]>>Object.fromEntries(fileEntries),\n\t}\n}\n",null]}
1
+ {"version":3,"sources":["../../../../src/server/impls/fastify.ts","/home/runner/work/equipped/equipped/dist/cjs/server/impls/fastify.cjs"],"names":[],"mappings":"AAAA,02BAA0B;AAC1B,iFAAwB;AACxB,iGAA4B;AAC5B,yFAA0B;AAC1B,qGAA6B;AAC7B,sGAA6B;AAC7B,yFAA0B;AAE1B,oFAAoB;AAEpB,gEAAe;AAEf,kDAAgC;AAChC,qDAAyB;AACzB,sDAAiC;AAEjC,8CAAwB;AACxB,wCAA0C;AAC1C,qCAAuB;AAEhB,MAAM,cAAA,QAAsB,gBAAqC;AAAA,EACvE,WAAA,CAAY,MAAA,EAAsB;AACjC,IAAA,MAAM,SAAA,EAAW,mBAAA,CAAS,GAAA,CAAI,CAAA;AAC9B,IAAA,MAAM,IAAA,EAAM,+BAAA;AAAQ,MACnB,mBAAA,EAAqB,IAAA;AAAA,MACrB,aAAA,EAAe,KAAA;AAAA,MACf,qBAAA,EAAuB,CAAC,MAAA,CAAO,QAAA,CAAS,GAAA;AAAA,MACxC,cAAA,EAAgB,MAAA,CAAO,QAAA,CAAS,IAAA,EAAM,QAAA,CAAS,IAAA,EAAM,KAAA,CAAA;AAAA,MACrD,GAAA,EAAK,EAAE,aAAA,EAAe,EAAE,WAAA,EAAa,MAAM,EAAE,CAAA;AAAA,MAC7C,oBAAA,EAAsB,CAAC,MAAA,EAAQ,IAAA,EAAA,GAC9B,IAAI,8BAAA;AAAA,QACH,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAA,GAAA,CAAW;AAAA,UACtB,QAAA,EAAU,kBAAC,KAAA,CAAM,OAAA,UAAW,IAAE,CAAA;AAAA,UAC9B,KAAA,EAAO,CAAA,EAAA;AACN,QAAA;AACH,MAAA;AACD,IAAA;AACS,IAAA;AACT,MAAA;AACO,QAAA;AACA,QAAA;AACF,UAAA;AACH,UAAA;AACA,UAAA;AACQ,UAAA;AACR,UAAA;AACA,UAAA;AACA,UAAA;AACD,QAAA;AACQ,QAAA;AAED,QAAA;AACE,UAAA;AACR,UAAA;AACA,UAAA;AACQ,UAAA;AACD,UAAA;AACM,UAAA;AACP,UAAA;AACN,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACC,QAAA;AACU,QAAA;AACX,MAAA;AACA,MAAA;AACK,QAAA;AACE,UAAA;AACL,QAAA;AACF,MAAA;AACA,MAAA;AACK,QAAA;AACL,MAAA;AACA,MAAA;AACK,QAAA;AACL,MAAA;AACO,MAAA;AACI,QAAA;AACA,QAAA;AACD,QAAA;AACF,QAAA;AACR,MAAA;AACA,IAAA;AAEG,IAAA;AACA,IAAA;AACA,IAAA;AACO,IAAA;AACE,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACZ,MAAA;AACA,MAAA;AACU,MAAA;AACF,MAAA;AACD,QAAA;AACA,QAAA;AACG,UAAA;AACA,UAAA;AACF,UAAA;AACN,UAAA;AACM,UAAA;AACN,UAAA;AACD,QAAA;AAEU,QAAA;AACX,MAAA;AACA,IAAA;AAMU,IAAA;AACN,MAAA;AACE,QAAA;AACL,QAAA;AACA,QAAA;AACC,UAAA;AACA,UAAA;AACD,QAAA;AACA,MAAA;AACH,EAAA;AACD;AAES;AACG,EAAA;AACK,EAAA;AACA,EAAA;AACV,EAAA;AACA,EAAA;AACC,EAAA;AACU,IAAA;AAC8B,IAAA;AAC/C,EAAA;AACD;ACdkB;AACA;AACA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/fastify.cjs","sourcesContent":["import fastifyCookie from '@fastify/cookie'\nimport fastifyCors from '@fastify/cors'\nimport fastifyFormBody from '@fastify/formbody'\nimport fastifyHelmet from '@fastify/helmet'\nimport fastifyMultipart from '@fastify/multipart'\nimport fastifyRateLimit from '@fastify/rate-limit'\nimport fastifyStatic from '@fastify/static'\nimport type { FastifyReply, FastifyRequest } from 'fastify'\nimport Fastify from 'fastify'\n// import fastifySlowDown from 'fastify-slow-down'\nimport qs from 'qs'\n\nimport { ValidationError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { getMediaDuration } from '../../utilities'\nimport { ServerConfig } from '../pipes'\nimport { Request } from '../requests'\nimport { IncomingFile, StatusCodes } from '../types'\nimport { Server } from './base'\n\nexport class FastifyServer extends Server<FastifyRequest, FastifyReply> {\n\tconstructor(config: ServerConfig) {\n\t\tconst instance = Instance.get()\n\t\tconst app = Fastify({\n\t\t\tignoreTrailingSlash: true,\n\t\t\tcaseSensitive: false,\n\t\t\tdisableRequestLogging: !config.requests.log,\n\t\t\tloggerInstance: config.requests.log ? instance.log : undefined,\n\t\t\tajv: { customOptions: { coerceTypes: false } },\n\t\t\tschemaErrorFormatter: (errors, data) =>\n\t\t\t\tnew ValidationError(\n\t\t\t\t\terrors.map((error) => ({\n\t\t\t\t\t\tmessages: [error.message ?? ''],\n\t\t\t\t\t\tfield: `${data}${error.instancePath}`.replaceAll('/', '.'),\n\t\t\t\t\t})),\n\t\t\t\t),\n\t\t})\n\t\tsuper(app.server, config, {\n\t\t\tparseRequest: async (req) => {\n\t\t\t\tconst allHeaders = Object.fromEntries(Object.entries(req.headers).map(([key, val]) => [key, val ?? null]))\n\t\t\t\tconst headers = {\n\t\t\t\t\t...allHeaders,\n\t\t\t\t\tAuthorization: req.headers['authorization']?.toString(),\n\t\t\t\t\tRefreshToken: req.headers['x-refresh-token']?.toString(),\n\t\t\t\t\tApiKey: req.headers['x-api-key']?.toString(),\n\t\t\t\t\tContentType: req.headers['content-type']?.toString(),\n\t\t\t\t\tReferer: req.headers['referer']?.toString(),\n\t\t\t\t\tUserAgent: req.headers['user-agent']?.toString(),\n\t\t\t\t}\n\t\t\t\tconst { body, files } = excludeBufferKeys(req.body ?? {})\n\n\t\t\t\treturn new Request({\n\t\t\t\t\tip: req.ip,\n\t\t\t\t\tbody,\n\t\t\t\t\tcookies: req.cookies ?? {},\n\t\t\t\t\tparams: req.params ?? <any>{},\n\t\t\t\t\tquery: req.query ?? {},\n\t\t\t\t\tmethod: <any>req.method,\n\t\t\t\t\tpath: req.url,\n\t\t\t\t\theaders,\n\t\t\t\t\tfiles,\n\t\t\t\t\tcontext: {},\n\t\t\t\t})\n\t\t\t},\n\t\t\thandleResponse: async (res, response) => {\n\t\t\t\tfor (const [key, { value, ...opts }] of Object.entries(response.cookies)) res = res.setCookie(key, value, opts)\n\t\t\t\tawait res.status(response.status).headers(response.headers).send(response.body)\n\t\t\t},\n\t\t\tregisterRoute: (method, path, cb) => {\n\t\t\t\tapp.register(async (inst) => {\n\t\t\t\t\tinst.route({ url: path, method, handler: cb })\n\t\t\t\t})\n\t\t\t},\n\t\t\tregisterErrorHandler: (cb) => {\n\t\t\t\tapp.setErrorHandler(cb)\n\t\t\t},\n\t\t\tregisterNotFoundHandler: (cb) => {\n\t\t\t\tapp.setNotFoundHandler(cb)\n\t\t\t},\n\t\t\tstart: async (port) => {\n\t\t\t\tawait app.ready()\n\t\t\t\tawait app.listen({ port, host: '0.0.0.0' })\n\t\t\t\tInstance.on('close', app.close, 1)\n\t\t\t\treturn true\n\t\t\t},\n\t\t})\n\n\t\tapp.decorateRequest('savedReq', null)\n\t\tapp.setValidatorCompiler(() => () => true)\n\t\tapp.setSerializerCompiler(() => (data) => JSON.stringify(data))\n\t\tif (config.publicPath) app.register(fastifyStatic, { root: config.publicPath })\n\t\tapp.register(fastifyCookie, {})\n\t\tapp.register(fastifyCors, this.cors)\n\t\tapp.register(fastifyFormBody, { parser: (str) => qs.parse(str) })\n\t\tapp.register(fastifyHelmet, { crossOriginResourcePolicy: { policy: 'cross-origin' }, contentSecurityPolicy: false })\n\t\tapp.register(fastifyMultipart, {\n\t\t\tattachFieldsToBody: 'keyValues',\n\t\t\tthrowFileSizeLimit: false,\n\t\t\tlimits: { fileSize: instance.settings.utils.maxFileUploadSizeInMb * 1024 * 1024 },\n\t\t\tonFile: async (f) => {\n\t\t\t\tconst buffer = await f.toBuffer()\n\t\t\t\tconst parsed: IncomingFile = {\n\t\t\t\t\tname: f.filename,\n\t\t\t\t\ttype: f.mimetype,\n\t\t\t\t\tsize: buffer.byteLength,\n\t\t\t\t\tisTruncated: f.file.truncated,\n\t\t\t\t\tdata: buffer,\n\t\t\t\t\tduration: await getMediaDuration(buffer),\n\t\t\t\t}\n\t\t\t\t// @ts-ignore\n\t\t\t\tf.value = parsed\n\t\t\t},\n\t\t})\n\t\t/* if (this.settings.slowdown.enabled) app.register(fastifySlowDown, {\n\t\t\ttimeWindow: this.settings.slowdown.periodInMs,\n\t\t\tdelayAfter: this.settings.slowdown.delayAfter,\n\t\t\tdelay: this.settings.slowdown.delayInMs\n\t\t}) */\n\t\tif (config.requests.rateLimit.enabled)\n\t\t\tapp.register(fastifyRateLimit, {\n\t\t\t\tmax: config.requests.rateLimit.limit,\n\t\t\t\ttimeWindow: config.requests.rateLimit.periodInMs,\n\t\t\t\terrorResponseBuilder: (_, context) => ({\n\t\t\t\t\tstatusCode: StatusCodes.TooManyRequests,\n\t\t\t\t\tmessage: JSON.stringify([{ message: `Too Many Requests. Retry in ${context.after}` }]),\n\t\t\t\t}),\n\t\t\t})\n\t}\n}\n\nfunction excludeBufferKeys<T>(body: T) {\n\tif (typeof body !== 'object') return { body, files: {} }\n\tconst entries = Object.entries(body ?? {})\n\tconst isFile = (val: any) => (Array.isArray(val) ? isFile(val.at(0)) : Buffer.isBuffer(val?.data))\n\tconst fileEntries = entries.filter(([_, value]) => isFile(value)).map(([key, value]) => [key, Array.isArray(value) ? value : [value]])\n\tconst nonFileEntries = entries.filter(([_, value]) => !isFile(value))\n\treturn {\n\t\tbody: <T>Object.fromEntries(nonFileEntries),\n\t\tfiles: <Record<string, IncomingFile[]>>Object.fromEntries(fileEntries),\n\t}\n}\n",null]}