anear-js-api 0.3.26 → 0.3.29

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/lib/index.js CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  const JsonApiResource = require('./models/JsonApiResource')
4
4
  const JsonApiArrayResource = require('./models/JsonApiArrayResource')
5
- const {AnearEvent, logger} = require('./models/AnearEvent')
5
+ const AnearEvent = require('./models/AnearEvent')
6
+ const logger = require('./utils/Logger')
6
7
  const AnearParticipant = require('./models/AnearParticipant')
7
8
  const AnearMessaging = require('./messaging/AnearMessaging')
8
9
  const AnearApiService = require('./api/ApiService')
@@ -385,7 +385,7 @@ class AnearMessaging {
385
385
  await this.closeParticipant(
386
386
  anearEvent,
387
387
  participantId,
388
- (anearEvent, participant) => anearEvent.participantClose(participant)
388
+ (anearEvent, participant) => anearEvent.participantExit(participant)
389
389
  )
390
390
  }
391
391
 
@@ -451,7 +451,7 @@ class AnearMessaging {
451
451
  }
452
452
 
453
453
  async participantLeaveMessagingCallback(anearEvent, message) {
454
- // this can be just a temporary leave (refresh browser for example), so pause any participant timers
454
+ // this can be just a temporary leave (a participant refreshing their browser for example), so pause any participant timers
455
455
  const userId = message.clientId
456
456
  const participantId = message.data.id
457
457
 
@@ -460,7 +460,11 @@ class AnearMessaging {
460
460
  this.interruptParticipantTimer(participantId)
461
461
  }
462
462
 
463
- async closeParticipant(anearEvent, participantId, callback) {
463
+ async closeParticipant(anearEvent, participantId, callback = null) {
464
+ // closes out a single Participant. This is invoked when a single
465
+ // participant leaves an event, and the event may possibly continue,
466
+ // or possibly exit. Or this may be called by the event when exiting
467
+ // and cleaning out any remaining participants.
464
468
  logger.debug(`closeParticipant(${participantId})`)
465
469
 
466
470
  this.destroyParticipantTimer(participantId)
@@ -471,7 +475,9 @@ class AnearMessaging {
471
475
  await this.detachParticipantPrivateChannel(anearEvent.id, participant)
472
476
 
473
477
  await this.runExclusive("closeParticipant", async () => {
474
- await callback(anearEvent, participant)
478
+ if (callback) {
479
+ await callback(anearEvent, participant)
480
+ }
475
481
  await anearEvent.update()
476
482
  })
477
483
  }
@@ -140,8 +140,8 @@ class AnearEvent extends JsonApiResource {
140
140
  // You may implement an async spectatorRefreshEventCallback() in your AnearEvent sub-class
141
141
  }
142
142
 
143
- async participantCloseEventCallback(participant) {
144
- throw new Error('You must implement an async participantCloseEventCallback() in your AnearEvent sub-class');
143
+ async participantExitEventCallback(participant) {
144
+ throw new Error('You must implement an async participantExitEventCallback() in your AnearEvent sub-class');
145
145
  }
146
146
 
147
147
  async participantActionEventCallback(participant, actionEventName, message) {
@@ -221,11 +221,11 @@ class AnearEvent extends JsonApiResource {
221
221
  }
222
222
  }
223
223
 
224
- async participantClose(participant) {
224
+ async participantExit(participant) {
225
+ // this informs the state machine that the participant has exited the event
226
+ // and removes that participant completely
227
+ this.anearStateMachine.sendParticipantExitEvent({ participant })
225
228
  this.participants.purge(participant)
226
-
227
- this.anearStateMachine.sendCloseEvent({ participant })
228
-
229
229
  await participant.remove()
230
230
  }
231
231
 
@@ -285,15 +285,29 @@ class AnearEvent extends JsonApiResource {
285
285
  }
286
286
 
287
287
  async transitionClosed() {
288
- this.cancelParticipantTimers()
288
+ await this.closeOutParticipants()
289
289
  await this.transitionNextNext()
290
290
  }
291
291
 
292
292
  async transitionCanceled() {
293
- this.cancelParticipantTimers()
293
+ await this.closeOutParticipants()
294
294
  await this.transitionEvent('cancel')
295
295
  }
296
296
 
297
+ async closeOutParticipants() {
298
+ // upon exiting the event, this will clean up
299
+ // any participants remaining
300
+ return Promise.all(
301
+ this.participants.all.map(
302
+ async participant => {
303
+ await this.messaging.closeParticipant(this, participant.id)
304
+ await participant.remove()
305
+ this.participants.purge(participant)
306
+ }
307
+ )
308
+ )
309
+ }
310
+
297
311
  eventChannelName () {
298
312
  return this.getChannelName('event')
299
313
  }
@@ -327,7 +341,4 @@ class AnearEvent extends JsonApiResource {
327
341
  }
328
342
  }
329
343
 
330
- module.exports = {
331
- AnearEvent,
332
- logger
333
- }
344
+ module.exports = AnearEvent
@@ -4,8 +4,9 @@ const { createMachine, interpret, State } = require('xstate')
4
4
  const logger = require('../utils/Logger')
5
5
 
6
6
  const JoinEvent = 'JOIN'
7
+ const ParticipantExitEvent = 'PARTICIPANT_EXIT'
7
8
  const RefreshEvent = 'REFRESH'
8
- const CloseEvent = 'CLOSE'
9
+ const CloseEvent = 'EVENT_CLOSE'
9
10
  const TimeoutEvent = 'TIMEOUT'
10
11
 
11
12
  class AnearXstate {
@@ -50,6 +51,10 @@ class AnearXstate {
50
51
  this.send(CloseEvent, params)
51
52
  }
52
53
 
54
+ sendParticipantExitEvent(params) {
55
+ this.send(ParticipantExitEvent, params)
56
+ }
57
+
53
58
  sendTimeoutEvent(params) {
54
59
  this.send(TimeoutEvent, params)
55
60
  }
@@ -35,8 +35,8 @@ const DefaultConfigFunc = (anearEvent) => {
35
35
  REFRESH: {
36
36
  target: 'refresh'
37
37
  },
38
- CLOSE: {
39
- target: 'close'
38
+ PARTICIPANT_EXIT: {
39
+ target: 'participant_exit'
40
40
  },
41
41
  TIMEOUT: {
42
42
  target: 'timeout'
@@ -62,10 +62,10 @@ const DefaultConfigFunc = (anearEvent) => {
62
62
  ...PromiseResolveReject
63
63
  }
64
64
  },
65
- close: {
65
+ participant_exit: {
66
66
  invoke: {
67
- id: 'close',
68
- src: 'closeEventHandler',
67
+ id: 'participant_exit',
68
+ src: 'participantExitEventHandler',
69
69
  ...PromiseResolveReject
70
70
  }
71
71
  },
@@ -95,7 +95,7 @@ const DefaultOptionsFunc = anearEvent => {
95
95
  services: {
96
96
  joinEventHandler: (context, event) => anearEvent.participantEnterEventCallback(event.participant),
97
97
  refreshEventHandler: (context, event) => anearEvent.participantRefreshEventCallback(event.participant, event.remainingTimeout),
98
- closeEventHandler: (context, event) => anearEvent.participantCloseEventCallback(event.participant),
98
+ participantExitEventHandler: (context, event) => anearEvent.participantExitEventCallback(event.participant),
99
99
  timeoutEventHandler: (context, event) => anearEvent.participantTimedOutEventCallback(event.participant),
100
100
  actionEventHandler: (context, event) => anearEvent.participantActionEventCallback(event.participant, event.type, event.payload)
101
101
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anear-js-api",
3
- "version": "0.3.26",
3
+ "version": "0.3.29",
4
4
  "description": "Javascript Developer API for Anear Apps",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -1,12 +1,12 @@
1
1
  "use strict"
2
2
  const { assign } = require('xstate')
3
- const { AnearEvent } = require('../lib/models/AnearEvent')
3
+ const AnearEvent = require('../lib/models/AnearEvent')
4
4
  const AnearParticipant = require('../lib/models/AnearParticipant')
5
5
  const MockMessaging = require('../lib/messaging/__mocks__/AnearMessaging')
6
6
 
7
7
  const mockParticipantEnterHandler = jest.fn()
8
8
  const mockParticipantRefreshHandler = jest.fn()
9
- const mockParticipantCloseHandler = jest.fn()
9
+ const mockParticipantExitHandler = jest.fn()
10
10
  const mockParticipantActionHandler = jest.fn()
11
11
 
12
12
  const TicTacToeMachineConfig = anearEvent => ({
@@ -30,8 +30,8 @@ const TicTacToeMachineConfig = anearEvent => ({
30
30
  REFRESH: {
31
31
  actions: 'refreshHandler'
32
32
  },
33
- CLOSE: {
34
- actions: 'closeHandler'
33
+ PARTICIPANT_EXIT: {
34
+ actions: 'participantExitHandler'
35
35
  }
36
36
  }
37
37
  },
@@ -40,8 +40,8 @@ const TicTacToeMachineConfig = anearEvent => ({
40
40
  BULLSEYE: {
41
41
  actions: 'actionHandler'
42
42
  },
43
- CLOSE: {
44
- actions: 'closeHandler'
43
+ PARTICIPANT_EXIT: {
44
+ actions: 'participantExitHandler'
45
45
  },
46
46
  REFRESH: {
47
47
  actions: 'refreshHandler'
@@ -59,8 +59,8 @@ const TicTacToeMachineOptions = anearEvent => ({
59
59
  refreshHandler: (context, event) => {
60
60
  anearEvent.myParticipantRefreshHandler(event.participant)
61
61
  },
62
- closeHandler: (context, event) => {
63
- anearEvent.myParticipantCloseHandler(event.participant)
62
+ participantExitHandler: (context, event) => {
63
+ anearEvent.myParticipantExitHandler(event.participant)
64
64
  },
65
65
  actionHandler: assign({score: (context, event) => context.score + event.payload.points}),
66
66
  }
@@ -84,8 +84,8 @@ class TestEvent extends AnearEvent {
84
84
  async myParticipantEnterHandler(...args) {
85
85
  return mockParticipantEnterHandler(...args)
86
86
  }
87
- async myParticipantCloseHandler(...args) {
88
- return mockParticipantCloseHandler(...args)
87
+ async myParticipantExitHandler(...args) {
88
+ return mockParticipantExitHandler(...args)
89
89
  }
90
90
  async myParticipantRefreshHandler(...args) {
91
91
  return mockParticipantRefreshHandler(...args)
@@ -110,8 +110,8 @@ class TestEventWithDefaultXState extends AnearEvent {
110
110
  return Promise.resolve()
111
111
  }
112
112
 
113
- participantCloseEventCallback(participant) {
114
- mockParticipantCloseHandler(participant)
113
+ participantExitEventCallback(participant) {
114
+ mockParticipantExitHandler(participant)
115
115
  return Promise.resolve()
116
116
  }
117
117
 
@@ -181,11 +181,11 @@ test('participant close with Default Xstate Config', async () => {
181
181
 
182
182
  const p1 = new TestPlayer(chatParticipant1)
183
183
 
184
- await t.participantClose(p1)
184
+ await t.participantExit(p1)
185
185
  await t.update()
186
186
 
187
- expect(mockParticipantCloseHandler).toHaveBeenCalledWith(p1)
188
- expect(mockParticipantCloseHandler).toHaveBeenCalledTimes(1)
187
+ expect(mockParticipantExitHandler).toHaveBeenCalledWith(p1)
188
+ expect(mockParticipantExitHandler).toHaveBeenCalledTimes(1)
189
189
  expect(t.participants.numActive(false)).toBe(0)
190
190
 
191
191
  await t.remove()
@@ -252,14 +252,14 @@ test('can add participants, not hosted', async () => {
252
252
  expect(t.participants.get(p2).name).toBe("bbondfl93")
253
253
  expect(p2.userType).toBe("participant")
254
254
 
255
- await t.participantClose(p1)
256
- await t.participantClose(p2)
255
+ await t.participantExit(p1)
256
+ await t.participantExit(p2)
257
257
  await t.update()
258
258
  await t.remove()
259
259
 
260
- expect(mockParticipantCloseHandler).toHaveBeenCalledWith(p1)
261
- expect(mockParticipantCloseHandler).toHaveBeenCalledWith(p2)
262
- expect(mockParticipantCloseHandler).toHaveBeenCalledTimes(2)
260
+ expect(mockParticipantExitHandler).toHaveBeenCalledWith(p1)
261
+ expect(mockParticipantExitHandler).toHaveBeenCalledWith(p2)
262
+ expect(mockParticipantExitHandler).toHaveBeenCalledTimes(2)
263
263
  expect(t.participants.numActive(false)).toBe(0)
264
264
  })
265
265
 
@@ -291,14 +291,14 @@ test('can add participant, hosted', async () => {
291
291
  expect(t.participants.numActive(false)).toBe(1)
292
292
  expect(t.participants.get(p2).name).toBe('bbondfl93')
293
293
 
294
- await t.participantClose(host)
295
- await t.participantClose(p2)
294
+ await t.participantExit(host)
295
+ await t.participantExit(p2)
296
296
  await t.update()
297
297
  await t.remove()
298
298
 
299
- expect(mockParticipantCloseHandler).toHaveBeenCalledWith(host)
300
- expect(mockParticipantCloseHandler).toHaveBeenCalledWith(p2)
301
- expect(mockParticipantCloseHandler).toHaveBeenCalledTimes(2)
299
+ expect(mockParticipantExitHandler).toHaveBeenCalledWith(host)
300
+ expect(mockParticipantExitHandler).toHaveBeenCalledWith(p2)
301
+ expect(mockParticipantExitHandler).toHaveBeenCalledTimes(2)
302
302
  expect(t.participants.numActive(false)).toBe(0)
303
303
  })
304
304
 
@@ -327,8 +327,8 @@ test('can be retrieved back from storage with participants, not hosted', async (
327
327
  expect(rehydratedPlayer1.context.name).toBe('machvee')
328
328
  expect(rehydratedPlayer2.context.name).toBe('bbondfl93')
329
329
 
330
- await rehydratedTestEvent.participantClose(rehydratedPlayer1)
331
- await rehydratedTestEvent.participantClose(rehydratedPlayer2)
330
+ await rehydratedTestEvent.participantExit(rehydratedPlayer1)
331
+ await rehydratedTestEvent.participantExit(rehydratedPlayer2)
332
332
  await rehydratedTestEvent.remove()
333
333
  })
334
334
 
@@ -354,8 +354,9 @@ test('can update state machine context via Action events', async () => {
354
354
 
355
355
  expect(t.anearStateMachine.context.score).toBe(92)
356
356
 
357
- await t.participantClose(p1)
358
- await t.participantClose(p2)
357
+ await t.participantExit(p1)
358
+ await t.participantExit(p2)
359
+ await t.closeOutParticipants()
359
360
  await t.remove()
360
361
  })
361
362
 
@@ -374,7 +375,7 @@ test('can reset All ParticipantTimers', async () => {
374
375
 
375
376
  expect(resetMock).toHaveBeenCalledTimes(1)
376
377
 
377
- await t.participantClose(p1)
378
- await t.participantClose(p2)
378
+ await t.participantExit(p1)
379
+ await t.participantExit(p2)
379
380
  await t.remove()
380
381
  })