serve-socket 5.4.0 → 6.0.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/fesm2022/serve-socket.mjs +207 -194
- package/fesm2022/serve-socket.mjs.map +1 -1
- package/index.d.ts +58 -32
- package/package.json +3 -2
|
@@ -3,7 +3,7 @@ import { NgModule, InjectionToken, Inject, Injectable } from '@angular/core';
|
|
|
3
3
|
import { CommonModule } from '@angular/common';
|
|
4
4
|
import { HttpClientModule, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
|
5
5
|
import { BehaviorSubject, Subject, filter, switchMap, map } from 'rxjs';
|
|
6
|
-
import {
|
|
6
|
+
import { connect } from 'mqtt';
|
|
7
7
|
import { pairwise, first, debounceTime, takeUntil } from 'rxjs/operators';
|
|
8
8
|
import * as i2 from 'ngx-toastr';
|
|
9
9
|
|
|
@@ -72,13 +72,25 @@ var SocketSuccessEventKeys;
|
|
|
72
72
|
SocketSuccessEventKeys["BILLING_CREDIT_NOTE_ISSUED"] = "BILLING_CREDIT_NOTE_ISSUED";
|
|
73
73
|
SocketSuccessEventKeys["BILLING_REFUND_PROCESSED"] = "BILLING_REFUND_PROCESSED";
|
|
74
74
|
})(SocketSuccessEventKeys || (SocketSuccessEventKeys = {}));
|
|
75
|
+
/**
|
|
76
|
+
* Topic convention (mirrors server messenger.gateway.ts):
|
|
77
|
+
* Server → user: serve-plus/user/{userId}/{event}
|
|
78
|
+
* Server → room: serve-plus/room/{roomId}/{event}
|
|
79
|
+
* Client → server: serve-plus/client/{userId}/{action} (payload = raw JWT string)
|
|
80
|
+
*
|
|
81
|
+
* System events handled internally (not forwarded to event subjects):
|
|
82
|
+
* JOIN_ROOM { roomId: string } — subscribe to serve-plus/room/{roomId}/#
|
|
83
|
+
* LEAVE_ROOM { roomId: string } — unsubscribe from serve-plus/room/{roomId}/#
|
|
84
|
+
* FORCE_DISCONNECT {} — disconnect
|
|
85
|
+
*/
|
|
75
86
|
class SocketService {
|
|
76
87
|
environment;
|
|
77
|
-
|
|
78
|
-
url;
|
|
88
|
+
mqttClient;
|
|
79
89
|
authToken;
|
|
80
90
|
connectionKey;
|
|
91
|
+
userId;
|
|
81
92
|
eventSubjects = new Map();
|
|
93
|
+
subscribedRooms = new Set();
|
|
82
94
|
connectionStatusSubject = new BehaviorSubject(false);
|
|
83
95
|
connectionStatus$ = this.connectionStatusSubject.asObservable();
|
|
84
96
|
reconnectSubject = new Subject();
|
|
@@ -86,247 +98,239 @@ class SocketService {
|
|
|
86
98
|
hasConnectedOnce = false;
|
|
87
99
|
healthySubject = new BehaviorSubject(false);
|
|
88
100
|
healthy$ = this.healthySubject.asObservable();
|
|
89
|
-
|
|
90
|
-
lastPongTime = 0;
|
|
101
|
+
TOPIC_PREFIX = 'serve-plus';
|
|
91
102
|
constructor(environment = defaultRealtimeStoreEnvironment) {
|
|
92
103
|
this.environment = environment;
|
|
93
|
-
this.url = this.environment.apiUrl;
|
|
94
104
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
decodeUserId(token) {
|
|
106
|
+
try {
|
|
107
|
+
const parts = token.split('.');
|
|
108
|
+
if (parts.length !== 3)
|
|
109
|
+
return undefined;
|
|
110
|
+
const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
|
|
111
|
+
return (payload.id ?? payload.sub);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
resolveBrokerUrl() {
|
|
118
|
+
if (this.environment.mqttUrl) {
|
|
119
|
+
return this.environment.mqttUrl;
|
|
100
120
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (this.authToken) {
|
|
111
|
-
socketOptions.auth = {
|
|
112
|
-
token: this.authToken
|
|
113
|
-
};
|
|
121
|
+
// Derive WebSocket MQTT URL from API URL
|
|
122
|
+
return this.environment.apiUrl
|
|
123
|
+
.replace(/^https/, 'wss')
|
|
124
|
+
.replace(/^http/, 'ws');
|
|
125
|
+
}
|
|
126
|
+
setupConnection() {
|
|
127
|
+
if (this.mqttClient) {
|
|
128
|
+
this.mqttClient.removeAllListeners();
|
|
129
|
+
this.mqttClient.end(true);
|
|
114
130
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
131
|
+
if (!this.authToken) {
|
|
132
|
+
console.warn('[MQTT] No auth token — cannot connect');
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.userId = this.decodeUserId(this.authToken);
|
|
136
|
+
if (!this.userId) {
|
|
137
|
+
console.warn('[MQTT] Could not decode user ID from token');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const options = {
|
|
141
|
+
username: this.userId,
|
|
142
|
+
password: this.authToken,
|
|
143
|
+
clean: true,
|
|
144
|
+
reconnectPeriod: 5000,
|
|
145
|
+
connectTimeout: 15000,
|
|
146
|
+
};
|
|
147
|
+
this.mqttClient = connect(this.resolveBrokerUrl(), options);
|
|
148
|
+
this.mqttClient.on('connect', () => {
|
|
149
|
+
console.log(this.hasConnectedOnce ? '[MQTT] Reconnected' : '[MQTT] Connected');
|
|
118
150
|
this.connectionStatusSubject.next(true);
|
|
119
|
-
this.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// hasConnectedOnce is an instance variable so it persists across resetWithNewToken() calls.
|
|
127
|
-
// Any connect after the very first one (regardless of socket recreation) triggers stores to reload.
|
|
128
|
-
this.socket.on('connect', () => {
|
|
151
|
+
this.healthySubject.next(true);
|
|
152
|
+
// Subscribe to personal user topic for all events and system commands
|
|
153
|
+
this.mqttClient.subscribe(`${this.TOPIC_PREFIX}/user/${this.userId}/#`, { qos: 1 });
|
|
154
|
+
// Re-subscribe to all previously joined rooms
|
|
155
|
+
this.subscribedRooms.forEach(roomId => {
|
|
156
|
+
this.mqttClient.subscribe(`${this.TOPIC_PREFIX}/room/${roomId}/#`, { qos: 1 });
|
|
157
|
+
});
|
|
129
158
|
if (this.hasConnectedOnce) {
|
|
130
|
-
console.log('Socket reconnected');
|
|
131
159
|
this.reconnectSubject.next();
|
|
132
160
|
}
|
|
133
161
|
this.hasConnectedOnce = true;
|
|
134
162
|
});
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
163
|
+
this.mqttClient.on('message', (topic, message) => {
|
|
164
|
+
try {
|
|
165
|
+
const payload = JSON.parse(message.toString());
|
|
166
|
+
const parts = topic.split('/');
|
|
167
|
+
const event = parts[parts.length - 1];
|
|
168
|
+
// Handle server-sent system events
|
|
169
|
+
if (event === 'JOIN_ROOM') {
|
|
170
|
+
const { roomId } = payload;
|
|
171
|
+
this.subscribeToRoom(roomId);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (event === 'LEAVE_ROOM') {
|
|
175
|
+
const { roomId } = payload;
|
|
176
|
+
this.unsubscribeFromRoom(roomId);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (event === 'FORCE_DISCONNECT') {
|
|
180
|
+
this.disconnect();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// Dispatch to registered event subjects
|
|
184
|
+
const subject = this.eventSubjects.get(event);
|
|
185
|
+
if (subject) {
|
|
186
|
+
console.log(`[MQTT] Event received: ${event}`, payload);
|
|
187
|
+
subject.next(payload);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
console.error(`[MQTT] Failed to parse message from topic ${topic}:`, err);
|
|
192
|
+
}
|
|
141
193
|
});
|
|
142
|
-
this.
|
|
143
|
-
console.
|
|
194
|
+
this.mqttClient.on('disconnect', () => {
|
|
195
|
+
console.log('[MQTT] Disconnected');
|
|
196
|
+
this.connectionStatusSubject.next(false);
|
|
197
|
+
this.healthySubject.next(false);
|
|
144
198
|
});
|
|
145
|
-
this.
|
|
146
|
-
console.error('
|
|
199
|
+
this.mqttClient.on('error', (err) => {
|
|
200
|
+
console.error('[MQTT] Connection error:', err.message);
|
|
147
201
|
});
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
this.lastPongTime = Date.now();
|
|
151
|
-
this.healthySubject.next(true);
|
|
202
|
+
this.mqttClient.on('reconnect', () => {
|
|
203
|
+
console.log('[MQTT] Reconnecting...');
|
|
152
204
|
});
|
|
153
|
-
// Start health check monitoring
|
|
154
|
-
this.startHealthCheck();
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Monitor connection health via ping/pong timing
|
|
158
|
-
*/
|
|
159
|
-
startHealthCheck() {
|
|
160
|
-
this.stopHealthCheck();
|
|
161
|
-
this.lastPongTime = Date.now();
|
|
162
|
-
// Check health every 30 seconds
|
|
163
|
-
this.healthCheckInterval = setInterval(() => {
|
|
164
|
-
if (!this.socket?.connected) {
|
|
165
|
-
this.healthySubject.next(false);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
const timeSinceLastPong = Date.now() - this.lastPongTime;
|
|
169
|
-
// If no pong in last 60 seconds, connection may be stale
|
|
170
|
-
if (timeSinceLastPong > 60000) {
|
|
171
|
-
console.warn('[Socket] Connection appears stale, forcing reconnect');
|
|
172
|
-
this.healthySubject.next(false);
|
|
173
|
-
this.socket.disconnect();
|
|
174
|
-
this.socket.connect();
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
this.healthySubject.next(true);
|
|
178
|
-
}
|
|
179
|
-
}, 30000);
|
|
180
205
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
this.
|
|
206
|
+
subscribeToRoom(roomId) {
|
|
207
|
+
this.subscribedRooms.add(roomId);
|
|
208
|
+
if (this.mqttClient?.connected) {
|
|
209
|
+
this.mqttClient.subscribe(`${this.TOPIC_PREFIX}/room/${roomId}/#`, { qos: 1 }, (err) => {
|
|
210
|
+
if (err) {
|
|
211
|
+
console.error(`[MQTT] Failed to subscribe to room ${roomId}:`, err.message);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
console.log(`[MQTT] Subscribed to room: ${roomId}`);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
185
217
|
}
|
|
186
218
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
this.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// Add the listener
|
|
193
|
-
console.log('registering', eventName);
|
|
194
|
-
this.socket.on(eventName, (data) => {
|
|
195
|
-
console.log(`[Socket] Event received: ${eventName}`, data);
|
|
196
|
-
subject.next(data);
|
|
197
|
-
});
|
|
198
|
-
});
|
|
219
|
+
unsubscribeFromRoom(roomId) {
|
|
220
|
+
this.subscribedRooms.delete(roomId);
|
|
221
|
+
if (this.mqttClient?.connected) {
|
|
222
|
+
this.mqttClient.unsubscribe(`${this.TOPIC_PREFIX}/room/${roomId}/#`);
|
|
223
|
+
}
|
|
199
224
|
}
|
|
200
225
|
/**
|
|
201
|
-
* Set authentication token for
|
|
226
|
+
* Set authentication token for MQTT connection.
|
|
227
|
+
* Call connect() afterwards to open the connection.
|
|
202
228
|
*/
|
|
203
229
|
setAuthToken(token) {
|
|
204
230
|
this.authToken = token;
|
|
205
231
|
}
|
|
206
232
|
/**
|
|
207
|
-
* Set connection key
|
|
233
|
+
* Set connection key included in outbound message headers.
|
|
208
234
|
*/
|
|
209
235
|
setConnectionKey(key) {
|
|
210
236
|
this.connectionKey = key;
|
|
211
237
|
}
|
|
212
238
|
/**
|
|
213
|
-
* Reset connection with new token
|
|
239
|
+
* Reset connection with new token.
|
|
240
|
+
* Idempotent: no-op if the same token is already active and connected.
|
|
214
241
|
*/
|
|
215
242
|
resetWithNewToken(token) {
|
|
243
|
+
const tokenUnchanged = !token || token === this.authToken;
|
|
244
|
+
const clientActive = this.mqttClient?.connected;
|
|
245
|
+
if (tokenUnchanged && clientActive) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
216
248
|
if (token) {
|
|
217
249
|
this.authToken = token;
|
|
218
250
|
}
|
|
219
|
-
|
|
220
|
-
this.socket.disconnect();
|
|
221
|
-
}
|
|
222
|
-
this.setupSocketConnection();
|
|
251
|
+
this.setupConnection();
|
|
223
252
|
}
|
|
224
253
|
connect(timeoutMs = 15000) {
|
|
225
|
-
|
|
226
|
-
if (this.socket?.connected) {
|
|
254
|
+
if (this.mqttClient?.connected) {
|
|
227
255
|
return Promise.resolve();
|
|
228
256
|
}
|
|
229
257
|
return new Promise((resolve) => {
|
|
230
258
|
const timeout = setTimeout(() => {
|
|
231
|
-
|
|
232
|
-
// Callers should rely on reconnect$ to re-authenticate once connected.
|
|
233
|
-
console.warn('[Socket] Connection timeout — socket will keep retrying in background');
|
|
259
|
+
console.warn('[MQTT] Connection timeout — client will keep retrying in background');
|
|
234
260
|
resolve();
|
|
235
261
|
}, timeoutMs);
|
|
236
|
-
this.
|
|
237
|
-
|
|
262
|
+
if (!this.mqttClient) {
|
|
263
|
+
this.setupConnection();
|
|
264
|
+
}
|
|
265
|
+
if (this.mqttClient?.connected) {
|
|
238
266
|
clearTimeout(timeout);
|
|
239
267
|
resolve();
|
|
240
268
|
return;
|
|
241
269
|
}
|
|
242
|
-
|
|
243
|
-
this.socket.once('connect', () => {
|
|
270
|
+
this.mqttClient?.once('connect', () => {
|
|
244
271
|
clearTimeout(timeout);
|
|
245
272
|
resolve();
|
|
246
273
|
});
|
|
247
|
-
this.socket.on('connect_error', (err) => {
|
|
248
|
-
// Log but don't reject — reconnection logic will keep retrying
|
|
249
|
-
console.warn('[Socket] connect_error:', err.message);
|
|
250
|
-
});
|
|
251
|
-
if (!this.socket.connected) {
|
|
252
|
-
this.socket.connect();
|
|
253
|
-
}
|
|
254
274
|
});
|
|
255
275
|
}
|
|
256
276
|
disconnect() {
|
|
257
|
-
this.
|
|
258
|
-
|
|
259
|
-
this.socket.disconnect();
|
|
277
|
+
if (this.mqttClient?.connected) {
|
|
278
|
+
this.mqttClient.end();
|
|
260
279
|
}
|
|
280
|
+
this.subscribedRooms.clear();
|
|
281
|
+
this.connectionStatusSubject.next(false);
|
|
261
282
|
this.healthySubject.next(false);
|
|
262
283
|
}
|
|
263
284
|
/**
|
|
264
|
-
* Emit event
|
|
285
|
+
* Emit an event to the server (client → server).
|
|
286
|
+
* Publishes to serve-plus/client/{userId}/{event}.
|
|
265
287
|
*/
|
|
266
288
|
emit(event, data) {
|
|
267
|
-
if (!this.
|
|
268
|
-
console.warn('
|
|
289
|
+
if (!this.mqttClient?.connected || !this.userId) {
|
|
290
|
+
console.warn('[MQTT] Not connected or no user ID. Call connect() first.');
|
|
269
291
|
return;
|
|
270
292
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
};
|
|
280
|
-
this.socket.emit(event, payload);
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
this.socket.emit(event, data);
|
|
284
|
-
}
|
|
293
|
+
const payload = {
|
|
294
|
+
payload: data ?? {},
|
|
295
|
+
headers: {
|
|
296
|
+
...(this.authToken && { _authToken: this.authToken }),
|
|
297
|
+
...(this.connectionKey && { connectionKey: this.connectionKey }),
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
this.mqttClient.publish(`${this.TOPIC_PREFIX}/client/${this.userId}/${event}`, JSON.stringify(payload), { qos: 1 });
|
|
285
301
|
}
|
|
286
302
|
/**
|
|
287
|
-
* Listen to events
|
|
303
|
+
* Listen to server-sent events. Returns a persistent Observable that
|
|
304
|
+
* survives reconnections (matching the previous socket.io behaviour).
|
|
288
305
|
*/
|
|
289
306
|
on(event) {
|
|
290
307
|
if (!this.eventSubjects.has(event)) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
// Set up listener if socket exists and is connected
|
|
294
|
-
if (this.socket?.connected) {
|
|
295
|
-
console.log(`[Socket] Registering listener for event: ${event}`);
|
|
296
|
-
this.socket.on(event, (data) => {
|
|
297
|
-
console.log(`[Socket] Event received: ${event}`, data);
|
|
298
|
-
subject.next(data);
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
console.log(`[Socket] Event ${event} registered but socket not connected yet - will attach on connection`);
|
|
303
|
-
}
|
|
308
|
+
this.eventSubjects.set(event, new Subject());
|
|
309
|
+
console.log(`[MQTT] Registered listener for event: ${event}`);
|
|
304
310
|
}
|
|
305
311
|
return this.eventSubjects.get(event).asObservable();
|
|
306
312
|
}
|
|
307
313
|
/**
|
|
308
|
-
* Listen
|
|
309
|
-
* @param event - Event name to listen for
|
|
310
|
-
* @param timeoutMs - Timeout in ms (default 30s, 0 = no timeout)
|
|
314
|
+
* Listen for a single event occurrence and return as a Promise.
|
|
311
315
|
*/
|
|
312
316
|
once(event, timeoutMs = 30000) {
|
|
313
|
-
if (!this.
|
|
314
|
-
return Promise.reject(new Error('
|
|
317
|
+
if (!this.mqttClient?.connected) {
|
|
318
|
+
return Promise.reject(new Error('[MQTT] Not connected. Call connect() first.'));
|
|
315
319
|
}
|
|
316
320
|
return new Promise((resolve, reject) => {
|
|
317
321
|
let timeoutId;
|
|
318
|
-
const
|
|
322
|
+
const subscription = this.on(event).subscribe((data) => {
|
|
319
323
|
if (timeoutId)
|
|
320
324
|
clearTimeout(timeoutId);
|
|
325
|
+
subscription.unsubscribe();
|
|
321
326
|
resolve(data);
|
|
322
|
-
};
|
|
327
|
+
});
|
|
323
328
|
if (timeoutMs > 0) {
|
|
324
329
|
timeoutId = setTimeout(() => {
|
|
325
|
-
|
|
326
|
-
reject(new Error(`Timeout waiting for event: ${event}`));
|
|
330
|
+
subscription.unsubscribe();
|
|
331
|
+
reject(new Error(`[MQTT] Timeout waiting for event: ${event}`));
|
|
327
332
|
}, timeoutMs);
|
|
328
333
|
}
|
|
329
|
-
this.socket.once(event, handler);
|
|
330
334
|
});
|
|
331
335
|
}
|
|
332
336
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SocketService, deps: [{ token: REALTIME_STORE_ENVIRONMENT }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -784,43 +788,48 @@ function provideRealtimeStoreEnvironment(environment) {
|
|
|
784
788
|
}
|
|
785
789
|
|
|
786
790
|
/**
|
|
787
|
-
* Handles the
|
|
788
|
-
*
|
|
791
|
+
* Handles the MQTT connection lifecycle for the driver app.
|
|
792
|
+
*
|
|
793
|
+
* Pattern:
|
|
794
|
+
* - Use setAuthToken() + connect() instead of resetWithNewToken() so an in-progress
|
|
795
|
+
* connection is never torn down by a duplicate call (e.g. on page refresh).
|
|
796
|
+
* - reconnect$ emits when the MQTT client re-establishes after a drop; use it to
|
|
797
|
+
* re-emit DRIVER_CONNECT so the server re-joins the driver to their rooms.
|
|
798
|
+
* - A 'online' event listener handles recovery when the network comes back.
|
|
789
799
|
*
|
|
790
800
|
* Usage:
|
|
791
|
-
* -
|
|
792
|
-
* -
|
|
801
|
+
* - AppComponent.ngOnInit: call connectFromStorage() ONCE to restore session.
|
|
802
|
+
* - LoginPage success handler: call connect(token) after receiving a new token.
|
|
793
803
|
*/
|
|
794
804
|
class DriverSocketConnectionService {
|
|
795
805
|
socketService;
|
|
796
806
|
TOKEN_KEY = 'driver_token';
|
|
797
|
-
|
|
807
|
+
networkListener;
|
|
798
808
|
constructor(socketService) {
|
|
799
809
|
this.socketService = socketService;
|
|
810
|
+
this.networkListener = () => this.connectFromStorage();
|
|
811
|
+
window.addEventListener('online', this.networkListener);
|
|
800
812
|
}
|
|
801
813
|
/** Connect using a freshly obtained token (e.g. after login). */
|
|
802
814
|
connect(token) {
|
|
803
815
|
localStorage.setItem(this.TOKEN_KEY, token);
|
|
804
|
-
this.socketService.
|
|
805
|
-
this.
|
|
816
|
+
this.socketService.setAuthToken(token);
|
|
817
|
+
this.socketService.connect();
|
|
806
818
|
}
|
|
807
819
|
/** Restore the socket connection from a persisted token (e.g. on app start). */
|
|
808
820
|
connectFromStorage() {
|
|
809
821
|
const token = localStorage.getItem(this.TOKEN_KEY);
|
|
810
822
|
if (token) {
|
|
811
|
-
this.socketService.
|
|
812
|
-
this.
|
|
823
|
+
this.socketService.setAuthToken(token);
|
|
824
|
+
this.socketService.connect();
|
|
813
825
|
}
|
|
814
826
|
}
|
|
815
827
|
disconnect() {
|
|
816
|
-
this.reconnectSubscription?.unsubscribe();
|
|
817
828
|
this.socketService.disconnect();
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
this.socketService.resetWithNewToken(token);
|
|
823
|
-
});
|
|
829
|
+
if (this.networkListener) {
|
|
830
|
+
window.removeEventListener('online', this.networkListener);
|
|
831
|
+
this.networkListener = undefined;
|
|
832
|
+
}
|
|
824
833
|
}
|
|
825
834
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DriverSocketConnectionService, deps: [{ token: SocketService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
826
835
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DriverSocketConnectionService, providedIn: 'root' });
|
|
@@ -833,42 +842,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
833
842
|
}], ctorParameters: () => [{ type: SocketService }] });
|
|
834
843
|
|
|
835
844
|
/**
|
|
836
|
-
* Handles the
|
|
837
|
-
*
|
|
845
|
+
* Handles the MQTT connection lifecycle for the customer-food (online customer) app.
|
|
846
|
+
*
|
|
847
|
+
* Pattern:
|
|
848
|
+
* - Use setAuthToken() + connect() instead of resetWithNewToken() so an in-progress
|
|
849
|
+
* connection is never torn down by a duplicate call (e.g. on page refresh).
|
|
850
|
+
* - reconnect$ emits when the MQTT client re-establishes after a drop; use it to
|
|
851
|
+
* re-emit CUSTOMER_CONNECT so the server re-joins the client to their rooms.
|
|
852
|
+
* - A 'online' event listener handles recovery when the network comes back.
|
|
838
853
|
*
|
|
839
854
|
* Usage:
|
|
840
|
-
* -
|
|
841
|
-
* -
|
|
855
|
+
* - AppComponent.ngOnInit: call connectFromStorage() ONCE to restore session.
|
|
856
|
+
* - LoginPage success handler: call connect(token) after receiving a new token.
|
|
842
857
|
*/
|
|
843
858
|
class OnlineCustomerSocketConnectionService {
|
|
844
859
|
socketService;
|
|
845
860
|
TOKEN_KEY = 'online_customer_token';
|
|
846
|
-
|
|
861
|
+
networkListener;
|
|
847
862
|
constructor(socketService) {
|
|
848
863
|
this.socketService = socketService;
|
|
864
|
+
this.networkListener = () => this.connectFromStorage();
|
|
865
|
+
window.addEventListener('online', this.networkListener);
|
|
849
866
|
}
|
|
850
867
|
/** Connect using a freshly obtained token (e.g. after login). */
|
|
851
868
|
connect(token) {
|
|
852
|
-
this.socketService.
|
|
853
|
-
this.
|
|
869
|
+
this.socketService.setAuthToken(token);
|
|
870
|
+
this.socketService.connect();
|
|
854
871
|
}
|
|
855
872
|
/** Restore the socket connection from a persisted token (e.g. on app start). */
|
|
856
873
|
connectFromStorage() {
|
|
857
874
|
const token = localStorage.getItem(this.TOKEN_KEY);
|
|
858
875
|
if (token) {
|
|
859
|
-
this.
|
|
860
|
-
this.subscribeToReconnect(token);
|
|
876
|
+
this.connect(token);
|
|
861
877
|
}
|
|
862
878
|
}
|
|
863
879
|
disconnect() {
|
|
864
|
-
this.reconnectSubscription?.unsubscribe();
|
|
865
880
|
this.socketService.disconnect();
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
this.socketService.resetWithNewToken(token);
|
|
871
|
-
});
|
|
881
|
+
if (this.networkListener) {
|
|
882
|
+
window.removeEventListener('online', this.networkListener);
|
|
883
|
+
this.networkListener = undefined;
|
|
884
|
+
}
|
|
872
885
|
}
|
|
873
886
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: OnlineCustomerSocketConnectionService, deps: [{ token: SocketService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
874
887
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: OnlineCustomerSocketConnectionService, providedIn: 'root' });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve-socket.mjs","sources":["../../../projects/serve-socket/src/lib/realtime-store.module.ts","../../../projects/serve-socket/src/lib/environment/realtime-store-environment.interface.ts","../../../projects/serve-socket/src/lib/environment/realtime-store-environment.token.ts","../../../projects/serve-socket/src/lib/socket.service.ts","../../../projects/serve-socket/src/lib/base-store.ts","../../../projects/serve-socket/src/lib/stores/table.store.ts","../../../projects/serve-socket/src/lib/stores/cart.store.ts","../../../projects/serve-socket/src/lib/stores/call-waiter.store.ts","../../../projects/serve-socket/src/lib/stores/notification.store.ts","../../../projects/serve-socket/src/lib/stores/delivery-order.store.ts","../../../projects/serve-socket/src/lib/stores/reservation.store.ts","../../../projects/serve-socket/src/lib/stores/inventory.store.ts","../../../projects/serve-socket/src/lib/providers.ts","../../../projects/serve-socket/src/lib/providers/realtime-store-environment.provider.ts","../../../projects/serve-socket/src/lib/driver-socket-connection.service.ts","../../../projects/serve-socket/src/lib/online-customer-socket-connection.service.ts","../../../projects/serve-socket/src/public-api.ts","../../../projects/serve-socket/src/serve-socket.ts"],"sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpClientModule } from '@angular/common/http';\n\n/**\n * @deprecated Use provideRealtimeStore() with standalone components instead\n */\n@NgModule({\n declarations: [],\n imports: [\n CommonModule,\n HttpClientModule // Kept for backward compatibility with Angular <14\n ],\n exports: []\n})\nexport class RealtimeStoreModule { }\n","import { SocketSuccessEventKeys } from '../socket.service';\n\nexport interface RealtimeStoreEnvironment {\n apiUrl: string;\n}\n\nexport const defaultRealtimeStoreEnvironment: RealtimeStoreEnvironment = {\n apiUrl: `http://${window.location.hostname}:3030`,\n};","import { InjectionToken } from '@angular/core';\nimport { RealtimeStoreEnvironment } from './realtime-store-environment.interface';\n\nexport const REALTIME_STORE_ENVIRONMENT = new InjectionToken<RealtimeStoreEnvironment>('REALTIME_STORE_ENVIRONMENT');","import { Injectable, Inject } from '@angular/core';\nimport { BehaviorSubject, Observable, Subject } from 'rxjs';\nimport { io, Socket } from 'socket.io-client';\nimport { REALTIME_STORE_ENVIRONMENT, RealtimeStoreEnvironment, defaultRealtimeStoreEnvironment } from './environment';\n\nexport enum SocketSuccessEventKeys {\n CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS = 'CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS',\n CUSTOMER_REMOVE_FROM_CART_SUCCESS = 'CUSTOMER_REMOVE_FROM_CART_SUCCESS',\n TABLE_JOIN_REQUEST_SENT_SUCCESS = 'TABLE_JOIN_REQUEST_SENT_SUCCESS',\n TABLE_CREATED_OR_UPDATED = 'TABLE_CREATED_OR_UPDATED',\n TABLE_RELEASED = 'TABLE_RELEASED',\n HOST_JOIN_REQUEST_APPROVED_SUCCESS = 'HOST_JOIN_REQUEST_APPROVED_SUCCESS',\n HOST_JOIN_REQUEST_DECLINED = 'HOST_JOIN_REQUEST_DECLINED',\n WAITER_CALL_CREATED_SUCCESS = 'WAITER_CALL_CREATED_SUCCESS',\n WAITER_CALL_ACKNOWLEDGED_SUCCESS = 'WAITER_CALL_ACKNOWLEDGED_SUCCESS',\n ERROR_MESSAGE_SUCCESS = 'ERROR_MESSAGE_SUCCESS',\n SUCCESS_MESSAGE_SUCCESS = 'SUCCESS_MESSAGE_SUCCESS',\n WARNING_MESSAGE_SUCCESS = 'WARNING_MESSAGE_SUCCESS',\n // Delivery\n NEW_DELIVERY_ORDER = 'NEW_DELIVERY_ORDER',\n ORDER_STATUS_UPDATED = 'ORDER_STATUS_UPDATED',\n DRIVER_LOCATION_UPDATED = 'DRIVER_LOCATION_UPDATED',\n // Reservations\n RESERVATION_CREATE_OR_UPDATE_SUCCESS = 'RESERVATION_CREATE_OR_UPDATE_SUCCESS',\n RESERVATION_REMOVE_SUCCESS = 'RESERVATION_REMOVE_SUCCESS',\n // Inventory\n INVENTORY_STOCK_UPDATED = 'INVENTORY_STOCK_UPDATED',\n INVENTORY_LOW_STOCK_ALERT = 'INVENTORY_LOW_STOCK_ALERT',\n INVENTORY_PURCHASE_ORDER_UPDATED = 'INVENTORY_PURCHASE_ORDER_UPDATED',\n // Billing\n BILLING_SUBSCRIPTION_UPDATED = 'BILLING_SUBSCRIPTION_UPDATED',\n BILLING_INVOICE_ISSUED = 'BILLING_INVOICE_ISSUED',\n BILLING_PAYMENT_RECEIVED = 'BILLING_PAYMENT_RECEIVED',\n BILLING_TRIAL_EXPIRING = 'BILLING_TRIAL_EXPIRING',\n BILLING_INVOICE_OVERDUE = 'BILLING_INVOICE_OVERDUE',\n BILLING_SUBSCRIPTION_SUSPENDED = 'BILLING_SUBSCRIPTION_SUSPENDED',\n BILLING_CREDIT_NOTE_ISSUED = 'BILLING_CREDIT_NOTE_ISSUED',\n BILLING_REFUND_PROCESSED = 'BILLING_REFUND_PROCESSED',\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class SocketService {\n private socket!: Socket;\n private readonly url: string;\n private authToken?: string;\n private connectionKey?: string;\n private readonly eventSubjects = new Map<string, Subject<any>>();\n\n private readonly connectionStatusSubject = new BehaviorSubject<boolean>(false);\n public connectionStatus$ = this.connectionStatusSubject.asObservable();\n\n private readonly reconnectSubject = new Subject<void>();\n public reconnect$ = this.reconnectSubject.asObservable();\n\n private hasConnectedOnce = false;\n\n private readonly healthySubject = new BehaviorSubject<boolean>(false);\n public healthy$ = this.healthySubject.asObservable();\n\n private healthCheckInterval?: ReturnType<typeof setInterval>;\n private lastPongTime = 0;\n\n constructor(\n @Inject(REALTIME_STORE_ENVIRONMENT) private readonly environment: RealtimeStoreEnvironment = defaultRealtimeStoreEnvironment\n ) {\n this.url = this.environment.apiUrl;\n }\n\n private setupSocketConnection(): void {\n // Cleanup existing socket to prevent memory leaks\n if (this.socket) {\n this.socket.removeAllListeners();\n this.socket.disconnect();\n }\n\n const socketOptions: any = {\n transports: ['websocket'],\n autoConnect: true,\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 1000,\n reconnectionDelayMax: 10000\n };\n\n // Add auth if token is available\n if (this.authToken) {\n socketOptions.auth = {\n token: this.authToken\n };\n }\n\n this.socket = io(this.url, socketOptions);\n\n this.socket.on('connect', () => {\n console.log('Socket connected');\n this.connectionStatusSubject.next(true);\n this.reestablishListeners();\n });\n\n this.socket.on('disconnect', () => {\n console.log('Socket disconnected');\n this.connectionStatusSubject.next(false);\n });\n\n // In Socket.IO v4 the 'reconnect' event is on the Manager (socket.io), not the socket.\n // hasConnectedOnce is an instance variable so it persists across resetWithNewToken() calls.\n // Any connect after the very first one (regardless of socket recreation) triggers stores to reload.\n this.socket.on('connect', () => {\n if (this.hasConnectedOnce) {\n console.log('Socket reconnected');\n this.reconnectSubject.next();\n }\n this.hasConnectedOnce = true;\n });\n\n // Keep the manager-level listener as a fallback for older versions\n this.socket.io.on('reconnect', () => {\n console.log('Socket manager reconnected');\n this.connectionStatusSubject.next(true);\n this.reconnectSubject.next();\n this.reestablishListeners();\n });\n\n this.socket.on('connect_error', (err) => {\n console.error('Connection error:', err.message);\n });\n\n this.socket.on('reconnect_error', (err) => {\n console.error('Reconnection error:', err.message);\n });\n\n // Socket.IO built-in ping/pong for health monitoring\n this.socket.io.on('ping', () => {\n this.lastPongTime = Date.now();\n this.healthySubject.next(true);\n });\n\n // Start health check monitoring\n this.startHealthCheck();\n }\n\n /**\n * Monitor connection health via ping/pong timing\n */\n private startHealthCheck(): void {\n this.stopHealthCheck();\n\n this.lastPongTime = Date.now();\n\n // Check health every 30 seconds\n this.healthCheckInterval = setInterval(() => {\n if (!this.socket?.connected) {\n this.healthySubject.next(false);\n return;\n }\n\n const timeSinceLastPong = Date.now() - this.lastPongTime;\n // If no pong in last 60 seconds, connection may be stale\n if (timeSinceLastPong > 60000) {\n console.warn('[Socket] Connection appears stale, forcing reconnect');\n this.healthySubject.next(false);\n this.socket.disconnect();\n this.socket.connect();\n } else {\n this.healthySubject.next(true);\n }\n }, 30000);\n }\n\n private stopHealthCheck(): void {\n if (this.healthCheckInterval) {\n clearInterval(this.healthCheckInterval);\n this.healthCheckInterval = undefined;\n }\n }\n\n private reestablishListeners(): void {\n console.log('Re-establishing listeners for', this.eventSubjects.size, 'events');\n this.eventSubjects.forEach((subject, eventName) => {\n // Remove any existing listener to avoid duplicates\n this.socket.off(eventName);\n // Add the listener\n console.log('registering', eventName);\n\n this.socket.on(eventName, (data) => {\n console.log(`[Socket] Event received: ${eventName}`, data);\n subject.next(data);\n });\n });\n }\n\n /**\n * Set authentication token for socket connection\n */\n public setAuthToken(token: string): void {\n this.authToken = token;\n }\n\n /**\n * Set connection key for socket connection\n */\n public setConnectionKey(key: string): void {\n this.connectionKey = key;\n }\n\n /**\n * Reset connection with new token\n */\n public resetWithNewToken(token?: string): void {\n if (token) {\n this.authToken = token;\n }\n\n if (this.socket) {\n this.socket.disconnect();\n }\n\n this.setupSocketConnection();\n }\n\n public connect(timeoutMs = 15000): Promise<void> {\n // Reuse existing connected socket\n if (this.socket?.connected) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n // Don't reject — the socket keeps reconnecting via reconnectionAttempts: Infinity.\n // Callers should rely on reconnect$ to re-authenticate once connected.\n console.warn('[Socket] Connection timeout — socket will keep retrying in background');\n resolve();\n }, timeoutMs);\n\n this.setupSocketConnection();\n\n if (this.socket.connected) {\n clearTimeout(timeout);\n resolve();\n return;\n }\n\n // Wait for the connect event\n this.socket.once('connect', () => {\n clearTimeout(timeout);\n resolve();\n });\n\n this.socket.on('connect_error', (err) => {\n // Log but don't reject — reconnection logic will keep retrying\n console.warn('[Socket] connect_error:', err.message);\n });\n\n if (!this.socket.connected) {\n this.socket.connect();\n }\n });\n }\n\n public disconnect(): void {\n this.stopHealthCheck();\n if (this.socket?.connected) {\n this.socket.disconnect();\n }\n this.healthySubject.next(false);\n }\n\n /**\n * Emit event with optional authentication headers\n */\n public emit(event: string, data?: any): void {\n if (!this.socket || this.socket.disconnected) {\n console.warn('Socket not connected. Call connect() first.');\n return;\n }\n\n // If auth token or connection key exists, wrap data with headers\n if (this.authToken || this.connectionKey) {\n const payload = {\n payload: data || {},\n headers: {\n ...(this.authToken && { _authToken: this.authToken }),\n ...(this.connectionKey && { connectionKey: this.connectionKey })\n }\n };\n this.socket.emit(event, payload);\n } else {\n this.socket.emit(event, data);\n }\n }\n\n /**\n * Listen to events with persistent subjects that survive reconnections\n */\n public on<T>(event: string): Observable<T> {\n if (!this.eventSubjects.has(event)) {\n const subject = new Subject<T>();\n this.eventSubjects.set(event, subject);\n\n // Set up listener if socket exists and is connected\n if (this.socket?.connected) {\n console.log(`[Socket] Registering listener for event: ${event}`);\n this.socket.on(event, (data: T) => {\n console.log(`[Socket] Event received: ${event}`, data);\n subject.next(data);\n });\n } else {\n console.log(`[Socket] Event ${event} registered but socket not connected yet - will attach on connection`);\n }\n }\n\n return this.eventSubjects.get(event)!.asObservable();\n }\n\n /**\n * Listen to event once and return as Promise\n * @param event - Event name to listen for\n * @param timeoutMs - Timeout in ms (default 30s, 0 = no timeout)\n */\n public once<T>(event: string, timeoutMs = 30000): Promise<T> {\n if (!this.socket || this.socket.disconnected) {\n return Promise.reject(new Error('Socket not connected. Call connect() first.'));\n }\n\n return new Promise((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const handler = (data: T) => {\n if (timeoutId) clearTimeout(timeoutId);\n resolve(data);\n };\n\n if (timeoutMs > 0) {\n timeoutId = setTimeout(() => {\n this.socket.off(event, handler);\n reject(new Error(`Timeout waiting for event: ${event}`));\n }, timeoutMs);\n }\n\n this.socket.once(event, handler);\n });\n }\n}\n\n","import { BehaviorSubject, filter, map, Observable, Subject, Subscription, switchMap } from 'rxjs';\nimport { debounceTime, first, pairwise, takeUntil } from 'rxjs/operators';\nimport { SocketService } from './socket.service';\n\nexport interface Entity {\n id?: string;\n}\n\nexport abstract class BaseStore<T extends Entity> {\n protected dataSubject = new BehaviorSubject<T[]>([]);\n public data$: Observable<T[]> = this.dataSubject.asObservable();\n\n protected loadingSubject = new BehaviorSubject<boolean>(false);\n public loading$: Observable<boolean> = this.loadingSubject.asObservable();\n\n protected errorSubject = new BehaviorSubject<string | null>(null);\n public error$: Observable<string | null> = this.errorSubject.asObservable();\n\n private readonly destroy$ = new Subject<void>();\n private refreshInProgress = false;\n\n constructor(\n protected socketService: SocketService\n ) {\n // Defer initialization to allow child class constructor parameters to be assigned\n queueMicrotask(() => {\n this.initialize().then(() => { });\n });\n }\n\n private async initialize(): Promise<void> {\n this.setupSocketSubscriptions();\n this.refresh();\n\n // Reload data after a disconnect → reconnect cycle.\n // Listening to connectionStatus$ is more reliable than reconnect$ because\n // connectionStatus$ is driven directly by socket connect/disconnect events.\n this.socketService.connectionStatus$.pipe(\n pairwise(),\n filter(([prev, curr]) => prev === true && curr === false), // detect disconnect\n switchMap(() =>\n this.socketService.connectionStatus$.pipe(\n filter(connected => connected), // wait for next reconnect\n first()\n )\n ),\n debounceTime(1000), // give server time to be fully ready\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.refresh();\n });\n }\n\n public refresh() {\n // Prevent concurrent refresh calls\n if (this.refreshInProgress) {\n return;\n }\n this.refreshInProgress = true;\n this.setLoading(true);\n\n this.preload()\n .then(x => this.dataSubject.next(x))\n .catch(err => {\n console.error(`[${this.constructor.name}] Preload failed:`, err);\n this.setError(err.message || 'Failed to load data');\n })\n .finally(() => {\n this.refreshInProgress = false;\n this.setLoading(false);\n });\n }\n\n /**\n * Clean up subscriptions when store is destroyed\n */\n public destroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // Abstract methods to be implemented by specific stores\n public abstract preload(): Promise<T[]>;\n\n protected abstract setupSocketSubscriptions(): void;\n\n // Helper methods for stores\n protected updateItems(items: T[]): void {\n console.log('setting', items);\n\n this.dataSubject.next(items);\n }\n\n protected updateItem(updatedItem: Partial<T> & Pick<T, 'id'>): void {\n console.log('upserting', updatedItem);\n\n const currentItems = this.dataSubject.value;\n const idField = 'id' as keyof T;\n\n const index = currentItems.findIndex(\n item => item[idField] === updatedItem[idField]\n );\n\n let updatedItems: T[];\n\n if (index > -1) {\n // 🔁 Update existing item\n updatedItems = currentItems.map((item, i) =>\n i === index ? { ...item, ...updatedItem } as T : item\n );\n } else {\n // ➕ Add new item\n updatedItems = [...currentItems, updatedItem as T];\n }\n\n this.dataSubject.next(updatedItems);\n }\n\n\n protected removeItem(id: string): void {\n console.log('removing', id);\n\n const currentItems = this.dataSubject.value;\n const idField = 'id' as keyof T;\n const filteredItems = currentItems.filter(item => item[idField] !== id);\n this.dataSubject.next(filteredItems);\n }\n\n protected setLoading(isLoading: boolean): void {\n this.loadingSubject.next(isLoading);\n }\n\n protected setError(error: string | null): void {\n this.errorSubject.next(error);\n }\n\n // Helper to subscribe to socket events with typesafety\n protected subscribeToEvent<R>(\n event: string,\n handler: (data: R) => void\n ): void {\n this.socketService.on<R>(event).subscribe(handler);\n }\n\n getAll(): T[] {\n return this.dataSubject.value;\n }\n\n getById(id: string): T | undefined {\n const field = 'id' as keyof T;\n return this.dataSubject.value.find(item => item[field] === id);\n }\n\n getById$(id: string): Observable<T | undefined> {\n const field = 'id' as keyof T;\n return this.data$.pipe(\n map(items => items.find(item => item[field] === id))\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Subject } from 'rxjs';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\nexport interface PendingJoinRequest {\n id: string;\n name: string;\n tableId: string;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class TableStore<T extends Entity> extends BaseStore<T> {\n // Store pending customer join requests\n private pendingJoinRequestsSubject = new BehaviorSubject<PendingJoinRequest[]>([]);\n public pendingJoinRequests$ = this.pendingJoinRequestsSubject.asObservable();\n\n // Emits when the current customer has been approved to join the table\n private approvedSubject = new Subject<void>();\n public approved$ = this.approvedSubject.asObservable();\n\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n protected override setupSocketSubscriptions(): void {\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.TABLE_CREATED_OR_UPDATED,\n (table) => this.updateItem(table)\n );\n\n this.subscribeToEvent<string>(\n SocketSuccessEventKeys.TABLE_RELEASED,\n (tableId) => this.removeItem(tableId)\n );\n\n this.subscribeToEvent<boolean>(\n SocketSuccessEventKeys.HOST_JOIN_REQUEST_APPROVED_SUCCESS,\n (status) => {\n if (status) {\n this.approvedSubject.next();\n }\n }\n );\n\n // Listen for customer join requests\n this.subscribeToEvent<PendingJoinRequest>(\n SocketSuccessEventKeys.TABLE_JOIN_REQUEST_SENT_SUCCESS,\n (request) => {\n console.log('[TableStore] Customer join request received:', request);\n const current = this.pendingJoinRequestsSubject.value;\n // Avoid duplicates\n if (!current.find(r => r.id === request.id)) {\n this.pendingJoinRequestsSubject.next([...current, request]);\n }\n }\n );\n }\n\n // Remove a pending join request (e.g., after approval/decline)\n public removePendingJoinRequest(customerId: string): void {\n const current = this.pendingJoinRequestsSubject.value;\n this.pendingJoinRequestsSubject.next(current.filter(r => r.id !== customerId));\n }\n\n // Clear all pending join requests\n public clearPendingJoinRequests(): void {\n this.pendingJoinRequestsSubject.next([]);\n }\n\n public abstract override preload(): Promise<T[]>;\n}\n","import { Injectable } from '@angular/core';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class CartStore<T extends Entity> extends BaseStore<T> {\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n console.log('[CartStore] Setting up socket subscriptions');\n console.log('[CartStore] CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS event:', SocketSuccessEventKeys.CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS);\n\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS,\n (cart) => {\n console.log('[CartStore] CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS handler called with:', cart);\n this.updateItem(cart);\n console.log(this.dataSubject.getValue());\n\n }\n );\n\n this.subscribeToEvent<string>(\n SocketSuccessEventKeys.CUSTOMER_REMOVE_FROM_CART_SUCCESS,\n (cartId) => {\n console.log('[CartStore] CUSTOMER_REMOVE_FROM_CART_SUCCESS handler called with:', cartId);\n this.removeItem(cartId);\n console.log(this.dataSubject.getValue());\n }\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class CallWaiterStore<T extends Entity> extends BaseStore<T> {\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n console.log('[CallWaiterStore] Setting up socket subscriptions');\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.WAITER_CALL_CREATED_SUCCESS,\n (request) => this.updateItem(request)\n );\n }\n\n public abstract override preload(): Promise<T[]>;\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\nimport { ToastrService } from 'ngx-toastr';\n\nexport interface CartEventData {\n id: string;\n tableId: string;\n menuItemId?: string;\n customerCarts?: Array<{\n id: string;\n status?: string;\n customer?: {\n name?: string;\n };\n }>;\n}\n\nexport interface ReadyOrderAlert {\n id: string;\n cartId: string;\n tableId: string;\n customerName: string;\n timestamp: Date;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class NotificationStore {\n private readonly defaultOptions = {\n closeButton: true,\n progressBar: true\n };\n\n // Ready order alerts with dismiss functionality\n private readyOrderAlertsSubject = new BehaviorSubject<ReadyOrderAlert[]>([]);\n public readyOrderAlerts$ = this.readyOrderAlertsSubject.asObservable();\n\n constructor(\n protected socketService: SocketService,\n private readonly toastr: ToastrService\n ) {\n this.setupSocketSubscriptions();\n\n this.socketService.reconnect$.subscribe(() => {\n this.setupSocketSubscriptions();\n });\n }\n\n private setupSocketSubscriptions(): void {\n // Error messages\n this.socketService.on<{ message: string }>(SocketSuccessEventKeys.ERROR_MESSAGE_SUCCESS)\n .subscribe((data) => this.showError(data.message));\n\n // Success messages\n this.socketService.on<{ message: string }>(SocketSuccessEventKeys.SUCCESS_MESSAGE_SUCCESS)\n .subscribe((data) => this.showSuccess(data.message));\n\n // Warning messages\n this.socketService.on<{ message: string }>(SocketSuccessEventKeys.WARNING_MESSAGE_SUCCESS)\n .subscribe((data) => this.showWarning(data.message));\n\n // Cart update notifications - check for PREPARED status\n this.socketService.on<CartEventData>(SocketSuccessEventKeys.CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS)\n .subscribe((cart) => {\n console.log('[NotificationStore] Cart updated:', cart);\n\n // Check if any customer cart has PREPARED status\n const preparedCarts = cart.customerCarts?.filter(cc => cc.status === 'PREPARED') || [];\n\n if (preparedCarts.length > 0) {\n // This is a ready order - show special notification with vibration\n const customerName = preparedCarts[0]?.customer?.name || 'Customer';\n this.handleReadyOrder(cart, customerName);\n }\n // No toast for regular cart updates\n });\n\n // Cart removal notifications - just log, no toast\n this.socketService.on<string>(SocketSuccessEventKeys.CUSTOMER_REMOVE_FROM_CART_SUCCESS)\n .subscribe((cartId) => {\n console.log('[NotificationStore] Cart removed:', cartId);\n });\n }\n\n /**\n * Handle ready order notification with vibration and dismissable alert\n */\n private handleReadyOrder(cart: CartEventData, customerName: string): void {\n console.log('[NotificationStore] Ready order detected!', cart);\n\n // Vibrate device if supported\n this.vibrateDevice();\n\n // Add to ready order alerts\n const alert: ReadyOrderAlert = {\n id: `${cart.id}-${Date.now()}`,\n cartId: cart.id,\n tableId: cart.tableId,\n customerName,\n timestamp: new Date()\n };\n\n const currentAlerts = this.readyOrderAlertsSubject.value;\n this.readyOrderAlertsSubject.next([alert, ...currentAlerts]);\n\n // Also show toast with longer duration\n this.toastr.success(\n `Order ready for ${customerName}`,\n '🍽️ Order Ready!',\n {\n ...this.defaultOptions,\n timeOut: 0, // No auto-dismiss\n extendedTimeOut: 0,\n tapToDismiss: true\n }\n );\n }\n\n /**\n * Vibrate the device if supported\n */\n private vibrateDevice(): void {\n try {\n if ('vibrate' in navigator) {\n // Vibrate pattern: 200ms on, 100ms off, 200ms on\n navigator.vibrate([200, 100, 200, 100, 200]);\n }\n } catch (e) {\n console.warn('[NotificationStore] Vibration not supported', e);\n }\n }\n\n /**\n * Dismiss a ready order alert\n */\n public dismissReadyOrderAlert(alertId: string): void {\n const currentAlerts = this.readyOrderAlertsSubject.value;\n this.readyOrderAlertsSubject.next(currentAlerts.filter(a => a.id !== alertId));\n }\n\n /**\n * Dismiss all ready order alerts\n */\n public dismissAllReadyOrderAlerts(): void {\n this.readyOrderAlertsSubject.next([]);\n }\n\n // Manual notification methods\n public showError(message: string, title: string = 'Error', timeOut: number = 5000): void {\n this.toastr.error(message, title, {\n ...this.defaultOptions,\n timeOut\n });\n }\n\n public showSuccess(message: string, title: string = 'Success', timeOut: number = 3000): void {\n this.toastr.success(message, title, {\n ...this.defaultOptions,\n timeOut\n });\n }\n\n public showWarning(message: string, title: string = 'Warning', timeOut: number = 4000): void {\n this.toastr.warning(message, title, {\n ...this.defaultOptions,\n timeOut\n });\n }\n\n public showInfo(message: string, title: string = 'Info', timeOut: number = 3000): void {\n this.toastr.info(message, title, {\n ...this.defaultOptions,\n timeOut\n });\n }\n\n // Clear all toasts\n public clearAll(): void {\n this.toastr.clear();\n }\n\n // Remove a specific toast by id\n public remove(toastId: number): void {\n this.toastr.remove(toastId);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\nexport interface DeliveryLocation {\n driverId: string;\n lat: number;\n lng: number;\n orderId: string;\n timestamp?: number;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class DeliveryOrderStore<T extends Entity> extends BaseStore<T> {\n private driverLocationSubject = new BehaviorSubject<DeliveryLocation | null>(null);\n public driverLocation$ = this.driverLocationSubject.asObservable();\n\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.NEW_DELIVERY_ORDER,\n (order) => this.updateItem(order)\n );\n\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.ORDER_STATUS_UPDATED,\n (order) => this.updateItem(order)\n );\n\n this.subscribeToEvent<DeliveryLocation>(\n SocketSuccessEventKeys.DRIVER_LOCATION_UPDATED,\n (location) => this.driverLocationSubject.next(location)\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class ReservationStore<T extends Entity> extends BaseStore<T> {\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.RESERVATION_CREATE_OR_UPDATE_SUCCESS,\n (reservation) => this.updateItem(reservation)\n );\n\n this.subscribeToEvent<string>(\n SocketSuccessEventKeys.RESERVATION_REMOVE_SUCCESS,\n (reservationId) => this.removeItem(reservationId)\n );\n }\n\n public abstract override preload(): Promise<T[]>;\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\nexport interface InventoryLowStockAlert {\n stockItemId: string;\n name: string;\n currentStock: number;\n threshold: number;\n branchId: string;\n}\n\nexport interface InventoryPurchaseOrderUpdate {\n purchaseOrderId: string;\n status: string;\n branchId: string;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class InventoryStore<T extends Entity> extends BaseStore<T> {\n private readonly lowStockAlertSubject = new BehaviorSubject<InventoryLowStockAlert | null>(null);\n public lowStockAlert$ = this.lowStockAlertSubject.asObservable();\n\n private readonly purchaseOrderUpdateSubject = new BehaviorSubject<InventoryPurchaseOrderUpdate | null>(null);\n public purchaseOrderUpdate$ = this.purchaseOrderUpdateSubject.asObservable();\n\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.INVENTORY_STOCK_UPDATED,\n (item) => this.updateItem(item)\n );\n\n this.subscribeToEvent<InventoryLowStockAlert>(\n SocketSuccessEventKeys.INVENTORY_LOW_STOCK_ALERT,\n (alert) => this.lowStockAlertSubject.next(alert)\n );\n\n this.subscribeToEvent<InventoryPurchaseOrderUpdate>(\n SocketSuccessEventKeys.INVENTORY_PURCHASE_ORDER_UPDATED,\n (update) => this.purchaseOrderUpdateSubject.next(update)\n );\n }\n\n public abstract override preload(): Promise<T[]>;\n}\n","import { EnvironmentProviders, importProvidersFrom } from '@angular/core';\nimport { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';\n\n/**\n * Provides all services needed for the realtime store to function.\n * Use this function in your standalone application's bootstrapApplication providers array.\n * \n * @example\n * ```typescript\n * bootstrapApplication(AppComponent, {\n * providers: [\n * provideRealtimeStore()\n * ]\n * });\n * ```\n */\nexport function provideRealtimeStore(): EnvironmentProviders[] {\n return [\n provideHttpClient(withInterceptorsFromDi())\n ];\n}\n","import { Provider } from '@angular/core';\nimport { REALTIME_STORE_ENVIRONMENT, RealtimeStoreEnvironment } from '../environment';\n\nexport function provideRealtimeStoreEnvironment(environment: RealtimeStoreEnvironment): Provider {\n return {\n provide: REALTIME_STORE_ENVIRONMENT,\n useValue: environment\n };\n}","import { Injectable } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { SocketService } from './socket.service';\n\n/**\n * Handles the socket connection lifecycle for the driver app.\n * Reads the driver token from localStorage and connects/reconnects with it.\n *\n * Usage:\n * - `AppComponent.ngOnInit`: call `connectFromStorage()` to restore session on app start.\n * - `LoginPage` success handler: call `connect(token)` after receiving a new token.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class DriverSocketConnectionService {\n private readonly TOKEN_KEY = 'driver_token';\n private reconnectSubscription?: Subscription;\n\n constructor(private readonly socketService: SocketService) {}\n\n /** Connect using a freshly obtained token (e.g. after login). */\n connect(token: string): void {\n localStorage.setItem(this.TOKEN_KEY, token);\n this.socketService.resetWithNewToken(token);\n this.subscribeToReconnect(token);\n }\n\n /** Restore the socket connection from a persisted token (e.g. on app start). */\n connectFromStorage(): void {\n const token = localStorage.getItem(this.TOKEN_KEY);\n if (token) {\n this.socketService.resetWithNewToken(token);\n this.subscribeToReconnect(token);\n }\n }\n\n disconnect(): void {\n this.reconnectSubscription?.unsubscribe();\n this.socketService.disconnect();\n }\n\n private subscribeToReconnect(token: string): void {\n this.reconnectSubscription?.unsubscribe();\n this.reconnectSubscription = this.socketService.reconnect$.subscribe(() => {\n this.socketService.resetWithNewToken(token);\n });\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { SocketService } from './socket.service';\n\n/**\n * Handles the socket connection lifecycle for the customer-food (online customer) app.\n * Reads the online customer token from localStorage and connects/reconnects with it.\n *\n * Usage:\n * - `AppComponent.ngOnInit`: call `connectFromStorage()` to restore session on app start.\n * - `LoginPage` success handler: call `connect(token)` after receiving a new token.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class OnlineCustomerSocketConnectionService {\n private readonly TOKEN_KEY = 'online_customer_token';\n private reconnectSubscription?: Subscription;\n\n constructor(private readonly socketService: SocketService) {}\n\n /** Connect using a freshly obtained token (e.g. after login). */\n connect(token: string): void {\n this.socketService.resetWithNewToken(token);\n this.subscribeToReconnect(token);\n }\n\n /** Restore the socket connection from a persisted token (e.g. on app start). */\n connectFromStorage(): void {\n const token = localStorage.getItem(this.TOKEN_KEY);\n if (token) {\n this.socketService.resetWithNewToken(token);\n this.subscribeToReconnect(token);\n }\n }\n\n disconnect(): void {\n this.reconnectSubscription?.unsubscribe();\n this.socketService.disconnect();\n }\n\n private subscribeToReconnect(token: string): void {\n this.reconnectSubscription?.unsubscribe();\n this.reconnectSubscription = this.socketService.reconnect$.subscribe(() => {\n this.socketService.resetWithNewToken(token);\n });\n }\n}\n","/*\n * Public API Surface of realtime-store\n */\n\nexport * from './lib/realtime-store.module';\nexport * from './lib/socket.service';\nexport * from './lib/base-store';\nexport * from './lib/stores/table.store';\nexport * from './lib/stores/cart.store';\nexport * from './lib/stores/call-waiter.store';\nexport * from './lib/stores/notification.store';\nexport * from './lib/stores/delivery-order.store';\nexport * from './lib/stores/reservation.store';\nexport * from './lib/stores/inventory.store';\nexport * from './lib/providers';\nexport * from './lib/environment';\nexport * from './lib/providers/realtime-store-environment.provider';\nexport * from './lib/driver-socket-connection.service';\nexport * from './lib/online-customer-socket-connection.service';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.SocketService"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"serve-socket.mjs","sources":["../../../projects/serve-socket/src/lib/realtime-store.module.ts","../../../projects/serve-socket/src/lib/environment/realtime-store-environment.interface.ts","../../../projects/serve-socket/src/lib/environment/realtime-store-environment.token.ts","../../../projects/serve-socket/src/lib/socket.service.ts","../../../projects/serve-socket/src/lib/base-store.ts","../../../projects/serve-socket/src/lib/stores/table.store.ts","../../../projects/serve-socket/src/lib/stores/cart.store.ts","../../../projects/serve-socket/src/lib/stores/call-waiter.store.ts","../../../projects/serve-socket/src/lib/stores/notification.store.ts","../../../projects/serve-socket/src/lib/stores/delivery-order.store.ts","../../../projects/serve-socket/src/lib/stores/reservation.store.ts","../../../projects/serve-socket/src/lib/stores/inventory.store.ts","../../../projects/serve-socket/src/lib/providers.ts","../../../projects/serve-socket/src/lib/providers/realtime-store-environment.provider.ts","../../../projects/serve-socket/src/lib/driver-socket-connection.service.ts","../../../projects/serve-socket/src/lib/online-customer-socket-connection.service.ts","../../../projects/serve-socket/src/public-api.ts","../../../projects/serve-socket/src/serve-socket.ts"],"sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpClientModule } from '@angular/common/http';\n\n/**\n * @deprecated Use provideRealtimeStore() with standalone components instead\n */\n@NgModule({\n declarations: [],\n imports: [\n CommonModule,\n HttpClientModule // Kept for backward compatibility with Angular <14\n ],\n exports: []\n})\nexport class RealtimeStoreModule { }\n","import { SocketSuccessEventKeys } from '../socket.service';\n\nexport interface RealtimeStoreEnvironment {\n apiUrl: string;\n /**\n * WebSocket URL for the MQTT broker (e.g. ws://localhost:9001 or wss://broker.example.com:8883).\n * If omitted, derived from apiUrl by replacing http → ws / https → wss.\n */\n mqttUrl?: string;\n}\n\nexport const defaultRealtimeStoreEnvironment: RealtimeStoreEnvironment = {\n apiUrl: `http://${window.location.hostname}:3030`,\n};","import { InjectionToken } from '@angular/core';\nimport { RealtimeStoreEnvironment } from './realtime-store-environment.interface';\n\nexport const REALTIME_STORE_ENVIRONMENT = new InjectionToken<RealtimeStoreEnvironment>('REALTIME_STORE_ENVIRONMENT');","import { Injectable, Inject } from '@angular/core';\nimport { BehaviorSubject, Observable, Subject } from 'rxjs';\nimport { connect, MqttClient, IClientOptions } from 'mqtt';\nimport { REALTIME_STORE_ENVIRONMENT, RealtimeStoreEnvironment, defaultRealtimeStoreEnvironment } from './environment';\n\nexport enum SocketSuccessEventKeys {\n CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS = 'CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS',\n CUSTOMER_REMOVE_FROM_CART_SUCCESS = 'CUSTOMER_REMOVE_FROM_CART_SUCCESS',\n TABLE_JOIN_REQUEST_SENT_SUCCESS = 'TABLE_JOIN_REQUEST_SENT_SUCCESS',\n TABLE_CREATED_OR_UPDATED = 'TABLE_CREATED_OR_UPDATED',\n TABLE_RELEASED = 'TABLE_RELEASED',\n HOST_JOIN_REQUEST_APPROVED_SUCCESS = 'HOST_JOIN_REQUEST_APPROVED_SUCCESS',\n HOST_JOIN_REQUEST_DECLINED = 'HOST_JOIN_REQUEST_DECLINED',\n WAITER_CALL_CREATED_SUCCESS = 'WAITER_CALL_CREATED_SUCCESS',\n WAITER_CALL_ACKNOWLEDGED_SUCCESS = 'WAITER_CALL_ACKNOWLEDGED_SUCCESS',\n ERROR_MESSAGE_SUCCESS = 'ERROR_MESSAGE_SUCCESS',\n SUCCESS_MESSAGE_SUCCESS = 'SUCCESS_MESSAGE_SUCCESS',\n WARNING_MESSAGE_SUCCESS = 'WARNING_MESSAGE_SUCCESS',\n // Delivery\n NEW_DELIVERY_ORDER = 'NEW_DELIVERY_ORDER',\n ORDER_STATUS_UPDATED = 'ORDER_STATUS_UPDATED',\n DRIVER_LOCATION_UPDATED = 'DRIVER_LOCATION_UPDATED',\n // Reservations\n RESERVATION_CREATE_OR_UPDATE_SUCCESS = 'RESERVATION_CREATE_OR_UPDATE_SUCCESS',\n RESERVATION_REMOVE_SUCCESS = 'RESERVATION_REMOVE_SUCCESS',\n // Inventory\n INVENTORY_STOCK_UPDATED = 'INVENTORY_STOCK_UPDATED',\n INVENTORY_LOW_STOCK_ALERT = 'INVENTORY_LOW_STOCK_ALERT',\n INVENTORY_PURCHASE_ORDER_UPDATED = 'INVENTORY_PURCHASE_ORDER_UPDATED',\n // Billing\n BILLING_SUBSCRIPTION_UPDATED = 'BILLING_SUBSCRIPTION_UPDATED',\n BILLING_INVOICE_ISSUED = 'BILLING_INVOICE_ISSUED',\n BILLING_PAYMENT_RECEIVED = 'BILLING_PAYMENT_RECEIVED',\n BILLING_TRIAL_EXPIRING = 'BILLING_TRIAL_EXPIRING',\n BILLING_INVOICE_OVERDUE = 'BILLING_INVOICE_OVERDUE',\n BILLING_SUBSCRIPTION_SUSPENDED = 'BILLING_SUBSCRIPTION_SUSPENDED',\n BILLING_CREDIT_NOTE_ISSUED = 'BILLING_CREDIT_NOTE_ISSUED',\n BILLING_REFUND_PROCESSED = 'BILLING_REFUND_PROCESSED',\n}\n\n/**\n * Topic convention (mirrors server messenger.gateway.ts):\n * Server → user: serve-plus/user/{userId}/{event}\n * Server → room: serve-plus/room/{roomId}/{event}\n * Client → server: serve-plus/client/{userId}/{action} (payload = raw JWT string)\n *\n * System events handled internally (not forwarded to event subjects):\n * JOIN_ROOM { roomId: string } — subscribe to serve-plus/room/{roomId}/#\n * LEAVE_ROOM { roomId: string } — unsubscribe from serve-plus/room/{roomId}/#\n * FORCE_DISCONNECT {} — disconnect\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class SocketService {\n private mqttClient?: MqttClient;\n private authToken?: string;\n private connectionKey?: string;\n private userId?: string;\n private readonly eventSubjects = new Map<string, Subject<unknown>>();\n private readonly subscribedRooms = new Set<string>();\n\n private readonly connectionStatusSubject = new BehaviorSubject<boolean>(false);\n public connectionStatus$ = this.connectionStatusSubject.asObservable();\n\n private readonly reconnectSubject = new Subject<void>();\n public reconnect$ = this.reconnectSubject.asObservable();\n\n private hasConnectedOnce = false;\n\n private readonly healthySubject = new BehaviorSubject<boolean>(false);\n public healthy$ = this.healthySubject.asObservable();\n\n private readonly TOPIC_PREFIX = 'serve-plus';\n\n constructor(\n @Inject(REALTIME_STORE_ENVIRONMENT) private readonly environment: RealtimeStoreEnvironment = defaultRealtimeStoreEnvironment\n ) {}\n\n private decodeUserId(token: string): string | undefined {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return undefined;\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));\n return (payload.id ?? payload.sub) as string | undefined;\n } catch {\n return undefined;\n }\n }\n\n private resolveBrokerUrl(): string {\n if (this.environment.mqttUrl) {\n return this.environment.mqttUrl;\n }\n // Derive WebSocket MQTT URL from API URL\n return this.environment.apiUrl\n .replace(/^https/, 'wss')\n .replace(/^http/, 'ws');\n }\n\n private setupConnection(): void {\n if (this.mqttClient) {\n this.mqttClient.removeAllListeners();\n this.mqttClient.end(true);\n }\n\n if (!this.authToken) {\n console.warn('[MQTT] No auth token — cannot connect');\n return;\n }\n\n this.userId = this.decodeUserId(this.authToken);\n if (!this.userId) {\n console.warn('[MQTT] Could not decode user ID from token');\n return;\n }\n\n const options: IClientOptions = {\n username: this.userId,\n password: this.authToken,\n clean: true,\n reconnectPeriod: 5000,\n connectTimeout: 15000,\n };\n\n this.mqttClient = connect(this.resolveBrokerUrl(), options);\n\n this.mqttClient.on('connect', () => {\n console.log(this.hasConnectedOnce ? '[MQTT] Reconnected' : '[MQTT] Connected');\n this.connectionStatusSubject.next(true);\n this.healthySubject.next(true);\n\n // Subscribe to personal user topic for all events and system commands\n this.mqttClient!.subscribe(`${this.TOPIC_PREFIX}/user/${this.userId}/#`, { qos: 1 });\n\n // Re-subscribe to all previously joined rooms\n this.subscribedRooms.forEach(roomId => {\n this.mqttClient!.subscribe(`${this.TOPIC_PREFIX}/room/${roomId}/#`, { qos: 1 });\n });\n\n if (this.hasConnectedOnce) {\n this.reconnectSubject.next();\n }\n this.hasConnectedOnce = true;\n });\n\n this.mqttClient.on('message', (topic: string, message: Buffer) => {\n try {\n const payload = JSON.parse(message.toString()) as unknown;\n const parts = topic.split('/');\n const event = parts[parts.length - 1];\n\n // Handle server-sent system events\n if (event === 'JOIN_ROOM') {\n const { roomId } = payload as { roomId: string };\n this.subscribeToRoom(roomId);\n return;\n }\n if (event === 'LEAVE_ROOM') {\n const { roomId } = payload as { roomId: string };\n this.unsubscribeFromRoom(roomId);\n return;\n }\n if (event === 'FORCE_DISCONNECT') {\n this.disconnect();\n return;\n }\n\n // Dispatch to registered event subjects\n const subject = this.eventSubjects.get(event);\n if (subject) {\n console.log(`[MQTT] Event received: ${event}`, payload);\n subject.next(payload);\n }\n } catch (err) {\n console.error(`[MQTT] Failed to parse message from topic ${topic}:`, err);\n }\n });\n\n this.mqttClient.on('disconnect', () => {\n console.log('[MQTT] Disconnected');\n this.connectionStatusSubject.next(false);\n this.healthySubject.next(false);\n });\n\n this.mqttClient.on('error', (err: Error) => {\n console.error('[MQTT] Connection error:', err.message);\n });\n\n this.mqttClient.on('reconnect', () => {\n console.log('[MQTT] Reconnecting...');\n });\n }\n\n private subscribeToRoom(roomId: string): void {\n this.subscribedRooms.add(roomId);\n if (this.mqttClient?.connected) {\n this.mqttClient.subscribe(`${this.TOPIC_PREFIX}/room/${roomId}/#`, { qos: 1 }, (err) => {\n if (err) {\n console.error(`[MQTT] Failed to subscribe to room ${roomId}:`, err.message);\n } else {\n console.log(`[MQTT] Subscribed to room: ${roomId}`);\n }\n });\n }\n }\n\n private unsubscribeFromRoom(roomId: string): void {\n this.subscribedRooms.delete(roomId);\n if (this.mqttClient?.connected) {\n this.mqttClient.unsubscribe(`${this.TOPIC_PREFIX}/room/${roomId}/#`);\n }\n }\n\n /**\n * Set authentication token for MQTT connection.\n * Call connect() afterwards to open the connection.\n */\n public setAuthToken(token: string): void {\n this.authToken = token;\n }\n\n /**\n * Set connection key included in outbound message headers.\n */\n public setConnectionKey(key: string): void {\n this.connectionKey = key;\n }\n\n /**\n * Reset connection with new token.\n * Idempotent: no-op if the same token is already active and connected.\n */\n public resetWithNewToken(token?: string): void {\n const tokenUnchanged = !token || token === this.authToken;\n const clientActive = this.mqttClient?.connected;\n if (tokenUnchanged && clientActive) {\n return;\n }\n if (token) {\n this.authToken = token;\n }\n this.setupConnection();\n }\n\n public connect(timeoutMs = 15000): Promise<void> {\n if (this.mqttClient?.connected) {\n return Promise.resolve();\n }\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n console.warn('[MQTT] Connection timeout — client will keep retrying in background');\n resolve();\n }, timeoutMs);\n\n if (!this.mqttClient) {\n this.setupConnection();\n }\n\n if (this.mqttClient?.connected) {\n clearTimeout(timeout);\n resolve();\n return;\n }\n\n this.mqttClient?.once('connect', () => {\n clearTimeout(timeout);\n resolve();\n });\n });\n }\n\n public disconnect(): void {\n if (this.mqttClient?.connected) {\n this.mqttClient.end();\n }\n this.subscribedRooms.clear();\n this.connectionStatusSubject.next(false);\n this.healthySubject.next(false);\n }\n\n /**\n * Emit an event to the server (client → server).\n * Publishes to serve-plus/client/{userId}/{event}.\n */\n public emit(event: string, data?: unknown): void {\n if (!this.mqttClient?.connected || !this.userId) {\n console.warn('[MQTT] Not connected or no user ID. Call connect() first.');\n return;\n }\n\n const payload = {\n payload: data ?? {},\n headers: {\n ...(this.authToken && { _authToken: this.authToken }),\n ...(this.connectionKey && { connectionKey: this.connectionKey }),\n },\n };\n\n this.mqttClient.publish(\n `${this.TOPIC_PREFIX}/client/${this.userId}/${event}`,\n JSON.stringify(payload),\n { qos: 1 },\n );\n }\n\n /**\n * Listen to server-sent events. Returns a persistent Observable that\n * survives reconnections (matching the previous socket.io behaviour).\n */\n public on<T>(event: string): Observable<T> {\n if (!this.eventSubjects.has(event)) {\n this.eventSubjects.set(event, new Subject<unknown>());\n console.log(`[MQTT] Registered listener for event: ${event}`);\n }\n return (this.eventSubjects.get(event) as Subject<T>).asObservable();\n }\n\n /**\n * Listen for a single event occurrence and return as a Promise.\n */\n public once<T>(event: string, timeoutMs = 30000): Promise<T> {\n if (!this.mqttClient?.connected) {\n return Promise.reject(new Error('[MQTT] Not connected. Call connect() first.'));\n }\n\n return new Promise((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const subscription = this.on<T>(event).subscribe((data) => {\n if (timeoutId) clearTimeout(timeoutId);\n subscription.unsubscribe();\n resolve(data);\n });\n\n if (timeoutMs > 0) {\n timeoutId = setTimeout(() => {\n subscription.unsubscribe();\n reject(new Error(`[MQTT] Timeout waiting for event: ${event}`));\n }, timeoutMs);\n }\n });\n }\n}\n\n","import { BehaviorSubject, filter, map, Observable, Subject, Subscription, switchMap } from 'rxjs';\nimport { debounceTime, first, pairwise, takeUntil } from 'rxjs/operators';\nimport { SocketService } from './socket.service';\n\nexport interface Entity {\n id?: string;\n}\n\nexport abstract class BaseStore<T extends Entity> {\n protected dataSubject = new BehaviorSubject<T[]>([]);\n public data$: Observable<T[]> = this.dataSubject.asObservable();\n\n protected loadingSubject = new BehaviorSubject<boolean>(false);\n public loading$: Observable<boolean> = this.loadingSubject.asObservable();\n\n protected errorSubject = new BehaviorSubject<string | null>(null);\n public error$: Observable<string | null> = this.errorSubject.asObservable();\n\n private readonly destroy$ = new Subject<void>();\n private refreshInProgress = false;\n\n constructor(\n protected socketService: SocketService\n ) {\n // Defer initialization to allow child class constructor parameters to be assigned\n queueMicrotask(() => {\n this.initialize().then(() => { });\n });\n }\n\n private async initialize(): Promise<void> {\n this.setupSocketSubscriptions();\n this.refresh();\n\n // Reload data after a disconnect → reconnect cycle.\n // Listening to connectionStatus$ is more reliable than reconnect$ because\n // connectionStatus$ is driven directly by socket connect/disconnect events.\n this.socketService.connectionStatus$.pipe(\n pairwise(),\n filter(([prev, curr]) => prev === true && curr === false), // detect disconnect\n switchMap(() =>\n this.socketService.connectionStatus$.pipe(\n filter(connected => connected), // wait for next reconnect\n first()\n )\n ),\n debounceTime(1000), // give server time to be fully ready\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.refresh();\n });\n }\n\n public refresh() {\n // Prevent concurrent refresh calls\n if (this.refreshInProgress) {\n return;\n }\n this.refreshInProgress = true;\n this.setLoading(true);\n\n this.preload()\n .then(x => this.dataSubject.next(x))\n .catch(err => {\n console.error(`[${this.constructor.name}] Preload failed:`, err);\n this.setError(err.message || 'Failed to load data');\n })\n .finally(() => {\n this.refreshInProgress = false;\n this.setLoading(false);\n });\n }\n\n /**\n * Clean up subscriptions when store is destroyed\n */\n public destroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // Abstract methods to be implemented by specific stores\n public abstract preload(): Promise<T[]>;\n\n protected abstract setupSocketSubscriptions(): void;\n\n // Helper methods for stores\n protected updateItems(items: T[]): void {\n console.log('setting', items);\n\n this.dataSubject.next(items);\n }\n\n protected updateItem(updatedItem: Partial<T> & Pick<T, 'id'>): void {\n console.log('upserting', updatedItem);\n\n const currentItems = this.dataSubject.value;\n const idField = 'id' as keyof T;\n\n const index = currentItems.findIndex(\n item => item[idField] === updatedItem[idField]\n );\n\n let updatedItems: T[];\n\n if (index > -1) {\n // 🔁 Update existing item\n updatedItems = currentItems.map((item, i) =>\n i === index ? { ...item, ...updatedItem } as T : item\n );\n } else {\n // ➕ Add new item\n updatedItems = [...currentItems, updatedItem as T];\n }\n\n this.dataSubject.next(updatedItems);\n }\n\n\n protected removeItem(id: string): void {\n console.log('removing', id);\n\n const currentItems = this.dataSubject.value;\n const idField = 'id' as keyof T;\n const filteredItems = currentItems.filter(item => item[idField] !== id);\n this.dataSubject.next(filteredItems);\n }\n\n protected setLoading(isLoading: boolean): void {\n this.loadingSubject.next(isLoading);\n }\n\n protected setError(error: string | null): void {\n this.errorSubject.next(error);\n }\n\n // Helper to subscribe to socket events with typesafety\n protected subscribeToEvent<R>(\n event: string,\n handler: (data: R) => void\n ): void {\n this.socketService.on<R>(event).subscribe(handler);\n }\n\n getAll(): T[] {\n return this.dataSubject.value;\n }\n\n getById(id: string): T | undefined {\n const field = 'id' as keyof T;\n return this.dataSubject.value.find(item => item[field] === id);\n }\n\n getById$(id: string): Observable<T | undefined> {\n const field = 'id' as keyof T;\n return this.data$.pipe(\n map(items => items.find(item => item[field] === id))\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject, Subject } from 'rxjs';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\nexport interface PendingJoinRequest {\n id: string;\n name: string;\n tableId: string;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class TableStore<T extends Entity> extends BaseStore<T> {\n // Store pending customer join requests\n private pendingJoinRequestsSubject = new BehaviorSubject<PendingJoinRequest[]>([]);\n public pendingJoinRequests$ = this.pendingJoinRequestsSubject.asObservable();\n\n // Emits when the current customer has been approved to join the table\n private approvedSubject = new Subject<void>();\n public approved$ = this.approvedSubject.asObservable();\n\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n protected override setupSocketSubscriptions(): void {\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.TABLE_CREATED_OR_UPDATED,\n (table) => this.updateItem(table)\n );\n\n this.subscribeToEvent<string>(\n SocketSuccessEventKeys.TABLE_RELEASED,\n (tableId) => this.removeItem(tableId)\n );\n\n this.subscribeToEvent<boolean>(\n SocketSuccessEventKeys.HOST_JOIN_REQUEST_APPROVED_SUCCESS,\n (status) => {\n if (status) {\n this.approvedSubject.next();\n }\n }\n );\n\n // Listen for customer join requests\n this.subscribeToEvent<PendingJoinRequest>(\n SocketSuccessEventKeys.TABLE_JOIN_REQUEST_SENT_SUCCESS,\n (request) => {\n console.log('[TableStore] Customer join request received:', request);\n const current = this.pendingJoinRequestsSubject.value;\n // Avoid duplicates\n if (!current.find(r => r.id === request.id)) {\n this.pendingJoinRequestsSubject.next([...current, request]);\n }\n }\n );\n }\n\n // Remove a pending join request (e.g., after approval/decline)\n public removePendingJoinRequest(customerId: string): void {\n const current = this.pendingJoinRequestsSubject.value;\n this.pendingJoinRequestsSubject.next(current.filter(r => r.id !== customerId));\n }\n\n // Clear all pending join requests\n public clearPendingJoinRequests(): void {\n this.pendingJoinRequestsSubject.next([]);\n }\n\n public abstract override preload(): Promise<T[]>;\n}\n","import { Injectable } from '@angular/core';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class CartStore<T extends Entity> extends BaseStore<T> {\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n console.log('[CartStore] Setting up socket subscriptions');\n console.log('[CartStore] CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS event:', SocketSuccessEventKeys.CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS);\n\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS,\n (cart) => {\n console.log('[CartStore] CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS handler called with:', cart);\n this.updateItem(cart);\n console.log(this.dataSubject.getValue());\n\n }\n );\n\n this.subscribeToEvent<string>(\n SocketSuccessEventKeys.CUSTOMER_REMOVE_FROM_CART_SUCCESS,\n (cartId) => {\n console.log('[CartStore] CUSTOMER_REMOVE_FROM_CART_SUCCESS handler called with:', cartId);\n this.removeItem(cartId);\n console.log(this.dataSubject.getValue());\n }\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class CallWaiterStore<T extends Entity> extends BaseStore<T> {\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n console.log('[CallWaiterStore] Setting up socket subscriptions');\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.WAITER_CALL_CREATED_SUCCESS,\n (request) => this.updateItem(request)\n );\n }\n\n public abstract override preload(): Promise<T[]>;\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\nimport { ToastrService } from 'ngx-toastr';\n\nexport interface CartEventData {\n id: string;\n tableId: string;\n menuItemId?: string;\n customerCarts?: Array<{\n id: string;\n status?: string;\n customer?: {\n name?: string;\n };\n }>;\n}\n\nexport interface ReadyOrderAlert {\n id: string;\n cartId: string;\n tableId: string;\n customerName: string;\n timestamp: Date;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class NotificationStore {\n private readonly defaultOptions = {\n closeButton: true,\n progressBar: true\n };\n\n // Ready order alerts with dismiss functionality\n private readyOrderAlertsSubject = new BehaviorSubject<ReadyOrderAlert[]>([]);\n public readyOrderAlerts$ = this.readyOrderAlertsSubject.asObservable();\n\n constructor(\n protected socketService: SocketService,\n private readonly toastr: ToastrService\n ) {\n this.setupSocketSubscriptions();\n\n this.socketService.reconnect$.subscribe(() => {\n this.setupSocketSubscriptions();\n });\n }\n\n private setupSocketSubscriptions(): void {\n // Error messages\n this.socketService.on<{ message: string }>(SocketSuccessEventKeys.ERROR_MESSAGE_SUCCESS)\n .subscribe((data) => this.showError(data.message));\n\n // Success messages\n this.socketService.on<{ message: string }>(SocketSuccessEventKeys.SUCCESS_MESSAGE_SUCCESS)\n .subscribe((data) => this.showSuccess(data.message));\n\n // Warning messages\n this.socketService.on<{ message: string }>(SocketSuccessEventKeys.WARNING_MESSAGE_SUCCESS)\n .subscribe((data) => this.showWarning(data.message));\n\n // Cart update notifications - check for PREPARED status\n this.socketService.on<CartEventData>(SocketSuccessEventKeys.CUSTOMER_CREATE_OR_UPDATE_CART_SUCCESS)\n .subscribe((cart) => {\n console.log('[NotificationStore] Cart updated:', cart);\n\n // Check if any customer cart has PREPARED status\n const preparedCarts = cart.customerCarts?.filter(cc => cc.status === 'PREPARED') || [];\n\n if (preparedCarts.length > 0) {\n // This is a ready order - show special notification with vibration\n const customerName = preparedCarts[0]?.customer?.name || 'Customer';\n this.handleReadyOrder(cart, customerName);\n }\n // No toast for regular cart updates\n });\n\n // Cart removal notifications - just log, no toast\n this.socketService.on<string>(SocketSuccessEventKeys.CUSTOMER_REMOVE_FROM_CART_SUCCESS)\n .subscribe((cartId) => {\n console.log('[NotificationStore] Cart removed:', cartId);\n });\n }\n\n /**\n * Handle ready order notification with vibration and dismissable alert\n */\n private handleReadyOrder(cart: CartEventData, customerName: string): void {\n console.log('[NotificationStore] Ready order detected!', cart);\n\n // Vibrate device if supported\n this.vibrateDevice();\n\n // Add to ready order alerts\n const alert: ReadyOrderAlert = {\n id: `${cart.id}-${Date.now()}`,\n cartId: cart.id,\n tableId: cart.tableId,\n customerName,\n timestamp: new Date()\n };\n\n const currentAlerts = this.readyOrderAlertsSubject.value;\n this.readyOrderAlertsSubject.next([alert, ...currentAlerts]);\n\n // Also show toast with longer duration\n this.toastr.success(\n `Order ready for ${customerName}`,\n '🍽️ Order Ready!',\n {\n ...this.defaultOptions,\n timeOut: 0, // No auto-dismiss\n extendedTimeOut: 0,\n tapToDismiss: true\n }\n );\n }\n\n /**\n * Vibrate the device if supported\n */\n private vibrateDevice(): void {\n try {\n if ('vibrate' in navigator) {\n // Vibrate pattern: 200ms on, 100ms off, 200ms on\n navigator.vibrate([200, 100, 200, 100, 200]);\n }\n } catch (e) {\n console.warn('[NotificationStore] Vibration not supported', e);\n }\n }\n\n /**\n * Dismiss a ready order alert\n */\n public dismissReadyOrderAlert(alertId: string): void {\n const currentAlerts = this.readyOrderAlertsSubject.value;\n this.readyOrderAlertsSubject.next(currentAlerts.filter(a => a.id !== alertId));\n }\n\n /**\n * Dismiss all ready order alerts\n */\n public dismissAllReadyOrderAlerts(): void {\n this.readyOrderAlertsSubject.next([]);\n }\n\n // Manual notification methods\n public showError(message: string, title: string = 'Error', timeOut: number = 5000): void {\n this.toastr.error(message, title, {\n ...this.defaultOptions,\n timeOut\n });\n }\n\n public showSuccess(message: string, title: string = 'Success', timeOut: number = 3000): void {\n this.toastr.success(message, title, {\n ...this.defaultOptions,\n timeOut\n });\n }\n\n public showWarning(message: string, title: string = 'Warning', timeOut: number = 4000): void {\n this.toastr.warning(message, title, {\n ...this.defaultOptions,\n timeOut\n });\n }\n\n public showInfo(message: string, title: string = 'Info', timeOut: number = 3000): void {\n this.toastr.info(message, title, {\n ...this.defaultOptions,\n timeOut\n });\n }\n\n // Clear all toasts\n public clearAll(): void {\n this.toastr.clear();\n }\n\n // Remove a specific toast by id\n public remove(toastId: number): void {\n this.toastr.remove(toastId);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\nexport interface DeliveryLocation {\n driverId: string;\n lat: number;\n lng: number;\n orderId: string;\n timestamp?: number;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class DeliveryOrderStore<T extends Entity> extends BaseStore<T> {\n private driverLocationSubject = new BehaviorSubject<DeliveryLocation | null>(null);\n public driverLocation$ = this.driverLocationSubject.asObservable();\n\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.NEW_DELIVERY_ORDER,\n (order) => this.updateItem(order)\n );\n\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.ORDER_STATUS_UPDATED,\n (order) => this.updateItem(order)\n );\n\n this.subscribeToEvent<DeliveryLocation>(\n SocketSuccessEventKeys.DRIVER_LOCATION_UPDATED,\n (location) => this.driverLocationSubject.next(location)\n );\n }\n}\n","import { Injectable } from '@angular/core';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class ReservationStore<T extends Entity> extends BaseStore<T> {\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.RESERVATION_CREATE_OR_UPDATE_SUCCESS,\n (reservation) => this.updateItem(reservation)\n );\n\n this.subscribeToEvent<string>(\n SocketSuccessEventKeys.RESERVATION_REMOVE_SUCCESS,\n (reservationId) => this.removeItem(reservationId)\n );\n }\n\n public abstract override preload(): Promise<T[]>;\n}\n","import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\nimport { BaseStore, Entity } from '../base-store';\nimport { SocketService, SocketSuccessEventKeys } from '../socket.service';\n\nexport interface InventoryLowStockAlert {\n stockItemId: string;\n name: string;\n currentStock: number;\n threshold: number;\n branchId: string;\n}\n\nexport interface InventoryPurchaseOrderUpdate {\n purchaseOrderId: string;\n status: string;\n branchId: string;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport abstract class InventoryStore<T extends Entity> extends BaseStore<T> {\n private readonly lowStockAlertSubject = new BehaviorSubject<InventoryLowStockAlert | null>(null);\n public lowStockAlert$ = this.lowStockAlertSubject.asObservable();\n\n private readonly purchaseOrderUpdateSubject = new BehaviorSubject<InventoryPurchaseOrderUpdate | null>(null);\n public purchaseOrderUpdate$ = this.purchaseOrderUpdateSubject.asObservable();\n\n constructor(\n protected override socketService: SocketService\n ) {\n super(socketService);\n }\n\n protected override setupSocketSubscriptions(): void {\n this.subscribeToEvent<T>(\n SocketSuccessEventKeys.INVENTORY_STOCK_UPDATED,\n (item) => this.updateItem(item)\n );\n\n this.subscribeToEvent<InventoryLowStockAlert>(\n SocketSuccessEventKeys.INVENTORY_LOW_STOCK_ALERT,\n (alert) => this.lowStockAlertSubject.next(alert)\n );\n\n this.subscribeToEvent<InventoryPurchaseOrderUpdate>(\n SocketSuccessEventKeys.INVENTORY_PURCHASE_ORDER_UPDATED,\n (update) => this.purchaseOrderUpdateSubject.next(update)\n );\n }\n\n public abstract override preload(): Promise<T[]>;\n}\n","import { EnvironmentProviders, importProvidersFrom } from '@angular/core';\nimport { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';\n\n/**\n * Provides all services needed for the realtime store to function.\n * Use this function in your standalone application's bootstrapApplication providers array.\n * \n * @example\n * ```typescript\n * bootstrapApplication(AppComponent, {\n * providers: [\n * provideRealtimeStore()\n * ]\n * });\n * ```\n */\nexport function provideRealtimeStore(): EnvironmentProviders[] {\n return [\n provideHttpClient(withInterceptorsFromDi())\n ];\n}\n","import { Provider } from '@angular/core';\nimport { REALTIME_STORE_ENVIRONMENT, RealtimeStoreEnvironment } from '../environment';\n\nexport function provideRealtimeStoreEnvironment(environment: RealtimeStoreEnvironment): Provider {\n return {\n provide: REALTIME_STORE_ENVIRONMENT,\n useValue: environment\n };\n}","import { Injectable } from '@angular/core';\nimport { SocketService } from './socket.service';\n\n/**\n * Handles the MQTT connection lifecycle for the driver app.\n *\n * Pattern:\n * - Use setAuthToken() + connect() instead of resetWithNewToken() so an in-progress\n * connection is never torn down by a duplicate call (e.g. on page refresh).\n * - reconnect$ emits when the MQTT client re-establishes after a drop; use it to\n * re-emit DRIVER_CONNECT so the server re-joins the driver to their rooms.\n * - A 'online' event listener handles recovery when the network comes back.\n *\n * Usage:\n * - AppComponent.ngOnInit: call connectFromStorage() ONCE to restore session.\n * - LoginPage success handler: call connect(token) after receiving a new token.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class DriverSocketConnectionService {\n private readonly TOKEN_KEY = 'driver_token';\n private networkListener?: () => void;\n\n constructor(private readonly socketService: SocketService) {\n this.networkListener = () => this.connectFromStorage();\n window.addEventListener('online', this.networkListener);\n }\n\n /** Connect using a freshly obtained token (e.g. after login). */\n connect(token: string): void {\n localStorage.setItem(this.TOKEN_KEY, token);\n this.socketService.setAuthToken(token);\n this.socketService.connect();\n }\n\n /** Restore the socket connection from a persisted token (e.g. on app start). */\n connectFromStorage(): void {\n const token = localStorage.getItem(this.TOKEN_KEY);\n if (token) {\n this.socketService.setAuthToken(token);\n this.socketService.connect();\n }\n }\n\n disconnect(): void {\n this.socketService.disconnect();\n if (this.networkListener) {\n window.removeEventListener('online', this.networkListener);\n this.networkListener = undefined;\n }\n }\n}\n","import { Injectable } from '@angular/core';\nimport { SocketService } from './socket.service';\n\n/**\n * Handles the MQTT connection lifecycle for the customer-food (online customer) app.\n *\n * Pattern:\n * - Use setAuthToken() + connect() instead of resetWithNewToken() so an in-progress\n * connection is never torn down by a duplicate call (e.g. on page refresh).\n * - reconnect$ emits when the MQTT client re-establishes after a drop; use it to\n * re-emit CUSTOMER_CONNECT so the server re-joins the client to their rooms.\n * - A 'online' event listener handles recovery when the network comes back.\n *\n * Usage:\n * - AppComponent.ngOnInit: call connectFromStorage() ONCE to restore session.\n * - LoginPage success handler: call connect(token) after receiving a new token.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class OnlineCustomerSocketConnectionService {\n private readonly TOKEN_KEY = 'online_customer_token';\n private networkListener?: () => void;\n\n constructor(private readonly socketService: SocketService) {\n this.networkListener = () => this.connectFromStorage();\n window.addEventListener('online', this.networkListener);\n }\n\n /** Connect using a freshly obtained token (e.g. after login). */\n connect(token: string): void {\n this.socketService.setAuthToken(token);\n this.socketService.connect();\n }\n\n /** Restore the socket connection from a persisted token (e.g. on app start). */\n connectFromStorage(): void {\n const token = localStorage.getItem(this.TOKEN_KEY);\n if (token) {\n this.connect(token);\n }\n }\n\n disconnect(): void {\n this.socketService.disconnect();\n if (this.networkListener) {\n window.removeEventListener('online', this.networkListener);\n this.networkListener = undefined;\n }\n }\n}\n","/*\n * Public API Surface of realtime-store\n */\n\nexport * from './lib/realtime-store.module';\nexport * from './lib/socket.service';\nexport * from './lib/base-store';\nexport * from './lib/stores/table.store';\nexport * from './lib/stores/cart.store';\nexport * from './lib/stores/call-waiter.store';\nexport * from './lib/stores/notification.store';\nexport * from './lib/stores/delivery-order.store';\nexport * from './lib/stores/reservation.store';\nexport * from './lib/stores/inventory.store';\nexport * from './lib/providers';\nexport * from './lib/environment';\nexport * from './lib/providers/realtime-store-environment.provider';\nexport * from './lib/driver-socket-connection.service';\nexport * from './lib/online-customer-socket-connection.service';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.SocketService"],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ declare class RealtimeStoreModule {
|
|
|
17
17
|
|
|
18
18
|
interface RealtimeStoreEnvironment {
|
|
19
19
|
apiUrl: string;
|
|
20
|
+
/**
|
|
21
|
+
* WebSocket URL for the MQTT broker (e.g. ws://localhost:9001 or wss://broker.example.com:8883).
|
|
22
|
+
* If omitted, derived from apiUrl by replacing http → ws / https → wss.
|
|
23
|
+
*/
|
|
24
|
+
mqttUrl?: string;
|
|
20
25
|
}
|
|
21
26
|
declare const defaultRealtimeStoreEnvironment: RealtimeStoreEnvironment;
|
|
22
27
|
|
|
@@ -52,13 +57,25 @@ declare enum SocketSuccessEventKeys {
|
|
|
52
57
|
BILLING_CREDIT_NOTE_ISSUED = "BILLING_CREDIT_NOTE_ISSUED",
|
|
53
58
|
BILLING_REFUND_PROCESSED = "BILLING_REFUND_PROCESSED"
|
|
54
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Topic convention (mirrors server messenger.gateway.ts):
|
|
62
|
+
* Server → user: serve-plus/user/{userId}/{event}
|
|
63
|
+
* Server → room: serve-plus/room/{roomId}/{event}
|
|
64
|
+
* Client → server: serve-plus/client/{userId}/{action} (payload = raw JWT string)
|
|
65
|
+
*
|
|
66
|
+
* System events handled internally (not forwarded to event subjects):
|
|
67
|
+
* JOIN_ROOM { roomId: string } — subscribe to serve-plus/room/{roomId}/#
|
|
68
|
+
* LEAVE_ROOM { roomId: string } — unsubscribe from serve-plus/room/{roomId}/#
|
|
69
|
+
* FORCE_DISCONNECT {} — disconnect
|
|
70
|
+
*/
|
|
55
71
|
declare class SocketService {
|
|
56
72
|
private readonly environment;
|
|
57
|
-
private
|
|
58
|
-
private readonly url;
|
|
73
|
+
private mqttClient?;
|
|
59
74
|
private authToken?;
|
|
60
75
|
private connectionKey?;
|
|
76
|
+
private userId?;
|
|
61
77
|
private readonly eventSubjects;
|
|
78
|
+
private readonly subscribedRooms;
|
|
62
79
|
private readonly connectionStatusSubject;
|
|
63
80
|
connectionStatus$: Observable<boolean>;
|
|
64
81
|
private readonly reconnectSubject;
|
|
@@ -66,42 +83,41 @@ declare class SocketService {
|
|
|
66
83
|
private hasConnectedOnce;
|
|
67
84
|
private readonly healthySubject;
|
|
68
85
|
healthy$: Observable<boolean>;
|
|
69
|
-
private
|
|
70
|
-
private lastPongTime;
|
|
86
|
+
private readonly TOPIC_PREFIX;
|
|
71
87
|
constructor(environment?: RealtimeStoreEnvironment);
|
|
72
|
-
private
|
|
88
|
+
private decodeUserId;
|
|
89
|
+
private resolveBrokerUrl;
|
|
90
|
+
private setupConnection;
|
|
91
|
+
private subscribeToRoom;
|
|
92
|
+
private unsubscribeFromRoom;
|
|
73
93
|
/**
|
|
74
|
-
*
|
|
75
|
-
|
|
76
|
-
private startHealthCheck;
|
|
77
|
-
private stopHealthCheck;
|
|
78
|
-
private reestablishListeners;
|
|
79
|
-
/**
|
|
80
|
-
* Set authentication token for socket connection
|
|
94
|
+
* Set authentication token for MQTT connection.
|
|
95
|
+
* Call connect() afterwards to open the connection.
|
|
81
96
|
*/
|
|
82
97
|
setAuthToken(token: string): void;
|
|
83
98
|
/**
|
|
84
|
-
* Set connection key
|
|
99
|
+
* Set connection key included in outbound message headers.
|
|
85
100
|
*/
|
|
86
101
|
setConnectionKey(key: string): void;
|
|
87
102
|
/**
|
|
88
|
-
* Reset connection with new token
|
|
103
|
+
* Reset connection with new token.
|
|
104
|
+
* Idempotent: no-op if the same token is already active and connected.
|
|
89
105
|
*/
|
|
90
106
|
resetWithNewToken(token?: string): void;
|
|
91
107
|
connect(timeoutMs?: number): Promise<void>;
|
|
92
108
|
disconnect(): void;
|
|
93
109
|
/**
|
|
94
|
-
* Emit event
|
|
110
|
+
* Emit an event to the server (client → server).
|
|
111
|
+
* Publishes to serve-plus/client/{userId}/{event}.
|
|
95
112
|
*/
|
|
96
|
-
emit(event: string, data?:
|
|
113
|
+
emit(event: string, data?: unknown): void;
|
|
97
114
|
/**
|
|
98
|
-
* Listen to events
|
|
115
|
+
* Listen to server-sent events. Returns a persistent Observable that
|
|
116
|
+
* survives reconnections (matching the previous socket.io behaviour).
|
|
99
117
|
*/
|
|
100
118
|
on<T>(event: string): Observable<T>;
|
|
101
119
|
/**
|
|
102
|
-
* Listen
|
|
103
|
-
* @param event - Event name to listen for
|
|
104
|
-
* @param timeoutMs - Timeout in ms (default 30s, 0 = no timeout)
|
|
120
|
+
* Listen for a single event occurrence and return as a Promise.
|
|
105
121
|
*/
|
|
106
122
|
once<T>(event: string, timeoutMs?: number): Promise<T>;
|
|
107
123
|
static ɵfac: i0.ɵɵFactoryDeclaration<SocketService, never>;
|
|
@@ -300,47 +316,57 @@ declare function provideRealtimeStore(): EnvironmentProviders[];
|
|
|
300
316
|
declare function provideRealtimeStoreEnvironment(environment: RealtimeStoreEnvironment): Provider;
|
|
301
317
|
|
|
302
318
|
/**
|
|
303
|
-
* Handles the
|
|
304
|
-
*
|
|
319
|
+
* Handles the MQTT connection lifecycle for the driver app.
|
|
320
|
+
*
|
|
321
|
+
* Pattern:
|
|
322
|
+
* - Use setAuthToken() + connect() instead of resetWithNewToken() so an in-progress
|
|
323
|
+
* connection is never torn down by a duplicate call (e.g. on page refresh).
|
|
324
|
+
* - reconnect$ emits when the MQTT client re-establishes after a drop; use it to
|
|
325
|
+
* re-emit DRIVER_CONNECT so the server re-joins the driver to their rooms.
|
|
326
|
+
* - A 'online' event listener handles recovery when the network comes back.
|
|
305
327
|
*
|
|
306
328
|
* Usage:
|
|
307
|
-
* -
|
|
308
|
-
* -
|
|
329
|
+
* - AppComponent.ngOnInit: call connectFromStorage() ONCE to restore session.
|
|
330
|
+
* - LoginPage success handler: call connect(token) after receiving a new token.
|
|
309
331
|
*/
|
|
310
332
|
declare class DriverSocketConnectionService {
|
|
311
333
|
private readonly socketService;
|
|
312
334
|
private readonly TOKEN_KEY;
|
|
313
|
-
private
|
|
335
|
+
private networkListener?;
|
|
314
336
|
constructor(socketService: SocketService);
|
|
315
337
|
/** Connect using a freshly obtained token (e.g. after login). */
|
|
316
338
|
connect(token: string): void;
|
|
317
339
|
/** Restore the socket connection from a persisted token (e.g. on app start). */
|
|
318
340
|
connectFromStorage(): void;
|
|
319
341
|
disconnect(): void;
|
|
320
|
-
private subscribeToReconnect;
|
|
321
342
|
static ɵfac: i0.ɵɵFactoryDeclaration<DriverSocketConnectionService, never>;
|
|
322
343
|
static ɵprov: i0.ɵɵInjectableDeclaration<DriverSocketConnectionService>;
|
|
323
344
|
}
|
|
324
345
|
|
|
325
346
|
/**
|
|
326
|
-
* Handles the
|
|
327
|
-
*
|
|
347
|
+
* Handles the MQTT connection lifecycle for the customer-food (online customer) app.
|
|
348
|
+
*
|
|
349
|
+
* Pattern:
|
|
350
|
+
* - Use setAuthToken() + connect() instead of resetWithNewToken() so an in-progress
|
|
351
|
+
* connection is never torn down by a duplicate call (e.g. on page refresh).
|
|
352
|
+
* - reconnect$ emits when the MQTT client re-establishes after a drop; use it to
|
|
353
|
+
* re-emit CUSTOMER_CONNECT so the server re-joins the client to their rooms.
|
|
354
|
+
* - A 'online' event listener handles recovery when the network comes back.
|
|
328
355
|
*
|
|
329
356
|
* Usage:
|
|
330
|
-
* -
|
|
331
|
-
* -
|
|
357
|
+
* - AppComponent.ngOnInit: call connectFromStorage() ONCE to restore session.
|
|
358
|
+
* - LoginPage success handler: call connect(token) after receiving a new token.
|
|
332
359
|
*/
|
|
333
360
|
declare class OnlineCustomerSocketConnectionService {
|
|
334
361
|
private readonly socketService;
|
|
335
362
|
private readonly TOKEN_KEY;
|
|
336
|
-
private
|
|
363
|
+
private networkListener?;
|
|
337
364
|
constructor(socketService: SocketService);
|
|
338
365
|
/** Connect using a freshly obtained token (e.g. after login). */
|
|
339
366
|
connect(token: string): void;
|
|
340
367
|
/** Restore the socket connection from a persisted token (e.g. on app start). */
|
|
341
368
|
connectFromStorage(): void;
|
|
342
369
|
disconnect(): void;
|
|
343
|
-
private subscribeToReconnect;
|
|
344
370
|
static ɵfac: i0.ɵɵFactoryDeclaration<OnlineCustomerSocketConnectionService, never>;
|
|
345
371
|
static ɵprov: i0.ɵɵInjectableDeclaration<OnlineCustomerSocketConnectionService>;
|
|
346
372
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serve-socket",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Real-time WebSocket service for restaurant waiter coordination",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Serve+ Team",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
],
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@angular/common": ">=15.0.0",
|
|
21
|
-
"@angular/core": ">=15.0.0"
|
|
21
|
+
"@angular/core": ">=15.0.0",
|
|
22
|
+
"mqtt": ">=5.0.0"
|
|
22
23
|
},
|
|
23
24
|
"dependencies": {
|
|
24
25
|
"tslib": "^2.3.0"
|