@unchainedshop/core-events 4.3.3 → 4.4.0
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/README.md +83 -2
- package/lib/db/EventsCollection.d.ts +1 -2
- package/lib/db/EventsCollection.js +1 -2
- package/lib/events-index.d.ts +2 -3
- package/lib/events-index.js +1 -2
- package/lib/module/configureEventHistoryAdapter.d.ts +1 -2
- package/lib/module/configureEventHistoryAdapter.js +0 -2
- package/lib/module/configureEventsModule.d.ts +3 -4
- package/lib/module/configureEventsModule.js +3 -4
- package/package.json +10 -9
- package/lib/db/EventsCollection.d.ts.map +0 -1
- package/lib/db/EventsCollection.js.map +0 -1
- package/lib/db/EventsSchema.d.ts +0 -3
- package/lib/db/EventsSchema.d.ts.map +0 -1
- package/lib/db/EventsSchema.js +0 -9
- package/lib/db/EventsSchema.js.map +0 -1
- package/lib/events-index.d.ts.map +0 -1
- package/lib/events-index.js.map +0 -1
- package/lib/module/configureEventHistoryAdapter.d.ts.map +0 -1
- package/lib/module/configureEventHistoryAdapter.js.map +0 -1
- package/lib/module/configureEventsModule.d.ts.map +0 -1
- package/lib/module/configureEventsModule.js.map +0 -1
- package/src/db/EventsCollection.ts +0 -41
- package/src/events-index.ts +0 -3
- package/src/module/buildFindSelector.test.ts +0 -46
- package/src/module/configureEventHistoryAdapter.ts +0 -21
- package/src/module/configureEventsModule.ts +0 -168
- package/tsconfig.json +0 -10
package/README.md
CHANGED
|
@@ -1,3 +1,84 @@
|
|
|
1
|
-
|
|
1
|
+
[](https://npmjs.com/package/@unchainedshop/core-events)
|
|
2
|
+
[](https://opensource.org/licenses/EUPL-1.2)
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
# @unchainedshop/core-events
|
|
5
|
+
|
|
6
|
+
Event history module for the Unchained Engine. Persists emitted events to the database and provides querying capabilities for event analytics and auditing.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @unchainedshop/core-events
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { configureEventsModule } from '@unchainedshop/core-events';
|
|
18
|
+
|
|
19
|
+
const eventsModule = await configureEventsModule({ db });
|
|
20
|
+
|
|
21
|
+
// Find events by type
|
|
22
|
+
const orderEvents = await eventsModule.findEvents({
|
|
23
|
+
types: ['ORDER_CREATE', 'ORDER_PAID'],
|
|
24
|
+
limit: 100,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Get event statistics
|
|
28
|
+
const report = await eventsModule.getReport({
|
|
29
|
+
types: ['ORDER_CREATE'],
|
|
30
|
+
dateRange: { start: '2024-01-01', end: '2024-12-31' },
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## API Overview
|
|
35
|
+
|
|
36
|
+
### Module Configuration
|
|
37
|
+
|
|
38
|
+
| Export | Description |
|
|
39
|
+
|--------|-------------|
|
|
40
|
+
| `configureEventsModule` | Configure and return the events module |
|
|
41
|
+
|
|
42
|
+
### Queries
|
|
43
|
+
|
|
44
|
+
| Method | Description |
|
|
45
|
+
|--------|-------------|
|
|
46
|
+
| `findEvent` | Find a single event by ID or filter |
|
|
47
|
+
| `findEvents` | Find events with filtering, sorting, and pagination |
|
|
48
|
+
| `count` | Count events matching query |
|
|
49
|
+
| `getReport` | Get aggregated event statistics by type and date |
|
|
50
|
+
|
|
51
|
+
### Mutations
|
|
52
|
+
|
|
53
|
+
| Method | Description |
|
|
54
|
+
|--------|-------------|
|
|
55
|
+
| `create` | Create a new event record |
|
|
56
|
+
|
|
57
|
+
### Helper Methods
|
|
58
|
+
|
|
59
|
+
| Method | Description |
|
|
60
|
+
|--------|-------------|
|
|
61
|
+
| `type` | Get event type, returns 'UNKNOWN' for unregistered types |
|
|
62
|
+
|
|
63
|
+
### Types
|
|
64
|
+
|
|
65
|
+
| Export | Description |
|
|
66
|
+
|--------|-------------|
|
|
67
|
+
| `Event` | Event document type |
|
|
68
|
+
| `EventQuery` | Query parameters type |
|
|
69
|
+
| `EventReport` | Report output type |
|
|
70
|
+
| `EventsModule` | Module interface type |
|
|
71
|
+
|
|
72
|
+
## Event History
|
|
73
|
+
|
|
74
|
+
This module automatically integrates with `@unchainedshop/events` to persist all emitted events to the database. Events are stored with:
|
|
75
|
+
|
|
76
|
+
- Event type
|
|
77
|
+
- Payload data
|
|
78
|
+
- Timestamp
|
|
79
|
+
|
|
80
|
+
This enables event sourcing patterns, audit trails, and analytics.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
EUPL-1.2
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { mongodb } from '@unchainedshop/mongodb';
|
|
2
|
-
import { TimestampFields } from '@unchainedshop/mongodb';
|
|
2
|
+
import type { TimestampFields } from '@unchainedshop/mongodb';
|
|
3
3
|
export type Event = {
|
|
4
4
|
_id: string;
|
|
5
5
|
type: string;
|
|
@@ -7,4 +7,3 @@ export type Event = {
|
|
|
7
7
|
payload?: Record<string, unknown>;
|
|
8
8
|
} & TimestampFields;
|
|
9
9
|
export declare const EventsCollection: (db: mongodb.Db) => Promise<mongodb.Collection<Event>>;
|
|
10
|
-
//# sourceMappingURL=EventsCollection.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isDocumentDBCompatModeEnabled } from '@unchainedshop/mongodb';
|
|
1
|
+
import { isDocumentDBCompatModeEnabled, mongodb } from '@unchainedshop/mongodb';
|
|
2
2
|
import { buildDbIndexes } from '@unchainedshop/mongodb';
|
|
3
3
|
const TWO_DAYS_SEC = 172800;
|
|
4
4
|
export const EventsCollection = async (db) => {
|
|
@@ -26,4 +26,3 @@ export const EventsCollection = async (db) => {
|
|
|
26
26
|
]);
|
|
27
27
|
return Events;
|
|
28
28
|
};
|
|
29
|
-
//# sourceMappingURL=EventsCollection.js.map
|
package/lib/events-index.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export type { Event } from './db/EventsCollection.
|
|
2
|
-
export * from './module/configureEventsModule.
|
|
3
|
-
//# sourceMappingURL=events-index.d.ts.map
|
|
1
|
+
export type { Event } from './db/EventsCollection.ts';
|
|
2
|
+
export * from './module/configureEventsModule.ts';
|
package/lib/events-index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
//# sourceMappingURL=events-index.js.map
|
|
1
|
+
export * from "./module/configureEventsModule.js";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { RawPayloadType } from '@unchainedshop/events';
|
|
1
|
+
import type { RawPayloadType } from '@unchainedshop/events';
|
|
2
2
|
export declare const configureEventHistoryAdapter: (createFn: ({ type, payload }: RawPayloadType<any> & {
|
|
3
3
|
type: string;
|
|
4
4
|
}) => Promise<unknown>) => void;
|
|
5
|
-
//# sourceMappingURL=configureEventHistoryAdapter.d.ts.map
|
|
@@ -3,7 +3,6 @@ export const configureEventHistoryAdapter = (createFn) => {
|
|
|
3
3
|
if (!getEmitHistoryAdapter()) {
|
|
4
4
|
const adapter = {
|
|
5
5
|
subscribe: () => {
|
|
6
|
-
// Do nothing
|
|
7
6
|
},
|
|
8
7
|
publish: async (eventName, { payload }) => {
|
|
9
8
|
await createFn({
|
|
@@ -15,4 +14,3 @@ export const configureEventHistoryAdapter = (createFn) => {
|
|
|
15
14
|
setEmitHistoryAdapter(adapter);
|
|
16
15
|
}
|
|
17
16
|
};
|
|
18
|
-
//# sourceMappingURL=configureEventHistoryAdapter.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { mongodb, ModuleInput } from '@unchainedshop/mongodb';
|
|
2
|
-
import { SortOption, DateFilterInput } from '@unchainedshop/utils';
|
|
3
|
-
import { Event } from '../db/EventsCollection.
|
|
1
|
+
import { mongodb, type ModuleInput } from '@unchainedshop/mongodb';
|
|
2
|
+
import { type SortOption, type DateFilterInput } from '@unchainedshop/utils';
|
|
3
|
+
import { type Event } from '../db/EventsCollection.ts';
|
|
4
4
|
export interface EventReport {
|
|
5
5
|
emitCount: number;
|
|
6
6
|
type: string;
|
|
@@ -36,4 +36,3 @@ export declare const configureEventsModule: ({ db }: ModuleInput<Record<string,
|
|
|
36
36
|
}) => Promise<EventReport[]>;
|
|
37
37
|
}>;
|
|
38
38
|
export type EventsModule = Awaited<ReturnType<typeof configureEventsModule>>;
|
|
39
|
-
//# sourceMappingURL=configureEventsModule.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { generateDbFilterById, buildSortOptions, generateDbObjectId, assertDocumentDBCompatMode, } from '@unchainedshop/mongodb';
|
|
1
|
+
import { mongodb, generateDbFilterById, buildSortOptions, generateDbObjectId, assertDocumentDBCompatMode, } from '@unchainedshop/mongodb';
|
|
2
2
|
import { getRegisteredEvents } from '@unchainedshop/events';
|
|
3
3
|
import { SortDirection } from '@unchainedshop/utils';
|
|
4
|
-
import { EventsCollection } from
|
|
5
|
-
import { configureEventHistoryAdapter } from
|
|
4
|
+
import { EventsCollection } from "../db/EventsCollection.js";
|
|
5
|
+
import { configureEventHistoryAdapter } from "./configureEventHistoryAdapter.js";
|
|
6
6
|
import { createLogger } from '@unchainedshop/logger';
|
|
7
7
|
const logger = createLogger('unchained:core-events');
|
|
8
8
|
export const buildFindSelector = ({ types, queryString, created }) => {
|
|
@@ -115,4 +115,3 @@ export const configureEventsModule = async ({ db }) => {
|
|
|
115
115
|
},
|
|
116
116
|
};
|
|
117
117
|
};
|
|
118
|
-
//# sourceMappingURL=configureEventsModule.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/core-events",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"main": "lib/events-index.js",
|
|
5
5
|
"types": "lib/events-index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"build": "tsc -b",
|
|
10
10
|
"prepublishOnly": "npm run clean && npm run build",
|
|
11
11
|
"watch": "tsc -w",
|
|
12
|
-
"test": "
|
|
13
|
-
"test:watch": "
|
|
12
|
+
"test": "node --test",
|
|
13
|
+
"test:watch": "node --test --watch"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
@@ -22,8 +22,10 @@
|
|
|
22
22
|
"core"
|
|
23
23
|
],
|
|
24
24
|
"authors": [
|
|
25
|
-
"
|
|
26
|
-
"
|
|
25
|
+
"Pascal Kaufmann",
|
|
26
|
+
"Mikael Araya",
|
|
27
|
+
"Vedran Rudelj",
|
|
28
|
+
"Joël Meiller"
|
|
27
29
|
],
|
|
28
30
|
"license": "EUPL-1.2",
|
|
29
31
|
"bugs": {
|
|
@@ -31,12 +33,11 @@
|
|
|
31
33
|
},
|
|
32
34
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
33
35
|
"dependencies": {
|
|
34
|
-
"@unchainedshop/events": "^4.
|
|
35
|
-
"@unchainedshop/utils": "^4.
|
|
36
|
+
"@unchainedshop/events": "^4.4.0",
|
|
37
|
+
"@unchainedshop/utils": "^4.4.0"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
|
-
"@types/node": "^
|
|
39
|
-
"tsx": "^4.20.3",
|
|
40
|
+
"@types/node": "^25.0.0",
|
|
40
41
|
"typescript": "^5.8.3"
|
|
41
42
|
}
|
|
42
43
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventsCollection.d.ts","sourceRoot":"","sources":["../../src/db/EventsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAIzD,MAAM,MAAM,KAAK,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,GAAG,eAAe,CAAC;AAEpB,eAAO,MAAM,gBAAgB,GAAU,IAAI,OAAO,CAAC,EAAE,uCA2BpD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventsCollection.js","sourceRoot":"","sources":["../../src/db/EventsCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAW,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGxD,MAAM,YAAY,GAAG,MAAM,CAAC;AAS5B,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,EAAc,EAAE,EAAE;IACvD,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAQ,QAAQ,CAAC,CAAC;IAE9C,IAAI,CAAC,6BAA6B,EAAE,EAAE,CAAC;QACrC,MAAM,cAAc,CAAC,MAAM,EAAE;YAC3B;gBACE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;gBACpC,OAAO,EAAE;oBACP,OAAO,EAAE;wBACP,GAAG,EAAE,CAAC;wBACN,IAAI,EAAE,CAAC;qBACR;oBACD,IAAI,EAAE,wBAAwB;iBAC/B;aACF;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,cAAc,CAAC,MAAM,EAAE;QAC3B;YACE,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;YACtB,OAAO,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE;SAC/D;QACD,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;KAClD,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
|
package/lib/db/EventsSchema.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventsSchema.d.ts","sourceRoot":"","sources":["../../src/db/EventsSchema.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,cAAc,CAAC;AAExC,eAAO,MAAM,YAAY,cAQxB,CAAC"}
|
package/lib/db/EventsSchema.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Schemas } from '@unchainedshop/utils';
|
|
2
|
-
import SimpleSchema from 'simpl-schema';
|
|
3
|
-
export const EventsSchema = new SimpleSchema({
|
|
4
|
-
type: { type: String, required: true },
|
|
5
|
-
payload: { type: Object, blackbox: true },
|
|
6
|
-
context: { type: Object, blackbox: true },
|
|
7
|
-
...Schemas.timestampFields,
|
|
8
|
-
}, { requiredByDefault: false });
|
|
9
|
-
//# sourceMappingURL=EventsSchema.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EventsSchema.js","sourceRoot":"","sources":["../../src/db/EventsSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,YAAY,MAAM,cAAc,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,YAAY,CAC1C;IACE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACtC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzC,GAAG,OAAO,CAAC,eAAe;CAC3B,EACD,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAC7B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"events-index.d.ts","sourceRoot":"","sources":["../src/events-index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEtD,cAAc,mCAAmC,CAAC"}
|
package/lib/events-index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"events-index.js","sourceRoot":"","sources":["../src/events-index.ts"],"names":[],"mappings":"AAEA,cAAc,mCAAmC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configureEventHistoryAdapter.d.ts","sourceRoot":"","sources":["../../src/module/configureEventHistoryAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,eAAO,MAAM,4BAA4B,GACvC,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,OAAO,CAAC,SAgB1F,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configureEventHistoryAdapter.js","sourceRoot":"","sources":["../../src/module/configureEventHistoryAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAe,MAAM,uBAAuB,CAAC;AAGlG,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAC1C,QAAyF,EACzF,EAAE;IACF,IAAI,CAAC,qBAAqB,EAAE,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAgB;YAC3B,SAAS,EAAE,GAAG,EAAE;gBACd,aAAa;YACf,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;gBACxC,MAAM,QAAQ,CAAC;oBACb,IAAI,EAAE,SAAS;oBACf,OAAO;iBACR,CAAC,CAAC;YACL,CAAC;SACF,CAAC;QACF,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configureEventsModule.d.ts","sourceRoot":"","sources":["../../src/module/configureEventsModule.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAIP,WAAW,EAEZ,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAiB,UAAU,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAoB,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAKpE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,IAAI,CAAA;KAAE,CAAC;CACxC;AAED,eAAO,MAAM,iBAAiB,GAAI,iCAAiC,UAAU;WAClD,GAAG;YAAU,GAAG;cAAY,GAAG;CAazD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAU,QAAQ,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;kBAI7E,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;sCAgBrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,YACvD,OAAO,CAAC,WAAW;oDAW5B,UAAU,GAAG;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;KACrB,KAAG,OAAO,CAAC,KAAK,EAAE,CAAC;kBASN,KAAK;mBAOE,UAAU;wCAQ5B;QAAE,SAAS,CAAC,EAAE,eAAe,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAQ,OAAO,CAAC,WAAW,EAAE,CAAC;EA+DrF,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"configureEventsModule.js","sourceRoot":"","sources":["../../src/module/configureEventsModule.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { isDocumentDBCompatModeEnabled, mongodb } from '@unchainedshop/mongodb';
|
|
2
|
-
import { buildDbIndexes } from '@unchainedshop/mongodb';
|
|
3
|
-
import { TimestampFields } from '@unchainedshop/mongodb';
|
|
4
|
-
|
|
5
|
-
const TWO_DAYS_SEC = 172800;
|
|
6
|
-
|
|
7
|
-
export type Event = {
|
|
8
|
-
_id: string;
|
|
9
|
-
type: string;
|
|
10
|
-
context?: Record<string, unknown>;
|
|
11
|
-
payload?: Record<string, unknown>;
|
|
12
|
-
} & TimestampFields;
|
|
13
|
-
|
|
14
|
-
export const EventsCollection = async (db: mongodb.Db) => {
|
|
15
|
-
const Events = db.collection<Event>('events');
|
|
16
|
-
|
|
17
|
-
if (!isDocumentDBCompatModeEnabled()) {
|
|
18
|
-
await buildDbIndexes(Events, [
|
|
19
|
-
{
|
|
20
|
-
index: { _id: 'text', type: 'text' },
|
|
21
|
-
options: {
|
|
22
|
-
weights: {
|
|
23
|
-
_id: 8,
|
|
24
|
-
type: 4,
|
|
25
|
-
},
|
|
26
|
-
name: 'events_fulltext_search',
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
]);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
await buildDbIndexes(Events, [
|
|
33
|
-
{
|
|
34
|
-
index: { created: -1 },
|
|
35
|
-
options: { expireAfterSeconds: TWO_DAYS_SEC, name: 'created' },
|
|
36
|
-
},
|
|
37
|
-
{ index: { type: 1 }, options: { name: 'type' } },
|
|
38
|
-
]);
|
|
39
|
-
|
|
40
|
-
return Events;
|
|
41
|
-
};
|
package/src/events-index.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test';
|
|
2
|
-
import assert from 'node:assert';
|
|
3
|
-
import { buildFindSelector } from './configureEventsModule.js';
|
|
4
|
-
|
|
5
|
-
describe('buildFindSelector', () => {
|
|
6
|
-
it('Return correct filter object when passed create, queryString, types', () => {
|
|
7
|
-
assert.deepStrictEqual(
|
|
8
|
-
buildFindSelector({
|
|
9
|
-
created: { start: new Date('2022-12-03T18:23:38.278Z') },
|
|
10
|
-
queryString: 'Hello world',
|
|
11
|
-
types: ['PRODUCT_CREATED'],
|
|
12
|
-
}),
|
|
13
|
-
{
|
|
14
|
-
type: { $in: ['PRODUCT_CREATED'] },
|
|
15
|
-
$text: { $search: 'Hello world' },
|
|
16
|
-
created: { $gte: new Date('2022-12-03T18:23:38.278Z') },
|
|
17
|
-
},
|
|
18
|
-
);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('Return correct filter object when passed create, queryString', () => {
|
|
22
|
-
assert.deepStrictEqual(
|
|
23
|
-
buildFindSelector({
|
|
24
|
-
created: { start: new Date('2022-12-03T18:23:38.278Z') },
|
|
25
|
-
queryString: 'Hello world',
|
|
26
|
-
}),
|
|
27
|
-
{
|
|
28
|
-
$text: { $search: 'Hello world' },
|
|
29
|
-
created: { $gte: new Date('2022-12-03T18:23:38.278Z') },
|
|
30
|
-
},
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('Return correct filter object when passed create', () => {
|
|
35
|
-
assert.deepStrictEqual(
|
|
36
|
-
buildFindSelector({ created: { start: new Date('2022-12-03T18:23:38.278Z') } }),
|
|
37
|
-
{
|
|
38
|
-
created: { $gte: new Date('2022-12-03T18:23:38.278Z') },
|
|
39
|
-
},
|
|
40
|
-
);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('Return correct filter object when passed no argument', () => {
|
|
44
|
-
assert.deepStrictEqual(buildFindSelector({}), {});
|
|
45
|
-
});
|
|
46
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { getEmitHistoryAdapter, setEmitHistoryAdapter, EmitAdapter } from '@unchainedshop/events';
|
|
2
|
-
import { RawPayloadType } from '@unchainedshop/events';
|
|
3
|
-
|
|
4
|
-
export const configureEventHistoryAdapter = (
|
|
5
|
-
createFn: ({ type, payload }: RawPayloadType<any> & { type: string }) => Promise<unknown>,
|
|
6
|
-
) => {
|
|
7
|
-
if (!getEmitHistoryAdapter()) {
|
|
8
|
-
const adapter: EmitAdapter = {
|
|
9
|
-
subscribe: () => {
|
|
10
|
-
// Do nothing
|
|
11
|
-
},
|
|
12
|
-
publish: async (eventName, { payload }) => {
|
|
13
|
-
await createFn({
|
|
14
|
-
type: eventName,
|
|
15
|
-
payload,
|
|
16
|
-
});
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
setEmitHistoryAdapter(adapter);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
mongodb,
|
|
3
|
-
generateDbFilterById,
|
|
4
|
-
buildSortOptions,
|
|
5
|
-
generateDbObjectId,
|
|
6
|
-
ModuleInput,
|
|
7
|
-
assertDocumentDBCompatMode,
|
|
8
|
-
} from '@unchainedshop/mongodb';
|
|
9
|
-
import { getRegisteredEvents } from '@unchainedshop/events';
|
|
10
|
-
import { SortDirection, SortOption, DateFilterInput } from '@unchainedshop/utils';
|
|
11
|
-
import { EventsCollection, Event } from '../db/EventsCollection.js';
|
|
12
|
-
import { configureEventHistoryAdapter } from './configureEventHistoryAdapter.js';
|
|
13
|
-
import { createLogger } from '@unchainedshop/logger';
|
|
14
|
-
|
|
15
|
-
const logger = createLogger('unchained:core-events');
|
|
16
|
-
export interface EventReport {
|
|
17
|
-
emitCount: number;
|
|
18
|
-
type: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface EventQuery {
|
|
22
|
-
types?: string[];
|
|
23
|
-
queryString?: string;
|
|
24
|
-
created?: { end?: Date; start?: Date };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const buildFindSelector = ({ types, queryString, created }: EventQuery) => {
|
|
28
|
-
const selector: { type?: any; $text?: any; created?: any } = {};
|
|
29
|
-
|
|
30
|
-
if (types && Array.isArray(types)) selector.type = { $in: types };
|
|
31
|
-
if (queryString) {
|
|
32
|
-
assertDocumentDBCompatMode();
|
|
33
|
-
selector.$text = { $search: queryString };
|
|
34
|
-
}
|
|
35
|
-
if (created) {
|
|
36
|
-
selector.created = created?.end
|
|
37
|
-
? { $gte: created.start || new Date(0), $lte: created.end }
|
|
38
|
-
: { $gte: created.start || new Date(0) };
|
|
39
|
-
}
|
|
40
|
-
return selector;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const configureEventsModule = async ({ db }: ModuleInput<Record<string, never>>) => {
|
|
44
|
-
const Events = await EventsCollection(db);
|
|
45
|
-
|
|
46
|
-
const create = async (
|
|
47
|
-
doc: Omit<Event, '_id' | 'created'> & Pick<Partial<Event>, '_id' | 'created'>,
|
|
48
|
-
) => {
|
|
49
|
-
const result = await Events.insertOne({
|
|
50
|
-
_id: generateDbObjectId(),
|
|
51
|
-
created: new Date(),
|
|
52
|
-
...doc,
|
|
53
|
-
});
|
|
54
|
-
return result.insertedId;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
await configureEventHistoryAdapter(create);
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
create,
|
|
61
|
-
|
|
62
|
-
findEvent: async (
|
|
63
|
-
{ eventId, ...rest }: mongodb.Filter<Event> & { eventId: string },
|
|
64
|
-
options?: mongodb.FindOptions,
|
|
65
|
-
) => {
|
|
66
|
-
const selector = eventId ? generateDbFilterById<Event>(eventId) : rest;
|
|
67
|
-
return Events.findOne(selector, options);
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
findEvents: async ({
|
|
71
|
-
limit,
|
|
72
|
-
offset,
|
|
73
|
-
sort,
|
|
74
|
-
...query
|
|
75
|
-
}: EventQuery & {
|
|
76
|
-
limit?: number;
|
|
77
|
-
offset?: number;
|
|
78
|
-
sort?: SortOption[];
|
|
79
|
-
}): Promise<Event[]> => {
|
|
80
|
-
const defaultSort = [{ key: 'created', value: SortDirection.DESC }] as SortOption[];
|
|
81
|
-
return Events.find(buildFindSelector(query), {
|
|
82
|
-
skip: offset,
|
|
83
|
-
limit,
|
|
84
|
-
sort: buildSortOptions(sort || defaultSort),
|
|
85
|
-
}).toArray();
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
type: (event: Event) => {
|
|
89
|
-
if (getRegisteredEvents().includes(event.type)) {
|
|
90
|
-
return event.type;
|
|
91
|
-
}
|
|
92
|
-
return 'UNKNOWN';
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
count: async (query: EventQuery) => {
|
|
96
|
-
const count = await Events.countDocuments(buildFindSelector(query));
|
|
97
|
-
return count;
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
getReport: async ({
|
|
101
|
-
dateRange,
|
|
102
|
-
types,
|
|
103
|
-
}: { dateRange?: DateFilterInput; types?: string[] } = {}): Promise<EventReport[]> => {
|
|
104
|
-
const match: any = {};
|
|
105
|
-
|
|
106
|
-
if (dateRange?.start || dateRange?.end) {
|
|
107
|
-
const conditions: any[] = [];
|
|
108
|
-
if (dateRange.start) {
|
|
109
|
-
const fromDate = new Date(dateRange.start);
|
|
110
|
-
conditions.push({ created: { $gte: fromDate } });
|
|
111
|
-
}
|
|
112
|
-
if (dateRange.end) {
|
|
113
|
-
const toDate = new Date(dateRange.end);
|
|
114
|
-
conditions.push({ created: { $lte: toDate } });
|
|
115
|
-
}
|
|
116
|
-
if (conditions.length) {
|
|
117
|
-
match.$or = conditions;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (types?.length) {
|
|
122
|
-
match.type = { $in: types };
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const pipeline = [
|
|
126
|
-
Object.keys(match).length ? { $match: match } : null,
|
|
127
|
-
{
|
|
128
|
-
$group: {
|
|
129
|
-
_id: {
|
|
130
|
-
type: '$type',
|
|
131
|
-
day: {
|
|
132
|
-
$dateToString: { format: '%Y-%m-%d', date: '$created' },
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
count: { $sum: 1 },
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
$group: {
|
|
140
|
-
_id: '$_id.type',
|
|
141
|
-
detail: {
|
|
142
|
-
$push: {
|
|
143
|
-
date: '$_id.day',
|
|
144
|
-
count: '$count',
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
emitCount: { $sum: '$count' },
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
$project: {
|
|
152
|
-
_id: 0,
|
|
153
|
-
type: '$_id',
|
|
154
|
-
emitCount: 1,
|
|
155
|
-
detail: 1,
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
{ $sort: { type: 1 } },
|
|
159
|
-
].filter(Boolean) as mongodb.BSON.Document[];
|
|
160
|
-
|
|
161
|
-
const report = await Events.aggregate<EventReport>(pipeline).toArray();
|
|
162
|
-
logger.info(report);
|
|
163
|
-
return report ?? [];
|
|
164
|
-
},
|
|
165
|
-
};
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
export type EventsModule = Awaited<ReturnType<typeof configureEventsModule>>;
|