Skip to content

Commit

Permalink
createSkyInspector
Browse files Browse the repository at this point in the history
  • Loading branch information
mellson committed Jan 26, 2024
1 parent 6036ddb commit c878733
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/friendly-pianos-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@statelyai/inspect': patch
---

Adds `createSkyInspector`, which allows you to inspect machines in Node or the browser. The inspection will send the events to a server backend through websockets and allows you to open and share a live inspection URL.
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.26.2",
"@types/jsdom": "^21.1.6",
"@types/uuid": "^9.0.8",
"jsdom": "^23.0.0",
"tsup": "^7.2.0",
"typescript": "^5.1.6",
Expand All @@ -18,7 +19,10 @@
"license": "MIT",
"dependencies": {
"fast-safe-stringify": "^2.1.1",
"isomorphic-ws": "^5.0.0"
"isomorphic-ws": "^5.0.0",
"partysocket": "^0.0.25",
"superjson": "^1",
"uuid": "^9.0.1"
},
"peerDependencies": {
"xstate": "^5.5.1"
Expand All @@ -30,7 +34,8 @@
"prepublishOnly": "tsup src/index.ts --dts",
"changeset": "changeset",
"release": "changeset publish",
"version": "changeset version"
"version": "changeset version",
"dev": "yarn build && ./scripts/dev.sh"
},
"publishConfig": {
"access": "public"
Expand Down
63 changes: 57 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions scripts/dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

# This script copies the source code of the packages in the packages/ directory
# to the node_modules/@statelyai/ directory of each destination project.

# Load environment variables from .env file
if [ -f .env ]; then
export $(cat .env | xargs)
fi

# Split the DEV_DESTINATIONS variable into an array
IFS=',' read -r -a destinations <<<"$DEV_DESTINATIONS"

# Package name
package="inspect"

for destination in "${destinations[@]}"; do
echo "Copying ${package} to ${destination}"
rm -rf "${destination}/node_modules/@statelyai/${package}"
cp -r "./" "${destination}/node_modules/@statelyai/${package}"
done
58 changes: 58 additions & 0 deletions src/createSkyInspector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import PartySocket from 'partysocket';
import { stringify } from 'superjson';
import { v4 as uuidv4 } from 'uuid';
import { createBrowserInspector } from './browser';
import {
InspectorOptions,
createInspector as inspectCreator,
} from './createInspector';
import { isNode } from './utils';

export function createSkyInspector(
options: {
apiKey?: string; // Not used yet, will be used to add additional premium features later
onerror?: (error: Error) => void;
} & InspectorOptions = {}
): ReturnType<typeof inspectCreator> {
const { host, apiBaseURL } = {
host: 'localhost:1999', // 'stately-sky-beta.mellson.partykit.dev'
apiBaseURL: 'http://localhost:3000/registry/api/sky', // 'https://stately.ai/registry/api/sky',
};
const server = apiBaseURL.replace('/api/sky', '');
const { apiKey, onerror, ...inspectorOptions } = options;
const sessionId = uuidv4(); // Generate a unique session ID
const room = `inspect-${sessionId}`;
const socket = new PartySocket({
host,
room,
WebSocket: isNode ? require('isomorphic-ws') : undefined,
});
const liveInspectUrl = `${server}/inspect/${sessionId}`;
socket.onerror = onerror ?? console.error;
socket.onopen = () => {
console.log('Connected to Sky, link to your live inspect session:');
console.log(liveInspectUrl);
};
if (isNode) {
return inspectCreator({
...inspectorOptions,
send(event) {
const skyEvent = apiKey ? { apiKey, ...event } : event;
socket.send(stringify(skyEvent));
},
});
} else {
const { filter, serialize } = inspectorOptions;
return createBrowserInspector({
...inspectorOptions,
url: liveInspectUrl,
serialize(event) {
if (!filter || filter(event)) {
const skyEvent = apiKey ? { apiKey, ...event } : event;
socket.send(stringify(skyEvent));
}
return serialize ? serialize(event) : event;
},
});
}
}
7 changes: 4 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export { createInspector } from './createInspector';
export { createWebSocketInspector, createWebSocketReceiver } from './webSocket';
export { createBrowserInspector, createBrowserReceiver } from './browser';
export { createInspector } from './createInspector';
export { createSkyInspector } from './createSkyInspector';
export type {
StatelyActorEvent,
StatelyInspectionEvent,
StatelyEventEvent,
StatelyInspectionEvent,
StatelySnapshotEvent,
} from './types';
export { createWebSocketInspector, createWebSocketReceiver } from './webSocket';
7 changes: 6 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AnyEventObject, AnyActorRef } from 'xstate';
import type { AnyActorRef, AnyEventObject } from 'xstate';

export function toEventObject(event: AnyEventObject | string): AnyEventObject {
if (typeof event === 'string') {
Expand All @@ -16,3 +16,8 @@ export function isActorRef(actorRef: any): actorRef is AnyActorRef {
typeof actorRef.send === 'function'
);
}

export const isNode =
typeof process !== 'undefined' &&
typeof process.versions?.node !== 'undefined' &&
typeof document === 'undefined';

0 comments on commit c878733

Please sign in to comment.