@unchainedshop/events 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Events (Unchained Engine)
2
+
3
+ This package contains business logic for the event emitter abstraction layer
@@ -0,0 +1,3 @@
1
+ export default {
2
+ presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'],
3
+ };
@@ -0,0 +1,3 @@
1
+ import { ContextNormalizerFunction, EventDirector as IEventDirector } from '@unchainedshop/types/events';
2
+ export declare const defaultNormalizer: ContextNormalizerFunction;
3
+ export declare const EventDirector: IEventDirector;
@@ -0,0 +1,66 @@
1
+ import { createLogger } from '@unchainedshop/logger';
2
+ const logger = createLogger('unchained:events');
3
+ export const defaultNormalizer = (context) => {
4
+ return {
5
+ userAgent: context?.userAgent,
6
+ language: context?.localeContext?.code,
7
+ country: context?.localeContext?.country,
8
+ remoteAddress: context?.remoteAddress,
9
+ referer: context?.req?.headers?.referer,
10
+ origin: context?.req?.headers?.origin,
11
+ userId: context?.userId,
12
+ };
13
+ };
14
+ const RegisteredEventsSet = new Set();
15
+ const RegisteredCallbacksSet = new Set();
16
+ let Adapter; // Public (customizable)
17
+ let HistoryAdapter; // (Per default: Core-events adapter to write into DB)
18
+ let ContextNormalizer = defaultNormalizer;
19
+ export const EventDirector = {
20
+ registerEvents: (events) => {
21
+ if (events.length) {
22
+ events.forEach((e) => RegisteredEventsSet.add(e));
23
+ logger.verbose(`EventDirector -> Registered ${JSON.stringify(events)}`);
24
+ }
25
+ },
26
+ getRegisteredEvents: () => {
27
+ return Array.from(RegisteredEventsSet);
28
+ },
29
+ setContextNormalizer: (fn) => {
30
+ ContextNormalizer = fn;
31
+ },
32
+ setEmitAdapter: (adapter) => {
33
+ Adapter = adapter;
34
+ },
35
+ getEmitAdapter: () => Adapter,
36
+ setEmitHistoryAdapter: (adapter) => {
37
+ HistoryAdapter = adapter;
38
+ },
39
+ getEmitHistoryAdapter: () => HistoryAdapter,
40
+ emit: async (eventName, data) => {
41
+ const extractedContext = ContextNormalizer(null);
42
+ if (!RegisteredEventsSet.has(eventName))
43
+ throw new Error(`Event with ${eventName} is not registered`);
44
+ Adapter?.publish(eventName, {
45
+ payload: { ...data },
46
+ context: extractedContext,
47
+ });
48
+ HistoryAdapter?.publish(eventName, {
49
+ payload: { ...data },
50
+ context: extractedContext,
51
+ });
52
+ logger.verbose(`EventDirector -> Emitted ${eventName} with ${JSON.stringify(data)}`);
53
+ },
54
+ subscribe: (eventName, callback) => {
55
+ const currentSubscription = `${eventName}${callback?.toString()}`; // used to avaoid registering the same event handler callback
56
+ if (!RegisteredEventsSet.has(eventName))
57
+ throw new Error(`Event with ${eventName} is not registered`);
58
+ if (!RegisteredCallbacksSet.has(currentSubscription)) {
59
+ Adapter?.subscribe(eventName, callback);
60
+ HistoryAdapter?.subscribe(eventName, callback);
61
+ RegisteredCallbacksSet.add(currentSubscription);
62
+ logger.verbose(`EventDirector -> Subscribed to ${eventName}`);
63
+ }
64
+ },
65
+ };
66
+ //# sourceMappingURL=EventDirector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventDirector.js","sourceRoot":"","sources":["../src/EventDirector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ declare const emit: (eventName: string, data?: string | Record<string, unknown>) => Promise<void>, getEmitAdapter: () => import("@unchainedshop/types/events").EmitAdapter, getEmitHistoryAdapter: () => import("@unchainedshop/types/events").EmitAdapter, getRegisteredEvents: () => string[], registerEvents: (events: string[]) => void, setEmitAdapter: (adapter: import("@unchainedshop/types/events").EmitAdapter) => void, setEmitHistoryAdapter: (adapter: import("@unchainedshop/types/events").EmitAdapter) => void, subscribe: (eventName: string, callback: (payload?: Record<string, unknown>) => void) => void;
2
+ export { emit, getEmitAdapter, getEmitHistoryAdapter, getRegisteredEvents, registerEvents, setEmitAdapter, setEmitHistoryAdapter, subscribe, };
@@ -0,0 +1,6 @@
1
+ import { EventDirector } from './EventDirector';
2
+ const { emit, getEmitAdapter, getEmitHistoryAdapter, getRegisteredEvents, registerEvents, setEmitAdapter, setEmitHistoryAdapter, subscribe, } = EventDirector;
3
+ const GLOBAL_EVENTS = ['PAGE_VIEW'];
4
+ registerEvents(GLOBAL_EVENTS);
5
+ export { emit, getEmitAdapter, getEmitHistoryAdapter, getRegisteredEvents, registerEvents, setEmitAdapter, setEmitHistoryAdapter, subscribe, };
6
+ //# sourceMappingURL=events-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events-index.js","sourceRoot":"","sources":["../src/events-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,EACJ,IAAI,EACJ,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,SAAS,GACV,GAAG,aAAa,CAAC;AAElB,MAAM,aAAa,GAAG,CAAC,WAAW,CAAC,CAAC;AACpC,cAAc,CAAC,aAAa,CAAC,CAAC;AAE9B,OAAO,EACL,IAAI,EACJ,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,SAAS,GACV,CAAC"}
package/package.js ADDED
@@ -0,0 +1,20 @@
1
+ Package.describe({
2
+ name: 'unchained:events',
3
+ version: '1.1.3',
4
+ summary: 'Unchained Engine: Event Director',
5
+ git: 'https://github.com/unchainedshop/unchained',
6
+ documentation: 'README.md',
7
+ });
8
+
9
+ Npm.depends({
10
+ redis: '4.1.0',
11
+ '@unchainedshop/logger': '1.1.3',
12
+ });
13
+
14
+ Package.onUse((api) => {
15
+ api.versionsFrom('2.7.3');
16
+ api.use('ecmascript');
17
+ api.use('typescript');
18
+
19
+ api.mainModule('src/events-index.ts', 'server');
20
+ });
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@unchainedshop/events",
3
+ "version": "1.1.3",
4
+ "main": "lib/events-index.js",
5
+ "types": "lib/events-index.d.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "clean": "rm -rf lib",
9
+ "build": "npm run clean && tsc -p tsconfig.build.json",
10
+ "watch": "tsc --watch",
11
+ "link:core": "npm link @unchainedshop/types",
12
+ "test": "jest --watch"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/unchainedshop/unchained.git"
17
+ },
18
+ "keywords": [
19
+ "unchained",
20
+ "ecommerce",
21
+ "core"
22
+ ],
23
+ "author": "Joël Meiller",
24
+ "license": "EUPL-1.2",
25
+ "bugs": {
26
+ "url": "https://github.com/unchainedshop/unchained/issues"
27
+ },
28
+ "homepage": "https://github.com/unchainedshop/unchained#readme",
29
+ "dependencies": {
30
+ "redis": "^4.1.0",
31
+ "@unchainedshop/logger": "latest"
32
+ },
33
+ "devDependencies": {
34
+ "@babel/core": "^7.18.6",
35
+ "@babel/preset-env": "^7.18.6",
36
+ "@babel/preset-typescript": "^7.18.6",
37
+ "@types/chai": "^4.3.1",
38
+ "@types/jest": "^28.1.3",
39
+ "@types/mocha": "^9.1.1",
40
+ "@unchainedshop/types": "latest",
41
+ "babel-jest": "^28.1.1",
42
+ "chai": "^4.3.6",
43
+ "cross-env": "^7.0.3",
44
+ "jest": "^28.1.1",
45
+ "ts-jest": "^28.0.5",
46
+ "ts-node": "^10.8.1",
47
+ "typescript": "^4.7.4"
48
+ }
49
+ }
@@ -0,0 +1,20 @@
1
+ import { EventEmitter } from 'events';
2
+ import { EmitAdapter } from '@unchainedshop/types/events';
3
+ import { setEmitAdapter } from 'meteor/unchained:events';
4
+
5
+ const NodeEventEmitter = (): EmitAdapter => {
6
+ const eventEmitter = new EventEmitter();
7
+
8
+ return {
9
+ publish: (eventName, payload) => {
10
+ eventEmitter.emit(eventName, payload);
11
+ },
12
+
13
+ subscribe: (eventName, callback) => {
14
+ return eventEmitter.on(eventName, callback);
15
+ },
16
+ };
17
+ };
18
+
19
+ const adapter = NodeEventEmitter();
20
+ setEmitAdapter(adapter);
@@ -0,0 +1,30 @@
1
+ import redis from 'redis';
2
+ import { EmitAdapter } from '@unchainedshop/types/events';
3
+ import { setEmitAdapter } from 'meteor/unchained:events';
4
+
5
+ const { REDIS_PORT = 6379, REDIS_HOST = '127.0.0.1' } = process.env;
6
+
7
+ const subscribedEvents = new Set();
8
+
9
+ const RedisEventEmitter = (): EmitAdapter => {
10
+ const redisPublisher = redis.createClient({
11
+ url: `redis://${REDIS_HOST}:${REDIS_PORT}`,
12
+ });
13
+
14
+ const redisSubscriber = redis.createClient({
15
+ url: `redis://${REDIS_HOST}:${REDIS_PORT}`,
16
+ });
17
+
18
+ return {
19
+ publish: (eventName, payload) => redisPublisher.publish(eventName, JSON.stringify(payload)),
20
+ subscribe: (eventName, callback) => {
21
+ redisSubscriber.on('message', (_channelName, payload) => callback(payload));
22
+ if (!subscribedEvents.has(eventName)) {
23
+ redisSubscriber.subscribe(eventName);
24
+ subscribedEvents.add(eventName);
25
+ }
26
+ },
27
+ };
28
+ };
29
+
30
+ setEmitAdapter(RedisEventEmitter());
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "allowSyntheticDefaultImports": true,
5
+ "declaration": true,
6
+ "esModuleInterop": true,
7
+ "experimentalDecorators": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "lib": ["esnext"],
10
+ "module": "esnext",
11
+ "moduleResolution": "node",
12
+ "noImplicitReturns": true,
13
+ "noUnusedLocals": false,
14
+ "outDir": "lib",
15
+ "preserveWatchOutput": true,
16
+ "skipLibCheck": true,
17
+ "sourceMap": true,
18
+ "target": "esnext",
19
+ "types": ["node"],
20
+ "baseUrl": ".", // This must be specified if "paths" is.
21
+ "paths": {
22
+ "meteor/unchained:*": ["node_modules/@unchainedshop/types/index.d.ts"]
23
+ }
24
+ },
25
+ "include": ["src"]
26
+ }