anear-js-api 0.4.2 → 0.4.4

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.
@@ -42,14 +42,10 @@ class AnearApi extends ApiService {
42
42
  logger.debug(`API: POST transition event ${eventName}`)
43
43
 
44
44
  const relationships = {event: eventId}
45
- try {
46
- const json = await this.post("transitions", {event_name: eventName}, relationships)
47
- const attrs = json.data.attributes
48
- logger.info(`API: newState is ${attrs.state}`)
49
- return attrs
50
- } catch(err) {
51
- logger.error(err)
52
- }
45
+ const json = await this.post("transitions", {event_name: eventName}, relationships)
46
+ const attrs = json.data.attributes
47
+ logger.debug(`API: newState is ${attrs.state}`)
48
+ return attrs
53
49
  }
54
50
 
55
51
  async getEventParticipantJson(participantId, geoLocation) {
@@ -28,6 +28,7 @@ class AnearMessaging {
28
28
  this.AnearEventClass = AnearEventClass
29
29
  this.AnearParticipantClass = AnearParticipantClass
30
30
  this.anearEvents = {}
31
+ this.eventChannels = {}
31
32
 
32
33
  const baseUrl = this.api.api_base_url
33
34
  const authUrl = `${baseUrl}/messaging_auth`
@@ -49,8 +50,6 @@ class AnearMessaging {
49
50
  }
50
51
  }
51
52
 
52
- this.eventChannels = {}
53
-
54
53
  this.initRealtime(clientOptions)
55
54
  }
56
55
 
@@ -59,30 +58,35 @@ class AnearMessaging {
59
58
 
60
59
  this.realtime = new Ably.Realtime(clientOptions)
61
60
 
62
- this.realtime.connection.on(
63
- "connected",
64
- async () => {
65
- await this.getAppInfo(AppId)
66
- logger.info("Ably connected!")
67
- await this.setupCreateEventChannel()
68
- await this.reloadAnyEventsInProgress(AppId)
69
- }
70
- )
61
+ const connectedCallback = async () => {
62
+ await this.getAppInfo(AppId)
63
+ logger.debug("Ably connected!")
64
+ await this.setupCreateEventChannel()
65
+ await this.reloadAnyEventsInProgress(AppId)
66
+ }
67
+
68
+ this.realtime.connection.on("connected", connectedCallback)
71
69
  }
72
70
 
73
71
  async getAppInfo(appId) {
72
+ // fetch the App info from the Anear API
74
73
  const anearApp = await this.api.getApp(appId)
75
- logger.info("================")
76
- logger.info(`STARTING APP ${anearApp.data.attributes['short-name']}`)
77
- logger.info("================")
74
+
75
+ logger.debug("================")
76
+ logger.debug(`STARTING APP ${anearApp.data.attributes['short-name']}`)
77
+ logger.debug("================")
78
78
  }
79
79
 
80
80
  getChannel(channelName, channelParams = ChannelParams) {
81
81
  return this.realtime.channels.get(channelName, channelParams)
82
82
  }
83
83
 
84
- async getAnearEventFromStorage(eventId) {
85
- return await this.AnearEventClass.getFromStorage(eventId, this)
84
+ getAnearEventFromStorage(eventId) {
85
+ return this.AnearEventClass.getFromStorage(eventId, this)
86
+ }
87
+
88
+ getAnearParticipantFromStorage(participantId) {
89
+ return this.AnearParticipantClass.getFromStorage(participantId, this)
86
90
  }
87
91
 
88
92
  async initEventRealtimeMessaging(anearEvent) {
@@ -94,14 +98,10 @@ class AnearMessaging {
94
98
 
95
99
  this.eventChannels[anearEvent.id] = {privates: {}}
96
100
 
97
- try {
98
- await this.setupSpectatorsChannel(anearEvent)
99
- this.setupEventsChannel(anearEvent)
100
- await this.setupParticipantsChannel(anearEvent)
101
- await this.setupActionsChannel(anearEvent)
102
- } catch(error) {
103
- logger.error(`initEventRealtimeMessaging(${anearEvent.id}): `, error)
104
- }
101
+ await this.setupSpectatorsChannel(anearEvent)
102
+ this.setupEventsChannel(anearEvent)
103
+ await this.setupParticipantsChannel(anearEvent)
104
+ await this.setupActionsChannel(anearEvent)
105
105
 
106
106
  logger.debug(`initEventRealtimeMessaging(${anearEvent.id}) is complete`)
107
107
 
@@ -113,76 +113,75 @@ class AnearMessaging {
113
113
  // create the AnearEvent subclass, persist it in storage, and
114
114
  // initialize its realtime messaging
115
115
  //
116
- logger.info(`createEventMessagingCallback(${message.name})`)
117
-
118
- try {
119
- const eventJson = JSON.parse(message.data)
120
- const anearEvent = new this.AnearEventClass(eventJson, this)
121
-
122
- //
123
- // if we are getting this event create message from history after a quick restart,
124
- // we just return if the event already exists
125
- //
126
- const eventExists = await anearEvent.exists()
127
-
128
- logger.info(`Event ${anearEvent.id} ${eventExists ? "already exists" : "does not exist"} in Storage`)
129
-
130
- let loadedEvent = anearEvent
131
-
132
- if (!eventExists) {
133
- await anearEvent.runExclusive(`createEventCallback ${anearEvent.id}`, async () => {
134
- await anearEvent.createdEventCallback()
135
- await anearEvent.persist()
136
- // start the state machine before initialiing Realtime Messaging
137
- // as REFRESH events come in and the state machine should be ready
138
- // to handle those XState events
139
- anearEvent.startStateMachine()
140
- await this.initEventRealtimeMessaging(anearEvent)
141
- })
142
- } else {
143
- loadedEvent = await this.getAnearEventFromStorage(anearEvent.id)
144
- await this.initEventRealtimeMessaging(loadedEvent)
145
- loadedEvent.startStateMachine()
146
- }
116
+ logger.debug(`createEventMessagingCallback(${message.name})`)
117
+
118
+ const eventJson = JSON.parse(message.data)
119
+ const anearEvent = new this.AnearEventClass(eventJson, this)
120
+
121
+ //
122
+ // if we are getting this event create message from history after a quick restart,
123
+ // we just return if the event already exists
124
+ //
125
+ const eventExists = await anearEvent.exists()
147
126
 
148
- logger.info(`New ${loadedEvent.constructor.name} Event: `, loadedEvent.toJSON())
127
+ logger.debug(
128
+ `Event ${anearEvent.id} ${eventExists ? "already exists" : "does not exist"} in Storage`
129
+ )
149
130
 
150
- this.anearEvents[loadedEvent.id] = loadedEvent
131
+ let loadedEvent = anearEvent
132
+
133
+ if (!eventExists) {
134
+ const messagingInitializedCallback = async () => {
135
+ await anearEvent.createdEventCallback()
136
+ await anearEvent.persist()
137
+ // start the state machine before initializing Realtime Messaging
138
+ // as REFRESH events come in and the state machine should be ready
139
+ // to handle those XState events
140
+ anearEvent.startStateMachine()
141
+ await this.initEventRealtimeMessaging(anearEvent)
142
+ }
151
143
 
152
- } catch(err) {
153
- logger.error(err)
144
+ await anearEvent.runExclusive(
145
+ `createEventCallback ${anearEvent.id}`,
146
+ messagingInitializedCallback
147
+ )
148
+ } else {
149
+ loadedEvent = await this.getAnearEventFromStorage(anearEvent.id)
150
+ await this.initEventRealtimeMessaging(loadedEvent)
151
+ loadedEvent.startStateMachine()
154
152
  }
153
+
154
+ logger.debug(`New ${loadedEvent.constructor.name} Event: `, loadedEvent.toJSON())
155
+
156
+ this.anearEvents[loadedEvent.id] = loadedEvent
155
157
  }
156
158
 
157
159
  async reloadAnyEventsInProgress(appId) {
158
- try {
159
- const anearApp = await this.api.getAppZones(appId)
160
- for (const zone of anearApp.data.relationships.zones.data) {
161
- const zoneEvents = await this.api.getZoneEvents(zone.id)
162
- const events = zoneEvents.data.relationships.events.data
163
-
164
- for (const eventData of events) {
165
- const eventJson = await this.api.getEvent(eventData.id)
166
- const anearEvent = new this.AnearEventClass(eventJson, this)
167
- await this.initEventRealtimeMessaging(anearEvent)
168
-
169
- const attachedParticipants = this.getPresentParticipants(anearEvent)
170
- // TBD: might want to change the attach and presence logic on
171
- // the actions channel. The Ably docs show subscribing to the
172
- // presence events on the actions channel, and instead of using History,
173
- // it does a get() to fetch all of the current members. This behavior
174
- // is useful for both event start, and event restart within this function
175
- // anearEvent.startStateMachine()
176
- //
177
- }
160
+ const anearApp = await this.api.getAppZones(appId)
161
+
162
+ for (const zone of anearApp.data.relationships.zones.data) {
163
+ const zoneEvents = await this.api.getZoneEvents(zone.id)
164
+ const events = zoneEvents.data.relationships.events.data
165
+
166
+ for (const eventData of events) {
167
+ const eventJson = await this.api.getEvent(eventData.id)
168
+ const anearEvent = new this.AnearEventClass(eventJson, this)
169
+ await this.initEventRealtimeMessaging(anearEvent)
170
+
171
+ const attachedParticipants = await this.getPresentParticipants(anearEvent)
172
+ // TBD: might want to change the attach and presence logic on
173
+ // the actions channel. The Ably docs show subscribing to the
174
+ // presence events on the actions channel, and instead of using History,
175
+ // it does a get() to fetch all of the current members. This behavior
176
+ // is useful for both event start, and event restart within this function
177
+ // anearEvent.startStateMachine()
178
+ //
178
179
  }
179
- } catch (err) {
180
- logger.error(err)
181
180
  }
182
181
  }
183
182
 
184
183
  async setupCreateEventChannel() {
185
- logger.info(`attaching to channel ${AnearCreateEventChannelName}`)
184
+ logger.debug(`attaching to channel ${AnearCreateEventChannelName}`)
186
185
 
187
186
  const createEventsChannel = this.getChannel(AnearCreateEventChannelName)
188
187
 
@@ -228,11 +227,11 @@ class AnearMessaging {
228
227
  return members.length
229
228
  }
230
229
 
231
- async getPresentParticipants(anearEvent) {
230
+ getPresentParticipants(anearEvent) {
232
231
  // returns the participant presence data for each member who is present on
233
232
  // the event's actions channel
234
233
  const channel = this.eventChannels[anearEvent.id].actions
235
- return await channel.presence.get()
234
+ return channel.presence.get() // returns Promise
236
235
  }
237
236
 
238
237
  async setupActionsChannel(anearEvent) {
@@ -329,29 +328,22 @@ class AnearMessaging {
329
328
  // check if the participant is already in storage, and if so, instantiate, else
330
329
  // instantiate from API response
331
330
  //
332
- try {
333
- const participantJson = await this.api.getEventParticipantJson(participantId)
334
- const participant = new this.AnearParticipantClass(participantJson, anearEvent)
331
+ const participantJson = await this.api.getEventParticipantJson(participantId)
332
+ const participant = new this.AnearParticipantClass(participantJson, anearEvent)
335
333
 
336
- const persistedAnearParticipant = await this.AnearParticipantClass.getFromStorage(participantId, anearEvent)
334
+ const persistedAnearParticipant = await this.AnearParticipantClass.getFromStorage(participantId, anearEvent)
337
335
 
338
- if (persistedAnearParticipant) {
339
- participant.context = persistedAnearParticipant.context
340
- }
336
+ if (persistedAnearParticipant) {
337
+ participant.context = persistedAnearParticipant.context
338
+ }
341
339
 
342
- await anearEvent.runExclusive(`participantEnterCallback ${participant.id}`, async () => {
343
- participant.geoLocation = geoLocation
340
+ await anearEvent.runExclusive(`participantEnterCallback ${participant.id}`, async () => {
341
+ participant.geoLocation = geoLocation
344
342
 
345
- await this.setupPrivatePublishingChannel(participant)
346
- await anearEvent.participantEnter(participant)
347
- await anearEvent.update()
348
- })
349
- } catch(error) {
350
- // participant not found or is not currently marked active at the API service
351
- // don't allow participation. FIX: we need to publish to the private channel
352
- // with an error message type.
353
- logger.error(`processParticipanEnter(${anearEvent.id}, ${participantId}) error: `, error)
354
- }
343
+ await this.setupPrivatePublishingChannel(participant)
344
+ await anearEvent.participantEnter(participant)
345
+ await anearEvent.update()
346
+ })
355
347
  }
356
348
 
357
349
  async spectatorEnterMessagingCallback(anearEvent, message) {
@@ -454,11 +446,7 @@ class AnearMessaging {
454
446
  }
455
447
 
456
448
  async attachChannel(channel) {
457
- try {
458
- return await channel.attach()
459
- } catch(err) {
460
- this.logErrorInfo(err)
461
- }
449
+ return await channel.attach()
462
450
  }
463
451
 
464
452
  subscribeEventMessages(channel, messageType, callback) {
@@ -471,22 +459,18 @@ class AnearMessaging {
471
459
  }
472
460
 
473
461
  async subscribePresenceEventWithHistory(channel, action, callback) {
474
- logger.info(`subscribePresenceEvents(${action}) for channel ${channel.name}`)
462
+ logger.debug(`subscribePresenceEvents(${action}) for channel ${channel.name}`)
475
463
 
476
464
  this.subscribePresenceEvent(channel, action, callback)
477
465
 
478
- try {
479
- const history = await channel.presence.history({limit: 25})
466
+ const history = await channel.presence.history({limit: 25})
480
467
 
481
- history.items.filter(message => message.action === action).forEach(
482
- async message => {
483
- logger.info(`presence history ${action} event received`, message)
484
- await callback(message)
485
- }
486
- )
487
- } catch(err) {
488
- logger.error('Unable to get presence history; err = ' + err.message)
489
- }
468
+ history.items.filter(message => message.action === action).forEach(
469
+ async message => {
470
+ logger.debug(`presence history ${action} event received`, message)
471
+ await callback(message)
472
+ }
473
+ )
490
474
  }
491
475
 
492
476
  async publishEventSpectatorsMessage(anearEvent, css, message, messageType = PublicDisplayMessageType) {
@@ -592,14 +576,10 @@ class AnearMessaging {
592
576
  }
593
577
 
594
578
  async publishChannelMessage(channel, messageType, payload) {
595
- try {
596
- await channel.publish(
597
- messageType,
598
- payload
599
- )
600
- } catch(err) {
601
- this.logErrorInfo(err)
602
- }
579
+ await channel.publish(
580
+ messageType,
581
+ payload
582
+ )
603
583
  }
604
584
 
605
585
  async detachAll(eventId) {
@@ -621,17 +601,13 @@ class AnearMessaging {
621
601
  async detachChannel (channel) {
622
602
  if (!channel || channel.state !== 'attached') return
623
603
 
624
- try {
625
- await channel.detach(this.logErrorInfo)
626
- logger.info(`channel ${channel.name} detached`)
627
- } catch(err) {
628
- this.logErrorInfo(err)
629
- }
604
+ await channel.detach(this.logErrorInfo)
605
+ logger.debug(`channel ${channel.name} detached`)
630
606
  }
631
607
 
632
608
  logErrorInfo(errInfo) {
633
609
  if (errInfo) {
634
- logger.error(`Ably ERROR (${errInfo.code}): ${errInfo.message}`)
610
+ logger.error("Ably ERROR:", errInfo)
635
611
  }
636
612
  }
637
613
  }
@@ -11,6 +11,8 @@ const logger = require('../utils/Logger')
11
11
 
12
12
  const PrivateDisplayMessageType = 'private_display'
13
13
 
14
+ const PlayableStates = ['closing', 'closed', 'canceled']
15
+
14
16
  class AnearEvent extends JsonApiResource {
15
17
 
16
18
  constructor(json, messaging) {
@@ -64,7 +66,7 @@ class AnearEvent extends JsonApiResource {
64
66
  }
65
67
 
66
68
  async getClonedEvent() {
67
- // if the current event was a clone of previous event, try to fetch if from
69
+ // if the current event was a clone of previous event, fetch if from
68
70
  // Peristence and return
69
71
  const clonedEventData = this.relationships["cloned-event"].data
70
72
  if (!clonedEventData) return null
@@ -221,13 +223,13 @@ class AnearEvent extends JsonApiResource {
221
223
  if (this.participants.exists(participant)) {
222
224
  logger.info(`AnearEvent: participant ${participant.id} exists. Refreshing...`)
223
225
 
224
- this.participants.add(participant) // update the participants entry
226
+ this.participants.add(participant) // update the participants record
225
227
 
226
228
  this.anearStateMachine.sendRefreshEvent({ participant })
227
229
 
228
230
  await participant.update()
229
231
  } else {
230
- this.participants.add(participant) // add the participants entry
232
+ this.participants.add(participant) // add the participants record
231
233
 
232
234
  this.anearStateMachine.sendJoinEvent({ participant })
233
235
 
@@ -271,18 +273,14 @@ class AnearEvent extends JsonApiResource {
271
273
  //
272
274
  logger.debug(`AnearEvent: transitionEvent(${eventName})`)
273
275
 
274
- try {
275
- const responseAttributes = await this.messaging.api.transitionEvent(this.id, eventName)
276
- const newState = responseAttributes.state
277
- this.attributes.state = newState
278
- await this.messaging.publishEventTransitionMessage(this, newState)
279
- } catch(err) {
280
- logger.error(`AnearEvent: transitionEvent error: ${err}`)
281
- }
276
+ const responseAttributes = await this.messaging.api.transitionEvent(this.id, eventName)
277
+ const newState = responseAttributes.state
278
+ this.attributes.state = newState
279
+ await this.messaging.publishEventTransitionMessage(this, newState)
282
280
  }
283
281
 
284
282
  isPlayable() {
285
- return !['closing', 'closed', 'canceled'].includes(this.eventState)
283
+ return !PlayableStates.includes(this.eventState)
286
284
  }
287
285
 
288
286
  async transitionToAnnounce() {
@@ -311,10 +309,9 @@ class AnearEvent extends JsonApiResource {
311
309
  return Promise.all(
312
310
  this.participants.all.map(
313
311
  async p => {
314
- const participant = await this.messaging.getAnearParticipantFromStorage(p.id)
315
312
  await this.messaging.closeParticipant(
316
313
  this,
317
- participant.id,
314
+ p.id,
318
315
  async (anearEvent, participant) => {
319
316
  await anearEvent.participantPurge(participant)
320
317
  }
@@ -11,7 +11,12 @@ const TimeoutEvent = 'TIMEOUT'
11
11
 
12
12
  class AnearXstate {
13
13
  constructor(machineConfig, machineOptions, previousState, anearEventContext) {
14
- this.machine = createMachine(machineConfig, machineOptions).withContext(anearEventContext)
14
+ const config = {predictableActionArguments: true, ...machineConfig}
15
+
16
+ this.machine = createMachine(
17
+ config,
18
+ machineOptions
19
+ ).withContext(anearEventContext)
15
20
 
16
21
  this._currentState = previousState ? State.create(previousState) : this.machine.initialState
17
22
  this._currentContext = anearEventContext
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anear-js-api",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Javascript Developer API for Anear Apps",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {