dolphin-server-modules 1.6.0 → 1.6.1

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.
@@ -850,7 +850,102 @@ await signaling.invite('user1', 'user2', { sdp: 'offer_data' });
850
850
  // 2. IoT / Medical Command
851
851
  await signaling.sendCommand('DoctorApp', 'Machine_01', { action: 'START' });
852
852
 
853
- निष्कर्ष (Conclusion)
853
+ १८. Folder Structure र Architecture बेस्ट प्राक्टिस (Zero to Scale)
854
+ एउटा ठूलो सङ्गठन वा IoT एप्लिकेसन डिजाइन गर्दा प्रोजेक्टलाई एउटै फाइलमा नराखी व्यवस्थित तरिकाले यसरी मिलाउनुपर्छ:
855
+
856
+ ```text
857
+ my-dolphin-app/
858
+ ├── src/
859
+ │ ├── config/ # Database, Redis जस्ता कन्फिगरेसन
860
+ │ ├── models/ # Mongoose/DB स्किमाहरू (Product.ts, SensorData.ts)
861
+ │ ├── controllers/ # लजिक र CRUD ह्यान्डलर (UserCtrl.ts, IoT_Ctrl.ts)
862
+ │ ├── middlewares/ # ZodValidation, AuthGuard, ErrorHandler
863
+ │ ├── routes/ # apiRouter (Independent Routing)
864
+ │ ├── realtime/ # IoT र WebSocket का इभेन्ट-ह्यान्डलर (pub/sub)
865
+ │ ├── app.ts # Dolphin Server र WebSockets (wss) को सेटअप
866
+ │ └── index.ts # सर्भर सुरु गर्ने (app.listen)
867
+ ├── package.json
868
+ └── tsconfig.json
869
+ ```
870
+ यो तरिका अपनाउँदा तपाइँको REST API र IoT को RealtimeCore कहिल्यै पनि नराम्रोसँग जेलिँदैन (Tight Coupling हुँदैन)।
871
+
872
+ १९. Global Error Handling (सर्भर क्र्यास हुनबाट बचाउने)
873
+ Dolphin मा तपाईंले लेखेको कुनै कस्टम लजिकले Error फाले पनि सर्भर क्र्यास हुनुहुँदैन। यसको लागि ग्लोबल मिडलवेयर (Global Middleware) प्रयोग गर्नुपर्छ:
874
+
875
+ ```typescript
876
+ app.use(async (ctx, next) => {
877
+ try {
878
+ if (next) await next();
879
+ } catch (error) {
880
+ console.error("🔥 SYSTEM ERROR:", error.message);
881
+ // क्लाईन्टलाई नराम्रो HTML को सट्टा राम्रो JSON पठाउने
882
+ ctx.status(500).json({
883
+ success: false,
884
+ message: "Internal Server Error",
885
+ error: process.env.NODE_ENV !== 'production' ? error.stack : undefined
886
+ });
887
+ }
888
+ });
889
+ ```
890
+
891
+ २०. Frontend सँग जोड्ने (React & IoT WebSockets)
892
+ फ्रन्टइन्ड (Frontend) बाट Dolphin API लाई कल गर्न तपाईंले सुरुमा CORS अन गर्नुपर्छ।
893
+
894
+ CORS Setup:
895
+ ```typescript
896
+ import cors from 'cors';
897
+ app.use(cors({ origin: 'http://localhost:3000', credentials: true }));
898
+ ```
899
+
900
+ React बाट IoT WebSocket जोड्ने:
901
+ ```javascript
902
+ import { useEffect, useState } from 'react';
903
+
904
+ function Dashboard() {
905
+ const [temp, setTemp] = useState(0);
906
+
907
+ useEffect(() => {
908
+ // 1. Dolphin को WebSocket मा कनेक्ट गर्ने
909
+ const ws = new WebSocket('ws://localhost:8080?id=React_Dashboard&type=monitor');
910
+
911
+ ws.onmessage = (event) => {
912
+ const parsed = JSON.parse(event.data);
913
+ if(parsed.topic === 'sensors/temperature') {
914
+ setTemp(parsed.payload.value);
915
+ }
916
+ };
917
+
918
+ // 2. Dolphin लाई कुन टपिक सुन्ने भनेर Subscribe मेसेज पठाउने
919
+ ws.onopen = () => {
920
+ ws.send(JSON.stringify({ action: 'subscribe', topic: 'sensors/temperature' }));
921
+ };
922
+
923
+ return () => ws.close();
924
+ }, []);
925
+
926
+ return <div><h1>लाइभ तापक्रम: {temp} °C 🌡️</h1></div>;
927
+ }
928
+ ```
929
+
930
+ २१. Production Deployment (सर्भर लाइभ गर्ने)
931
+ तपाईँको Dolphin सर्भर रकेट जस्तै तयार छ। अब यसलाई लाइभ (World Wide Web) मा राख्न PM2 प्रयोग गरिन्छ जसले क्र्यास भएको खण्डमा तुरुन्त (0.1ms) सर्भरलाई अटो-रिस्टार्ट (Auto-Restart) गर्छ।
932
+
933
+ PM2 इन्स्टल र सुरु गर्न:
934
+ ```bash
935
+ # 1. PM2 लाई Global रूपमा राख्ने
936
+ npm install -g pm2
937
+
938
+ # 2. तपाईंको Code लाई Build गर्ने
939
+ npm run build
940
+
941
+ # 3. PM2 द्वारा Background मा सर्भर सुरु गर्ने
942
+ pm2 start dist/index.js --name "dolphin-iot-backend"
943
+
944
+ # 4. सर्भरका Logs (Error/Info) हेर्न
945
+ pm2 logs dolphin-iot-backend
946
+ ```
947
+
948
+ २२. निष्कर्ष (Conclusion)
854
949
  बधाई छ! तपाईँले Dolphin Framework v2.0 को Master Guide पूरा गर्नुभयो। अब तपाईँ:
855
950
 
856
951
  ✅ हाई-पर्फर्मेन्स API सर्भर बनाउन
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './realtime/codec';
2
2
  export * from './realtime/index';
3
3
  export * from './swagger/swagger';
4
+ export * from './signaling/index';
package/dist/index.js CHANGED
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./realtime/codec"), exports);
18
18
  __exportStar(require("./realtime/index"), exports);
19
19
  __exportStar(require("./swagger/swagger"), exports);
20
+ __exportStar(require("./signaling/index"), exports);
20
21
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AACA,mDAAiC;AACjC,mDAAiC;AACjC,oDAAkC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AACA,mDAAiC;AACjC,mDAAiC;AACjC,oDAAkC;AAClC,oDAAkC"}
@@ -0,0 +1,47 @@
1
+ import { RealtimeCore } from '../realtime/core';
2
+ export declare enum SignalType {
3
+ INVITE = "INVITE",
4
+ ACCEPT = "ACCEPT",
5
+ REJECT = "REJECT",
6
+ END = "END",
7
+ ICE_CANDIDATE = "ICE_CANDIDATE",
8
+ COMMAND = "COMMAND",
9
+ COMMAND_ACK = "COMMAND_ACK",
10
+ TELEMETRY = "TELEMETRY",
11
+ ACK = "ACK"
12
+ }
13
+ export interface SignalingPayload {
14
+ msgId: string;
15
+ from: string;
16
+ to: string;
17
+ type: SignalType | string;
18
+ data?: any;
19
+ timestamp: number;
20
+ }
21
+ export type SignalHandler = (payload: SignalingPayload) => void;
22
+ export declare class UniversalSignaling {
23
+ private rt;
24
+ private pendingAcks;
25
+ constructor(rt: RealtimeCore);
26
+ /**
27
+ * Internal mechanism to send a signal directly to the device.
28
+ */
29
+ private sendRaw;
30
+ /**
31
+ * Used to acknowledge a signal natively
32
+ */
33
+ handleAck(msgId: string): void;
34
+ ack(from: string, to: string, msgIdToAck: string): void;
35
+ invite(from: string, to: string, data?: any): Promise<boolean>;
36
+ accept(from: string, to: string, sdp?: any): Promise<boolean>;
37
+ reject(from: string, to: string, reason?: string): Promise<boolean>;
38
+ end(from: string, to: string, reason?: string): Promise<boolean>;
39
+ iceCandidate(from: string, to: string, candidate: any): Promise<boolean>;
40
+ sendCommand(from: string, to: string, commandData: any, requireAck?: boolean): Promise<boolean>;
41
+ sendTelemetry(from: string, to: string | 'all', telemetryData: any): Promise<void>;
42
+ /**
43
+ * Listen to any incoming signals for a particular topic or private channel
44
+ */
45
+ onSignalFor(deviceId: string, handler: SignalHandler): void;
46
+ }
47
+ export declare function createSignaling(rt: RealtimeCore): UniversalSignaling;
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UniversalSignaling = exports.SignalType = void 0;
4
+ exports.createSignaling = createSignaling;
5
+ var SignalType;
6
+ (function (SignalType) {
7
+ // Connection / WebRTC
8
+ SignalType["INVITE"] = "INVITE";
9
+ SignalType["ACCEPT"] = "ACCEPT";
10
+ SignalType["REJECT"] = "REJECT";
11
+ SignalType["END"] = "END";
12
+ SignalType["ICE_CANDIDATE"] = "ICE_CANDIDATE";
13
+ // Custom Data / Control
14
+ SignalType["COMMAND"] = "COMMAND";
15
+ SignalType["COMMAND_ACK"] = "COMMAND_ACK";
16
+ SignalType["TELEMETRY"] = "TELEMETRY";
17
+ // General Acknowledgements
18
+ SignalType["ACK"] = "ACK";
19
+ })(SignalType || (exports.SignalType = SignalType = {}));
20
+ class UniversalSignaling {
21
+ rt;
22
+ pendingAcks = new Map();
23
+ constructor(rt) {
24
+ this.rt = rt;
25
+ }
26
+ /**
27
+ * Internal mechanism to send a signal directly to the device.
28
+ */
29
+ async sendRaw(to, type, data, from, requireAck = false, timeoutMs = 3000) {
30
+ const msgId = `sig_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
31
+ const payload = {
32
+ msgId,
33
+ from,
34
+ to,
35
+ type,
36
+ data,
37
+ timestamp: Date.now()
38
+ };
39
+ if (requireAck) {
40
+ return new Promise((resolve) => {
41
+ const timer = setTimeout(() => {
42
+ this.pendingAcks.delete(msgId);
43
+ resolve(false);
44
+ }, timeoutMs);
45
+ this.pendingAcks.set(msgId, { resolve, timer });
46
+ // Use RealtimeCore's privatePub channel
47
+ this.rt.privatePub(to, payload);
48
+ });
49
+ }
50
+ else {
51
+ this.rt.privatePub(to, payload);
52
+ return true;
53
+ }
54
+ }
55
+ /**
56
+ * Used to acknowledge a signal natively
57
+ */
58
+ handleAck(msgId) {
59
+ const pending = this.pendingAcks.get(msgId);
60
+ if (pending) {
61
+ clearTimeout(pending.timer);
62
+ pending.resolve(true);
63
+ this.pendingAcks.delete(msgId);
64
+ }
65
+ }
66
+ ack(from, to, msgIdToAck) {
67
+ this.rt.privatePub(to, {
68
+ msgId: `sig_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
69
+ type: SignalType.ACK,
70
+ from,
71
+ to,
72
+ data: { ackId: msgIdToAck },
73
+ timestamp: Date.now()
74
+ });
75
+ }
76
+ // --- WebRTC / Session Methods ---
77
+ async invite(from, to, data) {
78
+ return this.sendRaw(to, SignalType.INVITE, data, from, true);
79
+ }
80
+ async accept(from, to, sdp) {
81
+ return this.sendRaw(to, SignalType.ACCEPT, sdp, from);
82
+ }
83
+ async reject(from, to, reason) {
84
+ return this.sendRaw(to, SignalType.REJECT, { reason }, from);
85
+ }
86
+ async end(from, to, reason) {
87
+ return this.sendRaw(to, SignalType.END, { reason }, from);
88
+ }
89
+ async iceCandidate(from, to, candidate) {
90
+ return this.sendRaw(to, SignalType.ICE_CANDIDATE, candidate, from);
91
+ }
92
+ // --- Industrial / Medical Control Methods ---
93
+ async sendCommand(from, to, commandData, requireAck = true) {
94
+ return this.sendRaw(to, SignalType.COMMAND, commandData, from, requireAck);
95
+ }
96
+ async sendTelemetry(from, to, telemetryData) {
97
+ const payload = {
98
+ msgId: `tel_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
99
+ from,
100
+ to,
101
+ type: SignalType.TELEMETRY,
102
+ data: telemetryData,
103
+ timestamp: Date.now()
104
+ };
105
+ if (to === 'all') {
106
+ this.rt.publish(`telemetry/broadcast`, payload);
107
+ }
108
+ else {
109
+ this.rt.privatePub(to, payload);
110
+ }
111
+ }
112
+ /**
113
+ * Listen to any incoming signals for a particular topic or private channel
114
+ */
115
+ onSignalFor(deviceId, handler) {
116
+ this.rt.subscribe(`phone/signaling/${deviceId}`, (payload) => {
117
+ // Auto-handle native ACK processing
118
+ if (payload.type === SignalType.ACK && payload.data?.ackId) {
119
+ this.handleAck(payload.data.ackId);
120
+ }
121
+ handler(payload);
122
+ }, deviceId);
123
+ }
124
+ }
125
+ exports.UniversalSignaling = UniversalSignaling;
126
+ function createSignaling(rt) {
127
+ return new UniversalSignaling(rt);
128
+ }
129
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../signaling/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dolphin-server-modules",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "homepage": "https://github.com/Phuyalshankar/dolphin-server-modules#readme",
5
5
  "description": "Core utility modules for Auth, CRUD, and Controllers",
6
6
  "main": "dist/index.js",