Skip to content

Instantly share code, notes, and snippets.

@leeovery
Last active July 20, 2022 20:05
Show Gist options
  • Save leeovery/b5336e560e6f48116580bc6baa8be91d to your computer and use it in GitHub Desktop.
Save leeovery/b5336e560e6f48116580bc6baa8be91d to your computer and use it in GitHub Desktop.
xstate console logger
import typeOf from 'just-typeof';
const colors = {
heading: '#86c0d1',
title: '#80a0c2',
subtitle: '#a2bf8a',
body: '#d8dee9',
};
const styles = {
heading: `color: ${colors.heading}; font-weight: bold; font-size: 14px;`,
title: `color: ${colors.title}; font-weight: bold; font-size: 14px;`,
subtitle: `color: ${colors.subtitle}; font-weight: bold; font-size: 12px;`,
body: `color: ${colors.body}; font-size: 12px; font-style: italic;`,
};
const obj2DotStr = (object) => {
return Object.entries(object)
.map(([k, v]) => `${k}.${typeOf(v) === 'object' ? obj2DotStr(v) : v}`)[0];
};
const normalizeState = (value) => {
if (typeOf(value) === 'object') value = obj2DotStr(value);
return value;
};
const dumpContext = (state) => {
Object.entries(state.context).forEach(([key, value]) => {
if (['array', 'object'].includes(typeOf(value))) {
console.groupCollapsed(`%c${key}:`, styles.subtitle);
console.table(JSON.parse(JSON.stringify(value)));
console.groupEnd();
} else {
console.log(`%c${key}: %c${value}`, styles.subtitle, styles.body);
}
});
console.groupCollapsed(`%cRaw Context:`, styles.body);
console.log(state.context);
console.groupEnd();
};
const listeners = new Map;
export function logMachineTransitions(service, isDev = false) {
if (!isDev) return;
let machineName = service.id;
if (listeners.has(machineName)) return;
listeners.set(machineName, true);
function logChildMachines(service) {
service.children.forEach((child) => {
if (child?.machine) {
logMachineTransitions(child, isDev);
}
});
}
service.onStop(() => {
console.log(
`%c[XSTATE] %c${machineName}: %cStopped`,
styles.heading, styles.title, styles.body
);
listeners.delete(machineName);
});
console.groupCollapsed(
`%c[XSTATE] %c${machineName}: %cStarted`,
styles.heading, styles.title, styles.body
);
dumpContext(service.state);
console.groupEnd();
service.onTransition((currentState) => {
if (!currentState.changed) return;
logChildMachines(service);
let historyValue = normalizeState(currentState?.history?.value || 'null');
let currentValue = normalizeState(currentState.value);
if (historyValue === currentValue) return;
console.groupCollapsed(
`%c[XSTATE] %c${machineName}: %cfrom: %c${historyValue}%c to: %c${currentValue}`,
styles.heading, styles.title, styles.subtitle, styles.body, styles.subtitle, styles.body
);
dumpContext(currentState);
console.groupEnd();
});
}
import { useMachine as baseUseMachine, useService as baseUseService } from '@xstate/vue';
import { logMachineTransitions } from '@/use/machines/logMachineTransitions';
const wrapForLogging = (service) => {
logMachineTransitions(service, __NUXT__.config?.isDev || false);
};
export const useService = (passedService) => {
const { state, send, service } = baseUseService(passedService);
wrapForLogging(service.value);
return { state, send, service };
};
export const useMachine = (machine) => {
const { state, send, service } = baseUseMachine(machine);
wrapForLogging(service);
return { state, send, service };
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment