anear-js-api 0.4.20 → 0.4.22
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/.env.test +8 -0
- package/__mocks__/api/AnearApi.js +30 -0
- package/__mocks__/utils/RealtimeMessaging.js +17 -0
- package/jest.config.js +9 -0
- package/lib/AnearService.js +12 -0
- package/lib/api/AnearApi.js +41 -21
- package/lib/api/ApiService.js +1 -1
- package/lib/index.js +4 -8
- package/lib/models/AnearEvent.js +35 -254
- package/lib/models/AnearParticipant.js +19 -85
- package/lib/models/JsonApiResource.js +0 -49
- package/lib/state_machines/AnearCoreServiceMachine.js +264 -0
- package/lib/state_machines/AnearEventMachine.js +940 -0
- package/lib/state_machines/AnearParticipantMachine.js +286 -0
- package/lib/utils/AssetFileCollector.js +63 -0
- package/lib/utils/Constants.js +10 -0
- package/lib/utils/CssProcessing.js +65 -0
- package/lib/utils/CssUploader.js +82 -0
- package/lib/utils/ImageAssetsUploader.js +101 -0
- package/lib/utils/MetaProcessing.js +147 -0
- package/lib/utils/MetaViewPathParticipantProcessing.js +53 -0
- package/lib/utils/Participants.js +0 -13
- package/lib/utils/PugHelpers.js +14 -0
- package/lib/utils/PugLoader.js +48 -0
- package/lib/utils/RealtimeMessaging.js +159 -0
- package/package.json +7 -3
- package/tests/AnearEvent.test.js +65 -349
- package/tests/AnearParticipant.test.js +52 -51
- package/tests/AnearService.test.js +11 -0
- package/tests/PugLoader.test.js +24 -0
- package/tests/fixtures/AnearAppFixture.js +28 -0
- package/tests/fixtures/AnearEventFixture.js +1 -1
- package/tests/fixtures/test_pug_templates/subdir/template_3.pug +1 -0
- package/tests/fixtures/test_pug_templates/template_1.pug +1 -0
- package/tests/fixtures/test_pug_templates/template_2.pug +1 -0
- package/lib/api/__mocks__/AnearApi.js +0 -17
- package/lib/messaging/AnearMessaging.js +0 -645
- package/lib/messaging/__mocks__/AnearMessaging.js +0 -22
- package/lib/utils/AnearXstate.js +0 -86
- package/lib/utils/ParticipantTimer.js +0 -117
- package/lib/utils/Persist.js +0 -52
- package/tests/ParticipantTimer.test.js +0 -66
- package/tests/Participants.test.js +0 -234
- package/tests/Persist.test.js +0 -102
package/.env.test
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# connects with the machtest developer account
|
|
2
|
+
ANEARAPP_API_KEY=a197d1e4da2bfd4bb5d85ca82553f14f4fad2c5c650c25f49c8514eb80ef4fe1
|
|
3
|
+
ANEARAPP_API_VERSION=v1
|
|
4
|
+
ANEARAPP_APP_ID=e64a78d8-48f5-44f7-8b89-af2d6977a8c2
|
|
5
|
+
ANEARAPP_LOGGER_FILE=logs/development.log
|
|
6
|
+
ANEARAPP_LOGGER_LEVEL=debug
|
|
7
|
+
ANEARAPP_ABLY_LOG_LEVEL=2
|
|
8
|
+
ANEARAPP_PRESENCE_TIMEOUT_SECONDS=3600
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const logger = require('../../lib/utils/Logger')
|
|
4
|
+
const AnearAppData = require('../../tests/fixtures/AnearAppFixture')
|
|
5
|
+
|
|
6
|
+
class AnearApi {
|
|
7
|
+
constructor(apiKey, apiVersion) {
|
|
8
|
+
this.apiKey = apiKey
|
|
9
|
+
this.apiVersion = apiVersion
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
getAccount() {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getApp() {
|
|
16
|
+
return Promise.resolve(AnearAppData)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async transitionEvent(eventId, eventName='next') {
|
|
20
|
+
return {state: "announce"}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
getEventParticipant(participantId, geoLocation) {
|
|
24
|
+
return Promise.resolve(new AnearParticipant({}, {}))
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const anearApiInstance = new AnearApi()
|
|
29
|
+
|
|
30
|
+
module.exports = anearApiInstance
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const logger = require('../../lib/utils/Logger')
|
|
4
|
+
|
|
5
|
+
class RealtimeMessaging {
|
|
6
|
+
initRealtime(appId, appMachine) {
|
|
7
|
+
return this
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getChannel(channelName) {
|
|
11
|
+
return {}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const realtimeMessagingInstance = new RealtimeMessaging()
|
|
16
|
+
|
|
17
|
+
module.exports = realtimeMessagingInstance
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const AnearCoreServiceMachine = require('./state_machines/AnearCoreServiceMachine')
|
|
2
|
+
|
|
3
|
+
const AnearService = (appEventMachineFactory, appParticipantMachineFactory = null) => {
|
|
4
|
+
//
|
|
5
|
+
// developer provides appEventMachineFactory:
|
|
6
|
+
//
|
|
7
|
+
// appEventMachineFactory = anearEvent => { returns XState Machine) }
|
|
8
|
+
// optional appParticipantMachineFactory = anearParticipant => { returns XState Machine) }
|
|
9
|
+
//
|
|
10
|
+
AnearCoreServiceMachine(appEventMachineFactory, appParticipantMachineFactory)
|
|
11
|
+
}
|
|
12
|
+
module.exports = AnearService
|
package/lib/api/AnearApi.js
CHANGED
|
@@ -3,62 +3,82 @@ const logger = require('../utils/Logger')
|
|
|
3
3
|
const ApiService = require('./ApiService')
|
|
4
4
|
|
|
5
5
|
class AnearApi extends ApiService {
|
|
6
|
-
|
|
7
6
|
constructor(apiKey, apiVersion) {
|
|
8
7
|
super(apiKey, apiVersion)
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
getAccount() {
|
|
12
11
|
logger.debug("API: GET /accounts")
|
|
13
|
-
|
|
14
12
|
return this.get("accounts")
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
getEvent(eventId) {
|
|
18
16
|
logger.debug(`API: GET event ${eventId}`)
|
|
19
|
-
|
|
20
|
-
return this.get("events", {id: eventId})
|
|
17
|
+
return this.get("events", { id: eventId })
|
|
21
18
|
}
|
|
22
19
|
|
|
23
20
|
getAppZones(appId) {
|
|
24
21
|
logger.debug(`API: GET app_zones ${appId}`)
|
|
25
|
-
|
|
26
|
-
return this.get("app_zones", {id: appId})
|
|
22
|
+
return this.get("app_zones", { id: appId })
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
getApp(appId) {
|
|
30
26
|
logger.debug(`API: GET app ${appId}`)
|
|
31
|
-
|
|
32
|
-
return this.get("apps", {id: appId})
|
|
27
|
+
return this.get("apps", { id: appId })
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
getZoneEvents(zoneId) {
|
|
36
31
|
logger.debug(`API: GET zone_events ${zoneId}`)
|
|
37
|
-
|
|
38
|
-
return this.get("zone_events", {id: zoneId})
|
|
32
|
+
return this.get("zone_events", { id: zoneId })
|
|
39
33
|
}
|
|
40
34
|
|
|
41
|
-
async transitionEvent(eventId,
|
|
42
|
-
logger.debug(`API: POST transition event ${
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
const json = await this.post("transitions", {event_name: eventName}, relationships)
|
|
35
|
+
async transitionEvent(eventId, newStateName) {
|
|
36
|
+
logger.debug(`API: POST transition event ${newStateName}`)
|
|
37
|
+
const relationships = { event: eventId }
|
|
38
|
+
const json = await this.post("transitions", { state: newStateName }, relationships)
|
|
46
39
|
const attrs = json.data.attributes
|
|
47
|
-
logger.debug(`API: newState is ${attrs.state}`)
|
|
48
40
|
return attrs
|
|
49
41
|
}
|
|
50
42
|
|
|
51
|
-
getEventParticipantJson(participantId
|
|
43
|
+
getEventParticipantJson(participantId) {
|
|
52
44
|
logger.debug(`API: GET event_participant ${participantId}`)
|
|
53
|
-
|
|
54
|
-
return this.get("event_participants", {id: participantId})
|
|
45
|
+
return this.get("event_participants", { id: participantId })
|
|
55
46
|
}
|
|
56
47
|
|
|
57
48
|
getUser(userId) {
|
|
58
49
|
logger.debug(`API: GET user ${userId}`)
|
|
50
|
+
return this.get("users", { id: userId })
|
|
51
|
+
}
|
|
59
52
|
|
|
60
|
-
|
|
53
|
+
async getAppCssUploadUrl(appId, contentHash, fileSuffix = ".min.css") {
|
|
54
|
+
logger.debug(`API: POST get app styles upload URL for app ${appId} with suffix ${fileSuffix} and content_hash ${contentHash}`)
|
|
55
|
+
const postAttrs = { content_hash: contentHash, suffix: fileSuffix }
|
|
56
|
+
const relationships = { app: appId }
|
|
57
|
+
const json = await this.post("app_styles", postAttrs, relationships)
|
|
58
|
+
const attrs = json.data.attributes
|
|
59
|
+
logger.debug('getAppCssUploadUrl response:', attrs)
|
|
60
|
+
return attrs
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async getAppImageAssetsUploadUrls(appId, files) {
|
|
64
|
+
logger.debug(`API: POST get image assets upload URLs for app ${appId}`)
|
|
65
|
+
const postAttrs = { files }
|
|
66
|
+
const relationships = { app: appId }
|
|
67
|
+
const json = await this.post("app_image_assets", postAttrs, relationships)
|
|
68
|
+
const attrs = json.data.attributes
|
|
69
|
+
logger.debug('getAppImageAssetsUploadUrls response:', attrs)
|
|
70
|
+
return attrs
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
// Instantiate and export the API immediately
|
|
75
|
+
const apiKey = process.env.ANEARAPP_API_KEY
|
|
76
|
+
const apiVersion = process.env.ANEARAPP_API_VERSION
|
|
77
|
+
|
|
78
|
+
if (!apiKey || !apiVersion) {
|
|
79
|
+
throw new Error("API_KEY and API_VERSION must be defined in environment variables")
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const anearApiInstance = new AnearApi(apiKey, apiVersion)
|
|
83
|
+
|
|
84
|
+
module.exports = anearApiInstance
|
package/lib/api/ApiService.js
CHANGED
|
@@ -4,7 +4,7 @@ const ErrorResponse = require('./ErrorResponse')
|
|
|
4
4
|
const qs = require('qs')
|
|
5
5
|
const fetch = require('cross-fetch')
|
|
6
6
|
|
|
7
|
-
const DeveloperApiURL = 'https://api.
|
|
7
|
+
const DeveloperApiURL = 'https://api.anear.me/developer/'
|
|
8
8
|
|
|
9
9
|
class ApiService {
|
|
10
10
|
constructor(apiKey, apiVersion) {
|
package/lib/index.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const logger = require('./utils/Logger')
|
|
3
4
|
const JsonApiResource = require('./models/JsonApiResource')
|
|
4
5
|
const JsonApiArrayResource = require('./models/JsonApiArrayResource')
|
|
6
|
+
const AnearService = require('./AnearService')
|
|
5
7
|
const AnearEvent = require('./models/AnearEvent')
|
|
6
|
-
const logger = require('./utils/Logger')
|
|
7
8
|
const AnearParticipant = require('./models/AnearParticipant')
|
|
8
|
-
const AnearMessaging = require('./messaging/AnearMessaging')
|
|
9
|
-
const AnearApiService = require('./api/ApiService')
|
|
10
9
|
const Fixtures = require('../tests/fixtures')
|
|
11
|
-
const MockMessaging = require('./messaging/__mocks__/AnearMessaging')
|
|
12
10
|
|
|
13
11
|
module.exports = {
|
|
14
12
|
JsonApiResource,
|
|
@@ -16,9 +14,7 @@ module.exports = {
|
|
|
16
14
|
AnearEvent,
|
|
17
15
|
logger,
|
|
18
16
|
AnearParticipant,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Fixtures,
|
|
22
|
-
MockMessaging,
|
|
17
|
+
AnearService,
|
|
18
|
+
Fixtures
|
|
23
19
|
}
|
|
24
20
|
|
package/lib/models/AnearEvent.js
CHANGED
|
@@ -1,65 +1,57 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
|
|
3
|
-
const { Mutex } = require('async-mutex')
|
|
4
|
-
|
|
5
|
-
const AnearXstate = require('../utils/AnearXstate')
|
|
2
|
+
const logger = require('../utils/Logger')
|
|
6
3
|
|
|
7
4
|
const JsonApiResource = require('./JsonApiResource')
|
|
8
|
-
const Participants = require('../utils/Participants')
|
|
9
|
-
const logger = require('../utils/Logger')
|
|
10
5
|
|
|
11
|
-
const
|
|
6
|
+
const UnplayableStates = ['closing', 'closed', 'canceled']
|
|
12
7
|
|
|
13
8
|
class AnearEvent extends JsonApiResource {
|
|
14
9
|
|
|
15
|
-
constructor(json
|
|
10
|
+
constructor(json) {
|
|
16
11
|
super(json)
|
|
17
12
|
this.zone = this.findIncluded(this.relationships.zone)
|
|
18
13
|
this.app = this.findIncluded(this.zone.relationships.app)
|
|
19
|
-
this.
|
|
20
|
-
this.anearStateMachine = this.initStateMachine(json.previousState)
|
|
21
|
-
this.participants = new Participants(this, json.participants)
|
|
22
|
-
this.mutex = new Mutex()
|
|
14
|
+
this.send = () => {} // until initialized
|
|
23
15
|
}
|
|
24
16
|
|
|
25
|
-
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
17
|
+
get userId() {
|
|
18
|
+
return this.relationships.user.data.id
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get zoneId() {
|
|
22
|
+
return this.relationships.zone.data.id
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setMachine(service) {
|
|
26
|
+
if (service) {
|
|
27
|
+
this.send = service.send.bind(service)
|
|
28
|
+
} else {
|
|
29
|
+
this.send = () => {}
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
this.
|
|
33
|
+
announceEvent() {
|
|
34
|
+
this.send("ANNOUNCE")
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return {}
|
|
37
|
+
startEvent() {
|
|
38
|
+
this.send("START")
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return {}
|
|
41
|
+
cancelEvent() {
|
|
42
|
+
this.send("CANCEL")
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.stateMachineConfig(),
|
|
51
|
-
this.stateMachineOptions(),
|
|
52
|
-
previousState,
|
|
53
|
-
this.context
|
|
54
|
-
)
|
|
45
|
+
closeEvent() {
|
|
46
|
+
this.send("CLOSE")
|
|
55
47
|
}
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
pauseEvent() {
|
|
50
|
+
this.send("PAUSE")
|
|
59
51
|
}
|
|
60
52
|
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
resumeEvent() {
|
|
54
|
+
this.send("RESUME")
|
|
63
55
|
}
|
|
64
56
|
|
|
65
57
|
getClonedFromEvent() {
|
|
@@ -77,11 +69,6 @@ class AnearEvent extends JsonApiResource {
|
|
|
77
69
|
return clonedFrom ? clonedFrom.context : null
|
|
78
70
|
}
|
|
79
71
|
|
|
80
|
-
get stateMachineContext() {
|
|
81
|
-
// active XState context
|
|
82
|
-
return this.anearStateMachine.context
|
|
83
|
-
}
|
|
84
|
-
|
|
85
72
|
get eventState() {
|
|
86
73
|
return this.attributes.state
|
|
87
74
|
}
|
|
@@ -109,243 +96,37 @@ class AnearEvent extends JsonApiResource {
|
|
|
109
96
|
return this.attributes.flags.includes(flagName)
|
|
110
97
|
}
|
|
111
98
|
|
|
112
|
-
get css() {
|
|
113
|
-
// override with a String of CSS to be sent with each publishEvent*Message
|
|
114
|
-
// this will be compressed out of the initial publishEvent*Message
|
|
115
|
-
// and will only be received by the client when the CSS changes.
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
99
|
allowsSpectators() {
|
|
120
100
|
return !this.hasFlag("no_spectators")
|
|
121
101
|
}
|
|
122
102
|
|
|
123
|
-
|
|
124
|
-
return this.messaging.getSpectatorCount(this)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
isParticipantEventCreator(RParticipant) {
|
|
103
|
+
isParticipantEventCreator(participant) {
|
|
128
104
|
return participant.userId === this.userId
|
|
129
105
|
}
|
|
130
106
|
|
|
131
|
-
publishEventParticipantsMessage(message, timeoutMsecs=0) {
|
|
132
|
-
return this.messaging.publishEventParticipantsMessage(
|
|
133
|
-
this,
|
|
134
|
-
this.participants.active(),
|
|
135
|
-
this.css,
|
|
136
|
-
message,
|
|
137
|
-
timeoutMsecs
|
|
138
|
-
)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
async runExclusive(name, callback) {
|
|
142
|
-
logger.debug(`waiting for ${name} mutex`)
|
|
143
|
-
|
|
144
|
-
await this.mutex.runExclusive(
|
|
145
|
-
async () => {
|
|
146
|
-
logger.debug(`mutex ${name} locked!`)
|
|
147
|
-
await callback()
|
|
148
|
-
}
|
|
149
|
-
)
|
|
150
|
-
logger.debug(`mutex ${name} released!`)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
publishEventSpectatorsMessage(message, timeoutMsecs = 0) {
|
|
154
|
-
return this.messaging.publishEventSpectatorsMessage(this, this.css, message, timeoutMsecs, timeoutMsecs)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
publishEventPrivateMessage(participant, message, timeoutMsecs=0) {
|
|
158
|
-
return this.messaging.publishEventPrivateMessage(
|
|
159
|
-
this,
|
|
160
|
-
participant,
|
|
161
|
-
this.css,
|
|
162
|
-
message,
|
|
163
|
-
timeoutMsecs
|
|
164
|
-
)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
publishEventTransitionMessage(newState) {
|
|
168
|
-
return this.messaging.publishEventTransitionMessage(
|
|
169
|
-
this,
|
|
170
|
-
newState
|
|
171
|
-
)
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async participantEnter(participant) {
|
|
175
|
-
// Called each time a participant ENTERs (attaches to) the Event's Action Channel.
|
|
176
|
-
// This could be when joining an event for the first time, rejoining, or after a browser
|
|
177
|
-
// refresh/reconnect. If the participant exists in Storage and in this.participants,
|
|
178
|
-
// its probably due to a browser refresh, and we call Refresh. Else, its either a brand
|
|
179
|
-
// new participant or an anearEvent recovery after crash, and so we invoke new participant enter
|
|
180
|
-
//
|
|
181
|
-
if (participant.exists()) { // persisted in storage?
|
|
182
|
-
if (this.participants.exists(participant)) {
|
|
183
|
-
logger.debug(`AnearEvent: participant ${participant.id} exists. Refreshing...`)
|
|
184
|
-
|
|
185
|
-
// Likely here due to participant browser refresh
|
|
186
|
-
// get the existing participant, turn off his timer and send refresh event to StateMachine
|
|
187
|
-
const existingParticipant = this.participants.get(participant)
|
|
188
|
-
existingParticipant.interruptTimer()
|
|
189
|
-
this.anearStateMachine.sendRefreshEvent({participant: existingParticipant})
|
|
190
|
-
await existingParticipant.update()
|
|
191
|
-
} else {
|
|
192
|
-
// Likely here due to prior AnearEvent error and this is a event reload and restart
|
|
193
|
-
// add the participants record back into Participants and update persisted copy
|
|
194
|
-
this.participants.add(participant)
|
|
195
|
-
this.anearStateMachine.sendJoinEvent({ participant })
|
|
196
|
-
await participant.update()
|
|
197
|
-
}
|
|
198
|
-
} else {
|
|
199
|
-
// New Participant first-time join this AnearEvent
|
|
200
|
-
this.participants.add(participant) // add the participants record
|
|
201
|
-
this.anearStateMachine.sendJoinEvent({ participant })
|
|
202
|
-
await participant.persist()
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
participantExit(participant) {
|
|
207
|
-
// this informs the state machine that the participant has exited the event
|
|
208
|
-
// and removes that participant completely
|
|
209
|
-
this.anearStateMachine.sendParticipantExitEvent({ participant })
|
|
210
|
-
return this.participantPurge(participant)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
spectatorView(userId) {
|
|
214
|
-
this.anearStateMachine.sendSpectatorViewEvent({userId})
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
participantPurge(participant) {
|
|
218
|
-
this.participants.purge(participant)
|
|
219
|
-
return participant.remove()
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
participantAction(participant, actionEventName, actionPayload) {
|
|
223
|
-
this.anearStateMachine.sendActionEvent(actionEventName, {participant, payload: actionPayload})
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
participantTimedOut(participant) {
|
|
227
|
-
this.anearStateMachine.sendTimeoutEvent({ participant })
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
async transitionEvent(eventName='next') {
|
|
231
|
-
//
|
|
232
|
-
// Allows the app/game to transition the remote AnearEvent which can un/hide and event
|
|
233
|
-
// and change its discoverability by mobile web users. Apps can also determine when
|
|
234
|
-
// and how many mobile-app users can join and event.
|
|
235
|
-
//
|
|
236
|
-
// 1. send the transition event to the Anear API
|
|
237
|
-
// 2. get back the event newState from Anear API response
|
|
238
|
-
// 3. publish the new Event State to all subscribers (e.g. participants)
|
|
239
|
-
//
|
|
240
|
-
logger.debug(`AnearEvent: transitionEvent(${eventName})`)
|
|
241
|
-
|
|
242
|
-
const responseAttributes = await this.messaging.api.transitionEvent(this.id, eventName)
|
|
243
|
-
const newState = responseAttributes.state
|
|
244
|
-
this.attributes.state = newState
|
|
245
|
-
await this.messaging.publishEventTransitionMessage(this, newState)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
107
|
isPlayable() {
|
|
249
|
-
return !
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
async transitionToAnnounce() {
|
|
253
|
-
if (this.eventState === 'created') await this.transitionEvent('announce')
|
|
108
|
+
return !UnplayableStates.includes(this.eventState)
|
|
254
109
|
}
|
|
255
110
|
|
|
256
|
-
|
|
257
|
-
await this.transitionEvent('next')
|
|
258
|
-
await this.transitionEvent('next')
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
transitionLive() {
|
|
262
|
-
return this.transitionNextNext()
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
transitionClosed() {
|
|
266
|
-
return this.transitionNextNext()
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
transitionCanceled() {
|
|
270
|
-
return this.transitionEvent('cancel')
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
closeOutParticipants() {
|
|
274
|
-
// returns a Promise
|
|
275
|
-
// upon exiting the event, this will clean up any participants remaining
|
|
276
|
-
// by closing out their messaging channels and purging them
|
|
277
|
-
return Promise.all(
|
|
278
|
-
this.participants.all.map(
|
|
279
|
-
p => {
|
|
280
|
-
return this.messaging.closeParticipant(
|
|
281
|
-
this,
|
|
282
|
-
p.id,
|
|
283
|
-
async (anearEvent, participant) => {
|
|
284
|
-
await anearEvent.participantPurge(participant)
|
|
285
|
-
}
|
|
286
|
-
)
|
|
287
|
-
}
|
|
288
|
-
)
|
|
289
|
-
)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
purgeParticipants() {
|
|
293
|
-
// returns a Promise
|
|
294
|
-
// remove participants and host from Participants class and from Storage
|
|
295
|
-
const all = this.participants.all
|
|
296
|
-
if (this.participants.host) all.push(this.participants.host)
|
|
297
|
-
|
|
298
|
-
return Promise.all(
|
|
299
|
-
all.map(p => this.participantPurge(p))
|
|
300
|
-
)
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
resetParticipantTimers() {
|
|
304
|
-
// turns off any active AnearParticipant timer
|
|
305
|
-
this.participants.resetAllTimers()
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
destroyParticipantTimers() {
|
|
309
|
-
// turns off any active and removes all other AnearParticipant timer
|
|
310
|
-
this.participants.destroyAllTimers()
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
eventChannelName () {
|
|
111
|
+
get eventChannelName() {
|
|
314
112
|
return this.getChannelName('event')
|
|
315
113
|
}
|
|
316
114
|
|
|
317
|
-
participantsChannelName () {
|
|
115
|
+
get participantsChannelName () {
|
|
318
116
|
return this.getChannelName('participants')
|
|
319
117
|
}
|
|
320
118
|
|
|
321
|
-
actionsChannelName () {
|
|
119
|
+
get actionsChannelName () {
|
|
322
120
|
return this.getChannelName('actions')
|
|
323
121
|
}
|
|
324
122
|
|
|
325
|
-
spectatorsChannelName () {
|
|
123
|
+
get spectatorsChannelName () {
|
|
326
124
|
return this.getChannelName('spectators')
|
|
327
125
|
}
|
|
328
126
|
|
|
329
127
|
getChannelName (key) {
|
|
330
128
|
return this.attributes[`${key}-channel-name`]
|
|
331
129
|
}
|
|
332
|
-
|
|
333
|
-
async closeEvent() {
|
|
334
|
-
await this.closeOutParticipants()
|
|
335
|
-
await this.closeMessaging()
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
closeMessaging () {
|
|
339
|
-
return this.messaging.detachAll(this.id)
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
logDebugMessage(...args) {
|
|
343
|
-
logger.debug(...args)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
logError(context, event) {
|
|
347
|
-
logger.error("XState: ERROR: ", event.data)
|
|
348
|
-
}
|
|
349
130
|
}
|
|
350
131
|
|
|
351
132
|
module.exports = AnearEvent
|