@unchainedshop/core-events 4.3.4 → 4.5.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 CHANGED
@@ -1,3 +1,84 @@
1
- # Core Events (Unchained Engine)
1
+ [![npm version](https://img.shields.io/npm/v/@unchainedshop/core-events.svg)](https://npmjs.com/package/@unchainedshop/core-events)
2
+ [![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](https://opensource.org/licenses/EUPL-1.2)
2
3
 
3
- This package defines the event module which ensures the emitted events are written to the database as an Event History and offers a core module to search for events.
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
@@ -1,3 +1,2 @@
1
- export type { Event } from './db/EventsCollection.js';
2
- export * from './module/configureEventsModule.js';
3
- //# sourceMappingURL=events-index.d.ts.map
1
+ export type { Event } from './db/EventsCollection.ts';
2
+ export * from './module/configureEventsModule.ts';
@@ -1,2 +1 @@
1
- export * from './module/configureEventsModule.js';
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.js';
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 '../db/EventsCollection.js';
5
- import { configureEventHistoryAdapter } from './configureEventHistoryAdapter.js';
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,16 +1,17 @@
1
1
  {
2
2
  "name": "@unchainedshop/core-events",
3
- "version": "4.3.4",
3
+ "version": "4.5.0",
4
4
  "main": "lib/events-index.js",
5
5
  "types": "lib/events-index.d.ts",
6
6
  "type": "module",
7
+ "sideEffects": false,
7
8
  "scripts": {
8
9
  "clean": "tsc -b --clean",
9
10
  "build": "tsc -b",
10
11
  "prepublishOnly": "npm run clean && npm run build",
11
12
  "watch": "tsc -w",
12
- "test": "tsx --test",
13
- "test:watch": "tsx --test --watch"
13
+ "test": "node --test",
14
+ "test:watch": "node --test --watch"
14
15
  },
15
16
  "repository": {
16
17
  "type": "git",
@@ -22,8 +23,10 @@
22
23
  "core"
23
24
  ],
24
25
  "authors": [
25
- "Joël Meiller",
26
- "Pascal Kaufmann"
26
+ "Pascal Kaufmann",
27
+ "Mikael Araya",
28
+ "Vedran Rudelj",
29
+ "Joël Meiller"
27
30
  ],
28
31
  "license": "EUPL-1.2",
29
32
  "bugs": {
@@ -31,12 +34,11 @@
31
34
  },
32
35
  "homepage": "https://github.com/unchainedshop/unchained#readme",
33
36
  "dependencies": {
34
- "@unchainedshop/events": "^4.3.0",
35
- "@unchainedshop/utils": "^4.3.0"
37
+ "@unchainedshop/events": "^4.5.0",
38
+ "@unchainedshop/utils": "^4.5.0"
36
39
  },
37
40
  "devDependencies": {
38
- "@types/node": "^24.0.13",
39
- "tsx": "^4.20.3",
41
+ "@types/node": "^25.0.0",
40
42
  "typescript": "^5.8.3"
41
43
  }
42
44
  }
@@ -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"}
@@ -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"}
@@ -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
- };
@@ -1,3 +0,0 @@
1
- export type { Event } from './db/EventsCollection.js';
2
-
3
- export * from './module/configureEventsModule.js';
@@ -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>>;
package/tsconfig.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "../shared/base.tsconfig.json",
3
- "compilerOptions": {
4
- "declarationDir": "./lib",
5
- "rootDir": "./src",
6
- "outDir": "./lib",
7
-
8
- },
9
- "exclude": ["**/*.test.ts", "**/*.test.js", "tests", "lib"]
10
- }