dolphin-server-modules 2.11.7 → 2.11.8
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 +169 -21
- package/README.md +130 -106
- package/dist/gateway/gateway.d.ts +29 -0
- package/dist/gateway/gateway.js +119 -0
- package/dist/gateway/gateway.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/rpc/rpc.d.ts +38 -0
- package/dist/rpc/rpc.js +138 -0
- package/dist/rpc/rpc.js.map +1 -0
- package/dist/rpc/rpc.test.d.ts +1 -0
- package/dist/rpc/rpc.test.js +39 -0
- package/dist/rpc/rpc.test.js.map +1 -0
- package/dist/utils/adapters.d.ts +14 -0
- package/dist/utils/adapters.js +116 -0
- package/dist/utils/adapters.js.map +1 -0
- package/package.json +1 -1
|
@@ -58,6 +58,16 @@ Latest Version: v2.11.4 | Updated: 2026-05-27 | License: ISC
|
|
|
58
58
|
|
|
59
59
|
१८. API रेफरेन्स
|
|
60
60
|
|
|
61
|
+
१९. CCTV Camera & RTSP Streaming: भिडियो म्यानेजमेन्ट र P2P सिङ्क (New v2.11.7)
|
|
62
|
+
|
|
63
|
+
२०. Dolphin Microservices: API Gateway & WebRPC (New v2.11.7)
|
|
64
|
+
|
|
65
|
+
२१. Universal HTTP Adapters: Express र Fastify सँग इन्टिग्रेसन (New v2.11.7)
|
|
66
|
+
|
|
67
|
+
२२. Production Deployment (सर्भर लाइभ गर्ने)
|
|
68
|
+
|
|
69
|
+
२३. निष्कर्ष (Conclusion)
|
|
70
|
+
|
|
61
71
|
०. परिचय र दर्शन (Introduction & Philosophy)
|
|
62
72
|
Dolphin किन जन्मियो?
|
|
63
73
|
ब्याकइन्ड डेभलपमेन्टको दुनियाँमा एक्सप्रेस (Express) सबैभन्दा लोकप्रिय छ। तर एक्सप्रेस पूरानो भइसक्यो। यसमा धेरै अनावश्यक वजन (Bloat) छ र यो मोडर्न एउटा (Modern) async/await सँग सधैँ राम्रोसँग काम गर्दैन।
|
|
@@ -765,33 +775,171 @@ import { createDolphinServer } from 'dolphin-server-modules/server';
|
|
|
765
775
|
|
|
766
776
|
const app = createDolphinServer();
|
|
767
777
|
|
|
768
|
-
const UserSchema = z.
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
778
|
+
const UserSchema = z.१९. CCTV Camera & RTSP Streaming: भिडियो म्यानेजमेन्ट र P2P सिङ्क (New v2.11.7) 📹
|
|
779
|
+
Dolphin v2.11.7 मा थपिएको यो मोड्युलले औद्योगिक स्तरको भिडियो व्यवस्थापन प्रणाली (Video Management System - VMS) र टेलिकम इन्टरकम (Smart Intercom Telephony) को जग बसाल्छ।
|
|
780
|
+
|
|
781
|
+
१९.१ Camera & RTSP Streaming Architecture
|
|
782
|
+
- **CameraFrameModule**: यसले क्यामराबाट आउने बाइनरी इमेज बफर (`MJPEG`, `H264`, `H265`) हरूलाई बिना कुनै बाह्य सफ्टवेयर सिधै नोड जेएस (Node.js) बफरमै राखेर स्क्यान र पार्स गर्छ र `rt.pubPush` मार्फत लाइभ बाइनरी स्ट्रिम प्रसारण गर्छ।
|
|
783
|
+
- **RtspPullerModule**: आईपी क्यामरा वा NVR को RTSP युआरएलबाट भिडियो फिड तान्न यसमा दुईवटा ब्याकइन्ड छन्:
|
|
784
|
+
१. **Pure TCP Backend**: कुनै भारी FFmpeg बिना नै नेटिभ TCP सकेट पार्सर मार्फत भिडियो तान्छ, जसले CPU को भार ९५% सम्म घटाउँछ।
|
|
785
|
+
२. **FFmpeg Backend**: जटिल कोडेकहरू (जस्तै H.264/H.265) को MJPEG ट्रान्सकोडिङका लागि `ffmpeg` प्रोसेस चलाउँछ।
|
|
786
|
+
|
|
787
|
+
**RTSP क्यामरा जडान गर्ने उदाहरण:**
|
|
788
|
+
```typescript
|
|
789
|
+
import { createCameraModule, createRtspPuller } from 'dolphin-server-modules/realtime';
|
|
790
|
+
|
|
791
|
+
const camera = createCameraModule(rt);
|
|
792
|
+
const puller = createRtspPuller(camera);
|
|
793
|
+
|
|
794
|
+
// १. क्यामरा दर्ता गर्ने र RTSP फिड तान्न सुरु गर्ने
|
|
795
|
+
puller.addCamera({
|
|
796
|
+
cameraId: 'gate-camera-1',
|
|
797
|
+
url: 'rtsp://admin:password@192.168.1.100:554/stream1',
|
|
798
|
+
backend: 'tcp', // वा 'ffmpeg'
|
|
799
|
+
expectedWidth: 1280,
|
|
800
|
+
expectedHeight: 720
|
|
772
801
|
});
|
|
773
802
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
803
|
+
// २. लाइभ बफर बाइनरी स्ट्रिम सुन्ने
|
|
804
|
+
camera.subscribe('gate-camera-1', (frame) => {
|
|
805
|
+
console.log(`फ्रेम प्राप्त भयो! साइज: ${frame.sizeBytes} bytes | Codec: ${frame.codec}`);
|
|
806
|
+
});
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
१९.२ Universal WebRTC Intercom & Signaling System
|
|
810
|
+
यस मोड्युलमा अस्पतालको नर्स कलिङ र अपार्टमेन्ट डोरफोन प्रणालीका लागि उपयुक्त **SIP-style Signaling** संयन्त्र जडान गरिएको छ। यसले ब्राउजर र NVR बीच WebRTC P2P (Peer-to-Peer) अडियो/भिडियो जडान गराउँछ:
|
|
811
|
+
```typescript
|
|
812
|
+
import { createSignaling } from 'dolphin-server-modules/signaling';
|
|
813
|
+
|
|
814
|
+
const telecom = createSignaling(rt);
|
|
815
|
+
|
|
816
|
+
// १. इन्टरकम कल सुरु गर्ने (INVITE) र ACK ग्यारेन्टी गर्ने
|
|
817
|
+
const ackReceived = await telecom.invite('resident-app-101', 'guard-console', {
|
|
818
|
+
roomNo: '101',
|
|
819
|
+
enableVideo: true
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
if (ackReceived) {
|
|
823
|
+
console.log("गार्ड कन्सोलसँग सञ्चार सुरु भयो!");
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// २. गार्डले कल उठाउँदा (ACCEPT) र क्यामरा फिड P2P सिङ्क गराउँदा
|
|
827
|
+
await telecom.accept('guard-console', 'resident-app-101', sdpOffer);
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
---
|
|
831
|
+
|
|
832
|
+
२०. Dolphin Microservices: API Gateway & WebRPC (New v2.11.7) 🚀
|
|
833
|
+
डल्फिनलाई एउटै सर्भरबाट बहु-सर्भर माइक्रोसर्भिस आर्किटेक्चर (Microservices Architecture) मा लान दुईवटा नवीनतम मोड्युल थपिएका छन्।
|
|
834
|
+
|
|
835
|
+
२०.१ Dolphin API Gateway (केन्द्रीय प्रोक्सी ढोका)
|
|
836
|
+
यसले बाहिरबाट आउने HTTP र WebSocket अनुरोधहरूलाई सही माइक्रोसर्भिस (Auth, Products, Stream Services) मा पाइप (Stream pipe) र टनेल प्रोक्सी गर्छ:
|
|
837
|
+
```typescript
|
|
838
|
+
import { DolphinAPIGateway } from 'dolphin-server-modules/gateway';
|
|
839
|
+
|
|
840
|
+
const gateway = new DolphinAPIGateway({
|
|
841
|
+
routes: {
|
|
842
|
+
'/api/auth/*': 'http://localhost:3001', // Auth Service
|
|
843
|
+
'/api/products/*': 'http://localhost:3002', // Product CRUD Service
|
|
844
|
+
'/realtime': 'ws://localhost:3003' // Distributed Realtime Service
|
|
845
|
+
}
|
|
784
846
|
});
|
|
785
847
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
return ctx.html(html);
|
|
848
|
+
gateway.listen(3000, '0.0.0.0', () => {
|
|
849
|
+
console.log("Dolphin API Gateway successfully running on port 3000! 🎛️");
|
|
789
850
|
});
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
२०.२ Dolphin WebRPC (द्रुत अन्तर-सेवा सञ्चार)
|
|
854
|
+
जाभास्क्रिप्ट `Proxy` मा आधारित यो मोड्युलले दुई माइक्रोसर्भिस बीच बिना कुनै झन्झट स्थानीय फङ्सन कल गरे जस्तै गरी (Remote Procedure Call) काम गर्छ:
|
|
855
|
+
|
|
856
|
+
**RPC Server (UserService - Port 4001):**
|
|
857
|
+
```typescript
|
|
858
|
+
import { DolphinRPCServer } from 'dolphin-server-modules/rpc';
|
|
859
|
+
|
|
860
|
+
class UserService {
|
|
861
|
+
async getUserInfo(id: string) {
|
|
862
|
+
return { id, name: "Dr. Ram Prasad", role: "doctor" };
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
const rpcServer = new DolphinRPCServer();
|
|
867
|
+
rpcServer.register('User', new UserService());
|
|
868
|
+
rpcServer.listen(4001);
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
**RPC Client (OrderService calling UserService):**
|
|
872
|
+
```typescript
|
|
873
|
+
import { DolphinRPCClient } from 'dolphin-server-modules/rpc';
|
|
874
|
+
|
|
875
|
+
const client = new DolphinRPCClient({ url: 'http://localhost:4001' });
|
|
876
|
+
const userService = client.getService<any>('User');
|
|
790
877
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
878
|
+
// स्थानीय फङ्सन कल गरे जस्तै गरी रिमोट सर्भरको फङ्सन ए-सिङ्क कल गर्ने!
|
|
879
|
+
const doctor = await userService.getUserInfo('doc_789');
|
|
880
|
+
console.log(doctor.name); // Output: "Dr. Ram Prasad"
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
885
|
+
२१. Universal HTTP Adapters: Express र Fastify सँग इन्टिग्रेसन (New v2.11.7) 🔌
|
|
886
|
+
डल्फिनका कन्ट्रोलरहरू र CRUD रुटहरूलाई तपाईँले एक्सप्रेस (Express) वा फास्टिफाइ (Fastify) सर्भरमा सिधै प्लग-इन गर्न सक्नुहुन्छ। यसका लागि डल्फिनले `toExpress` र `toFastify` एडेप्टरहरू प्रदान गर्छ जसले फ्रेमवर्कको `ctx` लाई एक्सप्रेस/फास्टिफाइको `req/res` सँग स्वतः रूपान्तरण गर्छ:
|
|
887
|
+
|
|
888
|
+
```typescript
|
|
889
|
+
import express from 'express';
|
|
890
|
+
import { createCrudController, toExpress } from 'dolphin-server-modules';
|
|
891
|
+
import { db } from './db.js';
|
|
892
|
+
|
|
893
|
+
const app = express();
|
|
894
|
+
app.use(express.json());
|
|
895
|
+
|
|
896
|
+
const ctrl = createCrudController(db, 'Products');
|
|
897
|
+
|
|
898
|
+
// एक्सप्रेस भित्र डल्फिन कन्ट्रोलर रन गर्ने!
|
|
899
|
+
app.get('/api/products', toExpress(ctrl.getAll));
|
|
900
|
+
app.post('/api/products', toExpress(ctrl.create));
|
|
901
|
+
app.put('/api/products/:id', toExpress(ctrl.update));
|
|
902
|
+
|
|
903
|
+
app.listen(3000, () => console.log("Express integrated with Dolphin Controllers! 🔌"));
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
---
|
|
907
|
+
|
|
908
|
+
२२. Production Deployment (सर्भर लाइभ गर्ने)
|
|
909
|
+
तपाईँको Dolphin सर्भर रकेट जस्तै तयार छ। अब यसलाई लाइभ (World Wide Web) मा राख्न PM2 प्रयोग गरिन्छ जसले क्र्यास भएको खण्डमा तुरुन्त (0.1ms) सर्भरलाई अटो-रिस्टार्ट (Auto-Restart) गर्छ।
|
|
910
|
+
|
|
911
|
+
PM2 इन्स्टल र सुरु गर्न:
|
|
912
|
+
```bash
|
|
913
|
+
# 1. PM2 लाई Global रूपमा राख्ने
|
|
914
|
+
npm install -g pm2
|
|
915
|
+
|
|
916
|
+
# 2. तपाईंको Code लाई Build गर्ने
|
|
917
|
+
npm run build
|
|
918
|
+
|
|
919
|
+
# 3. PM2 द्वारा Background मा सर्भर सुरु गर्ने
|
|
920
|
+
pm2 start dist/index.js --name "dolphin-iot-backend"
|
|
921
|
+
|
|
922
|
+
# 4. सर्भरका Logs (Error/Info) हेर्न
|
|
923
|
+
pm2 logs dolphin-iot-backend
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
२३. निष्कर्ष (Conclusion)
|
|
927
|
+
बधाई छ! तपाईँले Dolphin Framework को Master Guide पूरा गर्नुभयो। अब तपाईँ:
|
|
928
|
+
|
|
929
|
+
✅ हाई-पर्फर्मेन्स API सर्भर बनाउन
|
|
930
|
+
✅ अटोमेटेड CRUD र भ्यालिडेसन प्रयोग गर्न
|
|
931
|
+
✅ RealtimeCore v2.0 सँग पूर्ण रियलटाइम एप्लिकेसन बनाउन
|
|
932
|
+
✅ pubPush/subPull सँग हाई-फ्रिक्वेन्सी डेटा ह्यान्डल गर्न
|
|
933
|
+
✅ pubFile/subFile सँग ठूला फाइलहरू रिज्युम सपोर्ट सहित ट्रान्सफर गर्न
|
|
934
|
+
✅ Device Management सँग डिभाइसहरू ट्र्याक गर्न
|
|
935
|
+
✅ WebRTC Intercom, IP Camera & RTSP Parser व्यवस्थापन गर्न
|
|
936
|
+
✅ Express/Fastify एडेप्टर र API Gateway सँग माइक्रोसर्भिस सञ्चालन गर्न
|
|
937
|
+
✅ अटो-जेनेरेटेड Swagger डकुमेन्टेसन बनाउन
|
|
938
|
+
|
|
939
|
+
सक्नुहुन्छ।
|
|
940
|
+
|
|
941
|
+
Happy Coding! 🐬🇳🇵
|
|
942
|
+
नेपालबाट विश्वस्तरको सफ्टवेयर बनाऔँ!��, तर फिल्टरिङ, सर्टिङ र लोड स्टेटहरू पनि म्यानेज गर्छ।
|
|
795
943
|
|
|
796
944
|
१६.१ स्टेट ट्र्याकिङ (State Tracking)
|
|
797
945
|
प्रत्येक कलेक्सनमा अब निम्न स्टेटहरू हुन्छन्:
|
package/README.md
CHANGED
|
@@ -1,107 +1,131 @@
|
|
|
1
|
-
# 🐬 Dolphin Framework (v2.11.
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-

|
|
5
|
-

|
|
6
|
-
|
|
7
|
-
**Dolphin** is a 2026-ready, ultra-lightweight, and 100% modular backend ecosystem built on native Node.js. Now featuring **Advanced Agentic AI (Cursor-Level)**—Dolphin doesn't just run your code; it understands your entire project, tracks symbols, and performs precision edits using semantic search.
|
|
8
|
-
|
|
9
|
-
> "Native performance. Agentic AI integration. Multi-model support."
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
### 📘 Official Master Guide (Nepal)
|
|
14
|
-
Dolphin Framework को विस्तृत र आधिकारिक गाइड उपलब्ध छ। यसमा **Auth, CRUD, Models, र Controllers** को १००% ट्युटोरियल समावेश छ।
|
|
15
|
-
|
|
16
|
-
👉 **[Dolphin Master Guide (Web Version)](https://raw.githack.com/Phuyalshankar/dolphin-server-modules/main/guide.html)** *(Most Up-to-Date)*
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 🤖 Cursor-Level AI Features (New in v2.11.4)
|
|
21
|
-
|
|
22
|
-
Dolphin v2.11.4 introduces a complete overhaul of the AI Agent, bringing it closer to professional AI editors like Cursor.
|
|
23
|
-
|
|
24
|
-
### 1. Semantic Project Search
|
|
25
|
-
The AI doesn't just look at one file; it indexes your entire project. When you ask a question, it uses semantic token overlap to find the 5 most relevant files automatically.
|
|
26
|
-
|
|
27
|
-
### 2. Symbol & Reference Tracking
|
|
28
|
-
Dolphin indexes every `function`, `class`, and `variable` across your project. The AI knows exactly where a symbol is defined and where it's used.
|
|
29
|
-
|
|
30
|
-
### 3. Precision Patching (No Full Re-writes)
|
|
31
|
-
Using the new **Patch Tool**, Dolphin performs surgical edits to your code. No more slow, risky full-file overwrites for small changes.
|
|
32
|
-
|
|
33
|
-
### 4. Multi-Model Support (Local & Cloud)
|
|
34
|
-
Use any AI provider you want. Supports **Google Gemini**, **Groq (Llama 3)**, and **Local Ollama (Gemma 3/Llama 3)**.
|
|
35
|
-
```bash
|
|
36
|
-
# To use Local Ollama, set this in .env:
|
|
37
|
-
USE_OLLAMA=true
|
|
38
|
-
OLLAMA_MODEL=gemma3:latest
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### 5. Personalized Support (Roman Nepali)
|
|
42
|
-
The agent understands and replies in **Roman Nepali** (e.g., "Sanchai hunuhunchha?"), making it more comfortable for Nepali developers.
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## 🛠️ CLI Usage
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
# Start the Autonomous AI Agent (Cursor Mode)
|
|
50
|
-
npx dolphin chat
|
|
51
|
-
|
|
52
|
-
# Architect a full production project
|
|
53
|
-
npx dolphin generate-full "e-commerce backend"
|
|
54
|
-
|
|
55
|
-
# Scaffold standard components (No AI needed)
|
|
56
|
-
npx dolphin add auth # Add Auth System
|
|
57
|
-
npx dolphin add crud Product # Add CRUD for Product
|
|
58
|
-
npx dolphin add adapter mongoose # Setup DB
|
|
59
|
-
|
|
60
|
-
# Initialize folders
|
|
61
|
-
npx dolphin init-prod
|
|
62
|
-
|
|
63
|
-
# Start Dev Server
|
|
64
|
-
npx dolphin serve --port=3000
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## 🚀
|
|
70
|
-
|
|
71
|
-
Dolphin
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
app.
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
1
|
+
# 🐬 Dolphin Framework (v2.11.7)
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
**Dolphin** is a 2026-ready, ultra-lightweight, and 100% modular backend ecosystem built on native Node.js. Now featuring **Advanced Agentic AI (Cursor-Level)**—Dolphin doesn't just run your code; it understands your entire project, tracks symbols, and performs precision edits using semantic search.
|
|
8
|
+
|
|
9
|
+
> "Native performance. Agentic AI integration. Multi-model support."
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### 📘 Official Master Guide (Nepal)
|
|
14
|
+
Dolphin Framework को विस्तृत र आधिकारिक गाइड उपलब्ध छ। यसमा **Auth, CRUD, Models, र Controllers** को १००% ट्युटोरियल समावेश छ।
|
|
15
|
+
|
|
16
|
+
👉 **[Dolphin Master Guide (Web Version)](https://raw.githack.com/Phuyalshankar/dolphin-server-modules/main/guide.html)** *(Most Up-to-Date)*
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 🤖 Cursor-Level AI Features (New in v2.11.4)
|
|
21
|
+
|
|
22
|
+
Dolphin v2.11.4 introduces a complete overhaul of the AI Agent, bringing it closer to professional AI editors like Cursor.
|
|
23
|
+
|
|
24
|
+
### 1. Semantic Project Search
|
|
25
|
+
The AI doesn't just look at one file; it indexes your entire project. When you ask a question, it uses semantic token overlap to find the 5 most relevant files automatically.
|
|
26
|
+
|
|
27
|
+
### 2. Symbol & Reference Tracking
|
|
28
|
+
Dolphin indexes every `function`, `class`, and `variable` across your project. The AI knows exactly where a symbol is defined and where it's used.
|
|
29
|
+
|
|
30
|
+
### 3. Precision Patching (No Full Re-writes)
|
|
31
|
+
Using the new **Patch Tool**, Dolphin performs surgical edits to your code. No more slow, risky full-file overwrites for small changes.
|
|
32
|
+
|
|
33
|
+
### 4. Multi-Model Support (Local & Cloud)
|
|
34
|
+
Use any AI provider you want. Supports **Google Gemini**, **Groq (Llama 3)**, and **Local Ollama (Gemma 3/Llama 3)**.
|
|
35
|
+
```bash
|
|
36
|
+
# To use Local Ollama, set this in .env:
|
|
37
|
+
USE_OLLAMA=true
|
|
38
|
+
OLLAMA_MODEL=gemma3:latest
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 5. Personalized Support (Roman Nepali)
|
|
42
|
+
The agent understands and replies in **Roman Nepali** (e.g., "Sanchai hunuhunchha?"), making it more comfortable for Nepali developers.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 🛠️ CLI Usage
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Start the Autonomous AI Agent (Cursor Mode)
|
|
50
|
+
npx dolphin chat
|
|
51
|
+
|
|
52
|
+
# Architect a full production project
|
|
53
|
+
npx dolphin generate-full "e-commerce backend"
|
|
54
|
+
|
|
55
|
+
# Scaffold standard components (No AI needed)
|
|
56
|
+
npx dolphin add auth # Add Auth System
|
|
57
|
+
npx dolphin add crud Product # Add CRUD for Product
|
|
58
|
+
npx dolphin add adapter mongoose # Setup DB
|
|
59
|
+
|
|
60
|
+
# Initialize folders
|
|
61
|
+
npx dolphin init-prod
|
|
62
|
+
|
|
63
|
+
# Start Dev Server
|
|
64
|
+
npx dolphin serve --port=3000
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 🚀 Microservices & Smart Intercom Ecosystem (New in v2.11.7)
|
|
70
|
+
|
|
71
|
+
Dolphin v2.11.7 introduces a complete suite of enterprise-grade microservice modules and smart building signaling/streaming pipelines:
|
|
72
|
+
|
|
73
|
+
### 1. Universal HTTP Framework Adapters
|
|
74
|
+
Run Dolphin's Mongoose-synced CRUD controllers and Auth middleware directly inside **Express** or **Fastify**!
|
|
75
|
+
```javascript
|
|
76
|
+
import express from 'express';
|
|
77
|
+
import { createCrudController, toExpress } from 'dolphin-server-modules';
|
|
78
|
+
|
|
79
|
+
const app = express();
|
|
80
|
+
const ctrl = createCrudController(db, 'Products');
|
|
81
|
+
|
|
82
|
+
app.get('/api/products', toExpress(ctrl.getAll));
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 2. High-Performance WebRPC
|
|
86
|
+
Decouple service interactions with a type-safe, Proxy-based, sub-millisecond remote procedure call (RPC) client/server engine:
|
|
87
|
+
```javascript
|
|
88
|
+
import { DolphinRPCClient } from 'dolphin-server-modules/rpc';
|
|
89
|
+
|
|
90
|
+
const client = new DolphinRPCClient({ url: 'http://localhost:4001' });
|
|
91
|
+
const userService = client.getService('User');
|
|
92
|
+
|
|
93
|
+
// Call remote methods asynchronously as if they were local!
|
|
94
|
+
const user = await userService.getUserInfo('user_123');
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. API Gateway Router
|
|
98
|
+
A zero-dependency reverse proxy server that redirects HTTP and WebSocket upgrade streams dynamically:
|
|
99
|
+
```javascript
|
|
100
|
+
import { DolphinAPIGateway } from 'dolphin-server-modules/gateway';
|
|
101
|
+
|
|
102
|
+
const gateway = new DolphinAPIGateway({
|
|
103
|
+
routes: {
|
|
104
|
+
'/api/auth/*': 'http://localhost:3001',
|
|
105
|
+
'/api/products/*': 'http://localhost:3002',
|
|
106
|
+
'/realtime': 'ws://localhost:3003'
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
gateway.listen(3000);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 4. CCTV Camera, RTSP Puller & WebRTC Intercom
|
|
113
|
+
- **RtspPullerModule**: Feeds streams from IP cameras/NVRs. Features a **Pure TCP RTP buffer parser** (zero external binaries/FFmpeg!) for low-resource environments, and FFmpeg Fallbacks.
|
|
114
|
+
- **UniversalSignaling**: A telecom-ready WebRTC signaling server with native invite-accept-reject-end handshakes and bidirectional ACK confirmations—perfect for smart doorphones and nurse calling systems!
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 🗺️ Roadmap
|
|
119
|
+
- [x] **Agentic AI Scaffolding**: Full project generation via Gemini/Groq
|
|
120
|
+
- [x] **Semantic Search & Symbol Indexing**: Precision context building
|
|
121
|
+
- [x] **Precision Patching**: AST-style surgical code edits
|
|
122
|
+
- [x] **Express/Fastify Adapters**: Pluggable Dolphin Context middleware
|
|
123
|
+
- [x] **Independent WebRPC & API Gateway**: High-speed microservices orchestration
|
|
124
|
+
- [x] **IP Camera RTSP & WebRTC Intercom**: Pure TCP stream parsing and VoIP SIP signaling
|
|
125
|
+
- [ ] **One-Click Deployment**: Deploy to Vercel/Cloudflare from CLI
|
|
126
|
+
- [ ] **Visual Debugger**: Built-in web dashboard for monitoring
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 📄 License
|
|
107
131
|
ISC © 2026 Shankar Phuyal & Dolphin Team.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
export interface GatewayRouteOptions {
|
|
3
|
+
routes: {
|
|
4
|
+
[prefix: string]: string;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* DolphinAPIGateway
|
|
9
|
+
* A lightweight, high-performance API Gateway supporting HTTP stream piping and
|
|
10
|
+
* dynamic WebSocket upgrade tunnel proxying with zero third-party routing dependencies.
|
|
11
|
+
*/
|
|
12
|
+
export declare class DolphinAPIGateway {
|
|
13
|
+
private routes;
|
|
14
|
+
private server;
|
|
15
|
+
private wss;
|
|
16
|
+
constructor(options: GatewayRouteOptions);
|
|
17
|
+
/**
|
|
18
|
+
* Find matching routing rule for the request path.
|
|
19
|
+
*/
|
|
20
|
+
private matchRoute;
|
|
21
|
+
/**
|
|
22
|
+
* Start the API Gateway.
|
|
23
|
+
*/
|
|
24
|
+
listen(port: number, host?: string, callback?: () => void): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
25
|
+
/**
|
|
26
|
+
* Stop the API Gateway.
|
|
27
|
+
*/
|
|
28
|
+
close(callback?: () => void): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
3
|
+
/**
|
|
4
|
+
* DolphinAPIGateway
|
|
5
|
+
* A lightweight, high-performance API Gateway supporting HTTP stream piping and
|
|
6
|
+
* dynamic WebSocket upgrade tunnel proxying with zero third-party routing dependencies.
|
|
7
|
+
*/
|
|
8
|
+
export class DolphinAPIGateway {
|
|
9
|
+
routes = [];
|
|
10
|
+
server = null;
|
|
11
|
+
wss = null;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
// Sort routes by specificity (longer prefixes first) to prevent routing clashes
|
|
14
|
+
const sortedKeys = Object.keys(options.routes).sort((a, b) => b.length - a.length);
|
|
15
|
+
for (const key of sortedKeys) {
|
|
16
|
+
const isWildcard = key.endsWith('*');
|
|
17
|
+
const prefix = isWildcard ? key.slice(0, -1) : key;
|
|
18
|
+
this.routes.push({
|
|
19
|
+
prefix,
|
|
20
|
+
target: options.routes[key].replace(/\/$/, ''),
|
|
21
|
+
isWildcard
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Find matching routing rule for the request path.
|
|
27
|
+
*/
|
|
28
|
+
matchRoute(pathname) {
|
|
29
|
+
for (const r of this.routes) {
|
|
30
|
+
if (r.isWildcard && pathname.startsWith(r.prefix)) {
|
|
31
|
+
return r;
|
|
32
|
+
}
|
|
33
|
+
if (!r.isWildcard && pathname === r.prefix) {
|
|
34
|
+
return r;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Start the API Gateway.
|
|
41
|
+
*/
|
|
42
|
+
listen(port, host = '0.0.0.0', callback) {
|
|
43
|
+
this.server = http.createServer(async (req, res) => {
|
|
44
|
+
const parsedUrl = new URL(req.url || '', `http://${req.headers.host || 'localhost'}`);
|
|
45
|
+
const matched = this.matchRoute(parsedUrl.pathname);
|
|
46
|
+
if (!matched) {
|
|
47
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
48
|
+
res.end(JSON.stringify({ error: 'Gateway Route Not Found' }));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Proxy HTTP Request Streams
|
|
52
|
+
const targetUrl = new URL(matched.target);
|
|
53
|
+
const targetPath = parsedUrl.pathname + parsedUrl.search;
|
|
54
|
+
const proxyReq = http.request({
|
|
55
|
+
host: targetUrl.hostname,
|
|
56
|
+
port: targetUrl.port ? parseInt(targetUrl.port) : (targetUrl.protocol === 'https:' ? 443 : 80),
|
|
57
|
+
path: targetPath,
|
|
58
|
+
method: req.method,
|
|
59
|
+
headers: req.headers
|
|
60
|
+
}, (proxyRes) => {
|
|
61
|
+
res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
|
|
62
|
+
proxyRes.pipe(res);
|
|
63
|
+
});
|
|
64
|
+
proxyReq.on('error', (err) => {
|
|
65
|
+
res.writeHead(502, { 'Content-Type': 'application/json' });
|
|
66
|
+
res.end(JSON.stringify({ error: `Gateway Proxy Error: ${err.message}` }));
|
|
67
|
+
});
|
|
68
|
+
req.pipe(proxyReq);
|
|
69
|
+
});
|
|
70
|
+
// Handle WebSocket Tunneling
|
|
71
|
+
this.wss = new WebSocketServer({ noServer: true });
|
|
72
|
+
this.server.on('upgrade', (request, socket, head) => {
|
|
73
|
+
const { pathname, search } = new URL(request.url || '', `http://${request.headers.host || 'localhost'}`);
|
|
74
|
+
const matched = this.matchRoute(pathname);
|
|
75
|
+
if (!matched) {
|
|
76
|
+
socket.destroy();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
this.wss?.handleUpgrade(request, socket, head, (ws) => {
|
|
80
|
+
const targetUrl = new URL(matched.target);
|
|
81
|
+
const wsProtocol = targetUrl.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
82
|
+
const targetWsUrl = `${wsProtocol}//${targetUrl.host}${pathname}${search}`;
|
|
83
|
+
const targetWs = new WebSocket(targetWsUrl);
|
|
84
|
+
targetWs.on('open', () => {
|
|
85
|
+
// Bidirectional message forwarding
|
|
86
|
+
ws.on('message', (message, isBinary) => {
|
|
87
|
+
if (targetWs.readyState === WebSocket.OPEN) {
|
|
88
|
+
targetWs.send(message, { binary: isBinary });
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
targetWs.on('message', (message, isBinary) => {
|
|
92
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
93
|
+
ws.send(message, { binary: isBinary });
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
// Event coordination & active socket cleanup
|
|
98
|
+
ws.on('close', () => targetWs.close());
|
|
99
|
+
targetWs.on('close', () => ws.close());
|
|
100
|
+
ws.on('error', () => targetWs.close());
|
|
101
|
+
targetWs.on('error', () => ws.close());
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
this.server.listen(port, host, callback);
|
|
105
|
+
return this.server;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Stop the API Gateway.
|
|
109
|
+
*/
|
|
110
|
+
close(callback) {
|
|
111
|
+
if (this.wss) {
|
|
112
|
+
this.wss.close();
|
|
113
|
+
}
|
|
114
|
+
if (this.server) {
|
|
115
|
+
this.server.close(callback);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/gateway/gateway.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,3 +14,6 @@ export * from './utils/ctx.js';
|
|
|
14
14
|
export * from './djson/djson.js';
|
|
15
15
|
export { DatabaseAdapter } from './curd/crud.js';
|
|
16
16
|
export type { DatabaseAdapter as AuthDatabaseAdapter } from './auth/auth.js';
|
|
17
|
+
export * from './rpc/rpc.js';
|
|
18
|
+
export * from './gateway/gateway.js';
|
|
19
|
+
export * from './utils/adapters.js';
|
package/dist/index.js
CHANGED
|
@@ -13,4 +13,8 @@ export * from './server/server.js';
|
|
|
13
13
|
export * from './router/router.js';
|
|
14
14
|
export * from './utils/ctx.js';
|
|
15
15
|
export * from './djson/djson.js';
|
|
16
|
+
// Microservices & HTTP Framework Adapters
|
|
17
|
+
export * from './rpc/rpc.js';
|
|
18
|
+
export * from './gateway/gateway.js';
|
|
19
|
+
export * from './utils/adapters.js';
|
|
16
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AAErC,gDAAgD;AAChD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AAErC,gDAAgD;AAChD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oCAAoC,CAAC;AACnD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AAMjC,0CAA0C;AAC1C,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* DolphinRPCServer
|
|
4
|
+
* Exposes service classes dynamically over HTTP with zero configuration.
|
|
5
|
+
*/
|
|
6
|
+
export declare class DolphinRPCServer {
|
|
7
|
+
private services;
|
|
8
|
+
private server;
|
|
9
|
+
/**
|
|
10
|
+
* Register a service instance under a specific name.
|
|
11
|
+
*/
|
|
12
|
+
register(serviceName: string, serviceInstance: any): void;
|
|
13
|
+
/**
|
|
14
|
+
* Start the RPC server.
|
|
15
|
+
*/
|
|
16
|
+
listen(port: number, host?: string, callback?: () => void): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
17
|
+
/**
|
|
18
|
+
* Stop the RPC server.
|
|
19
|
+
*/
|
|
20
|
+
close(callback?: () => void): void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* DolphinRPCClient
|
|
24
|
+
* Provides dynamic, Proxy-based invocation of remote service methods with full async support.
|
|
25
|
+
*/
|
|
26
|
+
export declare class DolphinRPCClient {
|
|
27
|
+
private host;
|
|
28
|
+
private port;
|
|
29
|
+
constructor(options?: {
|
|
30
|
+
url?: string;
|
|
31
|
+
host?: string;
|
|
32
|
+
port?: number;
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Obtain a dynamically proxied client for the specified service.
|
|
36
|
+
*/
|
|
37
|
+
getService<T = any>(serviceName: string): T;
|
|
38
|
+
}
|
package/dist/rpc/rpc.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
/**
|
|
3
|
+
* DolphinRPCServer
|
|
4
|
+
* Exposes service classes dynamically over HTTP with zero configuration.
|
|
5
|
+
*/
|
|
6
|
+
export class DolphinRPCServer {
|
|
7
|
+
services = new Map();
|
|
8
|
+
server = null;
|
|
9
|
+
/**
|
|
10
|
+
* Register a service instance under a specific name.
|
|
11
|
+
*/
|
|
12
|
+
register(serviceName, serviceInstance) {
|
|
13
|
+
this.services.set(serviceName, serviceInstance);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Start the RPC server.
|
|
17
|
+
*/
|
|
18
|
+
listen(port, host = '0.0.0.0', callback) {
|
|
19
|
+
this.server = http.createServer(async (req, res) => {
|
|
20
|
+
// CORS headers
|
|
21
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
22
|
+
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
23
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
24
|
+
if (req.method === 'OPTIONS') {
|
|
25
|
+
res.writeHead(204).end();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (req.method !== 'POST') {
|
|
29
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
30
|
+
res.end(JSON.stringify({ error: 'Method Not Allowed' }));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const chunks = [];
|
|
35
|
+
for await (const chunk of req)
|
|
36
|
+
chunks.push(chunk);
|
|
37
|
+
const bodyStr = Buffer.concat(chunks).toString();
|
|
38
|
+
const payload = JSON.parse(bodyStr);
|
|
39
|
+
const { service, method, args } = payload;
|
|
40
|
+
const instance = this.services.get(service);
|
|
41
|
+
if (!instance) {
|
|
42
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
43
|
+
res.end(JSON.stringify({ error: `Service "${service}" not found` }));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const fn = instance[method];
|
|
47
|
+
if (typeof fn !== 'function') {
|
|
48
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
49
|
+
res.end(JSON.stringify({ error: `Method "${method}" not found on service "${service}"` }));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Invoke the method dynamically with arguments
|
|
53
|
+
const result = await fn.apply(instance, args || []);
|
|
54
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
55
|
+
res.end(JSON.stringify({ result }));
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
59
|
+
res.end(JSON.stringify({ error: err.message || 'Internal Server Error' }));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
this.server.listen(port, host, callback);
|
|
63
|
+
return this.server;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Stop the RPC server.
|
|
67
|
+
*/
|
|
68
|
+
close(callback) {
|
|
69
|
+
if (this.server) {
|
|
70
|
+
this.server.close(callback);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* DolphinRPCClient
|
|
76
|
+
* Provides dynamic, Proxy-based invocation of remote service methods with full async support.
|
|
77
|
+
*/
|
|
78
|
+
export class DolphinRPCClient {
|
|
79
|
+
host;
|
|
80
|
+
port;
|
|
81
|
+
constructor(options = {}) {
|
|
82
|
+
if (options.url) {
|
|
83
|
+
const parsed = new URL(options.url);
|
|
84
|
+
this.host = parsed.hostname;
|
|
85
|
+
this.port = parseInt(parsed.port || '80');
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.host = options.host || 'localhost';
|
|
89
|
+
this.port = options.port || 3000;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Obtain a dynamically proxied client for the specified service.
|
|
94
|
+
*/
|
|
95
|
+
getService(serviceName) {
|
|
96
|
+
return new Proxy({}, {
|
|
97
|
+
get: (target, method) => {
|
|
98
|
+
return (...args) => {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
const payload = JSON.stringify({ service: serviceName, method, args });
|
|
101
|
+
const req = http.request({
|
|
102
|
+
host: this.host,
|
|
103
|
+
port: this.port,
|
|
104
|
+
path: '/',
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: {
|
|
107
|
+
'Content-Type': 'application/json',
|
|
108
|
+
'Content-Length': Buffer.byteLength(payload)
|
|
109
|
+
}
|
|
110
|
+
}, (res) => {
|
|
111
|
+
const chunks = [];
|
|
112
|
+
res.on('data', chunk => chunks.push(chunk));
|
|
113
|
+
res.on('end', () => {
|
|
114
|
+
const responseStr = Buffer.concat(chunks).toString();
|
|
115
|
+
try {
|
|
116
|
+
const data = JSON.parse(responseStr);
|
|
117
|
+
if (data.error) {
|
|
118
|
+
reject(new Error(data.error));
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
resolve(data.result);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
reject(new Error(`Failed to parse response: ${responseStr}`));
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
req.on('error', (err) => reject(err));
|
|
130
|
+
req.write(payload);
|
|
131
|
+
req.end();
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=rpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/rpc/rpc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DolphinRPCServer, DolphinRPCClient } from './rpc';
|
|
2
|
+
class CalculatorService {
|
|
3
|
+
add(a, b) {
|
|
4
|
+
return a + b;
|
|
5
|
+
}
|
|
6
|
+
async greet(name) {
|
|
7
|
+
return `Hello ${name}`;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
describe('Dolphin RPC Module', () => {
|
|
11
|
+
let server;
|
|
12
|
+
let client;
|
|
13
|
+
const PORT = 5678;
|
|
14
|
+
beforeAll((done) => {
|
|
15
|
+
server = new DolphinRPCServer();
|
|
16
|
+
server.register('Calculator', new CalculatorService());
|
|
17
|
+
server.listen(PORT, '127.0.0.1', done);
|
|
18
|
+
client = new DolphinRPCClient({ url: `http://localhost:${PORT}` });
|
|
19
|
+
});
|
|
20
|
+
afterAll((done) => {
|
|
21
|
+
server.close(done);
|
|
22
|
+
});
|
|
23
|
+
test('should invoke remote methods successfully', async () => {
|
|
24
|
+
const calc = client.getService('Calculator');
|
|
25
|
+
const sum = await calc.add(10, 15);
|
|
26
|
+
expect(sum).toBe(25);
|
|
27
|
+
const greeting = await calc.greet('Dolphin');
|
|
28
|
+
expect(greeting).toBe('Hello Dolphin');
|
|
29
|
+
});
|
|
30
|
+
test('should fail when service does not exist', async () => {
|
|
31
|
+
const missing = client.getService('MissingService');
|
|
32
|
+
await expect(missing.foo()).rejects.toThrow('Service "MissingService" not found');
|
|
33
|
+
});
|
|
34
|
+
test('should fail when method does not exist', async () => {
|
|
35
|
+
const calc = client.getService('Calculator');
|
|
36
|
+
await expect(calc.missingMethod()).rejects.toThrow('Method "missingMethod" not found on service "Calculator"');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=rpc.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.test.js","sourceRoot":"","sources":["../../src/rpc/rpc.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAE3D,MAAM,iBAAiB;IACrB,GAAG,CAAC,CAAS,EAAE,CAAS;QACtB,OAAO,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAY;QACtB,OAAO,SAAS,IAAI,EAAE,CAAC;IACzB,CAAC;CACF;AAED,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,IAAI,MAAwB,CAAC;IAC7B,IAAI,MAAwB,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC;IAElB,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;QACjB,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QAChC,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,iBAAiB,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;QACvC,MAAM,GAAG,IAAI,gBAAgB,CAAC,EAAE,GAAG,EAAE,oBAAoB,IAAI,EAAE,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE;QAChB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAoB,YAAY,CAAC,CAAC;QAEhE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAErB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;QACpD,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAM,YAAY,CAAC,CAAC;QAClD,MAAM,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,0DAA0D,CAAC,CAAC;IACjH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Adapters for Express and Fastify
|
|
3
|
+
* Maps native requests/responses to Dolphin's standard ctx structure.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Express Adapter
|
|
7
|
+
* Maps (req, res, next) to Dolphin's standard ctx structure.
|
|
8
|
+
*/
|
|
9
|
+
export declare function toExpress(handler: Function): (req: any, res: any, next: any) => Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Fastify Adapter
|
|
12
|
+
* Maps (request, reply) to Dolphin's standard ctx structure.
|
|
13
|
+
*/
|
|
14
|
+
export declare function toFastify(handler: Function): (request: any, reply: any) => Promise<void>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Adapters for Express and Fastify
|
|
3
|
+
* Maps native requests/responses to Dolphin's standard ctx structure.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Express Adapter
|
|
7
|
+
* Maps (req, res, next) to Dolphin's standard ctx structure.
|
|
8
|
+
*/
|
|
9
|
+
export function toExpress(handler) {
|
|
10
|
+
return async (req, res, next) => {
|
|
11
|
+
let pendingStatus = 200;
|
|
12
|
+
const ctx = {
|
|
13
|
+
req,
|
|
14
|
+
res,
|
|
15
|
+
params: req.params || {},
|
|
16
|
+
query: req.query || {},
|
|
17
|
+
body: req.body || {},
|
|
18
|
+
state: res.locals || {},
|
|
19
|
+
json: (data, status) => {
|
|
20
|
+
const finalStatus = status !== undefined ? status : pendingStatus;
|
|
21
|
+
res.status(finalStatus).json(data);
|
|
22
|
+
return ctx;
|
|
23
|
+
},
|
|
24
|
+
text: (data, status) => {
|
|
25
|
+
const finalStatus = status !== undefined ? status : pendingStatus;
|
|
26
|
+
res.status(finalStatus).send(String(data));
|
|
27
|
+
return ctx;
|
|
28
|
+
},
|
|
29
|
+
html: (data, status) => {
|
|
30
|
+
const finalStatus = status !== undefined ? status : pendingStatus;
|
|
31
|
+
res.status(finalStatus).send(String(data));
|
|
32
|
+
return ctx;
|
|
33
|
+
},
|
|
34
|
+
status: (code) => {
|
|
35
|
+
pendingStatus = code;
|
|
36
|
+
return ctx;
|
|
37
|
+
},
|
|
38
|
+
setHeader: (name, value) => {
|
|
39
|
+
res.setHeader(name, value);
|
|
40
|
+
return ctx;
|
|
41
|
+
},
|
|
42
|
+
getHeader: (name) => {
|
|
43
|
+
return req.headers[name.toLowerCase()];
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
// If the handler is a middleware and takes next
|
|
48
|
+
if (handler.length >= 2) {
|
|
49
|
+
await handler(ctx, next);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const result = await handler(ctx);
|
|
53
|
+
// If the handler returned a response directly instead of calling ctx.json()
|
|
54
|
+
if (result !== undefined && result !== null && !res.headersSent) {
|
|
55
|
+
ctx.json(result);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
next(err);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Fastify Adapter
|
|
66
|
+
* Maps (request, reply) to Dolphin's standard ctx structure.
|
|
67
|
+
*/
|
|
68
|
+
export function toFastify(handler) {
|
|
69
|
+
return async (request, reply) => {
|
|
70
|
+
let pendingStatus = 200;
|
|
71
|
+
const ctx = {
|
|
72
|
+
req: request.raw,
|
|
73
|
+
res: reply.raw,
|
|
74
|
+
params: request.params || {},
|
|
75
|
+
query: request.query || {},
|
|
76
|
+
body: request.body || {},
|
|
77
|
+
state: request.state || {},
|
|
78
|
+
json: (data, status) => {
|
|
79
|
+
const finalStatus = status !== undefined ? status : pendingStatus;
|
|
80
|
+
reply.status(finalStatus).send(data);
|
|
81
|
+
return ctx;
|
|
82
|
+
},
|
|
83
|
+
text: (data, status) => {
|
|
84
|
+
const finalStatus = status !== undefined ? status : pendingStatus;
|
|
85
|
+
reply.status(finalStatus).type('text/plain').send(String(data));
|
|
86
|
+
return ctx;
|
|
87
|
+
},
|
|
88
|
+
html: (data, status) => {
|
|
89
|
+
const finalStatus = status !== undefined ? status : pendingStatus;
|
|
90
|
+
reply.status(finalStatus).type('text/html').send(String(data));
|
|
91
|
+
return ctx;
|
|
92
|
+
},
|
|
93
|
+
status: (code) => {
|
|
94
|
+
pendingStatus = code;
|
|
95
|
+
return ctx;
|
|
96
|
+
},
|
|
97
|
+
setHeader: (name, value) => {
|
|
98
|
+
reply.header(name, value);
|
|
99
|
+
return ctx;
|
|
100
|
+
},
|
|
101
|
+
getHeader: (name) => {
|
|
102
|
+
return request.headers[name.toLowerCase()];
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
try {
|
|
106
|
+
const result = await handler(ctx);
|
|
107
|
+
if (result !== undefined && result !== null && !reply.sent) {
|
|
108
|
+
ctx.json(result);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
reply.send(err);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=adapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/utils/adapters.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED