feat(ui): Add machine library for authoring flows#8919
Conversation
- Tighten Actor.send and Actor.can to accept TEvent only, removing the AnyEventObject escape hatch that silently swallowed typos - Add context init option to CreateActorOptions so runtime dependencies can be injected at actor-creation time without module-level closures - Add types.test-d.ts with @ts-expect-error guards and expectTypeOf assertions covering send/can rejection, snapshot types, and assign - Extract delete-organization-machine and leave-organization-machine as module-level factories; migrate both sections to useMachine with the split-component pattern (loader + ready) so the machine is always instantiated with a non-null organization/membership
…mounts In StrictMode (on by default in Next.js dev), React runs effects twice: start → stop → start. The second start() hit the `if (started) return` guard and bailed out, leaving status = 'stopped'. Every subsequent send() then short-circuited, so dialogs driven by useMachine never opened. Fix: stop() resets `started = false` to allow a clean restart, and start() sets status = 'active' before entering state so a restart-after-stop works.
…-fire After stop() + start() (StrictMode, Suspense remount), the actor was re-entering whatever state it was stopped in. If that state had an invoke (e.g. deleting), the async function would fire a second time. Fix: start() now resets context and value to their initial values before entering state, so a restart always begins from idle rather than continuing a half-completed flow. Adds a regression test for the double-invoke case.
…factories useMachine creates the actor once, so any function passed inline to the machine factory is captured from the first render only. If membership or organization changed under the same mount, the old .destroy() would fire. Fix: pin a ref to the prop on every render; the machine receives a stable wrapper that reads from the ref at call time. Adds a regression test that re-renders with a fresh destroy prop before triggering the flow and asserts the fresh function is invoked.
…Effect Replaces the ref-wrapper workaround in section components with the XState pattern: actor.setContext() silently patches context each render so invoke sources always call the latest prop-derived function without stale closures. Section machine factories are now module-level singletons; the destroy/leave function is injected via useMachine options.context instead of a closure.
This reverts commit a521f2e.
TransitionConfig, Transition, InvokeConfig, StateConfig, and MachineConfig now accept an optional TStates extends string = string generic. When callers supply it, initial and transition targets are constrained to that literal union; the default of string preserves the existing behaviour for untyped machines. StateConfig.on keys are now Partial<Record<TEvent['type'], ...>> so event type typos (e.g. 'CANEEL' instead of 'CANCEL') are caught at the createMachine call site rather than silently accepted. Type tests cover both constraints.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: e1c94a8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited) Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/eslint-plugin
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
Adds a `UseMachineOptions` type that extends `CreateActorOptions` with an optional `onDone` callback, fired once when the machine reaches a final state. Auth flows can now declaratively hand off (navigate, redirect) without a `useEffect` watching `snapshot.status` externally.
Resolves a promise with the first snapshot satisfying a predicate. Rejects when the actor becomes non-active without the predicate passing, or when an optional timeout elapses (WaitForTimeoutError). Eliminates manual subscribe wiring in async tests and flow orchestration.
Adds setTimeout-based delayed transitions via a new `after` key on state nodes — the idiomatic way to model OTP expiry and resend cooldowns without leaking timers into components. Timers are cancelled on state exit and on stop(), so they never outlive the state or the actor.
No auth flow or component pulls it in; deferred()+tick() covers test needs. Can be added when something concrete requires it.
Description
Checklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change