UNPKG

@xstate/inspect

Version:
126 lines (121 loc) 4.62 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _tslib = require('./_virtual/_tslib.js'); var xstate = require('xstate'); var inspectMachine = require('./inspectMachine.js'); var utils = require('./utils.js'); var services = new Set(); var serviceMap = new Map(); var serviceListeners = new Set(); function createDevTools() { globalThis.__xstate__ = { services: services, register: function (service) { services.add(service); serviceMap.set(service.sessionId, service); serviceListeners.forEach(function (listener) { return listener(service); }); service.onStop(function () { services.delete(service); serviceMap.delete(service.sessionId); }); }, onRegister: function (listener) { serviceListeners.add(listener); services.forEach(function (service) { return listener(service); }); return { unsubscribe: function () { serviceListeners.delete(listener); } }; } }; } function inspect(options) { var server = options.server; createDevTools(); var inspectService = xstate.interpret(inspectMachine.createInspectMachine(globalThis.__xstate__, options)).start(); var client = xstate.toActorRef({ id: '@@xstate/ws-client', send: function (event) { server.clients.forEach(function (wsClient) { if (wsClient.readyState === wsClient.OPEN) { wsClient.send(JSON.stringify(event)); } }); }, subscribe: function () { return { unsubscribe: function () { return void 0; } }; }, getSnapshot: function () { return undefined; } }); server.on('connection', function connection(wsClient) { wsClient.on('message', function incoming(data, isBinary) { if (isBinary) { return; } var jsonMessage = JSON.parse(data.toString()); inspectService.send(_tslib.__assign(_tslib.__assign({}, jsonMessage), { client: client })); }); }); globalThis.__xstate__.onRegister(function (service) { inspectService.send({ type: 'service.register', machine: JSON.stringify(service.machine), state: JSON.stringify(service.state || service.initialState), id: service.id, sessionId: service.sessionId }); inspectService.send({ type: 'service.event', event: utils.stringify((service.state || service.initialState)._event), sessionId: service.sessionId }); // monkey-patch service.send so that we know when an event was sent // to a service *before* it is processed, since other events might occur // while the sent one is being processed, which throws the order off var originalSend = service.send.bind(service); service.send = function inspectSend(event, payload) { inspectService.send({ type: 'service.event', event: utils.stringify(xstate.toSCXMLEvent(xstate.toEventObject(event, payload))), sessionId: service.sessionId }); return originalSend(event, payload); }; service.subscribe(function (state) { inspectService.send({ type: 'service.state', state: utils.stringify(state), sessionId: service.sessionId }); }); service.onStop(function () { inspectService.send({ type: 'service.stop', sessionId: service.sessionId }); }); }); var inspector = xstate.toActorRef({ id: '@@xstate/inspector', send: function (event) { inspectService.send(event); }, subscribe: function () { return { unsubscribe: function () { return void 0; } }; }, disconnect: function () { server.close(); inspectService.stop(); }, getSnapshot: function () { return undefined; } }); server.on('close', function () { inspectService.stop(); server.clients.forEach(function (client) { return client.terminate(); }); }); return inspector; } exports.inspect = inspect;