Skip to content

Commit 46d47fc

Browse files
author
Alex Yang
committed
add index.ts
1 parent 22f8059 commit 46d47fc

File tree

6 files changed

+292
-2
lines changed

6 files changed

+292
-2
lines changed

.DS_Store

6 KB
Binary file not shown.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
dist

package-lock.json

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
"name": "mock-echo",
33
"version": "0.0.1",
44
"description": "Mock laravel Echo",
5-
"main": "index.js",
5+
"main": "dist/index.js",
66
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1"
7+
"build": "tsc",
8+
"dev": "tsc -w",
9+
"prepublish": "npm run build"
810
},
911
"repository": {
1012
"type": "git",
@@ -20,5 +22,13 @@
2022
"bugs": {
2123
"url": "https://github.com/alexxiyang/mock-echo/issues"
2224
},
25+
"dependencies": {
26+
"lodash": "^4.17.10"
27+
},
28+
"devDependencies": {
29+
"@types/lodash": "^4.14.93",
30+
"@types/node": "^6.0.60",
31+
"typescript": "^2.6.0"
32+
},
2333
"homepage": "https://github.com/alexxiyang/mock-echo#readme"
2434
}

src/index.ts

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import _ from 'lodash'
2+
3+
class Channel {
4+
events: object
5+
clientEvents: Array<string>
6+
constructor () {
7+
this.events = {}
8+
}
9+
listen (eventName: string, fn: any) {
10+
this.events[eventName] = fn;
11+
return this
12+
}
13+
broadcast (eventName, event) {
14+
if (typeof this.events[eventName] === 'undefined') {
15+
console.error(`Channel didn't listen to event: ${eventName}`);
16+
return
17+
}
18+
this.events[eventName](event);
19+
}
20+
eventExist (eventName) {
21+
return typeof this.events[eventName] !== 'undefined'
22+
}
23+
24+
clientEventExist (eventName) {
25+
return typeof this.clientEvents[`client-${eventName}`] !== 'undefined'
26+
}
27+
}
28+
29+
class PrivateChannel extends Channel {
30+
clientEvents: Array<string>
31+
notificationFn: any
32+
constructor () {
33+
super()
34+
this.clientEvents = []
35+
this.notificationFn = null
36+
}
37+
38+
userWhisper (eventName, event) {
39+
if (typeof this.clientEvents[`client-${eventName}`] === 'undefined') {
40+
console.error(`Channel didn't listen to client event: ${eventName}`)
41+
return
42+
}
43+
this.clientEvents[`client-${eventName}`](event)
44+
}
45+
46+
listenForWhisper (eventName, whisperFn) {
47+
this.clientEvents[`client-${eventName}`] = whisperFn
48+
return this
49+
}
50+
51+
notification (notificationFn) {
52+
this.notificationFn = notificationFn
53+
return this
54+
}
55+
56+
notify (notifiable) {
57+
this.notificationFn(notifiable)
58+
}
59+
}
60+
61+
class PresenceChannel extends PrivateChannel {
62+
users: Array<any>
63+
hereFn: any
64+
joiningFn: any
65+
leavingFn: any
66+
67+
constructor () {
68+
super()
69+
this.users = []
70+
this.hereFn = null
71+
this.joiningFn = null
72+
this.leavingFn = null
73+
}
74+
75+
iJoin (user: any) {
76+
if (user == null) {
77+
console.error('user is null!')
78+
return
79+
}
80+
81+
user.subId = Math.floor(Math.random() * 1000)
82+
this.users.push(user)
83+
84+
let broadcastUsers = this.getBroadcastUsers()
85+
this.hereFn(broadcastUsers)
86+
}
87+
userJoin (user) {
88+
if (user == null) {
89+
console.error('user is null!')
90+
return
91+
}
92+
93+
let subId = Math.floor(Math.random() * 1000)
94+
user.subId = subId
95+
this.users.push(user)
96+
97+
let broadcastUser = this.getBroadcastUser(user)
98+
this.joiningFn(broadcastUser)
99+
100+
return subId;
101+
}
102+
userLeave (subId) {
103+
if (subId == null) {
104+
console.error('subId is null!')
105+
return
106+
}
107+
108+
let leavingUser = this.findUserBySubId(subId)
109+
if (leavingUser == null) {
110+
console.error(`Cannot find user by subId ${subId} !`)
111+
return
112+
}
113+
let broadcastUser = this.getBroadcastUser(leavingUser)
114+
this.leavingFn(broadcastUser)
115+
}
116+
findUserBySubId (subId) {
117+
let targetUser = null
118+
for(let i = this.users.length -1; i >= 0 ; i--){
119+
let user = this.users[i]
120+
if (user.subId === subId) {
121+
targetUser = user
122+
this.users.splice(i, 1)
123+
}
124+
}
125+
return targetUser
126+
}
127+
getBroadcastUser (user) {
128+
let broadcastUser = _.cloneDeep(user)
129+
delete broadcastUser['subId']
130+
return broadcastUser
131+
}
132+
getBroadcastUsers () {
133+
let broadcastUsers = []
134+
for (let i = 0; i < this.users.length; i++) {
135+
broadcastUsers.push(this.getBroadcastUser(this.users[i]))
136+
}
137+
return broadcastUsers
138+
}
139+
here (fn) {
140+
this.hereFn = fn
141+
return this
142+
}
143+
joining (fn) {
144+
this.joiningFn = fn
145+
return this
146+
}
147+
leaving (fn) {
148+
this.leavingFn = fn
149+
return this
150+
}
151+
152+
notification (notificationFn) {
153+
console.error(`Presence channel doesn't support notification`)
154+
return this
155+
}
156+
}
157+
158+
class MockEcho {
159+
channels: object
160+
constructor () {
161+
this.channels = {};
162+
}
163+
private(channelName) {
164+
return this.listenChannelByFullName(`private-${channelName}`);
165+
}
166+
channel(channelName) {
167+
return this.listenChannelByFullName(channelName);
168+
}
169+
join(channelName) {
170+
let presenceChannel = this.listenChannelByFullName(`presence-${channelName}`)
171+
return presenceChannel
172+
}
173+
174+
listenChannelByFullName(fullName) {
175+
if (typeof this.channels[fullName] === 'undefined') {
176+
if (fullName.startsWith('presence-')) {
177+
this.channels[fullName] = new PresenceChannel()
178+
} else if (fullName.startsWith('private-')) {
179+
this.channels[fullName] = new PrivateChannel()
180+
} else {
181+
this.channels[fullName] = new Channel()
182+
}
183+
}
184+
return this.channels[fullName]
185+
}
186+
getPrivateChannel(channelName) {
187+
return this.getChannelByFullName(`private-${channelName}`);
188+
}
189+
getChannel(channelName) {
190+
return this.getChannelByFullName(channelName);
191+
}
192+
getPresenceChannel (channelName) {
193+
return this.getChannelByFullName(`presence-${channelName}`);
194+
}
195+
getChannelByFullName(fullName) {
196+
if (typeof this.channels[fullName] === 'undefined') {
197+
console.error(`Echo doesn't have channel: ${fullName}`);
198+
return
199+
}
200+
return this.channels[fullName];
201+
}
202+
channelExistByFullName (fullName) {
203+
return typeof this.channels[fullName] !== 'undefined';
204+
}
205+
privateChannelExist (channelName) {
206+
return this.channelExistByFullName(`private-${channelName}`)
207+
}
208+
channelExist (channelName) {
209+
return this.channelExistByFullName(channelName)
210+
}
211+
presenceChannelExist (channelName) {
212+
return this.channelExistByFullName(`presence-${channelName}`)
213+
}
214+
}
215+
216+
export default MockEcho;

tsconfig.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"compilerOptions": {
3+
"allowSyntheticDefaultImports": true,
4+
"module": "commonjs",
5+
"moduleResolution": "node",
6+
"noImplicitAny": false,
7+
"outDir": "./dist",
8+
"pretty": true,
9+
"preserveConstEnums": true,
10+
"removeComments": true,
11+
"target": "es5",
12+
"lib": ["es2015", "dom"],
13+
"types": ["node"]
14+
},
15+
"files": [
16+
"src/index.ts"
17+
],
18+
"exclude": [
19+
"node_modules"
20+
],
21+
"compileOnSave": false,
22+
"buildOnSave": false,
23+
"atom": {
24+
"formatOnSave": false,
25+
"rewriteTsconfig": false
26+
},
27+
"typeRoots": [
28+
"../node_modules/@types"
29+
]
30+
}
31+

0 commit comments

Comments
 (0)