equipped 5.1.7 → 5.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/audit/events.cjs +27 -20
- package/dist/cjs/audit/events.cjs.map +1 -1
- package/dist/cjs/audit/events.min.cjs +1 -1
- package/dist/cjs/audit/events.min.cjs.map +1 -1
- package/dist/cjs/server/impls/fastify.cjs +4 -2
- package/dist/cjs/server/impls/fastify.cjs.map +1 -1
- package/dist/cjs/server/impls/fastify.min.cjs +1 -1
- package/dist/cjs/server/impls/fastify.min.cjs.map +1 -1
- package/dist/esm/audit/events.min.mjs +1 -1
- package/dist/esm/audit/events.min.mjs.map +1 -1
- package/dist/esm/audit/events.mjs +27 -20
- package/dist/esm/audit/events.mjs.map +1 -1
- package/dist/esm/server/impls/fastify.min.mjs +1 -1
- package/dist/esm/server/impls/fastify.min.mjs.map +1 -1
- package/dist/esm/server/impls/fastify.mjs +4 -2
- package/dist/esm/server/impls/fastify.mjs.map +1 -1
- package/dist/types/audit/events.js +27 -20
- package/dist/types/audit/index.d.ts +3 -5
- package/dist/types/server/impls/fastify.js +4 -2
- package/package.json +228 -227
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
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.1.8](https://github.com/kevinand11/equipped/compare/v5.1.7...v5.1.8) (2026-01-09)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* add firstRun to event context ([0f47b76](https://github.com/kevinand11/equipped/commit/0f47b762525aff5e51acfe1676e9b4e5b31a84eb))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* update fastify options ([27524e2](https://github.com/kevinand11/equipped/commit/27524e231b4a5c306015986de25fa48f9a87a6a5))
|
|
16
|
+
|
|
5
17
|
### [5.1.7](https://github.com/kevinand11/equipped/compare/v5.1.6...v5.1.7) (2025-12-07)
|
|
6
18
|
|
|
7
19
|
|
|
@@ -14,13 +14,17 @@ class EventAudit {
|
|
|
14
14
|
mapper: (model) => ({ ...model, toJSON: () => model }),
|
|
15
15
|
options: { skipAudit: true }
|
|
16
16
|
});
|
|
17
|
-
_indexcjs5.Instance.on(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
_indexcjs5.Instance.on(
|
|
18
|
+
"start",
|
|
19
|
+
() => {
|
|
20
|
+
setInterval(async () => {
|
|
21
|
+
const queue = [...this.asyncQueue];
|
|
22
|
+
this.asyncQueue = [];
|
|
23
|
+
await Promise.all(queue.map((job) => job()));
|
|
24
|
+
}, 200);
|
|
25
|
+
},
|
|
26
|
+
4
|
|
27
|
+
);
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
__init() {this.definitions = {}}
|
|
@@ -43,19 +47,17 @@ class EventAudit {
|
|
|
43
47
|
{ getTime: () => ts, makeId: () => key }
|
|
44
48
|
);
|
|
45
49
|
}
|
|
46
|
-
async #processEvent(event,
|
|
50
|
+
async #processEvent(event, firstRun) {
|
|
47
51
|
return this.db.session(async () => {
|
|
48
52
|
const def = this.definitions[event.name];
|
|
49
53
|
if (!def) throw new (0, _indexcjs3.EquippedError)("audit definition not found", { event });
|
|
50
54
|
try {
|
|
51
|
-
await this.table.updateOne(
|
|
52
|
-
{ key: event.key },
|
|
53
|
-
{ $set: { steps: [createStep({ status: "start", ts: Date.now() })] } }
|
|
54
|
-
);
|
|
55
|
+
await this.table.updateOne({ key: event.key }, { $set: { steps: [createStep({ status: "start", ts: Date.now() })] } });
|
|
55
56
|
const context = {
|
|
56
57
|
key: event.key,
|
|
57
58
|
by: event.by,
|
|
58
|
-
|
|
59
|
+
at: new Date(event.ts),
|
|
60
|
+
firstRun
|
|
59
61
|
};
|
|
60
62
|
const result = await def.handle(event.body, context);
|
|
61
63
|
await _optionalChain([def, 'access', _ => _.sync, 'optionalCall', _2 => _2(result, event.body, context)]);
|
|
@@ -63,14 +65,19 @@ class EventAudit {
|
|
|
63
65
|
const asyncHandle = async () => {
|
|
64
66
|
try {
|
|
65
67
|
await _optionalChain([def, 'access', _3 => _3.async, 'optionalCall', _4 => _4(result, event.body, context)]);
|
|
66
|
-
await this.table.updateOne(
|
|
68
|
+
await this.table.updateOne(
|
|
69
|
+
{ key: event.key },
|
|
70
|
+
{ $push: { steps: createStep({ status: "async", ts: Date.now() }) } }
|
|
71
|
+
);
|
|
67
72
|
} catch (err) {
|
|
68
73
|
const error = err instanceof Error ? err.message : String(err);
|
|
69
|
-
await this.table.updateOne(
|
|
74
|
+
await this.table.updateOne(
|
|
75
|
+
{ key: event.key },
|
|
76
|
+
{ $push: { steps: createStep({ status: "error", error, ts: Date.now() }) } }
|
|
77
|
+
);
|
|
70
78
|
}
|
|
71
|
-
;
|
|
72
79
|
};
|
|
73
|
-
if (
|
|
80
|
+
if (!context.firstRun) await asyncHandle();
|
|
74
81
|
else this.asyncQueue.push(asyncHandle);
|
|
75
82
|
return result;
|
|
76
83
|
} catch (err) {
|
|
@@ -88,12 +95,12 @@ class EventAudit {
|
|
|
88
95
|
all: true
|
|
89
96
|
})
|
|
90
97
|
);
|
|
91
|
-
for (const event of events) await this.#processEvent(event,
|
|
98
|
+
for (const event of events) await this.#processEvent(event, false);
|
|
92
99
|
}
|
|
93
100
|
async rerun(key) {
|
|
94
101
|
const event = await this.table.findOne({ key });
|
|
95
102
|
if (!event) throw new (0, _indexcjs3.EquippedError)("audit event not found", { key });
|
|
96
|
-
await this.#processEvent(event,
|
|
103
|
+
await this.#processEvent(event, false);
|
|
97
104
|
}
|
|
98
105
|
register(name, def) {
|
|
99
106
|
if (this.definitions[name]) throw new (0, _indexcjs3.EquippedError)(`${name} already has a registered handler`, {});
|
|
@@ -101,7 +108,7 @@ class EventAudit {
|
|
|
101
108
|
_valleyed.v.compile(def.pipe);
|
|
102
109
|
return async (payload, context) => {
|
|
103
110
|
const event = await this.#createEvent(name, payload, context);
|
|
104
|
-
return this.#processEvent(event,
|
|
111
|
+
return this.#processEvent(event, true);
|
|
105
112
|
};
|
|
106
113
|
}
|
|
107
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/audit/events.ts","/home/runner/work/equipped/equipped/dist/cjs/audit/events.cjs"],"names":[],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/audit/events.cjs","sourcesContent":["import { type Pipe, type PipeInput, type PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, type Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\nimport { Instance } from '../instance'\n\nexport type EventDefinition<P extends Pipe<any, any>, R> = {\n\tpipe: P\n\thandle: (payload: PipeOutput<P>, context: EventContext) => R | Promise<R>\n\tsync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n\tasync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n}\n\nexport type EventContext = {\n\tkey: string\n\tby: string | undefined\n\tdate: Date\n}\n\nexport type EventDoc = {\n\tkey: string\n\tname: string\n\tts: number\n\tbody: unknown\n\tsteps: { status: 'start' | 'sync' | 'async' | 'error', ts: number, error?: string }[]\n\tby?: string\n}\ntype Context = { by?: string; at?: Date; }\n\nfunction createStep (step: EventDoc['steps'][number]) {\n\treturn step\n}\n\nexport class EventAudit {\n\tprivate table: Table<any, EventDoc, EventDoc & { toJSON: () => Record<string, unknown> }, any>\n\tprivate definitions: Record<string, EventDefinition<any, any>> = {}\n\tprivate asyncQueue: (() => Promise<void>)[] = []\n\n\tconstructor(\n\t\tprivate db: Db<any>,\n\t\tdbName: string,\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\n\t\tInstance.on('start', () => {\n\t\t\tsetInterval(async () => {\n\t\t\t\tconst queue = [...this.asyncQueue]\n\t\t\t\tthis.asyncQueue = []\n\t\t\t\tawait Promise.all(queue.map((job) => job()))\n\t\t\t}, 200)\n\t\t}, 4)\n\t}\n\n\tasync #createEvent(name: string, payload: unknown, context: Context) {\n\t\tconst def = this.definitions[name]\n\t\tif (!def) throw new EquippedError('audit definition not found', { name, payload })\n\n\t\tconst validBody = v.assert(def.pipe, payload)\n\t\tconst ts = context.at ?? new Date()\n\t\tconst key = Instance.createId({ time: ts })\n\n\t\treturn await this.table.insertOne(\n\t\t\t{\n\t\t\t\tkey,\n\t\t\t\tname,\n\t\t\t\tts: ts.getTime(),\n\t\t\t\tbody: validBody,\n\t\t\t\tby: context.by,\n\t\t\t\tsteps: []\n\t\t\t},\n\t\t\t{ getTime: () => ts, makeId: () => key },\n\t\t)\n\t}\n\n\tasync #processEvent<R>(event: EventDoc, callbackWait: boolean) {\n\t\treturn this.db.session(async () => {\n\t\t\tconst def = this.definitions[event.name]\n\t\t\tif (!def) throw new EquippedError('audit definition 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: { steps: [createStep({ status: 'start', ts: Date.now() })] } },\n\t\t\t\t)\n\t\t\t\tconst context: EventContext = {\n\t\t\t\t\tkey: event.key,\n\t\t\t\t\tby: event.by,\n\t\t\t\t\tdate: new Date(event.ts),\n\t\t\t\t}\n\t\t\t\tconst result = await def.handle(event.body, context)\n\t\t\t\tawait def.sync?.(result, event.body, context)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'sync', ts: Date.now() }) } })\n\n\t\t\t\tconst asyncHandle = async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait def.async?.(result, event.body, context)\n\t\t\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'async', ts: Date.now() }) } })\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } })\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (callbackWait) await asyncHandle()\n\t\t\t\telse this.asyncQueue.push(asyncHandle)\n\t\t\t\treturn result as R\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } })\n\t\t\t\tthrow err\n\t\t\t}\n\t\t})\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, true)\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, true)\n\t}\n\n\tregister<P extends Pipe<any, any>, R>(name: string, def: EventDefinition<P, R>) {\n\t\tif (this.definitions[name]) throw new EquippedError(`${name} already has a registered handler`, {})\n\t\tthis.definitions[name] = def\n\t\tv.compile(def.pipe)\n\t\treturn async (payload: PipeInput<P>, context: Context)=> {\n\t\t\tconst event = await this.#createEvent(name, payload, context)\n\t\t\treturn this.#processEvent<R>(event, false)\n\t\t}\n\t}\n}\n",null]}
|
|
1
|
+
{"version":3,"sources":["../../../src/audit/events.ts","/home/runner/work/equipped/equipped/dist/cjs/audit/events.cjs"],"names":[],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/audit/events.cjs","sourcesContent":["import { type Pipe, type PipeInput, type PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, type Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\nimport { Instance } from '../instance'\n\nexport type EventDefinition<P extends Pipe<any, any>, R> = {\n\tpipe: P\n\thandle: (payload: PipeOutput<P>, context: EventContext) => R | Promise<R>\n\tsync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n\tasync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n}\n\nexport type EventContext = {\n\tkey: string\n\tby: string | undefined\n\tat: Date\n\tfirstRun: boolean\n}\n\nexport type EventDoc = {\n\tkey: string\n\tname: string\n\tts: number\n\tbody: unknown\n\tsteps: { status: 'start' | 'sync' | 'async' | 'error'; ts: number; error?: string }[]\n\tby?: string\n}\ntype Context = Partial<Pick<EventContext, 'by' | 'at'>>\n\nfunction createStep(step: EventDoc['steps'][number]) {\n\treturn step\n}\n\nexport class EventAudit {\n\tprivate table: Table<any, EventDoc, EventDoc & { toJSON: () => Record<string, unknown> }, any>\n\tprivate definitions: Record<string, EventDefinition<any, any>> = {}\n\tprivate asyncQueue: (() => Promise<void>)[] = []\n\n\tconstructor(\n\t\tprivate db: Db<any>,\n\t\tdbName: string,\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\n\t\tInstance.on(\n\t\t\t'start',\n\t\t\t() => {\n\t\t\t\tsetInterval(async () => {\n\t\t\t\t\tconst queue = [...this.asyncQueue]\n\t\t\t\t\tthis.asyncQueue = []\n\t\t\t\t\tawait Promise.all(queue.map((job) => job()))\n\t\t\t\t}, 200)\n\t\t\t},\n\t\t\t4,\n\t\t)\n\t}\n\n\tasync #createEvent(name: string, payload: unknown, context: Context) {\n\t\tconst def = this.definitions[name]\n\t\tif (!def) throw new EquippedError('audit definition not found', { name, payload })\n\n\t\tconst validBody = v.assert(def.pipe, payload)\n\t\tconst ts = context.at ?? new Date()\n\t\tconst key = Instance.createId({ time: ts })\n\n\t\treturn await this.table.insertOne(\n\t\t\t{\n\t\t\t\tkey,\n\t\t\t\tname,\n\t\t\t\tts: ts.getTime(),\n\t\t\t\tbody: validBody,\n\t\t\t\tby: context.by,\n\t\t\t\tsteps: [],\n\t\t\t},\n\t\t\t{ getTime: () => ts, makeId: () => key },\n\t\t)\n\t}\n\n\tasync #processEvent<R>(event: EventDoc, firstRun: boolean) {\n\t\treturn this.db.session(async () => {\n\t\t\tconst def = this.definitions[event.name]\n\t\t\tif (!def) throw new EquippedError('audit definition not found', { event })\n\t\t\ttry {\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $set: { steps: [createStep({ status: 'start', ts: Date.now() })] } })\n\t\t\t\tconst context: EventContext = {\n\t\t\t\t\tkey: event.key,\n\t\t\t\t\tby: event.by,\n\t\t\t\t\tat: new Date(event.ts),\n\t\t\t\t\tfirstRun,\n\t\t\t\t}\n\t\t\t\tconst result = await def.handle(event.body, context)\n\t\t\t\tawait def.sync?.(result, event.body, context)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'sync', ts: Date.now() }) } })\n\n\t\t\t\tconst asyncHandle = async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait def.async?.(result, event.body, context)\n\t\t\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t\t\t{ $push: { steps: createStep({ status: 'async', ts: Date.now() }) } },\n\t\t\t\t\t\t)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t\t\t{ $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } },\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!context.firstRun) await asyncHandle()\n\t\t\t\telse this.asyncQueue.push(asyncHandle)\n\t\t\t\treturn result as R\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } })\n\t\t\t\tthrow err\n\t\t\t}\n\t\t})\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, false)\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, false)\n\t}\n\n\tregister<P extends Pipe<any, any>, R>(name: string, def: EventDefinition<P, R>) {\n\t\tif (this.definitions[name]) throw new EquippedError(`${name} already has a registered handler`, {})\n\t\tthis.definitions[name] = def\n\t\tv.compile(def.pipe)\n\t\treturn async (payload: PipeInput<P>, context: Context) => {\n\t\t\tconst event = await this.#createEvent(name, payload, context)\n\t\t\treturn this.#processEvent<R>(event, true)\n\t\t}\n\t}\n}\n",null]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); 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 _valleyed = require('valleyed');var _indexmincjs = require('../dbs/index.min.cjs');var _indexmincjs3 = require('../errors/index.min.cjs');var _indexmincjs5 = require('../instance/index.min.cjs');function P(u){return u}class k{constructor(t,s){;k.prototype.__init.call(this);k.prototype.__init2.call(this);this.db=t;this.table=t.use({db:s,col:"__audits",mapper:e=>({...e,toJSON:()=>e}),options:{skipAudit:!0}}),_indexmincjs5.Instance.on("start",()=>{setInterval(async()=>{const e=[...this.asyncQueue];this.asyncQueue=[],await Promise.all(e.map(n=>n()))},200)},4)}__init() {this.definitions={}}__init2() {this.asyncQueue=[]}async#e(t,s,e){const n=this.definitions[t];if(!n)throw new (0, _indexmincjs3.EquippedError)("audit definition not found",{name:t,payload:s});const a=_valleyed.v.assert(n.pipe,s),i=_nullishCoalesce(e.at, () => (new Date)),r=_indexmincjs5.Instance.createId({time:i});return await this.table.insertOne({key:r,name:t,ts:i.getTime(),body:a,by:e.by,steps:[]},{getTime:()=>i,makeId:()=>r})}async#t(t,s){return this.db.session(async()=>{const e=this.definitions[t.name];if(!e)throw new (0, _indexmincjs3.EquippedError)("audit definition not found",{event:t});try{await this.table.updateOne({key:t.key},{$set:{steps:[{status:"start",ts:Date.now()}]}});const n={key:t.key,by:t.by,
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); 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 _valleyed = require('valleyed');var _indexmincjs = require('../dbs/index.min.cjs');var _indexmincjs3 = require('../errors/index.min.cjs');var _indexmincjs5 = require('../instance/index.min.cjs');function P(u){return u}class k{constructor(t,s){;k.prototype.__init.call(this);k.prototype.__init2.call(this);this.db=t;this.table=t.use({db:s,col:"__audits",mapper:e=>({...e,toJSON:()=>e}),options:{skipAudit:!0}}),_indexmincjs5.Instance.on("start",()=>{setInterval(async()=>{const e=[...this.asyncQueue];this.asyncQueue=[],await Promise.all(e.map(n=>n()))},200)},4)}__init() {this.definitions={}}__init2() {this.asyncQueue=[]}async#e(t,s,e){const n=this.definitions[t];if(!n)throw new (0, _indexmincjs3.EquippedError)("audit definition not found",{name:t,payload:s});const a=_valleyed.v.assert(n.pipe,s),i=_nullishCoalesce(e.at, () => (new Date)),r=_indexmincjs5.Instance.createId({time:i});return await this.table.insertOne({key:r,name:t,ts:i.getTime(),body:a,by:e.by,steps:[]},{getTime:()=>i,makeId:()=>r})}async#t(t,s){return this.db.session(async()=>{const e=this.definitions[t.name];if(!e)throw new (0, _indexmincjs3.EquippedError)("audit definition not found",{event:t});try{await this.table.updateOne({key:t.key},{$set:{steps:[{status:"start",ts:Date.now()}]}});const n={key:t.key,by:t.by,at:new Date(t.ts),firstRun:s},a=await e.handle(t.body,n);await _optionalChain([e, 'access', _ => _.sync, 'optionalCall', _2 => _2(a,t.body,n)]),await this.table.updateOne({key:t.key},{$push:{steps:{status:"sync",ts:Date.now()}}});const i=async()=>{try{await _optionalChain([e, 'access', _3 => _3.async, 'optionalCall', _4 => _4(a,t.body,n)]),await this.table.updateOne({key:t.key},{$push:{steps:{status:"async",ts:Date.now()}}})}catch(r){const c=r instanceof Error?r.message:String(r);await this.table.updateOne({key:t.key},{$push:{steps:{status:"error",error:c,ts:Date.now()}}})}};return n.firstRun?this.asyncQueue.push(i):await i(),a}catch(n){const a=n instanceof Error?n.message:String(n);throw await this.table.updateOne({key:t.key},{$push:{steps:{status:"error",error:a,ts:Date.now()}}}),n}})}async replay(t){const{results:s}=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 s)await this.#t(e,!1)}async rerun(t){const s=await this.table.findOne({key:t});if(!s)throw new (0, _indexmincjs3.EquippedError)("audit event not found",{key:t});await this.#t(s,!1)}register(t,s){if(this.definitions[t])throw new (0, _indexmincjs3.EquippedError)(`${t} already has a registered handler`,{});return this.definitions[t]=s,_valleyed.v.compile(s.pipe),async(e,n)=>{const a=await this.#e(t,e,n);return this.#t(a,!0)}}}exports.EventAudit = k;
|
|
2
2
|
//# sourceMappingURL=events.min.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/audit/events.ts"],"names":["db","model","Instance","queue","job","#createEvent","name","payload","EquippedError","context","key","ts","validBody","#processEvent","callbackWait","def","event","result","asyncHandle","err","error","from","events","wrapQueryParams"],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/audit/events.min.cjs","sourcesContent":["import { type Pipe, type PipeInput, type PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, type Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\nimport { Instance } from '../instance'\n\nexport type EventDefinition<P extends Pipe<any, any>, R> = {\n\tpipe: P\n\thandle: (payload: PipeOutput<P>, context: EventContext) => R | Promise<R>\n\tsync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n\tasync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n}\n\nexport type EventContext = {\n\tkey: string\n\tby: string | undefined\n\tdate: Date\n}\n\nexport type EventDoc = {\n\tkey: string\n\tname: string\n\tts: number\n\tbody: unknown\n\tsteps: { status: 'start' | 'sync' | 'async' | 'error', ts: number, error?: string }[]\n\tby?: string\n}\ntype Context = { by?: string; at?: Date; }\n\nfunction createStep (step: EventDoc['steps'][number]) {\n\treturn step\n}\n\nexport class EventAudit {\n\tprivate table: Table<any, EventDoc, EventDoc & { toJSON: () => Record<string, unknown> }, any>\n\tprivate definitions: Record<string, EventDefinition<any, any>> = {}\n\tprivate asyncQueue: (() => Promise<void>)[] = []\n\n\tconstructor(\n\t\tprivate db: Db<any>,\n\t\tdbName: string,\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\n\t\tInstance.on('start', () => {\n\t\t\tsetInterval(async () => {\n\t\t\t\tconst queue = [...this.asyncQueue]\n\t\t\t\tthis.asyncQueue = []\n\t\t\t\tawait Promise.all(queue.map((job) => job()))\n\t\t\t}, 200)\n\t\t}, 4)\n\t}\n\n\tasync #createEvent(name: string, payload: unknown, context: Context) {\n\t\tconst def = this.definitions[name]\n\t\tif (!def) throw new EquippedError('audit definition not found', { name, payload })\n\n\t\tconst validBody = v.assert(def.pipe, payload)\n\t\tconst ts = context.at ?? new Date()\n\t\tconst key = Instance.createId({ time: ts })\n\n\t\treturn await this.table.insertOne(\n\t\t\t{\n\t\t\t\tkey,\n\t\t\t\tname,\n\t\t\t\tts: ts.getTime(),\n\t\t\t\tbody: validBody,\n\t\t\t\tby: context.by,\n\t\t\t\tsteps: []\n\t\t\t},\n\t\t\t{ getTime: () => ts, makeId: () => key },\n\t\t)\n\t}\n\n\tasync #processEvent<R>(event: EventDoc, callbackWait: boolean) {\n\t\treturn this.db.session(async () => {\n\t\t\tconst def = this.definitions[event.name]\n\t\t\tif (!def) throw new EquippedError('audit definition 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: { steps: [createStep({ status: 'start', ts: Date.now() })] } },\n\t\t\t\t)\n\t\t\t\tconst context: EventContext = {\n\t\t\t\t\tkey: event.key,\n\t\t\t\t\tby: event.by,\n\t\t\t\t\tdate: new Date(event.ts),\n\t\t\t\t}\n\t\t\t\tconst result = await def.handle(event.body, context)\n\t\t\t\tawait def.sync?.(result, event.body, context)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'sync', ts: Date.now() }) } })\n\n\t\t\t\tconst asyncHandle = async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait def.async?.(result, event.body, context)\n\t\t\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'async', ts: Date.now() }) } })\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } })\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (callbackWait) await asyncHandle()\n\t\t\t\telse this.asyncQueue.push(asyncHandle)\n\t\t\t\treturn result as R\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } })\n\t\t\t\tthrow err\n\t\t\t}\n\t\t})\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, true)\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, true)\n\t}\n\n\tregister<P extends Pipe<any, any>, R>(name: string, def: EventDefinition<P, R>) {\n\t\tif (this.definitions[name]) throw new EquippedError(`${name} already has a registered handler`, {})\n\t\tthis.definitions[name] = def\n\t\tv.compile(def.pipe)\n\t\treturn async (payload: PipeInput<P>, context: Context)=> {\n\t\t\tconst event = await this.#createEvent(name, payload, context)\n\t\t\treturn this.#processEvent<R>(event, false)\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/audit/events.ts"],"names":["db","model","Instance","queue","job","#createEvent","name","payload","EquippedError","context","key","ts","validBody","#processEvent","firstRun","def","event","result","asyncHandle","err","error","from","events","wrapQueryParams"],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/audit/events.min.cjs","sourcesContent":["import { type Pipe, type PipeInput, type PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, type Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\nimport { Instance } from '../instance'\n\nexport type EventDefinition<P extends Pipe<any, any>, R> = {\n\tpipe: P\n\thandle: (payload: PipeOutput<P>, context: EventContext) => R | Promise<R>\n\tsync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n\tasync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n}\n\nexport type EventContext = {\n\tkey: string\n\tby: string | undefined\n\tat: Date\n\tfirstRun: boolean\n}\n\nexport type EventDoc = {\n\tkey: string\n\tname: string\n\tts: number\n\tbody: unknown\n\tsteps: { status: 'start' | 'sync' | 'async' | 'error'; ts: number; error?: string }[]\n\tby?: string\n}\ntype Context = Partial<Pick<EventContext, 'by' | 'at'>>\n\nfunction createStep(step: EventDoc['steps'][number]) {\n\treturn step\n}\n\nexport class EventAudit {\n\tprivate table: Table<any, EventDoc, EventDoc & { toJSON: () => Record<string, unknown> }, any>\n\tprivate definitions: Record<string, EventDefinition<any, any>> = {}\n\tprivate asyncQueue: (() => Promise<void>)[] = []\n\n\tconstructor(\n\t\tprivate db: Db<any>,\n\t\tdbName: string,\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\n\t\tInstance.on(\n\t\t\t'start',\n\t\t\t() => {\n\t\t\t\tsetInterval(async () => {\n\t\t\t\t\tconst queue = [...this.asyncQueue]\n\t\t\t\t\tthis.asyncQueue = []\n\t\t\t\t\tawait Promise.all(queue.map((job) => job()))\n\t\t\t\t}, 200)\n\t\t\t},\n\t\t\t4,\n\t\t)\n\t}\n\n\tasync #createEvent(name: string, payload: unknown, context: Context) {\n\t\tconst def = this.definitions[name]\n\t\tif (!def) throw new EquippedError('audit definition not found', { name, payload })\n\n\t\tconst validBody = v.assert(def.pipe, payload)\n\t\tconst ts = context.at ?? new Date()\n\t\tconst key = Instance.createId({ time: ts })\n\n\t\treturn await this.table.insertOne(\n\t\t\t{\n\t\t\t\tkey,\n\t\t\t\tname,\n\t\t\t\tts: ts.getTime(),\n\t\t\t\tbody: validBody,\n\t\t\t\tby: context.by,\n\t\t\t\tsteps: [],\n\t\t\t},\n\t\t\t{ getTime: () => ts, makeId: () => key },\n\t\t)\n\t}\n\n\tasync #processEvent<R>(event: EventDoc, firstRun: boolean) {\n\t\treturn this.db.session(async () => {\n\t\t\tconst def = this.definitions[event.name]\n\t\t\tif (!def) throw new EquippedError('audit definition not found', { event })\n\t\t\ttry {\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $set: { steps: [createStep({ status: 'start', ts: Date.now() })] } })\n\t\t\t\tconst context: EventContext = {\n\t\t\t\t\tkey: event.key,\n\t\t\t\t\tby: event.by,\n\t\t\t\t\tat: new Date(event.ts),\n\t\t\t\t\tfirstRun,\n\t\t\t\t}\n\t\t\t\tconst result = await def.handle(event.body, context)\n\t\t\t\tawait def.sync?.(result, event.body, context)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'sync', ts: Date.now() }) } })\n\n\t\t\t\tconst asyncHandle = async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait def.async?.(result, event.body, context)\n\t\t\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t\t\t{ $push: { steps: createStep({ status: 'async', ts: Date.now() }) } },\n\t\t\t\t\t\t)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t\t\t{ $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } },\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!context.firstRun) await asyncHandle()\n\t\t\t\telse this.asyncQueue.push(asyncHandle)\n\t\t\t\treturn result as R\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } })\n\t\t\t\tthrow err\n\t\t\t}\n\t\t})\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, false)\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, false)\n\t}\n\n\tregister<P extends Pipe<any, any>, R>(name: string, def: EventDefinition<P, R>) {\n\t\tif (this.definitions[name]) throw new EquippedError(`${name} already has a registered handler`, {})\n\t\tthis.definitions[name] = def\n\t\tv.compile(def.pipe)\n\t\treturn async (payload: PipeInput<P>, context: Context) => {\n\t\t\tconst event = await this.#createEvent(name, payload, context)\n\t\t\treturn this.#processEvent<R>(event, true)\n\t\t}\n\t}\n}\n"]}
|
|
@@ -17,11 +17,13 @@ class FastifyServer extends _basecjs.Server {
|
|
|
17
17
|
constructor(config) {
|
|
18
18
|
const instance = _indexcjs3.Instance.get();
|
|
19
19
|
const app = _fastify2.default.call(void 0, {
|
|
20
|
-
ignoreTrailingSlash: true,
|
|
21
|
-
caseSensitive: false,
|
|
22
20
|
disableRequestLogging: !config.requests.log,
|
|
23
21
|
loggerInstance: config.requests.log ? instance.log : void 0,
|
|
24
22
|
ajv: { customOptions: { coerceTypes: false } },
|
|
23
|
+
routerOptions: {
|
|
24
|
+
ignoreTrailingSlash: true,
|
|
25
|
+
caseSensitive: false
|
|
26
|
+
},
|
|
25
27
|
schemaErrorFormatter: (errors, data) => new (0, _indexcjs.ValidationError)(
|
|
26
28
|
errors.map((error) => ({
|
|
27
29
|
messages: [_nullishCoalesce(error.message, () => ( ""))],
|
|
@@ -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,wCAA+C;AAC/C,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,
|
|
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,wCAA+C;AAC/C,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,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,aAAA,EAAe;AAAA,QACd,mBAAA,EAAqB,IAAA;AAAA,QACrB,aAAA,EAAe;AAAA,MAChB,CAAA;AAAA,MACA,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 type { ServerConfig } from '../pipes'\nimport { Request } from '../requests'\nimport { type 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\tdisableRequestLogging: !config.requests.log,\n\t\t\tloggerInstance: config.requests.log ? instance.log : undefined,\n\t\t\tajv: { customOptions: { coerceTypes: false } },\n\t\t\trouterOptions: {\n\t\t\t\tignoreTrailingSlash: true,\n\t\t\t\tcaseSensitive: false,\n\t\t\t},\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]}
|
|
@@ -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 _cookie = require('@fastify/cookie'); var _cookie2 = _interopRequireDefault(_cookie);var _cors = require('@fastify/cors'); var _cors2 = _interopRequireDefault(_cors);var _formbody = require('@fastify/formbody'); var _formbody2 = _interopRequireDefault(_formbody);var _helmet = require('@fastify/helmet'); var _helmet2 = _interopRequireDefault(_helmet);var _multipart = require('@fastify/multipart'); var _multipart2 = _interopRequireDefault(_multipart);var _ratelimit = require('@fastify/rate-limit'); var _ratelimit2 = _interopRequireDefault(_ratelimit);var _static = require('@fastify/static'); var _static2 = _interopRequireDefault(_static);var _fastify = require('fastify'); var _fastify2 = _interopRequireDefault(_fastify);var _qs = require('qs'); var _qs2 = _interopRequireDefault(_qs);var _indexmincjs = require('../../errors/index.min.cjs');var _indexmincjs3 = require('../../instance/index.min.cjs');var _indexmincjs5 = require('../../utilities/index.min.cjs');var _requestsmincjs = require('../requests.min.cjs');var _typesmincjs = require('../types.min.cjs');var _basemincjs = require('./base.min.cjs');class _ extends _basemincjs.Server{constructor(i){const o=_indexmincjs3.Instance.get(),r=_fastify2.default.call(void 0, {
|
|
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 _cookie = require('@fastify/cookie'); var _cookie2 = _interopRequireDefault(_cookie);var _cors = require('@fastify/cors'); var _cors2 = _interopRequireDefault(_cors);var _formbody = require('@fastify/formbody'); var _formbody2 = _interopRequireDefault(_formbody);var _helmet = require('@fastify/helmet'); var _helmet2 = _interopRequireDefault(_helmet);var _multipart = require('@fastify/multipart'); var _multipart2 = _interopRequireDefault(_multipart);var _ratelimit = require('@fastify/rate-limit'); var _ratelimit2 = _interopRequireDefault(_ratelimit);var _static = require('@fastify/static'); var _static2 = _interopRequireDefault(_static);var _fastify = require('fastify'); var _fastify2 = _interopRequireDefault(_fastify);var _qs = require('qs'); var _qs2 = _interopRequireDefault(_qs);var _indexmincjs = require('../../errors/index.min.cjs');var _indexmincjs3 = require('../../instance/index.min.cjs');var _indexmincjs5 = require('../../utilities/index.min.cjs');var _requestsmincjs = require('../requests.min.cjs');var _typesmincjs = require('../types.min.cjs');var _basemincjs = require('./base.min.cjs');class _ extends _basemincjs.Server{constructor(i){const o=_indexmincjs3.Instance.get(),r=_fastify2.default.call(void 0, {disableRequestLogging:!i.requests.log,loggerInstance:i.requests.log?o.log:void 0,ajv:{customOptions:{coerceTypes:!1}},routerOptions:{ignoreTrailingSlash:!0,caseSensitive:!1},schemaErrorFormatter:(e,t)=>new (0, _indexmincjs.ValidationError)(e.map(s=>({messages:[_nullishCoalesce(s.message, () => (""))],field:`${t}${s.instancePath}`.replaceAll("/",".")})))});super(r.server,i,{parseRequest:async e=>{const s={...Object.fromEntries(Object.entries(e.headers).map(([m,u])=>[m,_nullishCoalesce(u, () => (null))])),Authorization:_optionalChain([e, 'access', _2 => _2.headers, 'access', _3 => _3.authorization, 'optionalAccess', _4 => _4.toString, 'call', _5 => _5()]),RefreshToken:_optionalChain([e, 'access', _6 => _6.headers, 'access', _7 => _7["x-refresh-token"], 'optionalAccess', _8 => _8.toString, 'call', _9 => _9()]),ApiKey:_optionalChain([e, 'access', _10 => _10.headers, 'access', _11 => _11["x-api-key"], 'optionalAccess', _12 => _12.toString, 'call', _13 => _13()]),ContentType:_optionalChain([e, 'access', _14 => _14.headers, 'access', _15 => _15["content-type"], 'optionalAccess', _16 => _16.toString, 'call', _17 => _17()]),Referer:_optionalChain([e, 'access', _18 => _18.headers, 'access', _19 => _19.referer, 'optionalAccess', _20 => _20.toString, 'call', _21 => _21()]),UserAgent:_optionalChain([e, 'access', _22 => _22.headers, 'access', _23 => _23["user-agent"], 'optionalAccess', _24 => _24.toString, 'call', _25 => _25()])},{body:a,files:l}=w(_nullishCoalesce(e.body, () => ({})));return new (0, _requestsmincjs.Request)({ip:e.ip,body:a,cookies:_nullishCoalesce(e.cookies, () => ({})),params:_nullishCoalesce(e.params, () => ({})),query:_nullishCoalesce(e.query, () => ({})),method:e.method,path:e.url,headers:s,files:l,context:{}})},handleResponse:async(e,t)=>{for(const[s,{value:a,...l}]of Object.entries(t.cookies))e=e.setCookie(s,a,l);await e.status(t.status).headers(t.headers).send(t.body)},registerRoute:(e,t,s)=>{r.register(async a=>{a.route({url:t,method:e,handler:s})})},registerErrorHandler:e=>{r.setErrorHandler(e)},registerNotFoundHandler:e=>{r.setNotFoundHandler(e)},start:async e=>(await r.ready(),await r.listen({port:e,host:"0.0.0.0"}),_indexmincjs3.Instance.on("close",r.close,1),!0)}),r.decorateRequest("savedReq",null),r.setValidatorCompiler(()=>()=>!0),r.setSerializerCompiler(()=>e=>JSON.stringify(e)),i.publicPath&&r.register(_static2.default,{root:i.publicPath}),r.register(_cookie2.default,{}),r.register(_cors2.default,this.cors),r.register(_formbody2.default,{parser:e=>_qs2.default.parse(e)}),r.register(_helmet2.default,{crossOriginResourcePolicy:{policy:"cross-origin"},contentSecurityPolicy:!1}),r.register(_multipart2.default,{attachFieldsToBody:"keyValues",throwFileSizeLimit:!1,limits:{fileSize:o.settings.utils.maxFileUploadSizeInMb*1024*1024},onFile:async e=>{const t=await e.toBuffer(),s={name:e.filename,type:e.mimetype,size:t.byteLength,isTruncated:e.file.truncated,data:t,duration:await _indexmincjs5.getMediaDuration.call(void 0, t)};e.value=s}}),i.requests.rateLimit.enabled&&r.register(_ratelimit2.default,{max:i.requests.rateLimit.limit,timeWindow:i.requests.rateLimit.periodInMs,errorResponseBuilder:(e,t)=>({statusCode:_typesmincjs.StatusCodes.TooManyRequests,message:JSON.stringify([{message:`Too Many Requests. Retry in ${t.after}`}])})})}}function w(n){if(typeof n!="object")return{body:n,files:{}};const i=Object.entries(_nullishCoalesce(n, () => ({}))),o=t=>Array.isArray(t)?o(t.at(0)):Buffer.isBuffer(_optionalChain([t, 'optionalAccess', _26 => _26.data])),r=i.filter(([t,s])=>o(s)).map(([t,s])=>[t,Array.isArray(s)?s:[s]]),e=i.filter(([t,s])=>!o(s));return{body:Object.fromEntries(e),files:Object.fromEntries(r)}}exports.FastifyServer = _;
|
|
2
2
|
//# sourceMappingURL=fastify.min.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/server/impls/fastify.ts"],"names":["getMediaDuration","config","instance"
|
|
1
|
+
{"version":3,"sources":["../../../../src/server/impls/fastify.ts"],"names":["getMediaDuration","config","instance"],"mappings":"AAAA,02BAA0B,iFACF,iGACI,yFACF,qGACG,sGACA,yFACH,oFAEN,gEAEL,yDAGN,4DACAA,6DAGT,qDACS,+CAGIC,4CAGV,MAAwBA,EAAO,QAAS,kBAAA,CAAA,WACxC,CAAA,CAAA,CAAA,CAAA,MAAuB,CAAA,CAAA,sBAAA,CAAA,GAAS,CAAA,CAAA,CAAA,CAAMC,CAAAA,+BAAS,CAAA,qBACxC,CAAA,CAAA,CAAA,CAAA,QAAiB,CAAA,GAAA,CAAA,cACxB,CAAA,CAAA,CAAA,QACC,CAAA,GAAA,CAAA,CAAA,CAAA,GAAA,CAAA,KAAA,CAAA,CAAqB,GACrB,CAAA,CAAA,aAAe,CAChB,CAAA,WACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,aACC,CAAA,CAAA,mBAEE,CAAA,CAAA,CAAA,CAAU,aAAkB,CAAE,CAAA,CAC9B,CAAA,CAAA,oBAAuB,CAAA,CAAA,CAAA,CAAA,CAAY,CAAA,EAAG,IAAA,iCAAA,CAAA,CAAA,CAAA,GAAW,CAAA,CAAA,EAAK,CAAA,CAAA,QAGzD,CACD,kBAAA,CAAA,CAAA,OAAU,SAAA,IAAA,CAAQD,CAAAA,KACjB,CAAA,CAAA,EAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/fastify.min.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 type { ServerConfig } from '../pipes'\nimport { Request } from '../requests'\nimport { type 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\tdisableRequestLogging: !config.requests.log,\n\t\t\tloggerInstance: config.requests.log ? instance.log : undefined,\n\t\t\tajv: { customOptions: { coerceTypes: false } },\n\t\t\trouterOptions: {\n\t\t\t\tignoreTrailingSlash: true,\n\t\t\t\tcaseSensitive: false,\n\t\t\t},\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"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{v as p}from"valleyed";import{Conditions as d,wrapQueryParams as l}from "../dbs/index.min.mjs";import{EquippedError as o}from "../errors/index.min.mjs";import{Instance as y}from "../instance/index.min.mjs";function P(u){return u}class k{constructor(t,s){this.db=t;this.table=t.use({db:s,col:"__audits",mapper:e=>({...e,toJSON:()=>e}),options:{skipAudit:!0}}),y.on("start",()=>{setInterval(async()=>{const e=[...this.asyncQueue];this.asyncQueue=[],await Promise.all(e.map(n=>n()))},200)},4)}table;definitions={};asyncQueue=[];async#e(t,s,e){const n=this.definitions[t];if(!n)throw new o("audit definition not found",{name:t,payload:s});const a=p.assert(n.pipe,s),i=e.at??new Date,r=y.createId({time:i});return await this.table.insertOne({key:r,name:t,ts:i.getTime(),body:a,by:e.by,steps:[]},{getTime:()=>i,makeId:()=>r})}async#t(t,s){return this.db.session(async()=>{const e=this.definitions[t.name];if(!e)throw new o("audit definition not found",{event:t});try{await this.table.updateOne({key:t.key},{$set:{steps:[{status:"start",ts:Date.now()}]}});const n={key:t.key,by:t.by,
|
|
1
|
+
import{v as p}from"valleyed";import{Conditions as d,wrapQueryParams as l}from "../dbs/index.min.mjs";import{EquippedError as o}from "../errors/index.min.mjs";import{Instance as y}from "../instance/index.min.mjs";function P(u){return u}class k{constructor(t,s){this.db=t;this.table=t.use({db:s,col:"__audits",mapper:e=>({...e,toJSON:()=>e}),options:{skipAudit:!0}}),y.on("start",()=>{setInterval(async()=>{const e=[...this.asyncQueue];this.asyncQueue=[],await Promise.all(e.map(n=>n()))},200)},4)}table;definitions={};asyncQueue=[];async#e(t,s,e){const n=this.definitions[t];if(!n)throw new o("audit definition not found",{name:t,payload:s});const a=p.assert(n.pipe,s),i=e.at??new Date,r=y.createId({time:i});return await this.table.insertOne({key:r,name:t,ts:i.getTime(),body:a,by:e.by,steps:[]},{getTime:()=>i,makeId:()=>r})}async#t(t,s){return this.db.session(async()=>{const e=this.definitions[t.name];if(!e)throw new o("audit definition not found",{event:t});try{await this.table.updateOne({key:t.key},{$set:{steps:[{status:"start",ts:Date.now()}]}});const n={key:t.key,by:t.by,at:new Date(t.ts),firstRun:s},a=await e.handle(t.body,n);await e.sync?.(a,t.body,n),await this.table.updateOne({key:t.key},{$push:{steps:{status:"sync",ts:Date.now()}}});const i=async()=>{try{await e.async?.(a,t.body,n),await this.table.updateOne({key:t.key},{$push:{steps:{status:"async",ts:Date.now()}}})}catch(r){const c=r instanceof Error?r.message:String(r);await this.table.updateOne({key:t.key},{$push:{steps:{status:"error",error:c,ts:Date.now()}}})}};return n.firstRun?this.asyncQueue.push(i):await i(),a}catch(n){const a=n instanceof Error?n.message:String(n);throw await this.table.updateOne({key:t.key},{$push:{steps:{status:"error",error:a,ts:Date.now()}}}),n}})}async replay(t){const{results:s}=await this.table.query(l({where:[...t?[{field:"ts",value:t.getTime(),condition:d.gte}]:[]],sort:[{field:"ts",desc:!1}],all:!0}));for(const e of s)await this.#t(e,!1)}async rerun(t){const s=await this.table.findOne({key:t});if(!s)throw new o("audit event not found",{key:t});await this.#t(s,!1)}register(t,s){if(this.definitions[t])throw new o(`${t} already has a registered handler`,{});return this.definitions[t]=s,p.compile(s.pipe),async(e,n)=>{const a=await this.#e(t,e,n);return this.#t(a,!0)}}}export{k as EventAudit};
|
|
2
2
|
//# sourceMappingURL=events.min.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/audit/events.ts"],"sourcesContent":["import { type Pipe, type PipeInput, type PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, type Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\nimport { Instance } from '../instance'\n\nexport type EventDefinition<P extends Pipe<any, any>, R> = {\n\tpipe: P\n\thandle: (payload: PipeOutput<P>, context: EventContext) => R | Promise<R>\n\tsync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n\tasync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n}\n\nexport type EventContext = {\n\tkey: string\n\tby: string | undefined\n\
|
|
1
|
+
{"version":3,"sources":["../../../src/audit/events.ts"],"sourcesContent":["import { type Pipe, type PipeInput, type PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, type Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\nimport { Instance } from '../instance'\n\nexport type EventDefinition<P extends Pipe<any, any>, R> = {\n\tpipe: P\n\thandle: (payload: PipeOutput<P>, context: EventContext) => R | Promise<R>\n\tsync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n\tasync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n}\n\nexport type EventContext = {\n\tkey: string\n\tby: string | undefined\n\tat: Date\n\tfirstRun: boolean\n}\n\nexport type EventDoc = {\n\tkey: string\n\tname: string\n\tts: number\n\tbody: unknown\n\tsteps: { status: 'start' | 'sync' | 'async' | 'error'; ts: number; error?: string }[]\n\tby?: string\n}\ntype Context = Partial<Pick<EventContext, 'by' | 'at'>>\n\nfunction createStep(step: EventDoc['steps'][number]) {\n\treturn step\n}\n\nexport class EventAudit {\n\tprivate table: Table<any, EventDoc, EventDoc & { toJSON: () => Record<string, unknown> }, any>\n\tprivate definitions: Record<string, EventDefinition<any, any>> = {}\n\tprivate asyncQueue: (() => Promise<void>)[] = []\n\n\tconstructor(\n\t\tprivate db: Db<any>,\n\t\tdbName: string,\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\n\t\tInstance.on(\n\t\t\t'start',\n\t\t\t() => {\n\t\t\t\tsetInterval(async () => {\n\t\t\t\t\tconst queue = [...this.asyncQueue]\n\t\t\t\t\tthis.asyncQueue = []\n\t\t\t\t\tawait Promise.all(queue.map((job) => job()))\n\t\t\t\t}, 200)\n\t\t\t},\n\t\t\t4,\n\t\t)\n\t}\n\n\tasync #createEvent(name: string, payload: unknown, context: Context) {\n\t\tconst def = this.definitions[name]\n\t\tif (!def) throw new EquippedError('audit definition not found', { name, payload })\n\n\t\tconst validBody = v.assert(def.pipe, payload)\n\t\tconst ts = context.at ?? new Date()\n\t\tconst key = Instance.createId({ time: ts })\n\n\t\treturn await this.table.insertOne(\n\t\t\t{\n\t\t\t\tkey,\n\t\t\t\tname,\n\t\t\t\tts: ts.getTime(),\n\t\t\t\tbody: validBody,\n\t\t\t\tby: context.by,\n\t\t\t\tsteps: [],\n\t\t\t},\n\t\t\t{ getTime: () => ts, makeId: () => key },\n\t\t)\n\t}\n\n\tasync #processEvent<R>(event: EventDoc, firstRun: boolean) {\n\t\treturn this.db.session(async () => {\n\t\t\tconst def = this.definitions[event.name]\n\t\t\tif (!def) throw new EquippedError('audit definition not found', { event })\n\t\t\ttry {\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $set: { steps: [createStep({ status: 'start', ts: Date.now() })] } })\n\t\t\t\tconst context: EventContext = {\n\t\t\t\t\tkey: event.key,\n\t\t\t\t\tby: event.by,\n\t\t\t\t\tat: new Date(event.ts),\n\t\t\t\t\tfirstRun,\n\t\t\t\t}\n\t\t\t\tconst result = await def.handle(event.body, context)\n\t\t\t\tawait def.sync?.(result, event.body, context)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'sync', ts: Date.now() }) } })\n\n\t\t\t\tconst asyncHandle = async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait def.async?.(result, event.body, context)\n\t\t\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t\t\t{ $push: { steps: createStep({ status: 'async', ts: Date.now() }) } },\n\t\t\t\t\t\t)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t\t\t{ $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } },\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!context.firstRun) await asyncHandle()\n\t\t\t\telse this.asyncQueue.push(asyncHandle)\n\t\t\t\treturn result as R\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } })\n\t\t\t\tthrow err\n\t\t\t}\n\t\t})\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, false)\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, false)\n\t}\n\n\tregister<P extends Pipe<any, any>, R>(name: string, def: EventDefinition<P, R>) {\n\t\tif (this.definitions[name]) throw new EquippedError(`${name} already has a registered handler`, {})\n\t\tthis.definitions[name] = def\n\t\tv.compile(def.pipe)\n\t\treturn async (payload: PipeInput<P>, context: Context) => {\n\t\t\tconst event = await this.#createEvent(name, payload, context)\n\t\t\treturn this.#processEvent<R>(event, true)\n\t\t}\n\t}\n}\n"],"mappings":"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","names":["v","Conditions","wrapQueryParams","EquippedError","Instance","createStep","step","EventAudit","db","dbName","model","queue","job","#createEvent","name","payload","context","def","validBody","ts","key","#processEvent","event","firstRun","result","asyncHandle","err","error","from","events"]}
|
|
@@ -14,13 +14,17 @@ class EventAudit {
|
|
|
14
14
|
mapper: (model) => ({ ...model, toJSON: () => model }),
|
|
15
15
|
options: { skipAudit: true }
|
|
16
16
|
});
|
|
17
|
-
Instance.on(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
Instance.on(
|
|
18
|
+
"start",
|
|
19
|
+
() => {
|
|
20
|
+
setInterval(async () => {
|
|
21
|
+
const queue = [...this.asyncQueue];
|
|
22
|
+
this.asyncQueue = [];
|
|
23
|
+
await Promise.all(queue.map((job) => job()));
|
|
24
|
+
}, 200);
|
|
25
|
+
},
|
|
26
|
+
4
|
|
27
|
+
);
|
|
24
28
|
}
|
|
25
29
|
table;
|
|
26
30
|
definitions = {};
|
|
@@ -43,19 +47,17 @@ class EventAudit {
|
|
|
43
47
|
{ getTime: () => ts, makeId: () => key }
|
|
44
48
|
);
|
|
45
49
|
}
|
|
46
|
-
async #processEvent(event,
|
|
50
|
+
async #processEvent(event, firstRun) {
|
|
47
51
|
return this.db.session(async () => {
|
|
48
52
|
const def = this.definitions[event.name];
|
|
49
53
|
if (!def) throw new EquippedError("audit definition not found", { event });
|
|
50
54
|
try {
|
|
51
|
-
await this.table.updateOne(
|
|
52
|
-
{ key: event.key },
|
|
53
|
-
{ $set: { steps: [createStep({ status: "start", ts: Date.now() })] } }
|
|
54
|
-
);
|
|
55
|
+
await this.table.updateOne({ key: event.key }, { $set: { steps: [createStep({ status: "start", ts: Date.now() })] } });
|
|
55
56
|
const context = {
|
|
56
57
|
key: event.key,
|
|
57
58
|
by: event.by,
|
|
58
|
-
|
|
59
|
+
at: new Date(event.ts),
|
|
60
|
+
firstRun
|
|
59
61
|
};
|
|
60
62
|
const result = await def.handle(event.body, context);
|
|
61
63
|
await def.sync?.(result, event.body, context);
|
|
@@ -63,14 +65,19 @@ class EventAudit {
|
|
|
63
65
|
const asyncHandle = async () => {
|
|
64
66
|
try {
|
|
65
67
|
await def.async?.(result, event.body, context);
|
|
66
|
-
await this.table.updateOne(
|
|
68
|
+
await this.table.updateOne(
|
|
69
|
+
{ key: event.key },
|
|
70
|
+
{ $push: { steps: createStep({ status: "async", ts: Date.now() }) } }
|
|
71
|
+
);
|
|
67
72
|
} catch (err) {
|
|
68
73
|
const error = err instanceof Error ? err.message : String(err);
|
|
69
|
-
await this.table.updateOne(
|
|
74
|
+
await this.table.updateOne(
|
|
75
|
+
{ key: event.key },
|
|
76
|
+
{ $push: { steps: createStep({ status: "error", error, ts: Date.now() }) } }
|
|
77
|
+
);
|
|
70
78
|
}
|
|
71
|
-
;
|
|
72
79
|
};
|
|
73
|
-
if (
|
|
80
|
+
if (!context.firstRun) await asyncHandle();
|
|
74
81
|
else this.asyncQueue.push(asyncHandle);
|
|
75
82
|
return result;
|
|
76
83
|
} catch (err) {
|
|
@@ -88,12 +95,12 @@ class EventAudit {
|
|
|
88
95
|
all: true
|
|
89
96
|
})
|
|
90
97
|
);
|
|
91
|
-
for (const event of events) await this.#processEvent(event,
|
|
98
|
+
for (const event of events) await this.#processEvent(event, false);
|
|
92
99
|
}
|
|
93
100
|
async rerun(key) {
|
|
94
101
|
const event = await this.table.findOne({ key });
|
|
95
102
|
if (!event) throw new EquippedError("audit event not found", { key });
|
|
96
|
-
await this.#processEvent(event,
|
|
103
|
+
await this.#processEvent(event, false);
|
|
97
104
|
}
|
|
98
105
|
register(name, def) {
|
|
99
106
|
if (this.definitions[name]) throw new EquippedError(`${name} already has a registered handler`, {});
|
|
@@ -101,7 +108,7 @@ class EventAudit {
|
|
|
101
108
|
v.compile(def.pipe);
|
|
102
109
|
return async (payload, context) => {
|
|
103
110
|
const event = await this.#createEvent(name, payload, context);
|
|
104
|
-
return this.#processEvent(event,
|
|
111
|
+
return this.#processEvent(event, true);
|
|
105
112
|
};
|
|
106
113
|
}
|
|
107
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/audit/events.ts"],"sourcesContent":["import { type Pipe, type PipeInput, type PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, type Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\nimport { Instance } from '../instance'\n\nexport type EventDefinition<P extends Pipe<any, any>, R> = {\n\tpipe: P\n\thandle: (payload: PipeOutput<P>, context: EventContext) => R | Promise<R>\n\tsync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n\tasync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n}\n\nexport type EventContext = {\n\tkey: string\n\tby: string | undefined\n\
|
|
1
|
+
{"version":3,"sources":["../../../src/audit/events.ts"],"sourcesContent":["import { type Pipe, type PipeInput, type PipeOutput, v } from 'valleyed'\n\nimport { Conditions, Db, type Table, wrapQueryParams } from '../dbs'\nimport { EquippedError } from '../errors'\nimport { Instance } from '../instance'\n\nexport type EventDefinition<P extends Pipe<any, any>, R> = {\n\tpipe: P\n\thandle: (payload: PipeOutput<P>, context: EventContext) => R | Promise<R>\n\tsync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n\tasync?: (result: R, payload: PipeOutput<P>, context: EventContext) => void\n}\n\nexport type EventContext = {\n\tkey: string\n\tby: string | undefined\n\tat: Date\n\tfirstRun: boolean\n}\n\nexport type EventDoc = {\n\tkey: string\n\tname: string\n\tts: number\n\tbody: unknown\n\tsteps: { status: 'start' | 'sync' | 'async' | 'error'; ts: number; error?: string }[]\n\tby?: string\n}\ntype Context = Partial<Pick<EventContext, 'by' | 'at'>>\n\nfunction createStep(step: EventDoc['steps'][number]) {\n\treturn step\n}\n\nexport class EventAudit {\n\tprivate table: Table<any, EventDoc, EventDoc & { toJSON: () => Record<string, unknown> }, any>\n\tprivate definitions: Record<string, EventDefinition<any, any>> = {}\n\tprivate asyncQueue: (() => Promise<void>)[] = []\n\n\tconstructor(\n\t\tprivate db: Db<any>,\n\t\tdbName: string,\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\n\t\tInstance.on(\n\t\t\t'start',\n\t\t\t() => {\n\t\t\t\tsetInterval(async () => {\n\t\t\t\t\tconst queue = [...this.asyncQueue]\n\t\t\t\t\tthis.asyncQueue = []\n\t\t\t\t\tawait Promise.all(queue.map((job) => job()))\n\t\t\t\t}, 200)\n\t\t\t},\n\t\t\t4,\n\t\t)\n\t}\n\n\tasync #createEvent(name: string, payload: unknown, context: Context) {\n\t\tconst def = this.definitions[name]\n\t\tif (!def) throw new EquippedError('audit definition not found', { name, payload })\n\n\t\tconst validBody = v.assert(def.pipe, payload)\n\t\tconst ts = context.at ?? new Date()\n\t\tconst key = Instance.createId({ time: ts })\n\n\t\treturn await this.table.insertOne(\n\t\t\t{\n\t\t\t\tkey,\n\t\t\t\tname,\n\t\t\t\tts: ts.getTime(),\n\t\t\t\tbody: validBody,\n\t\t\t\tby: context.by,\n\t\t\t\tsteps: [],\n\t\t\t},\n\t\t\t{ getTime: () => ts, makeId: () => key },\n\t\t)\n\t}\n\n\tasync #processEvent<R>(event: EventDoc, firstRun: boolean) {\n\t\treturn this.db.session(async () => {\n\t\t\tconst def = this.definitions[event.name]\n\t\t\tif (!def) throw new EquippedError('audit definition not found', { event })\n\t\t\ttry {\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $set: { steps: [createStep({ status: 'start', ts: Date.now() })] } })\n\t\t\t\tconst context: EventContext = {\n\t\t\t\t\tkey: event.key,\n\t\t\t\t\tby: event.by,\n\t\t\t\t\tat: new Date(event.ts),\n\t\t\t\t\tfirstRun,\n\t\t\t\t}\n\t\t\t\tconst result = await def.handle(event.body, context)\n\t\t\t\tawait def.sync?.(result, event.body, context)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'sync', ts: Date.now() }) } })\n\n\t\t\t\tconst asyncHandle = async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait def.async?.(result, event.body, context)\n\t\t\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t\t\t{ $push: { steps: createStep({ status: 'async', ts: Date.now() }) } },\n\t\t\t\t\t\t)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\t\t\tawait this.table.updateOne(\n\t\t\t\t\t\t\t{ key: event.key },\n\t\t\t\t\t\t\t{ $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } },\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!context.firstRun) await asyncHandle()\n\t\t\t\telse this.asyncQueue.push(asyncHandle)\n\t\t\t\treturn result as R\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err.message : String(err)\n\t\t\t\tawait this.table.updateOne({ key: event.key }, { $push: { steps: createStep({ status: 'error', error, ts: Date.now() }) } })\n\t\t\t\tthrow err\n\t\t\t}\n\t\t})\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, false)\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, false)\n\t}\n\n\tregister<P extends Pipe<any, any>, R>(name: string, def: EventDefinition<P, R>) {\n\t\tif (this.definitions[name]) throw new EquippedError(`${name} already has a registered handler`, {})\n\t\tthis.definitions[name] = def\n\t\tv.compile(def.pipe)\n\t\treturn async (payload: PipeInput<P>, context: Context) => {\n\t\t\tconst event = await this.#createEvent(name, payload, context)\n\t\t\treturn this.#processEvent<R>(event, true)\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import c from"@fastify/cookie";import
|
|
1
|
+
import c from"@fastify/cookie";import p from"@fastify/cors";import y from"@fastify/formbody";import d from"@fastify/helmet";import g from"@fastify/multipart";import h from"@fastify/rate-limit";import S from"@fastify/static";import R from"fastify";import F from"qs";import{ValidationError as b}from "../../errors/index.min.mjs";import{Instance as f}from "../../instance/index.min.mjs";import{getMediaDuration as O}from "../../utilities/index.min.mjs";import{Request as T}from "../requests.min.mjs";import{StatusCodes as k}from "../types.min.mjs";import{Server as C}from "./base.min.mjs";class _ extends C{constructor(i){const o=f.get(),r=R({disableRequestLogging:!i.requests.log,loggerInstance:i.requests.log?o.log:void 0,ajv:{customOptions:{coerceTypes:!1}},routerOptions:{ignoreTrailingSlash:!0,caseSensitive:!1},schemaErrorFormatter:(e,t)=>new b(e.map(s=>({messages:[s.message??""],field:`${t}${s.instancePath}`.replaceAll("/",".")})))});super(r.server,i,{parseRequest:async e=>{const s={...Object.fromEntries(Object.entries(e.headers).map(([m,u])=>[m,u??null])),Authorization:e.headers.authorization?.toString(),RefreshToken:e.headers["x-refresh-token"]?.toString(),ApiKey:e.headers["x-api-key"]?.toString(),ContentType:e.headers["content-type"]?.toString(),Referer:e.headers.referer?.toString(),UserAgent:e.headers["user-agent"]?.toString()},{body:a,files:l}=w(e.body??{});return new T({ip:e.ip,body:a,cookies:e.cookies??{},params:e.params??{},query:e.query??{},method:e.method,path:e.url,headers:s,files:l,context:{}})},handleResponse:async(e,t)=>{for(const[s,{value:a,...l}]of Object.entries(t.cookies))e=e.setCookie(s,a,l);await e.status(t.status).headers(t.headers).send(t.body)},registerRoute:(e,t,s)=>{r.register(async a=>{a.route({url:t,method:e,handler:s})})},registerErrorHandler:e=>{r.setErrorHandler(e)},registerNotFoundHandler:e=>{r.setNotFoundHandler(e)},start:async e=>(await r.ready(),await r.listen({port:e,host:"0.0.0.0"}),f.on("close",r.close,1),!0)}),r.decorateRequest("savedReq",null),r.setValidatorCompiler(()=>()=>!0),r.setSerializerCompiler(()=>e=>JSON.stringify(e)),i.publicPath&&r.register(S,{root:i.publicPath}),r.register(c,{}),r.register(p,this.cors),r.register(y,{parser:e=>F.parse(e)}),r.register(d,{crossOriginResourcePolicy:{policy:"cross-origin"},contentSecurityPolicy:!1}),r.register(g,{attachFieldsToBody:"keyValues",throwFileSizeLimit:!1,limits:{fileSize:o.settings.utils.maxFileUploadSizeInMb*1024*1024},onFile:async e=>{const t=await e.toBuffer(),s={name:e.filename,type:e.mimetype,size:t.byteLength,isTruncated:e.file.truncated,data:t,duration:await O(t)};e.value=s}}),i.requests.rateLimit.enabled&&r.register(h,{max:i.requests.rateLimit.limit,timeWindow:i.requests.rateLimit.periodInMs,errorResponseBuilder:(e,t)=>({statusCode:k.TooManyRequests,message:JSON.stringify([{message:`Too Many Requests. Retry in ${t.after}`}])})})}}function w(n){if(typeof n!="object")return{body:n,files:{}};const i=Object.entries(n??{}),o=t=>Array.isArray(t)?o(t.at(0)):Buffer.isBuffer(t?.data),r=i.filter(([t,s])=>o(s)).map(([t,s])=>[t,Array.isArray(s)?s:[s]]),e=i.filter(([t,s])=>!o(s));return{body:Object.fromEntries(e),files:Object.fromEntries(r)}}export{_ as FastifyServer};
|
|
2
2
|
//# sourceMappingURL=fastify.min.mjs.map
|