peer-kit / src / ardegazu / peer / connect.cljs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
;; ported-from: src/connect.ts @ v1.3.0
;;
;; The one-call entry: join a game room as a headless peer. Installs the origin
;; shims, resolves the app definition, and wires createNet into a small
;; event-emitting surface.
(ns ardegazu.peer.connect
  (:require ["node:events" :refer (EventEmitter)]
            [ardegazu.peer.apps :as apps]
            [ardegazu.peer.core.net :as net]
            [ardegazu.peer.node.env :as env]
            [shadow.cljs.modern :refer (defclass js-await)]))

(defclass RoomPeer
  (extends EventEmitter)
  (constructor [this n app]
    (super)
    (unchecked-set this "net" n)
    (unchecked-set this "app" app)))

(let [proto (.-prototype RoomPeer)]
  (js/Object.defineProperty
   proto "myId"
   #js {:get (fn [] (this-as self (unchecked-get (unchecked-get self "net") "myId")))
        :configurable true})
  (unchecked-set proto "send"
                 (fn [to frame]
                   (this-as self ((unchecked-get (unchecked-get self "net") "send") to frame))))
  (unchecked-set proto "broadcast"
                 (fn [frame]
                   (this-as self ((unchecked-get (unchecked-get self "net") "broadcast") frame))))
  (unchecked-set proto "identityOf"
                 (fn [id]
                   (this-as self ((unchecked-get (unchecked-get self "net") "identityOf") id))))
  (unchecked-set proto "close"
                 (fn [] (this-as self ((unchecked-get (unchecked-get self "net") "close"))))))

(defn connect
  "opts = #js {:app :roomSecret :identity? :origin? :webrtc?}"
  [opts]
  (-> (js/Promise.resolve nil)
      (.then
       (fn [_]
         (let [app-name (unchecked-get opts "app")
               app (unchecked-get apps/GAMES app-name)]
           (when-not ^boolean (js* "!!(~{})" app)
             (throw (js/Error. (str "unknown app: " app-name))))
           (let [origin (unchecked-get opts "origin")]
             (env/install-origin (if ^boolean (js* "~{} == null" origin) apps/DEFAULT-ORIGIN origin)))
           ;; `let peer!: RoomPeer` — the callbacks fire before the peer exists
           ;; during createNet, and `peer?.emit(...)` swallows those
           (let [holder (volatile! nil)
                 emit (fn [& args]
                        (let [p @holder]
                          (when (some? p) (.apply (.-emit ^js p) p (into-array args))))
                        js/undefined)]
             (js-await [n (net/create-net
                           (js-obj "secret" (unchecked-get opts "roomSecret")
                                   "appSalt" (unchecked-get app "salt")
                                   "protocolPrefix" (unchecked-get app "protocolPrefix")
                                   "descriptorUrl" (unchecked-get apps/SIGNAL "descriptorUrl")
                                   "turnUrl" (unchecked-get apps/SIGNAL "turnUrl")
                                   "relayFallback" (unchecked-get apps/SIGNAL "relayFallback")
                                   "identity" (let [i (unchecked-get opts "identity")]
                                                (if ^boolean (js* "~{} == null" i) nil i))
                                   "webrtc" (unchecked-get opts "webrtc"))
                           (js-obj
                            "onRoomRoster" (fn [peers] (emit "roster" peers))
                            "onPeerOpen" (fn [id] (emit "peerOpen" id))
                            "onPeerGone" (fn [id] (emit "peerGone" id))
                            "onMessage" (fn [from payload] (emit "message" from payload))
                            "onStatus" (fn [] (emit "status"))
                            "onPeerIdentity" (fn [id ident] (emit "peerIdentity" id ident))))]
               (let [p (RoomPeer. n app-name)]
                 (vreset! holder p)
                 p))))))))

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/peer-kit.git