anear-js-api 0.4.3 → 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,34 +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
86
  }
87
87
 
88
- async getAnearParticipantFromStorage(participantId) {
89
- return await this.AnearParticipantClass.getFromStorage(participantId, this)
88
+ getAnearParticipantFromStorage(participantId) {
89
+ return this.AnearParticipantClass.getFromStorage(participantId, this)
90
90
  }
91
91
 
92
92
  async initEventRealtimeMessaging(anearEvent) {
@@ -98,14 +98,10 @@ class AnearMessaging {
98
98
 
99
99
  this.eventChannels[anearEvent.id] = {privates: {}}
100
100
 
101
- try {
102
- await this.setupSpectatorsChannel(anearEvent)
103
- this.setupEventsChannel(anearEvent)
104
- await this.setupParticipantsChannel(anearEvent)
105
- await this.setupActionsChannel(anearEvent)
106
- } catch(error) {
107
- logger.error(`initEventRealtimeMessaging(${anearEvent.id}): `, error)
108
- }
101
+ await this.setupSpectatorsChannel(anearEvent)
102
+ this.setupEventsChannel(anearEvent)
103
+ await this.setupParticipantsChannel(anearEvent)
104
+ await this.setupActionsChannel(anearEvent)
109
105
 
110
106
  logger.debug(`initEventRealtimeMessaging(${anearEvent.id}) is complete`)
111
107
 
@@ -117,76 +113,75 @@ class AnearMessaging {
117
113
  // create the AnearEvent subclass, persist it in storage, and
118
114
  // initialize its realtime messaging
119
115
  //
120
- logger.info(`createEventMessagingCallback(${message.name})`)
121
-
122
- try {
123
- const eventJson = JSON.parse(message.data)
124
- const anearEvent = new this.AnearEventClass(eventJson, this)
125
-
126
- //
127
- // if we are getting this event create message from history after a quick restart,
128
- // we just return if the event already exists
129
- //
130
- const eventExists = await anearEvent.exists()
131
-
132
- logger.info(`Event ${anearEvent.id} ${eventExists ? "already exists" : "does not exist"} in Storage`)
133
-
134
- let loadedEvent = anearEvent
135
-
136
- if (!eventExists) {
137
- await anearEvent.runExclusive(`createEventCallback ${anearEvent.id}`, async () => {
138
- await anearEvent.createdEventCallback()
139
- await anearEvent.persist()
140
- // start the state machine before initialiing Realtime Messaging
141
- // as REFRESH events come in and the state machine should be ready
142
- // to handle those XState events
143
- anearEvent.startStateMachine()
144
- await this.initEventRealtimeMessaging(anearEvent)
145
- })
146
- } else {
147
- loadedEvent = await this.getAnearEventFromStorage(anearEvent.id)
148
- await this.initEventRealtimeMessaging(loadedEvent)
149
- loadedEvent.startStateMachine()
150
- }
116
+ logger.debug(`createEventMessagingCallback(${message.name})`)
151
117
 
152
- logger.info(`New ${loadedEvent.constructor.name} Event: `, loadedEvent.toJSON())
118
+ const eventJson = JSON.parse(message.data)
119
+ const anearEvent = new this.AnearEventClass(eventJson, this)
153
120
 
154
- this.anearEvents[loadedEvent.id] = loadedEvent
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()
126
+
127
+ logger.debug(
128
+ `Event ${anearEvent.id} ${eventExists ? "already exists" : "does not exist"} in Storage`
129
+ )
130
+
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
+ }
155
143
 
156
- } catch(err) {
157
- 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()
158
152
  }
153
+
154
+ logger.debug(`New ${loadedEvent.constructor.name} Event: `, loadedEvent.toJSON())
155
+
156
+ this.anearEvents[loadedEvent.id] = loadedEvent
159
157
  }
160
158
 
161
159
  async reloadAnyEventsInProgress(appId) {
162
- try {
163
- const anearApp = await this.api.getAppZones(appId)
164
- for (const zone of anearApp.data.relationships.zones.data) {
165
- const zoneEvents = await this.api.getZoneEvents(zone.id)
166
- const events = zoneEvents.data.relationships.events.data
167
-
168
- for (const eventData of events) {
169
- const eventJson = await this.api.getEvent(eventData.id)
170
- const anearEvent = new this.AnearEventClass(eventJson, this)
171
- await this.initEventRealtimeMessaging(anearEvent)
172
-
173
- const attachedParticipants = this.getPresentParticipants(anearEvent)
174
- // TBD: might want to change the attach and presence logic on
175
- // the actions channel. The Ably docs show subscribing to the
176
- // presence events on the actions channel, and instead of using History,
177
- // it does a get() to fetch all of the current members. This behavior
178
- // is useful for both event start, and event restart within this function
179
- // anearEvent.startStateMachine()
180
- //
181
- }
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
+ //
182
179
  }
183
- } catch (err) {
184
- logger.error(err)
185
180
  }
186
181
  }
187
182
 
188
183
  async setupCreateEventChannel() {
189
- logger.info(`attaching to channel ${AnearCreateEventChannelName}`)
184
+ logger.debug(`attaching to channel ${AnearCreateEventChannelName}`)
190
185
 
191
186
  const createEventsChannel = this.getChannel(AnearCreateEventChannelName)
192
187
 
@@ -232,11 +227,11 @@ class AnearMessaging {
232
227
  return members.length
233
228
  }
234
229
 
235
- async getPresentParticipants(anearEvent) {
230
+ getPresentParticipants(anearEvent) {
236
231
  // returns the participant presence data for each member who is present on
237
232
  // the event's actions channel
238
233
  const channel = this.eventChannels[anearEvent.id].actions
239
- return await channel.presence.get()
234
+ return channel.presence.get() // returns Promise
240
235
  }
241
236
 
242
237
  async setupActionsChannel(anearEvent) {
@@ -333,29 +328,22 @@ class AnearMessaging {
333
328
  // check if the participant is already in storage, and if so, instantiate, else
334
329
  // instantiate from API response
335
330
  //
336
- try {
337
- const participantJson = await this.api.getEventParticipantJson(participantId)
338
- const participant = new this.AnearParticipantClass(participantJson, anearEvent)
331
+ const participantJson = await this.api.getEventParticipantJson(participantId)
332
+ const participant = new this.AnearParticipantClass(participantJson, anearEvent)
339
333
 
340
- const persistedAnearParticipant = await this.AnearParticipantClass.getFromStorage(participantId, anearEvent)
334
+ const persistedAnearParticipant = await this.AnearParticipantClass.getFromStorage(participantId, anearEvent)
341
335
 
342
- if (persistedAnearParticipant) {
343
- participant.context = persistedAnearParticipant.context
344
- }
336
+ if (persistedAnearParticipant) {
337
+ participant.context = persistedAnearParticipant.context
338
+ }
345
339
 
346
- await anearEvent.runExclusive(`participantEnterCallback ${participant.id}`, async () => {
347
- participant.geoLocation = geoLocation
340
+ await anearEvent.runExclusive(`participantEnterCallback ${participant.id}`, async () => {
341
+ participant.geoLocation = geoLocation
348
342
 
349
- await this.setupPrivatePublishingChannel(participant)
350
- await anearEvent.participantEnter(participant)
351
- await anearEvent.update()
352
- })
353
- } catch(error) {
354
- // participant not found or is not currently marked active at the API service
355
- // don't allow participation. FIX: we need to publish to the private channel
356
- // with an error message type.
357
- logger.error(`processParticipanEnter(${anearEvent.id}, ${participantId}) error: `, error)
358
- }
343
+ await this.setupPrivatePublishingChannel(participant)
344
+ await anearEvent.participantEnter(participant)
345
+ await anearEvent.update()
346
+ })
359
347
  }
360
348
 
361
349
  async spectatorEnterMessagingCallback(anearEvent, message) {
@@ -458,11 +446,7 @@ class AnearMessaging {
458
446
  }
459
447
 
460
448
  async attachChannel(channel) {
461
- try {
462
- return await channel.attach()
463
- } catch(err) {
464
- this.logErrorInfo(err)
465
- }
449
+ return await channel.attach()
466
450
  }
467
451
 
468
452
  subscribeEventMessages(channel, messageType, callback) {
@@ -475,22 +459,18 @@ class AnearMessaging {
475
459
  }
476
460
 
477
461
  async subscribePresenceEventWithHistory(channel, action, callback) {
478
- logger.info(`subscribePresenceEvents(${action}) for channel ${channel.name}`)
462
+ logger.debug(`subscribePresenceEvents(${action}) for channel ${channel.name}`)
479
463
 
480
464
  this.subscribePresenceEvent(channel, action, callback)
481
465
 
482
- try {
483
- const history = await channel.presence.history({limit: 25})
466
+ const history = await channel.presence.history({limit: 25})
484
467
 
485
- history.items.filter(message => message.action === action).forEach(
486
- async message => {
487
- logger.info(`presence history ${action} event received`, message)
488
- await callback(message)
489
- }
490
- )
491
- } catch(err) {
492
- logger.error('Unable to get presence history; err = ' + err.message)
493
- }
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
+ )
494
474
  }
495
475
 
496
476
  async publishEventSpectatorsMessage(anearEvent, css, message, messageType = PublicDisplayMessageType) {
@@ -596,14 +576,10 @@ class AnearMessaging {
596
576
  }
597
577
 
598
578
  async publishChannelMessage(channel, messageType, payload) {
599
- try {
600
- await channel.publish(
601
- messageType,
602
- payload
603
- )
604
- } catch(err) {
605
- this.logErrorInfo(err)
606
- }
579
+ await channel.publish(
580
+ messageType,
581
+ payload
582
+ )
607
583
  }
608
584
 
609
585
  async detachAll(eventId) {
@@ -625,17 +601,13 @@ class AnearMessaging {
625
601
  async detachChannel (channel) {
626
602
  if (!channel || channel.state !== 'attached') return
627
603
 
628
- try {
629
- await channel.detach(this.logErrorInfo)
630
- logger.info(`channel ${channel.name} detached`)
631
- } catch(err) {
632
- this.logErrorInfo(err)
633
- }
604
+ await channel.detach(this.logErrorInfo)
605
+ logger.debug(`channel ${channel.name} detached`)
634
606
  }
635
607
 
636
608
  logErrorInfo(errInfo) {
637
609
  if (errInfo) {
638
- logger.error(`Ably ERROR (${errInfo.code}): ${errInfo.message}`)
610
+ logger.error("Ably ERROR:", errInfo)
639
611
  }
640
612
  }
641
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() {
@@ -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.3",
3
+ "version": "0.4.4",
4
4
  "description": "Javascript Developer API for Anear Apps",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {