@statelyai/sky
Advanced tools
Comparing version 0.0.6 to 0.0.7
import { Actor, AnyStateMachine } from 'xstate'; | ||
import { SkyConfigFile } from "./types.js"; | ||
export declare function actorFromStately<T extends AnyStateMachine>({ apiKey: _apiKey, url, sessionId, runOnSky, onPlayerJoined, onPlayerLeft, }: { | ||
export declare function actorFromStately<T extends AnyStateMachine>({ apiKey: _apiKey, url, sessionId, onPlayerJoined, onPlayerLeft, }: { | ||
apiKey?: string; | ||
url: string; | ||
sessionId: string; | ||
runOnSky?: boolean; | ||
onPlayerJoined?: ({ numberOfPlayers }: { | ||
@@ -9,0 +8,0 @@ numberOfPlayers: number; |
@@ -63,3 +63,2 @@ 'use strict'; | ||
sessionId, | ||
runOnSky = true, | ||
onPlayerJoined, | ||
@@ -71,110 +70,106 @@ onPlayerLeft | ||
} | ||
if (!runOnSky) { | ||
return xstate.createActor(skyConfig.machine); | ||
} else { | ||
let actor; | ||
let partySocket; | ||
let actor; | ||
let partySocket; | ||
// Get the host for Partykit and the API base URL for Stately Studio | ||
const { | ||
// Get the host for Partykit and the API base URL for Stately Studio | ||
const { | ||
host, | ||
apiBaseURL | ||
} = skyConnectionInfo(); | ||
const { | ||
actorId, | ||
machine | ||
} = skyConfig; | ||
const apiKey = _apiKey ?? SKY_API_KEY; | ||
if (!apiKey) { | ||
throw new Error(`You need to provide an API key to use the Stately Sky actor with url ${url}`); | ||
} | ||
return new Promise((resolve, reject) => { | ||
// Close the previous socket if it exists, this can easily happen when using React | ||
if (partySocket && partySocket.OPEN) { | ||
partySocket.close(); | ||
} | ||
// Create a unique room for this actor run | ||
const room = `${actorId}-${sessionId}`; | ||
partySocket = new PartySocket__default["default"]({ | ||
host, | ||
apiBaseURL | ||
} = skyConnectionInfo(); | ||
const { | ||
actorId, | ||
machine | ||
} = skyConfig; | ||
const apiKey = _apiKey ?? SKY_API_KEY; | ||
if (!apiKey) { | ||
throw new Error(`You need to provide an API key to use the Stately Sky actor with url ${url}`); | ||
} | ||
return new Promise((resolve, reject) => { | ||
// Close the previous socket if it exists, this can easily happen when using React | ||
if (partySocket && partySocket.OPEN) { | ||
partySocket.close(); | ||
} | ||
// Create a unique room for this actor run | ||
const room = `${actorId}-${sessionId}`; | ||
partySocket = new PartySocket__default["default"]({ | ||
host, | ||
room | ||
room | ||
}); | ||
partySocket.onerror = err => reject(err); | ||
partySocket.onopen = () => { | ||
if (!partySocket) return; | ||
return sendToSky(partySocket, { | ||
apiKey, | ||
type: 'actor.init', | ||
apiBaseURL, | ||
actorId, | ||
sessionId | ||
}); | ||
partySocket.onerror = err => reject(err); | ||
partySocket.onopen = () => { | ||
if (!partySocket) return; | ||
return sendToSky(partySocket, { | ||
apiKey, | ||
type: 'actor.init', | ||
apiBaseURL, | ||
actorId, | ||
sessionId | ||
}); | ||
}; | ||
}; | ||
// TODO: test what happens on reconnect | ||
// TODO: handle eventual consistency if users manage to get into different states | ||
partySocket.onmessage = evt => { | ||
const skyEvent = superjson__default["default"].parse(evt.data); | ||
if (skyEvent.apiKey !== apiKey) return; | ||
switch (skyEvent.type) { | ||
case 'player.joined': | ||
{ | ||
onPlayerJoined?.({ | ||
numberOfPlayers: skyEvent.numberOfPlayers | ||
}); | ||
break; | ||
} | ||
case 'player.left': | ||
{ | ||
onPlayerLeft?.({ | ||
numberOfPlayers: skyEvent.numberOfPlayers | ||
}); | ||
break; | ||
} | ||
case 'actor.error': | ||
{ | ||
throw new Error(skyEvent.error); | ||
} | ||
case 'actor.start': | ||
{ | ||
// Start the actor with the initial value from Sky | ||
actor = xstate.createActor(machine, { | ||
state: skyEvent.persistedState | ||
}); | ||
// TODO: test what happens on reconnect | ||
// TODO: handle eventual consistency if users manage to get into different states | ||
partySocket.onmessage = evt => { | ||
const skyEvent = superjson__default["default"].parse(evt.data); | ||
if (skyEvent.apiKey !== apiKey) return; | ||
switch (skyEvent.type) { | ||
case 'player.joined': | ||
{ | ||
onPlayerJoined?.({ | ||
numberOfPlayers: skyEvent.numberOfPlayers | ||
}); | ||
break; | ||
} | ||
case 'player.left': | ||
{ | ||
onPlayerLeft?.({ | ||
numberOfPlayers: skyEvent.numberOfPlayers | ||
}); | ||
break; | ||
} | ||
case 'actor.error': | ||
{ | ||
throw new Error(skyEvent.error); | ||
} | ||
case 'actor.start': | ||
{ | ||
// Start the actor with the initial value from Sky | ||
actor = xstate.createActor(machine, { | ||
state: skyEvent.persistedState | ||
}); | ||
// Send all events from the actor to Sky except for events that originate from Sky | ||
const originalSend = actor.send; | ||
actor.send = function (event) { | ||
// Send the event to the actor | ||
originalSend.call(this, event); | ||
// Send all events from the actor to Sky except for events that originate from Sky | ||
const originalSend = actor.send; | ||
actor.send = function (event) { | ||
// Send the event to the actor | ||
originalSend.call(this, event); | ||
// Don't start an infinite loop by sending events back to Sky | ||
if (event.sendToSky === false || !partySocket) return; | ||
sendToSky(partySocket, { | ||
apiKey, | ||
type: 'actor.send', | ||
event | ||
}); | ||
}; | ||
resolve(actor); | ||
break; | ||
} | ||
case 'actor.send': | ||
{ | ||
// When we receive an event from Sky, we don't want to send it back - we only want to send it to the local actor | ||
actor?.send({ | ||
...skyEvent.event, | ||
sendToSky: false | ||
// Don't start an infinite loop by sending events back to Sky | ||
if (event.sendToSky === false || !partySocket) return; | ||
sendToSky(partySocket, { | ||
apiKey, | ||
type: 'actor.send', | ||
event | ||
}); | ||
break; | ||
} | ||
case 'actor.stop': | ||
{ | ||
actor?.stop(); | ||
break; | ||
} | ||
} | ||
}; | ||
}); | ||
} | ||
}; | ||
resolve(actor); | ||
break; | ||
} | ||
case 'actor.send': | ||
{ | ||
// When we receive an event from Sky, we don't want to send it back - we only want to send it to the local actor | ||
actor?.send({ | ||
...skyEvent.event, | ||
sendToSky: false | ||
}); | ||
break; | ||
} | ||
case 'actor.stop': | ||
{ | ||
actor?.stop(); | ||
break; | ||
} | ||
} | ||
}; | ||
}); | ||
} | ||
@@ -181,0 +176,0 @@ |
@@ -54,3 +54,2 @@ import PartySocket from 'partysocket'; | ||
sessionId, | ||
runOnSky = true, | ||
onPlayerJoined, | ||
@@ -62,110 +61,106 @@ onPlayerLeft | ||
} | ||
if (!runOnSky) { | ||
return createActor(skyConfig.machine); | ||
} else { | ||
let actor; | ||
let partySocket; | ||
let actor; | ||
let partySocket; | ||
// Get the host for Partykit and the API base URL for Stately Studio | ||
const { | ||
// Get the host for Partykit and the API base URL for Stately Studio | ||
const { | ||
host, | ||
apiBaseURL | ||
} = skyConnectionInfo(); | ||
const { | ||
actorId, | ||
machine | ||
} = skyConfig; | ||
const apiKey = _apiKey ?? SKY_API_KEY; | ||
if (!apiKey) { | ||
throw new Error(`You need to provide an API key to use the Stately Sky actor with url ${url}`); | ||
} | ||
return new Promise((resolve, reject) => { | ||
// Close the previous socket if it exists, this can easily happen when using React | ||
if (partySocket && partySocket.OPEN) { | ||
partySocket.close(); | ||
} | ||
// Create a unique room for this actor run | ||
const room = `${actorId}-${sessionId}`; | ||
partySocket = new PartySocket({ | ||
host, | ||
apiBaseURL | ||
} = skyConnectionInfo(); | ||
const { | ||
actorId, | ||
machine | ||
} = skyConfig; | ||
const apiKey = _apiKey ?? SKY_API_KEY; | ||
if (!apiKey) { | ||
throw new Error(`You need to provide an API key to use the Stately Sky actor with url ${url}`); | ||
} | ||
return new Promise((resolve, reject) => { | ||
// Close the previous socket if it exists, this can easily happen when using React | ||
if (partySocket && partySocket.OPEN) { | ||
partySocket.close(); | ||
} | ||
// Create a unique room for this actor run | ||
const room = `${actorId}-${sessionId}`; | ||
partySocket = new PartySocket({ | ||
host, | ||
room | ||
room | ||
}); | ||
partySocket.onerror = err => reject(err); | ||
partySocket.onopen = () => { | ||
if (!partySocket) return; | ||
return sendToSky(partySocket, { | ||
apiKey, | ||
type: 'actor.init', | ||
apiBaseURL, | ||
actorId, | ||
sessionId | ||
}); | ||
partySocket.onerror = err => reject(err); | ||
partySocket.onopen = () => { | ||
if (!partySocket) return; | ||
return sendToSky(partySocket, { | ||
apiKey, | ||
type: 'actor.init', | ||
apiBaseURL, | ||
actorId, | ||
sessionId | ||
}); | ||
}; | ||
}; | ||
// TODO: test what happens on reconnect | ||
// TODO: handle eventual consistency if users manage to get into different states | ||
partySocket.onmessage = evt => { | ||
const skyEvent = superjson.parse(evt.data); | ||
if (skyEvent.apiKey !== apiKey) return; | ||
switch (skyEvent.type) { | ||
case 'player.joined': | ||
{ | ||
onPlayerJoined?.({ | ||
numberOfPlayers: skyEvent.numberOfPlayers | ||
}); | ||
break; | ||
} | ||
case 'player.left': | ||
{ | ||
onPlayerLeft?.({ | ||
numberOfPlayers: skyEvent.numberOfPlayers | ||
}); | ||
break; | ||
} | ||
case 'actor.error': | ||
{ | ||
throw new Error(skyEvent.error); | ||
} | ||
case 'actor.start': | ||
{ | ||
// Start the actor with the initial value from Sky | ||
actor = createActor(machine, { | ||
state: skyEvent.persistedState | ||
}); | ||
// TODO: test what happens on reconnect | ||
// TODO: handle eventual consistency if users manage to get into different states | ||
partySocket.onmessage = evt => { | ||
const skyEvent = superjson.parse(evt.data); | ||
if (skyEvent.apiKey !== apiKey) return; | ||
switch (skyEvent.type) { | ||
case 'player.joined': | ||
{ | ||
onPlayerJoined?.({ | ||
numberOfPlayers: skyEvent.numberOfPlayers | ||
}); | ||
break; | ||
} | ||
case 'player.left': | ||
{ | ||
onPlayerLeft?.({ | ||
numberOfPlayers: skyEvent.numberOfPlayers | ||
}); | ||
break; | ||
} | ||
case 'actor.error': | ||
{ | ||
throw new Error(skyEvent.error); | ||
} | ||
case 'actor.start': | ||
{ | ||
// Start the actor with the initial value from Sky | ||
actor = createActor(machine, { | ||
state: skyEvent.persistedState | ||
}); | ||
// Send all events from the actor to Sky except for events that originate from Sky | ||
const originalSend = actor.send; | ||
actor.send = function (event) { | ||
// Send the event to the actor | ||
originalSend.call(this, event); | ||
// Send all events from the actor to Sky except for events that originate from Sky | ||
const originalSend = actor.send; | ||
actor.send = function (event) { | ||
// Send the event to the actor | ||
originalSend.call(this, event); | ||
// Don't start an infinite loop by sending events back to Sky | ||
if (event.sendToSky === false || !partySocket) return; | ||
sendToSky(partySocket, { | ||
apiKey, | ||
type: 'actor.send', | ||
event | ||
}); | ||
}; | ||
resolve(actor); | ||
break; | ||
} | ||
case 'actor.send': | ||
{ | ||
// When we receive an event from Sky, we don't want to send it back - we only want to send it to the local actor | ||
actor?.send({ | ||
...skyEvent.event, | ||
sendToSky: false | ||
// Don't start an infinite loop by sending events back to Sky | ||
if (event.sendToSky === false || !partySocket) return; | ||
sendToSky(partySocket, { | ||
apiKey, | ||
type: 'actor.send', | ||
event | ||
}); | ||
break; | ||
} | ||
case 'actor.stop': | ||
{ | ||
actor?.stop(); | ||
break; | ||
} | ||
} | ||
}; | ||
}); | ||
} | ||
}; | ||
resolve(actor); | ||
break; | ||
} | ||
case 'actor.send': | ||
{ | ||
// When we receive an event from Sky, we don't want to send it back - we only want to send it to the local actor | ||
actor?.send({ | ||
...skyEvent.event, | ||
sendToSky: false | ||
}); | ||
break; | ||
} | ||
case 'actor.stop': | ||
{ | ||
actor?.stop(); | ||
break; | ||
} | ||
} | ||
}; | ||
}); | ||
} | ||
@@ -172,0 +167,0 @@ |
{ | ||
"name": "@statelyai/sky", | ||
"version": "0.0.6", | ||
"version": "0.0.7", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "dist/statelyai-sky.cjs.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15268
446