dolphin-server-modules 1.6.0 → 1.7.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/DOLPHIN_MASTER_GUIDE_NEPALI.md +96 -1
- package/README.md +28 -2
- package/TUTORIAL_NEPALI.md +29 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/server/server.js +13 -0
- package/dist/server/server.js.map +1 -1
- package/dist/signaling/index.d.ts +52 -0
- package/dist/signaling/index.js +136 -0
- package/dist/signaling/index.js.map +1 -0
- package/package.json +3 -2
- package/scripts/client.js +226 -0
|
@@ -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
|
-
|
|
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/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 🐬 Dolphin Framework (v1.
|
|
1
|
+
# 🐬 Dolphin Framework (v1.7.0)
|
|
2
2
|
|
|
3
3
|
**Dolphin** is a 2026-ready, ultra-lightweight, and 100% modular backend ecosystem built on native Node.js. It's not just a framework; it's a universal toolkit for Web, Microservices, and Industrial IoT.
|
|
4
4
|
|
|
@@ -22,6 +22,7 @@ Dolphin Framework को विस्तृत र आधिकारिक ग
|
|
|
22
22
|
- **Auto-JSON Serialization**: Simply `return` an object from your handler!
|
|
23
23
|
- **Industrial IoT (IIoT)**: Native support for HL7, Modbus, and DICOM via binary plugins.
|
|
24
24
|
- **Unified Context (ctx)**: Modern developer experience with legacy middleware support.
|
|
25
|
+
- **Server-Served Client Library**: Zero-dependency frontend library for API, Auth, and Realtime—directly from your server.
|
|
25
26
|
|
|
26
27
|
---
|
|
27
28
|
|
|
@@ -47,7 +48,31 @@ app.get('/ping', (ctx) => {
|
|
|
47
48
|
app.listen(3000, () => console.log("🐬 Dolphin swimming on port 3000"));
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
### 2. Full
|
|
51
|
+
### 2. Full-stack Client Library (No NPM needed!)
|
|
52
|
+
Dolphin now serves its own client-side library. Just include a script tag and you get Auth, API, and Realtime out of the box.
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<!-- In your index.html -->
|
|
56
|
+
<script src="/dolphin-client.js"></script>
|
|
57
|
+
|
|
58
|
+
<script>
|
|
59
|
+
async function init() {
|
|
60
|
+
// 1. Auth & Token Management
|
|
61
|
+
await dolphin.auth.login("admin@test.com", "password123");
|
|
62
|
+
|
|
63
|
+
// 2. API + Auto-Auth Headers
|
|
64
|
+
const data = await dolphin.api.get('/products');
|
|
65
|
+
|
|
66
|
+
// 3. Realtime Mirroring & Pub/Sub
|
|
67
|
+
await dolphin.connect();
|
|
68
|
+
dolphin.onSignal(sig => {
|
|
69
|
+
if(sig.type === 'MIRROR') window.location.href = sig.data.url;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
</script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 3. Full CRUD API with Mongoose (v1.7.0)
|
|
51
76
|
|
|
52
77
|
> **Important:** Use `enforceOwnership: false` for public APIs (no auth required).
|
|
53
78
|
> Default is `true` — requires `userId` from auth middleware.
|
|
@@ -117,6 +142,7 @@ rt.subscribe('factory/machine/+', (data) => {
|
|
|
117
142
|
| **IoT Plugins** | `/realtime/plugins` | Native parsers for HL7, Modbus, and DICOM. |
|
|
118
143
|
| **Signaling** | `/signaling` | Universal WebRTC & Control Signaling module. |
|
|
119
144
|
| **Mongoose Adapter** | `/adapters/mongoose` | Full Mongoose ↔ CRUD bridge with query mapping. |
|
|
145
|
+
| **Client Lib** | `/dolphin-client.js` | Zero-dependency full-stack JS client. |
|
|
120
146
|
|
|
121
147
|
---
|
|
122
148
|
|
package/TUTORIAL_NEPALI.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Dolphin Framework: 0 to 100% Full Tutorial (Nepali) 🐬
|
|
1
|
+
# Dolphin Framework: 0 to 100% Full Tutorial (Nepali) 🐬 [v1.7.0]
|
|
2
2
|
|
|
3
3
|
Dolphin Framework मा तपाईँलाई स्वागत छ! यो गाइडमा हामी Dolphin प्रयोग गरेर एउटा शक्तिशाली, छिटो र आधुनिक API कसरी बनाउने भनेर सुरुदेखि अन्त्यसम्म सिक्नेछौँ।
|
|
4
4
|
|
|
@@ -229,7 +229,34 @@ await signaling.sendCommand('DoctorApp', 'Machine_01', { action: 'START' });
|
|
|
229
229
|
|
|
230
230
|
---
|
|
231
231
|
|
|
232
|
-
##
|
|
232
|
+
## १५. डल्फिन क्लाइन्ट लाइब्रेरी (Full-stack Client Library) [NEW]
|
|
233
|
+
|
|
234
|
+
डल्फिन सर्भरले अब आफैँ एउटा हलुका क्लाइन्ट लाइब्रेरी उपलब्ध गराउँछ। यसका लागि तपाईँले NPM इन्स्टल गर्नु पर्दैन।
|
|
235
|
+
|
|
236
|
+
### क. लाइब्रेरी लोड गर्ने
|
|
237
|
+
```html
|
|
238
|
+
<script src="/dolphin-client.js"></script>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### ख. प्रयोग गर्ने तरिका (API, Auth & Realtime)
|
|
242
|
+
```javascript
|
|
243
|
+
// १. अटो-इनिशियलाइज्ड 'dolphin' अब्जेक्ट प्रयोग गर्नुहोस्
|
|
244
|
+
async function setup() {
|
|
245
|
+
// २. लगइन गर्ने
|
|
246
|
+
await dolphin.auth.login("admin@test.com", "password");
|
|
247
|
+
|
|
248
|
+
// ३. डेटा फेच गर्ने (अटोमेटिक टोकन म्यानेजमेन्ट)
|
|
249
|
+
const products = await dolphin.api.get('/products');
|
|
250
|
+
|
|
251
|
+
// ४. रियल-टाइम पब-सब (Pub/Sub)
|
|
252
|
+
await dolphin.connect();
|
|
253
|
+
dolphin.subscribe("alerts", (data) => console.log("Alert:", data));
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## १६. अन्तिममा (Conclusion)
|
|
233
260
|
|
|
234
261
|
Dolphin Framework निकै छिटो र सजिलो छ। यसले तपाईँको ब्याकइन्ड डेभलपमेन्टको अनुभवलाई नयाँ उचाइमा पुर्याउँछ।
|
|
235
262
|
|
package/dist/index.d.ts
CHANGED
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"}
|
package/dist/server/server.js
CHANGED
|
@@ -5,10 +5,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createDolphinServer = createDolphinServer;
|
|
7
7
|
const node_http_1 = __importDefault(require("node:http"));
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
10
|
const ws_1 = require("ws");
|
|
9
11
|
const router_1 = require("../router/router");
|
|
10
12
|
function createDolphinServer(options = {}) {
|
|
11
13
|
const router = (0, router_1.createDolphinRouter)();
|
|
14
|
+
// Automatically serve the client library
|
|
15
|
+
router.get('/dolphin-client.js', (ctx) => {
|
|
16
|
+
const clientPath = node_path_1.default.join(process.cwd(), 'scripts', 'client.js');
|
|
17
|
+
if (node_fs_1.default.existsSync(clientPath)) {
|
|
18
|
+
const content = node_fs_1.default.readFileSync(clientPath, 'utf8');
|
|
19
|
+
ctx.setHeader('Content-Type', 'application/javascript');
|
|
20
|
+
ctx.res.end(content);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
return ctx.status(404).json({ error: 'Client library not found' });
|
|
24
|
+
});
|
|
12
25
|
const middlewares = [];
|
|
13
26
|
const wss = new ws_1.WebSocketServer({ noServer: true });
|
|
14
27
|
const server = node_http_1.default.createServer(async (req, res) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":";;;;;AAMA,kDAmOC;AAzOD,0DAA6B;AAC7B,sDAAyB;AACzB,0DAA6B;AAC7B,2BAAqC;AACrC,6CAAuD;AAEvD,SAAgB,mBAAmB,CAAC,UAA4D,EAAE;IAChG,MAAM,MAAM,GAAG,IAAA,4BAAmB,GAAE,CAAC;IAErC,yCAAyC;IACzC,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC,GAAG,EAAE,EAAE;QACvC,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QACpE,IAAI,iBAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,iBAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACpD,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,wBAAwB,CAAC,CAAC;YACxD,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAU,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,oBAAe,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,mBAAI,CAAC,YAAY,CAAC,KAAK,EAAE,GAAQ,EAAE,GAAQ,EAAE,EAAE;QAC5D,4BAA4B;QAC5B,IAAI,aAAa,GAAW,GAAG,CAAC;QAEhC,0BAA0B;QAC1B,MAAM,IAAI,GAAG,CAAC,IAAS,EAAE,WAAmB,EAAE,MAAe,EAAE,EAAE;YAC/D,IAAI,GAAG,CAAC,WAAW;gBAAE,OAAO;YAC5B,MAAM,WAAW,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC;YAClE,GAAG,CAAC,UAAU,GAAG,WAAW,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;YAE3C,IAAI,WAAW,KAAK,kBAAkB,EAAE,CAAC;gBACvC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YACxB,CAAC;YACD,aAAa,GAAG,GAAG,CAAC,CAAC,mBAAmB;QAC1C,CAAC,CAAC;QAEF,uBAAuB;QACvB,GAAG,CAAC,IAAI,GAAG,CAAC,IAAS,EAAE,MAAe,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC;QAClF,GAAG,CAAC,IAAI,GAAG,CAAC,IAAS,EAAE,MAAe,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QAC5E,GAAG,CAAC,IAAI,GAAG,CAAC,IAAS,EAAE,MAAe,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QAE3E,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;QAC7C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAI,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;QAEtD,MAAM,GAAG,GAAQ;YACf,GAAG;YACH,GAAG;YACH,MAAM,EAAE,EAAE;YACV,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,CAAC;YACjD,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,EAAE;YAET,IAAI,EAAE,CAAC,IAAS,EAAE,MAAe,EAAE,EAAE;gBACnC,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC;gBACvC,OAAO,GAAG,CAAC;YACb,CAAC;YAED,IAAI,EAAE,CAAC,IAAS,EAAE,MAAe,EAAE,EAAE;gBACnC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;gBACjC,OAAO,GAAG,CAAC;YACb,CAAC;YAED,IAAI,EAAE,CAAC,IAAS,EAAE,MAAe,EAAE,EAAE;gBACnC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;gBAChC,OAAO,GAAG,CAAC;YACb,CAAC;YAED,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;gBACvB,aAAa,GAAG,IAAI,CAAC;gBACrB,OAAO,GAAG,CAAC;YACb,CAAC;YAED,SAAS,EAAE,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE;gBACzC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC3B,OAAO,GAAG,CAAC;YACb,CAAC;YAED,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE;gBAC1B,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACzC,CAAC;SACF,CAAC;QAEF,8BAA8B;QAC9B,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,IAAI,GAAG,CAAC,aAAa;gBAAE,OAAO;YAC9B,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC1B,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACpB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACnB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,kCAAkC;QAClC,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QACtD,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAO,CAAC,EAAE,CAAC;YACnD,IAAI,WAAW,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,CAAC;gBAChD,oEAAoE;gBACpE,IAAK,GAAW,CAAC,IAAI;oBAAE,GAAG,CAAC,IAAI,GAAI,GAAW,CAAC,IAAI,CAAC;gBACpD,IAAK,GAAW,CAAC,IAAI;oBAAE,GAAG,CAAC,IAAI,GAAI,GAAW,CAAC,IAAI,CAAC;gBACpD,IAAK,GAAW,CAAC,KAAK;oBAAE,GAAG,CAAC,KAAK,GAAI,GAAW,CAAC,KAAK,CAAC;YACzD,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAU,EAAE,CAAC;gBACzB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG;oBAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAClD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAEjD,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;oBAC7C,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;wBACnC,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC;wBAClB,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC;oBACpB,CAAC;oBAAC,MAAM,CAAC;wBACP,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;wBACd,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;oBAChB,CAAC;gBACH,CAAC;qBAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,mCAAmC,CAAC,EAAE,CAAC;oBACrE,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;oBAChE,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC;oBAClB,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC;gBACpB,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC;oBACnB,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC1B,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC1B,IAAI,CAAC;gBACH,IAAI,MAAW,CAAC;gBAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;gBAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACzC,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,aAAa;wBAAE,MAAM;oBAEhD,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;oBAC5B,MAAM,IAAI,OAAO,CAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;wBAChD,IAAI,CAAC;4BACH,4CAA4C;4BAC5C,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gCACxB,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;4BACvC,CAAC;iCAAM,CAAC;gCACN,4BAA4B;gCAC5B,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;gCAC5B,OAAO,EAAE,CAAC;4BACZ,CAAC;wBACH,CAAC;wBAAC,OAAO,GAAG,EAAE,CAAC;4BACb,MAAM,CAAC,GAAG,CAAC,CAAC;wBACd,CAAC;oBACH,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,2DAA2D;gBAC3D,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;wBAC5C,+EAA+E;wBAC/E,MAAM,MAAM,GAAG,CAAC,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC;4BAC/F,CAAC,CAAC,MAAM,CAAC,MAAM;4BACf,CAAC,CAAC,aAAa,CAAC;wBAClB,IAAI,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC;oBAC3C,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAC;oBACtC,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;gBAC5C,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,IAAI,uBAAuB,EAAE,EAAE,kBAAkB,EAAE,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;gBACjG,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,qCAAqC;IACrC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QAC7C,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAI,EAAE,UAAU,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAE7E,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;YACtD,GAAG,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;gBAC9C,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;YACnC,+DAA+D;YAC/D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAI,EAAE,UAAU,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,WAAW,CAAC;YAE/F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAExC,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;gBACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;YAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5D,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,GAAG,MAAM;QACT,IAAI,EAAE,MAAM;QACZ,GAAG;QACH,GAAG,EAAE,CAAC,UAAwB,EAAE,EAAQ,EAAE,EAAE;YAC1C,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBAC3E,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QACD,MAAM,EAAE,CAAC,OAAe,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,QAAqB,EAAE,EAAE;YACrE,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,SAAS,EAAE,QAAQ,CAAC,CAAC;QAClE,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;KAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
MIRROR = "MIRROR",
|
|
12
|
+
ACK = "ACK"
|
|
13
|
+
}
|
|
14
|
+
export interface SignalingPayload {
|
|
15
|
+
msgId: string;
|
|
16
|
+
from: string;
|
|
17
|
+
to: string;
|
|
18
|
+
type: SignalType | string;
|
|
19
|
+
data?: any;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
}
|
|
22
|
+
export type SignalHandler = (payload: SignalingPayload) => void;
|
|
23
|
+
export declare class UniversalSignaling {
|
|
24
|
+
private rt;
|
|
25
|
+
private pendingAcks;
|
|
26
|
+
constructor(rt: RealtimeCore);
|
|
27
|
+
/**
|
|
28
|
+
* Internal mechanism to send a signal directly to the device.
|
|
29
|
+
*/
|
|
30
|
+
private sendRaw;
|
|
31
|
+
/**
|
|
32
|
+
* Used to acknowledge a signal natively
|
|
33
|
+
*/
|
|
34
|
+
handleAck(msgId: string): void;
|
|
35
|
+
ack(from: string, to: string, msgIdToAck: string): void;
|
|
36
|
+
invite(from: string, to: string, data?: any): Promise<boolean>;
|
|
37
|
+
accept(from: string, to: string, sdp?: any): Promise<boolean>;
|
|
38
|
+
reject(from: string, to: string, reason?: string): Promise<boolean>;
|
|
39
|
+
end(from: string, to: string, reason?: string): Promise<boolean>;
|
|
40
|
+
iceCandidate(from: string, to: string, candidate: any): Promise<boolean>;
|
|
41
|
+
sendCommand(from: string, to: string, commandData: any, requireAck?: boolean): Promise<boolean>;
|
|
42
|
+
sendTelemetry(from: string, to: string | 'all', telemetryData: any): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Mirror a URL to a specific device's pane
|
|
45
|
+
*/
|
|
46
|
+
mirror(from: string, to: string, url: string, options?: any): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Listen to any incoming signals for a particular topic or private channel
|
|
49
|
+
*/
|
|
50
|
+
onSignalFor(deviceId: string, handler: SignalHandler): void;
|
|
51
|
+
}
|
|
52
|
+
export declare function createSignaling(rt: RealtimeCore): UniversalSignaling;
|
|
@@ -0,0 +1,136 @@
|
|
|
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
|
+
SignalType["MIRROR"] = "MIRROR";
|
|
18
|
+
// General Acknowledgements
|
|
19
|
+
SignalType["ACK"] = "ACK";
|
|
20
|
+
})(SignalType || (exports.SignalType = SignalType = {}));
|
|
21
|
+
class UniversalSignaling {
|
|
22
|
+
rt;
|
|
23
|
+
pendingAcks = new Map();
|
|
24
|
+
constructor(rt) {
|
|
25
|
+
this.rt = rt;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Internal mechanism to send a signal directly to the device.
|
|
29
|
+
*/
|
|
30
|
+
async sendRaw(to, type, data, from, requireAck = false, timeoutMs = 3000) {
|
|
31
|
+
const msgId = `sig_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
32
|
+
const payload = {
|
|
33
|
+
msgId,
|
|
34
|
+
from,
|
|
35
|
+
to,
|
|
36
|
+
type,
|
|
37
|
+
data,
|
|
38
|
+
timestamp: Date.now()
|
|
39
|
+
};
|
|
40
|
+
if (requireAck) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
const timer = setTimeout(() => {
|
|
43
|
+
this.pendingAcks.delete(msgId);
|
|
44
|
+
resolve(false);
|
|
45
|
+
}, timeoutMs);
|
|
46
|
+
this.pendingAcks.set(msgId, { resolve, timer });
|
|
47
|
+
// Use RealtimeCore's privatePub channel
|
|
48
|
+
this.rt.privatePub(to, payload);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.rt.privatePub(to, payload);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Used to acknowledge a signal natively
|
|
58
|
+
*/
|
|
59
|
+
handleAck(msgId) {
|
|
60
|
+
const pending = this.pendingAcks.get(msgId);
|
|
61
|
+
if (pending) {
|
|
62
|
+
clearTimeout(pending.timer);
|
|
63
|
+
pending.resolve(true);
|
|
64
|
+
this.pendingAcks.delete(msgId);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
ack(from, to, msgIdToAck) {
|
|
68
|
+
this.rt.privatePub(to, {
|
|
69
|
+
msgId: `sig_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
70
|
+
type: SignalType.ACK,
|
|
71
|
+
from,
|
|
72
|
+
to,
|
|
73
|
+
data: { ackId: msgIdToAck },
|
|
74
|
+
timestamp: Date.now()
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
// --- WebRTC / Session Methods ---
|
|
78
|
+
async invite(from, to, data) {
|
|
79
|
+
return this.sendRaw(to, SignalType.INVITE, data, from, true);
|
|
80
|
+
}
|
|
81
|
+
async accept(from, to, sdp) {
|
|
82
|
+
return this.sendRaw(to, SignalType.ACCEPT, sdp, from);
|
|
83
|
+
}
|
|
84
|
+
async reject(from, to, reason) {
|
|
85
|
+
return this.sendRaw(to, SignalType.REJECT, { reason }, from);
|
|
86
|
+
}
|
|
87
|
+
async end(from, to, reason) {
|
|
88
|
+
return this.sendRaw(to, SignalType.END, { reason }, from);
|
|
89
|
+
}
|
|
90
|
+
async iceCandidate(from, to, candidate) {
|
|
91
|
+
return this.sendRaw(to, SignalType.ICE_CANDIDATE, candidate, from);
|
|
92
|
+
}
|
|
93
|
+
// --- Industrial / Medical Control Methods ---
|
|
94
|
+
async sendCommand(from, to, commandData, requireAck = true) {
|
|
95
|
+
return this.sendRaw(to, SignalType.COMMAND, commandData, from, requireAck);
|
|
96
|
+
}
|
|
97
|
+
async sendTelemetry(from, to, telemetryData) {
|
|
98
|
+
const payload = {
|
|
99
|
+
msgId: `tel_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
100
|
+
from,
|
|
101
|
+
to,
|
|
102
|
+
type: SignalType.TELEMETRY,
|
|
103
|
+
data: telemetryData,
|
|
104
|
+
timestamp: Date.now()
|
|
105
|
+
};
|
|
106
|
+
if (to === 'all') {
|
|
107
|
+
this.rt.publish(`telemetry/broadcast`, payload);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.rt.privatePub(to, payload);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Mirror a URL to a specific device's pane
|
|
115
|
+
*/
|
|
116
|
+
async mirror(from, to, url, options = {}) {
|
|
117
|
+
return this.sendRaw(to, SignalType.MIRROR, { url, ...options }, from);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Listen to any incoming signals for a particular topic or private channel
|
|
121
|
+
*/
|
|
122
|
+
onSignalFor(deviceId, handler) {
|
|
123
|
+
this.rt.subscribe(`phone/signaling/${deviceId}`, (payload) => {
|
|
124
|
+
// Auto-handle native ACK processing
|
|
125
|
+
if (payload.type === SignalType.ACK && payload.data?.ackId) {
|
|
126
|
+
this.handleAck(payload.data.ackId);
|
|
127
|
+
}
|
|
128
|
+
handler(payload);
|
|
129
|
+
}, deviceId);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.UniversalSignaling = UniversalSignaling;
|
|
133
|
+
function createSignaling(rt) {
|
|
134
|
+
return new UniversalSignaling(rt);
|
|
135
|
+
}
|
|
136
|
+
//# 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.
|
|
3
|
+
"version": "1.7.0",
|
|
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",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"README.md",
|
|
11
11
|
"LICENSE",
|
|
12
12
|
"TUTORIAL_NEPALI.md",
|
|
13
|
-
"DOLPHIN_MASTER_GUIDE_NEPALI.md"
|
|
13
|
+
"DOLPHIN_MASTER_GUIDE_NEPALI.md",
|
|
14
|
+
"scripts/client.js"
|
|
14
15
|
],
|
|
15
16
|
"exports": {
|
|
16
17
|
".": "./dist/index.js",
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dolphin Client v1.1 - Full-stack Realtime, API & Auth Client
|
|
3
|
+
* Zero-dependency, pure JS.
|
|
4
|
+
*
|
|
5
|
+
* यो लाइब्रेरी डल्फिन सर्भरबाट सिधै उपलब्ध हुने पब-सब, API र Auth लाइब्रेरी हो।
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
class APIHandler {
|
|
9
|
+
constructor(client) {
|
|
10
|
+
this.client = client;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async request(method, path, body = null, options = {}) {
|
|
14
|
+
const url = `${this.client.httpUrl}${path.startsWith('/') ? path : '/' + path}`;
|
|
15
|
+
const headers = {
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
...options.headers
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// अटोमेटिक टोकन इन्जेक्सन
|
|
21
|
+
if (this.client.accessToken) {
|
|
22
|
+
headers['Authorization'] = `Bearer ${this.client.accessToken}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const fetchOptions = {
|
|
26
|
+
method,
|
|
27
|
+
headers,
|
|
28
|
+
...options
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
if (body) {
|
|
32
|
+
fetchOptions.body = JSON.stringify(body);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const response = await fetch(url, fetchOptions);
|
|
36
|
+
|
|
37
|
+
// JSON वा Text ह्यान्डल गर्ने
|
|
38
|
+
const contentType = response.headers.get('content-type');
|
|
39
|
+
let data;
|
|
40
|
+
if (contentType && contentType.includes('application/json')) {
|
|
41
|
+
data = await response.json();
|
|
42
|
+
} else {
|
|
43
|
+
data = await response.text();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
throw { status: response.status, data };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get(path, options) { return this.request('GET', path, null, options); }
|
|
54
|
+
post(path, body, options) { return this.request('POST', path, body, options); }
|
|
55
|
+
put(path, body, options) { return this.request('PUT', path, body, options); }
|
|
56
|
+
del(path, options) { return this.request('DELETE', path, null, options); }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class AuthHandler {
|
|
60
|
+
constructor(client) {
|
|
61
|
+
this.client = client;
|
|
62
|
+
this.user = null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async login(email, password) {
|
|
66
|
+
const res = await this.client.api.post('/auth/login', { email, password });
|
|
67
|
+
if (res.accessToken) {
|
|
68
|
+
this.client.setToken(res.accessToken);
|
|
69
|
+
this.user = res.user;
|
|
70
|
+
}
|
|
71
|
+
return res;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async register(data) {
|
|
75
|
+
return await this.client.api.post('/auth/register', data);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async me() {
|
|
79
|
+
const res = await this.client.api.get('/auth/me');
|
|
80
|
+
if (res.success) {
|
|
81
|
+
this.user = res.data;
|
|
82
|
+
}
|
|
83
|
+
return res;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async logout() {
|
|
87
|
+
await this.client.api.post('/auth/logout');
|
|
88
|
+
this.client.setToken(null);
|
|
89
|
+
this.user = null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async forgotPassword(email) {
|
|
93
|
+
return await this.client.api.post('/auth/forgot-password', { email });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
class DolphinClient {
|
|
98
|
+
constructor(url = window.location.host, deviceId = 'web_' + Math.random().toString(36).substr(2, 5)) {
|
|
99
|
+
// Handle URL formatting
|
|
100
|
+
this.host = url.replace(/\/$/, "").replace(/^https?:\/\//, "");
|
|
101
|
+
this.httpUrl = `${window.location.protocol}//${this.host}`;
|
|
102
|
+
this.deviceId = deviceId;
|
|
103
|
+
|
|
104
|
+
this.socket = null;
|
|
105
|
+
this.accessToken = localStorage.getItem('dolphin_token');
|
|
106
|
+
|
|
107
|
+
// Sub-handlers
|
|
108
|
+
this.api = new APIHandler(this);
|
|
109
|
+
this.auth = new AuthHandler(this);
|
|
110
|
+
|
|
111
|
+
this.handlers = new Map(); // topic -> Set of callbacks
|
|
112
|
+
this.signalHandlers = new Set();
|
|
113
|
+
this.reconnectAttempts = 0;
|
|
114
|
+
this.maxReconnectAttempts = 5;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* टोकन सेट गर्ने र सेभ गर्ने
|
|
119
|
+
*/
|
|
120
|
+
setToken(token) {
|
|
121
|
+
this.accessToken = token;
|
|
122
|
+
if (token) {
|
|
123
|
+
localStorage.setItem('dolphin_token', token);
|
|
124
|
+
} else {
|
|
125
|
+
localStorage.removeItem('dolphin_token');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* रियल-टाइम सर्भरसँग कनेक्शन सुरु गर्ने
|
|
131
|
+
*/
|
|
132
|
+
async connect() {
|
|
133
|
+
return new Promise((resolve, reject) => {
|
|
134
|
+
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
135
|
+
const wsUrl = `${protocol}//${this.host}/realtime?deviceId=${this.deviceId}`;
|
|
136
|
+
|
|
137
|
+
console.log(`[Dolphin] Connecting to ${wsUrl}...`);
|
|
138
|
+
this.socket = new WebSocket(wsUrl);
|
|
139
|
+
|
|
140
|
+
this.socket.onopen = () => {
|
|
141
|
+
console.log(`[Dolphin] Connected as "${this.deviceId}" 🐬`);
|
|
142
|
+
this.reconnectAttempts = 0;
|
|
143
|
+
resolve();
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
this.socket.onmessage = (event) => {
|
|
147
|
+
this._handleMessage(event.data);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
this.socket.onclose = () => {
|
|
151
|
+
console.warn("[Dolphin] Connection closed");
|
|
152
|
+
this._maybeReconnect();
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
this.socket.onerror = (err) => {
|
|
156
|
+
console.error("[Dolphin] WebSocket Error:", err);
|
|
157
|
+
reject(err);
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
_handleMessage(data) {
|
|
163
|
+
try {
|
|
164
|
+
const parsed = JSON.parse(data);
|
|
165
|
+
|
|
166
|
+
// १. Signaling Messages
|
|
167
|
+
if (parsed.type && parsed.from && (parsed.to === this.deviceId || parsed.to === 'all')) {
|
|
168
|
+
this.signalHandlers.forEach(handler => handler(parsed));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// २. Pub/Sub Messages
|
|
172
|
+
if (parsed.topic && parsed.payload !== undefined) {
|
|
173
|
+
const topic = parsed.topic;
|
|
174
|
+
this.handlers.forEach((callbacks, pattern) => {
|
|
175
|
+
if (this._matchTopic(pattern, topic)) {
|
|
176
|
+
callbacks.forEach(cb => cb(parsed.payload, topic));
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
} catch (e) {
|
|
181
|
+
this.handlers.forEach((callbacks, pattern) => {
|
|
182
|
+
if (pattern === 'raw') callbacks.forEach(cb => cb(data));
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
_matchTopic(pattern, topic) {
|
|
188
|
+
if (pattern === topic || pattern === '#') return true;
|
|
189
|
+
const pParts = pattern.split('/');
|
|
190
|
+
const tParts = topic.split('/');
|
|
191
|
+
if (pParts.length !== tParts.length && !pattern.includes('#')) return false;
|
|
192
|
+
for (let i = 0; i < pParts.length; i++) {
|
|
193
|
+
if (pParts[i] === '#') return true;
|
|
194
|
+
if (pParts[i] !== '+' && pParts[i] !== tParts[i]) return false;
|
|
195
|
+
}
|
|
196
|
+
return pParts.length === tParts.length;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
subscribe(topic, callback) {
|
|
200
|
+
if (!this.handlers.has(topic)) this.handlers.set(topic, new Set());
|
|
201
|
+
this.handlers.get(topic).add(callback);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
publish(topic, payload) {
|
|
205
|
+
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
|
206
|
+
this.socket.send(JSON.stringify({ topic, payload }));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
onSignal(handler) {
|
|
211
|
+
this.signalHandlers.add(handler);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
_maybeReconnect() {
|
|
215
|
+
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
216
|
+
this.reconnectAttempts++;
|
|
217
|
+
const delay = Math.pow(2, this.reconnectAttempts) * 1000;
|
|
218
|
+
setTimeout(() => this.connect(), delay);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// विन्डो ग्लोबलमा उपलब्ध गराउने
|
|
224
|
+
window.DolphinClient = DolphinClient;
|
|
225
|
+
// अटो-इनिशियलाइज (Optional)
|
|
226
|
+
window.dolphin = new DolphinClient();
|