@nommos/core 0.0.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.
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Gets all the query parameters found on a given url
3
+ *
4
+ * @param url - the url from which we want to get the query parameters from
5
+ * @returns A record of query parameters' name and value
6
+ */
7
+ export declare function getQueryParams(url: string): Record<string, string>;
8
+ /**
9
+ * Removes trailing spaces in a string and convert to lowerCase.
10
+ *
11
+ * @param s - string to convert
12
+ * @returns normalized string in lowerCase and no trailing space.
13
+ */
14
+ export declare const normString: (s: string) => string;
15
+ /**
16
+ * Extract the browser, the operating system and the channel (3 or 7) from the user agent of a device
17
+ * @param ua - User Agent of the device
18
+ * @returns An Object with the browser, operating system and the channel used by the user agent.
19
+ */
20
+ export declare const userAgentInfo: (ua: string) => {
21
+ browser: string;
22
+ os: string;
23
+ channel: 3 | 7;
24
+ };
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.userAgentInfo = exports.normString = void 0;
4
+ exports.getQueryParams = getQueryParams;
5
+ const constants_1 = require("./constants");
6
+ /**
7
+ * Gets all the query parameters found on a given url
8
+ *
9
+ * @param url - the url from which we want to get the query parameters from
10
+ * @returns A record of query parameters' name and value
11
+ */
12
+ function getQueryParams(url) {
13
+ const params = {};
14
+ const urlObj = new URL(url);
15
+ urlObj.searchParams.forEach((value, key) => {
16
+ // Handle repeated keys as arrays
17
+ if (params[key] === undefined && value.length > 0) {
18
+ params[key] = value;
19
+ }
20
+ });
21
+ return params;
22
+ }
23
+ /**
24
+ * Removes trailing spaces in a string and convert to lowerCase.
25
+ *
26
+ * @param s - string to convert
27
+ * @returns normalized string in lowerCase and no trailing space.
28
+ */
29
+ const normString = (s) => s.trim().toLowerCase();
30
+ exports.normString = normString;
31
+ /**
32
+ * Extract the browser, the operating system and the channel (3 or 7) from the user agent of a device
33
+ * @param ua - User Agent of the device
34
+ * @returns An Object with the browser, operating system and the channel used by the user agent.
35
+ */
36
+ const userAgentInfo = (ua) => ({
37
+ browser: detect(ua, constants_1.BROWSER_DEFS),
38
+ os: detect(ua, constants_1.OS_DEFS),
39
+ channel: /Mobi|Android|iPhone|iPad|iPod|Windows Phone/i.test(ua) ? 3 : 7,
40
+ });
41
+ exports.userAgentInfo = userAgentInfo;
42
+ const detect = (ua, defs, fallback = 'Unknown') => {
43
+ for (const [re, name, map] of defs) {
44
+ const m = new RegExp(re).exec(ua);
45
+ if (m) {
46
+ const v = map ? map(m) : m[1];
47
+ return v ? `${name} ${v}` : name;
48
+ }
49
+ }
50
+ return fallback;
51
+ };
52
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../nommos/core/src/lib/utils.ts"],"names":[],"mappings":";;;AAUA,wCAYC;AAtBD,2CAAoD;AAIpD;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,GAAW;IACxC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAE5B,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACzC,iCAAiC;QACjC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACI,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAAnD,QAAA,UAAU,cAAyC;AAEhE;;;;GAIG;AACI,MAAM,aAAa,GAAG,CAC3B,EAAU,EACuC,EAAE,CAAC,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,wBAAY,CAAC;IACjC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,mBAAO,CAAC;IACvB,OAAO,EAAE,8CAA8C,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACzE,CAAC,CAAC;AANU,QAAA,aAAa,iBAMvB;AACH,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,IAAa,EAAE,QAAQ,GAAG,SAAS,EAAU,EAAE;IACzE,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,EAAE,CAAC;YACN,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACnC,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { AnalyticsEvent, FullConfig } from './types';
2
+ /**
3
+ * WebSocketClient
4
+ * ----------------
5
+ * A lightweight STOMP-over-WebSocket wrapper designed for publishing
6
+ * analytics events to a RabbitMQ broker. Includes:
7
+ * - connection lifecycle management
8
+ * - auto-reconnect support
9
+ * - offline event buffering
10
+ * - reactive connection status via RxJS
11
+ *
12
+ * Intended to be used inside applications where analytics events must
13
+ * never be lost due to temporary connection issues.
14
+ */
15
+ export declare class WebSocketClient {
16
+ /**
17
+ * The underlying STOMP client instance.
18
+ * Initialized in `connectAnalyticsStomp()`.
19
+ */
20
+ private analyticsClient;
21
+ /**
22
+ * Buffer containing analytics events produced before the socket
23
+ * becomes connected. They are automatically flushed on connection.
24
+ */
25
+ pendingEvents: AnalyticsEvent[];
26
+ private readonly stompAnalyticsConnected;
27
+ /**
28
+ * Reactive connection state for consumers who want to listen for
29
+ * connection availability changes.
30
+ *
31
+ * `true` -> connected
32
+ * `false` -> disconnected
33
+ */
34
+ stompAnalyticsConnected$: import("rxjs").Observable<boolean>;
35
+ /**
36
+ * Creates and configures a STOMP client instance.
37
+ *
38
+ * @param cfg Connection configuration (broker URL, credentials, reconnect delay, mode).
39
+ * @returns A configured but not yet activated STOMP `Client` instance.
40
+ */
41
+ private createStompClient;
42
+ /**
43
+ * Establishes a STOMP WebSocket connection and wires lifecycle handlers.
44
+ *
45
+ * - On successful connection:
46
+ * • Emits `true` for reactive subscribers
47
+ * • Flushes all queued analytics events
48
+ * - On broker error:
49
+ * • Logs structured error output
50
+ *
51
+ * @param cfg Configuration including URL, credentials, mode etc.
52
+ */
53
+ connectAnalyticsStomp(cfg: FullConfig): void;
54
+ /**
55
+ * Publishes an analytics event to a RabbitMQ queue.
56
+ *
57
+ * If the connection is not ready, the event is automatically queued
58
+ * and delivered once the socket reconnects.
59
+ *
60
+ * @param payload The analytics event to send.
61
+ */
62
+ publishAnalyticsMessage(payload: AnalyticsEvent): void;
63
+ /**
64
+ * Gracefully shuts down the STOMP client and updates connection status.
65
+ *
66
+ * Safe to call even if the client was never created or already disconnected.
67
+ */
68
+ disconnect(): void;
69
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketClient = void 0;
4
+ const stompjs_1 = require("@stomp/stompjs");
5
+ const rxjs_1 = require("rxjs");
6
+ const constants_1 = require("./constants");
7
+ /**
8
+ * WebSocketClient
9
+ * ----------------
10
+ * A lightweight STOMP-over-WebSocket wrapper designed for publishing
11
+ * analytics events to a RabbitMQ broker. Includes:
12
+ * - connection lifecycle management
13
+ * - auto-reconnect support
14
+ * - offline event buffering
15
+ * - reactive connection status via RxJS
16
+ *
17
+ * Intended to be used inside applications where analytics events must
18
+ * never be lost due to temporary connection issues.
19
+ */
20
+ class WebSocketClient {
21
+ constructor() {
22
+ /**
23
+ * The underlying STOMP client instance.
24
+ * Initialized in `connectAnalyticsStomp()`.
25
+ */
26
+ this.analyticsClient = null;
27
+ /**
28
+ * Buffer containing analytics events produced before the socket
29
+ * becomes connected. They are automatically flushed on connection.
30
+ */
31
+ this.pendingEvents = [];
32
+ this.stompAnalyticsConnected = new rxjs_1.BehaviorSubject(false);
33
+ /**
34
+ * Reactive connection state for consumers who want to listen for
35
+ * connection availability changes.
36
+ *
37
+ * `true` -> connected
38
+ * `false` -> disconnected
39
+ */
40
+ this.stompAnalyticsConnected$ = this.stompAnalyticsConnected.asObservable();
41
+ }
42
+ /**
43
+ * Creates and configures a STOMP client instance.
44
+ *
45
+ * @param cfg Connection configuration (broker URL, credentials, reconnect delay, mode).
46
+ * @returns A configured but not yet activated STOMP `Client` instance.
47
+ */
48
+ createStompClient(cfg) {
49
+ var _a, _b, _c, _d;
50
+ console.log('[Nommos Tracker] Rabbit Configs... ', cfg);
51
+ const client = new stompjs_1.Client({
52
+ brokerURL: (_a = cfg.rabbitUrl) !== null && _a !== void 0 ? _a : '',
53
+ connectHeaders: {
54
+ login: (_b = cfg.username) !== null && _b !== void 0 ? _b : '',
55
+ passcode: (_c = cfg.password) !== null && _c !== void 0 ? _c : '',
56
+ },
57
+ reconnectDelay: (_d = cfg.reconnectDelay) !== null && _d !== void 0 ? _d : 5000,
58
+ });
59
+ if (cfg.mode === 'dev') {
60
+ client.debug = (msg) => console.log('[Nommos Tracker]', msg);
61
+ }
62
+ else {
63
+ client.debug = () => {
64
+ /* empty */
65
+ }; // silence logs in non-dev mode
66
+ }
67
+ return client;
68
+ }
69
+ /**
70
+ * Establishes a STOMP WebSocket connection and wires lifecycle handlers.
71
+ *
72
+ * - On successful connection:
73
+ * • Emits `true` for reactive subscribers
74
+ * • Flushes all queued analytics events
75
+ * - On broker error:
76
+ * • Logs structured error output
77
+ *
78
+ * @param cfg Configuration including URL, credentials, mode etc.
79
+ */
80
+ connectAnalyticsStomp(cfg) {
81
+ this.analyticsClient = this.createStompClient(cfg);
82
+ this.analyticsClient.onConnect = () => {
83
+ console.log('[Nommos Tracker] Connected');
84
+ this.stompAnalyticsConnected.next(true);
85
+ // flush pending events
86
+ for (const m of this.pendingEvents) {
87
+ this.publishAnalyticsMessage(m);
88
+ }
89
+ this.pendingEvents = [];
90
+ };
91
+ this.analyticsClient.onStompError = (frame) => {
92
+ console.error('[Nommos Tracker] Broker error:', frame.headers['message']);
93
+ };
94
+ console.log('[Nommos Tracker] Activating STOMP client...');
95
+ this.analyticsClient.activate();
96
+ }
97
+ /**
98
+ * Publishes an analytics event to a RabbitMQ queue.
99
+ *
100
+ * If the connection is not ready, the event is automatically queued
101
+ * and delivered once the socket reconnects.
102
+ *
103
+ * @param payload The analytics event to send.
104
+ */
105
+ publishAnalyticsMessage(payload) {
106
+ var _a;
107
+ if (!((_a = this.analyticsClient) === null || _a === void 0 ? void 0 : _a.connected) || this.analyticsClient == null) {
108
+ this.pendingEvents.push(payload);
109
+ return;
110
+ }
111
+ this.analyticsClient.publish({
112
+ destination: constants_1.ANALYTICS_QUEUE,
113
+ headers: { 'content-type': 'application/json' },
114
+ body: JSON.stringify(payload),
115
+ });
116
+ }
117
+ /**
118
+ * Gracefully shuts down the STOMP client and updates connection status.
119
+ *
120
+ * Safe to call even if the client was never created or already disconnected.
121
+ */
122
+ disconnect() {
123
+ if (this.analyticsClient) {
124
+ this.analyticsClient.deactivate().then(() => {
125
+ this.stompAnalyticsConnected.next(false);
126
+ console.log('[Nommos Tracker] Disconnected');
127
+ });
128
+ }
129
+ }
130
+ }
131
+ exports.WebSocketClient = WebSocketClient;
132
+ //# sourceMappingURL=webSocket-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocket-client.js","sourceRoot":"","sources":["../../../../../nommos/core/src/lib/webSocket-client.ts"],"names":[],"mappings":"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"}