Skip to content

Migrate command emission

This historical v2 fragment illustrates command-owned event emission.

It is not current v3 code.

The input describes the caller’s intent and must survive migration.

Historical command fragment
commands: ({ actor, emit }) => ({
toggle: (mode: 'user' | 'system') => {
actor.send({ type: 'TOGGLE', mode });
emit('toggleRequested', { mode });
},
})

Keep request occurrences in the source.

This complete current module preserves mode, including repeated requests that do not change a projected value.

toggle-events.ts
import { createActor, emit, setup } from 'xstate';
import { igniteCore } from 'ignite-element/xstate';
const machine = setup({
types: {
events: {} as { type: 'TOGGLE'; mode: 'user' | 'system' },
emitted: {} as { type: 'toggleRequested'; mode: 'user' | 'system' },
},
actions: {
requested: emit(({ event }) => ({
type: 'toggleRequested',
mode: event.mode,
})),
},
}).createMachine({
initial: 'off',
states: {
off: {
on: { TOGGLE: { target: 'on', actions: 'requested' } },
},
on: {
on: { TOGGLE: { target: 'off', actions: 'requested' } },
},
},
});
const source = createActor(machine).start();
export const core = igniteCore({
source,
commands: ({ source: actor }) => ({
toggle: (mode: 'user' | 'system') => actor.send({ type: 'TOGGLE', mode }),
}),
events: event => ({
toggleRequested: event<{ mode: 'user' | 'system' }>(),
}),
});
export function dispose() {
try { core.dispose(); } finally { source.stop(); }
}

The source retains the toggle transition alongside the native emission.

A declaration makes the occurrence public to DOM and React web callbacks; headless native listeners infer it from the source.

Do not add an effect that produces toggleRequested again.

If the intended fact is a state change instead of a request, compare snapshots in effects under a distinct name.

The event counter shows both a native reset occurrence and a derived count change without duplicate producers.

A repeated request is not equivalent to a changed value.

Current commands receive { source }.

Effects receive { snapshot, prevSnapshot, select, emit } and return synchronous void.

Extracted callbacks may have an ordinary void annotation; they do not need return undefined.

Keep asynchronous work, retries, and cancellation in the source.

From the repository root:

Terminal window
node scripts/migrate-emit-to-effects.mjs

The script reports candidate old emission patterns.

Review each producer and input manually; it cannot decide whether an occurrence or comparison preserves application intent.

Use --report <path> to save its report.