diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 3618edf..0000000 --- a/.prettierignore +++ /dev/null @@ -1,8 +0,0 @@ -dist -node_modules -pnpm-lock.yaml -*.tgz -src -test -typetest -examples diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 1014c0e..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "semi": false, - "printWidth": 120, - "trailingComma": "none" -} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..0af0fbf --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["dprint.dprint"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ce6d05e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,28 @@ +{ + "dprint.path": "node_modules/.bin/dprint", + "editor.formatOnSave": true, + "editor.defaultFormatter": "dprint.dprint", + "editor.formatOnSaveMode": "file", + "files.insertFinalNewline": true, + "[typescript]": { + "editor.defaultFormatter": "dprint.dprint" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "dprint.dprint" + }, + "[javascript]": { + "editor.defaultFormatter": "dprint.dprint" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "dprint.dprint" + }, + "[json]": { + "editor.defaultFormatter": "dprint.dprint" + }, + "[jsonc]": { + "editor.defaultFormatter": "dprint.dprint" + }, + "[markdown]": { + "editor.defaultFormatter": "dprint.dprint" + } +} diff --git a/README.md b/README.md index dbdfecc..d2f7330 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ require upgrading Effect in lockstep; do not override the peer to another beta. ```ts import { Machine } from "@typeonce/effect-machine" -import { AtomMachine } from "@typeonce/effect-machine/reactivity" import { ClusterMachine } from "@typeonce/effect-machine/cluster" +import { AtomMachine } from "@typeonce/effect-machine/reactivity" ``` Each ESM entrypoint is independent and tree-shakeable. Importing the root does @@ -37,8 +37,8 @@ property contains the individual tagged schemas, and each case has a typed `make` constructor. ```ts -import { Schema } from "effect" import { Machine } from "@typeonce/effect-machine" +import { Schema } from "effect" const State = Schema.TaggedUnion({ Idle: {}, @@ -256,7 +256,9 @@ effects in `Machine.action`; actions are staged during planning and run by the managed runtime before it publishes the next state. ```ts -Save: ({ target }) => Machine.action(writeAuditLog, target.local.Saving.from()) +const handlers = { + Save: ({ target }) => Machine.action(writeAuditLog, target.local.Saving.from()) +} ``` The one-argument form returns `void` after staging. The two-argument form @@ -283,16 +285,18 @@ state interrupts the child. For a one-shot Effect, `Machine.invokeEffect` maps typed success and failure values directly to internal events: ```ts -invoke: ({ state }) => - Machine.invokeEffect({ - id: "save", - effect: save(state), - onSuccess: (entry) => InternalEvent.cases.Saved.make({ id: entry.id }), - onFailure: (error) => - InternalEvent.cases.SaveFailed.make({ - message: String(error) - }) - }) +const loading = { + invoke: ({ state }) => + Machine.invokeEffect({ + id: "save", + effect: save(state), + onSuccess: (entry) => InternalEvent.cases.Saved.make({ id: entry.id }), + onFailure: (error) => + InternalEvent.cases.SaveFailed.make({ + message: String(error) + }) + }) +} ``` Omit `onFailure` when the Effect cannot fail. Defects and interruption remain @@ -344,8 +348,8 @@ Exporting one descriptor remains the clearest module boundary. disposing the registry-owned reference stops it. ```ts -import { Atom } from "effect/unstable/reactivity" import { AtomMachine } from "@typeonce/effect-machine/reactivity" +import { Atom } from "effect/unstable/reactivity" const runtime = Atom.runtime(AppLayer) const machines = AtomMachine.bind(runtime) diff --git a/dprint.json b/dprint.json new file mode 100644 index 0000000..a500b54 --- /dev/null +++ b/dprint.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://dprint.dev/schemas/v0.json", + "incremental": false, + "includes": ["**/*.{ts,tsx,js,jsx,json,md}"], + "indentWidth": 2, + "lineWidth": 120, + "newLineKind": "lf", + "typescript": { + "semiColons": "asi", + "quoteStyle": "alwaysDouble", + "trailingCommas": "never", + "operatorPosition": "maintain", + "arrowFunction.useParentheses": "force" + }, + "excludes": [ + "LLMS.md", + "**/dist", + "**/build", + "**/docs", + "**/coverage", + "packages/**/CHANGELOG.md", + "!scratchpad/**/*", + ".agents", + ".context", + ".specs" + ], + "plugins": [ + "https://plugins.dprint.dev/typescript-0.93.4.wasm", + "https://plugins.dprint.dev/markdown-0.20.0.wasm", + "https://plugins.dprint.dev/json-0.21.1.wasm" + ] +} diff --git a/examples/platformer/src/machine.ts b/examples/platformer/src/machine.ts index 1315313..95299d2 100644 --- a/examples/platformer/src/machine.ts +++ b/examples/platformer/src/machine.ts @@ -1,5 +1,5 @@ -import { Effect, Schema } from "effect" import { Machine } from "@typeonce/effect-machine" +import { Effect, Schema } from "effect" // Domain schemas are shared by state payloads and the public physics protocol. export const Axis = Schema.Literals([-1, 0, 1]) @@ -127,12 +127,11 @@ const initialCharacter = () => character .locomotion(State.cases.Locomotion.make({}), (locomotion) => locomotion.Grounded(State.cases.Grounded.make({}), (grounded) => - grounded.Standing(State.cases.Standing.make({})) - ) - ) - .facing(State.cases.Facing.make({}), (facing) => facing.Right(State.cases.Right.make({}))) - .contact(State.cases.WallContact.make({}), (contact) => contact.NoWall(State.cases.NoWall.make({}))) - ) + grounded.Standing(State.cases.Standing.make({})))) + .facing(State.cases.Facing.make({}), (facing) => + facing.Right(State.cases.Right.make({}))) + .contact(State.cases.WallContact.make({}), (contact) => + contact.NoWall(State.cases.NoWall.make({})))) export const CharacterMachine = Machine.make({ id: "PlatformerCharacter", @@ -159,22 +158,17 @@ export const CharacterMachine = Machine.make({ .motion(State.cases.Motion.make({}), (motion) => motion.Jumping( State.cases.Jumping.make({ startedAt: event.at, push: 0, kind: "Ground" }) - ) - ) + )) .airJump(State.cases.AirJump.make({}), (airJump) => - airJump.AirJumpGroundLock(State.cases.AirJumpGroundLock.make({})) - ) - ) - ) - .facing(State.cases.Facing.make({}), (facing) => facing.Right(State.cases.Right.make({}))) + airJump.AirJumpGroundLock(State.cases.AirJumpGroundLock.make({}))))) + .facing(State.cases.Facing.make({}), (facing) => + facing.Right(State.cases.Right.make({}))) .contact(State.cases.WallContact.make({}), (contact) => event.wall === -1 ? contact.LeftWall(State.cases.LeftWall.make({})) : event.wall === 1 - ? contact.RightWall(State.cases.RightWall.make({})) - : contact.NoWall(State.cases.NoWall.make({})) - ) - ) + ? contact.RightWall(State.cases.RightWall.make({})) + : contact.NoWall(State.cases.NoWall.make({})))) }, states: { Standing: { @@ -220,7 +214,7 @@ export const CharacterMachine = Machine.make({ }, Airborne: { on: { - JumpPressed: Effect.fn(function* ({ event, runtime }) { + JumpPressed: Effect.fn(function*({ event, runtime }) { const machine = yield* runtime const push = awayFrom(event.wall) yield* machine.raise( @@ -230,14 +224,16 @@ export const CharacterMachine = Machine.make({ ) }), Landed: ({ event, target }) => - target.branch.Character.locomotion.Grounded(State.cases.Grounded.make({}), (grounded) => - grounded.Landing( - State.cases.Landing.make({ - impact: event.impact, - resumeAxis: event.axis, - landedAt: event.at - }) - ) + target.branch.Character.locomotion.Grounded( + State.cases.Grounded.make({}), + (grounded) => + grounded.Landing( + State.cases.Landing.make({ + impact: event.impact, + resumeAxis: event.axis, + landedAt: event.at + }) + ) ) }, states: { @@ -274,8 +270,7 @@ export const CharacterMachine = Machine.make({ on: { WallJump: { reenter: true, - transition: ({ target }) => - target.local.AirJumpWallLock(State.cases.AirJumpWallLock.make({})) + transition: ({ target }) => target.local.AirJumpWallLock(State.cases.AirJumpWallLock.make({})) } }, states: { @@ -284,8 +279,7 @@ export const CharacterMachine = Machine.make({ id: "ground-air-jump-unlock" }), on: { - AirJumpUnlocked: ({ target }) => - target.local.AirJumpReady(State.cases.AirJumpReady.make({})) + AirJumpUnlocked: ({ target }) => target.local.AirJumpReady(State.cases.AirJumpReady.make({})) } }, AirJumpWallLock: { @@ -293,13 +287,12 @@ export const CharacterMachine = Machine.make({ id: "wall-air-jump-unlock" }), on: { - AirJumpUnlocked: ({ target }) => - target.local.AirJumpReady(State.cases.AirJumpReady.make({})) + AirJumpUnlocked: ({ target }) => target.local.AirJumpReady(State.cases.AirJumpReady.make({})) } }, AirJumpReady: { on: { - TryAirJump: Effect.fn(function* ({ event, runtime, target }) { + TryAirJump: Effect.fn(function*({ event, runtime, target }) { const machine = yield* runtime yield* machine.raise(InternalEvent.cases.DoubleJump.make({ at: event.at })) return target.local.AirJumpSpent(State.cases.AirJumpSpent.make({})) @@ -325,8 +318,7 @@ export const CharacterMachine = Machine.make({ }, Right: { on: { - Move: ({ event, target }) => - event.axis === -1 ? target.local.Left(State.cases.Left.make({})) : undefined, + Move: ({ event, target }) => event.axis === -1 ? target.local.Left(State.cases.Left.make({})) : undefined, WallJump: ({ event, target }) => event.push === -1 ? target.local.Left(State.cases.Left.make({})) : undefined } @@ -339,8 +331,8 @@ export const CharacterMachine = Machine.make({ event.wall === -1 ? target.local.LeftWall(State.cases.LeftWall.make({})) : event.wall === 1 - ? target.local.RightWall(State.cases.RightWall.make({})) - : target.local.NoWall(State.cases.NoWall.make({})) + ? target.local.RightWall(State.cases.RightWall.make({})) + : target.local.NoWall(State.cases.NoWall.make({})) }, states: { NoWall: {}, diff --git a/examples/platformer/src/main.ts b/examples/platformer/src/main.ts index b9429a7..9048fc0 100644 --- a/examples/platformer/src/main.ts +++ b/examples/platformer/src/main.ts @@ -1,17 +1,17 @@ import "./styles.css" -import { Effect, Fiber, Stream } from "effect" import { Machine } from "@typeonce/effect-machine" +import { Effect, Fiber, Stream } from "effect" import { GameAdapter } from "./game.ts" import { activeStateData, airJumpMode, + type CharacterEvent, CharacterMachine, + type CharacterSnapshot, facingDirection, locomotionBranch, locomotionMode, - wallContact, - type CharacterEvent, - type CharacterSnapshot + wallContact } from "./machine.ts" const requiredElement = (selector: string) => { @@ -59,7 +59,7 @@ const publish = (next: CharacterSnapshot) => { }) } -const program = Effect.gen(function* () { +const program = Effect.gen(function*() { const actor = yield* Machine.start(CharacterMachine) deliver = (event) => Effect.runFork(actor.send(event).pipe(Effect.catchTag("StoppedError", () => Effect.void))) publish(yield* actor.state) diff --git a/examples/pokemon/src/machine.ts b/examples/pokemon/src/machine.ts index 1a48d31..7572e43 100644 --- a/examples/pokemon/src/machine.ts +++ b/examples/pokemon/src/machine.ts @@ -1,7 +1,7 @@ -import { Effect, Schema } from "effect" import { Machine } from "@typeonce/effect-machine" -import { Atom } from "effect/unstable/reactivity" import { AtomMachine } from "@typeonce/effect-machine/reactivity" +import { Effect, Schema } from "effect" +import { Atom } from "effect/unstable/reactivity" import { ReplaceMachine } from "./machines/replace.ts" import { SelectionMachine } from "./machines/selection.ts" import { Pokemon, PokemonService, ReplaceInTeam } from "./pokemon.ts" @@ -18,7 +18,7 @@ export const ReplaceChild = Machine.child("replace", ReplaceMachine) const machine = Machine.make({ states: States.states, events: [ReplaceInTeam], - initial: Effect.fn(function* () { + initial: Effect.fn(function*() { const pk = yield* PokemonService const team = yield* pk.getRandomTeam() return States.initial.ActiveTeam(new ActiveTeam({ team })) diff --git a/examples/pokemon/src/machines/replace.ts b/examples/pokemon/src/machines/replace.ts index d9ba1d0..8407506 100644 --- a/examples/pokemon/src/machines/replace.ts +++ b/examples/pokemon/src/machines/replace.ts @@ -1,5 +1,5 @@ -import { Effect, Schema } from "effect" import { Machine } from "@typeonce/effect-machine" +import { Effect, Schema } from "effect" import { Pokemon, PokemonService, ReplaceInTeam } from "../pokemon.ts" class Idle extends Schema.TaggedClass("Idle")("Idle", {}) {} @@ -24,7 +24,7 @@ const ReplaceWithRandomMachine = Machine.invoke({ Machine.effect( Effect.sleep("500 millis").pipe( Effect.andThen( - Effect.gen(function* () { + Effect.gen(function*() { const pk = yield* PokemonService const pokemon = yield* pk.getRandomPokemon() return new Replaced({ pokemon }) diff --git a/examples/pokemon/src/machines/selection.ts b/examples/pokemon/src/machines/selection.ts index d2a75ce..33e1a8a 100644 --- a/examples/pokemon/src/machines/selection.ts +++ b/examples/pokemon/src/machines/selection.ts @@ -1,5 +1,5 @@ -import { Effect, Option, Schema } from "effect" import { Machine } from "@typeonce/effect-machine" +import { Effect, Option, Schema } from "effect" import { Pokemon, PokemonService, ReplaceInTeam } from "../pokemon.ts" class Form extends Schema.TaggedClass
("Form")("Form", {}) {} @@ -49,7 +49,7 @@ const SearchMachine = ({ searchText }: { searchText: string }) => Machine.effect( Effect.sleep("500 millis").pipe( Effect.andThen( - Effect.gen(function* () { + Effect.gen(function*() { const pk = yield* PokemonService const pokemon = yield* pk.getByName(searchText) return new SearchResult({ result: pokemon }) @@ -95,8 +95,7 @@ export const SelectionMachine = Machine.make({ SelectionStates.initial.form(new Form(), (form) => form .search(new Search({ searchText: "" }), (search) => search.NoPokemon(new NoPokemon())) - .selection(new Selection(), (selection) => selection.Unselected(new Unselected())) - ) + .selection(new Selection(), (selection) => selection.Unselected(new Unselected()))) }).handle({ form: { states: { @@ -117,8 +116,7 @@ export const SelectionMachine = Machine.make({ target.full.form(new Form(), (form) => form .search(new Search({ searchText: "" }), (search) => search.NoPokemon(new NoPokemon())) - .selection(new Selection(), (selection) => selection.Unselected(new Unselected())) - ) + .selection(new Selection(), (selection) => selection.Unselected(new Unselected()))) ) ) } diff --git a/examples/pokemon/src/pokemon.ts b/examples/pokemon/src/pokemon.ts index 89c2acd..5fde6e7 100644 --- a/examples/pokemon/src/pokemon.ts +++ b/examples/pokemon/src/pokemon.ts @@ -23,7 +23,7 @@ export class ReplaceInTeam extends Schema.TaggedClass("ReplaceInT }) {} export class PokemonService extends Context.Service()("app/PokemonService", { - make: Effect.gen(function* () { + make: Effect.gen(function*() { const baseClient = yield* HttpClient.HttpClient const client = baseClient.pipe( HttpClient.mapRequest( @@ -32,7 +32,7 @@ export class PokemonService extends Context.Service()("app/Pokem ) return { - getRandomTeam: Effect.fn("PokemonService.getTeam")(function* () { + getRandomTeam: Effect.fn("PokemonService.getTeam")(function*() { const teamIndexes = yield* Random.shuffle(Array.range(1, 1025)).pipe(Effect.map(Array.take(6))) return yield* Effect.all( @@ -43,13 +43,13 @@ export class PokemonService extends Context.Service()("app/Pokem ) }), - getRandomPokemon: Effect.fn("PokemonService.getRandomPokemon")(function* () { + getRandomPokemon: Effect.fn("PokemonService.getRandomPokemon")(function*() { const index = yield* Random.nextIntBetween(1, 1025) const response = yield* client.get(`/pokemon/${index}`) return yield* HttpClientResponse.schemaBodyJson(Pokemon)(response) }), - getByName: Effect.fn("PokemonService.getByName")(function* (name: string) { + getByName: Effect.fn("PokemonService.getByName")(function*(name: string) { const response = yield* client.get(`/pokemon/${encodeURIComponent(name.trim().toLowerCase())}`) return yield* HttpClientResponse.matchStatus(response, { 404: () => Effect.succeed(Option.none()), diff --git a/examples/pokemon/src/router.tsx b/examples/pokemon/src/router.tsx index 823c8cd..161b56b 100644 --- a/examples/pokemon/src/router.tsx +++ b/examples/pokemon/src/router.tsx @@ -177,8 +177,7 @@ function PokemonGrid({ team }: { team: readonly (typeof Pokemon.Type)[] }) { new SelectPokemon({ id: pokemon.id }) - ) - } + )} > Select diff --git a/package.json b/package.json index a02e2f7..4f41cae 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,8 @@ "test:types": "tstyche", "typecheck": "tsc -p tsconfig.json --noEmit", "perf:types": "pnpm build && node scripts/type-performance.mjs", - "format": "prettier --write .", - "format:check": "prettier --check .", + "format": "dprint fmt", + "format:check": "dprint check", "test:consumer": "node scripts/test-consumer.mjs", "pack:check": "node scripts/pack-check.mjs", "check": "pnpm format:check && pnpm typecheck && pnpm build && pnpm test && pnpm test:types && pnpm test:consumer && pnpm pack:check", @@ -62,8 +62,8 @@ "@changesets/cli": "2.31.0", "@effect/vitest": "4.0.0-beta.102", "@types/node": "25.7.0", + "dprint": "0.55.2", "effect": "4.0.0-beta.102", - "prettier": "3.8.1", "tstyche": "7.2.1", "typescript": "6.0.3", "vitest": "4.1.10" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 43b5ddd..6c154ba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,12 +21,12 @@ importers: '@types/node': specifier: 25.7.0 version: 25.7.0 + dprint: + specifier: 0.55.2 + version: 0.55.2 effect: specifier: 4.0.0-beta.102 version: 4.0.0-beta.102 - prettier: - specifier: 3.8.1 - version: 3.8.1 tstyche: specifier: 7.2.1 version: 7.2.1(typescript@6.0.3) @@ -98,6 +98,90 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + '@dprint/android-arm64@0.55.2': + resolution: {integrity: sha512-cywqM0E2h8lCA/b5BMFcuascaGuekm2lnyKb5hRH9juKbsqKeR8A7qf2p3nVWRQ8cM7djOnQwhy8ecQ3qd6j9A==} + cpu: [arm64] + os: [android] + + '@dprint/android-x64@0.55.2': + resolution: {integrity: sha512-BvcqquD94dSYQP2FzBuojU/8vITpwz80uAkub2xCCx5g7zYdUZ98tK+N3GKfRS5AUJ1LpRPJgbO09rRLEo8leA==} + cpu: [x64] + os: [android] + + '@dprint/darwin-arm64@0.55.2': + resolution: {integrity: sha512-HjzasuPaC0EBHxEpS3Px/OPcxqZYln37xuAyYE0GFAhDuaotZEUpM8VE05Tzo4E32y7LKgLPT8CZVtEG5Ck7mQ==} + cpu: [arm64] + os: [darwin] + + '@dprint/darwin-x64@0.55.2': + resolution: {integrity: sha512-7XSF9XERvimg3XakXNlJRpJM9an5HKibWWShwCJr7Dz1Xp7P3pomjx9AtYV5EeD49GXu9FKdFfDiTC4BJtAVjA==} + cpu: [x64] + os: [darwin] + + '@dprint/linux-arm64-glibc@0.55.2': + resolution: {integrity: sha512-2h5oe4tHGXJOTLU5BxVJLGPP1qQQxxECdjUaRkLxGn2rZIEf/7HwoJ+TjwMUaIVg4QxAFxfiMJJ3MRZjumJpsg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@dprint/linux-arm64-musl@0.55.2': + resolution: {integrity: sha512-Z1X9mNLHWoSI7CHz888H2w27IV2UQ5lL/YbTwgguJM9ApLgvkMer5qr4pLlXF6vEY3+Rm0445eo3uojbjE7PTw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@dprint/linux-loong64-glibc@0.55.2': + resolution: {integrity: sha512-qxk4Cg/SjO14DALoG1MFZL+n6pEvCyd7VDHg1cQIpp82mZ+wtRaWkJqSaItWj12x8jihA32wAoQ/8OHz+5FFsQ==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@dprint/linux-loong64-musl@0.55.2': + resolution: {integrity: sha512-Mr+kRdZnxhUHBmhhADkYOo1g81PYvbh7eBo+lpMStgIvL/5Z93mGAcp/1NFcpeN02pilaI1N59awV08ApJ19cA==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@dprint/linux-ppc64-glibc@0.55.2': + resolution: {integrity: sha512-C8XEL3f3yg+MWZD4qlot+ibJ0GDPvCT5jq9ErwPdKteyIPpe6IPSqiEApYSQ194Q7audL8rgS0WdJsW4HNVhmw==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@dprint/linux-ppc64-musl@0.55.2': + resolution: {integrity: sha512-tSGe4bTmL5/EhNH38baCKWBGxOXVB0M5Loxnpls7wsQjuLpzWnzDCw4wiO3C7PrKLbAe4sJUWhbgdDXa3TJ2eQ==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@dprint/linux-riscv64-glibc@0.55.2': + resolution: {integrity: sha512-gSaoq9e3vGTfYm5jcEd86YysFsp8OJF/CGZgBzNNu3NSjLEs8VVgTObDxQI+U7ex2mA17lbpWyr3diejaaK+bg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@dprint/linux-x64-glibc@0.55.2': + resolution: {integrity: sha512-GBLWjuqTT5OGbqh2gQENQihhfRn/AjdDu2SVwjmbZcOFR80HMppIfFrIIolBB3FLyrZk+M8rMk8EAo0tQ3PAXw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@dprint/linux-x64-musl@0.55.2': + resolution: {integrity: sha512-GZEUpmtxCOiauRtqOqT/erAjy2ws8dOxx7oQJFf9g5bypisuapwymvr7fUVVb8nqccFqjx7E5kN4IxKDlzntHA==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@dprint/win32-arm64@0.55.2': + resolution: {integrity: sha512-dxDdxU4a6wQ4K0omdAxW7o0mUdOI03z0/Ah3N6O9Ja7wAMQI5sbfzq7DOJ739UVXtHSB4zBTtYuk1MrBOIyVQQ==} + cpu: [arm64] + os: [win32] + + '@dprint/win32-x64@0.55.2': + resolution: {integrity: sha512-UTiDSShHbrkx+z719/MffgwGYD8PaypdVmG4vVJVjmF5Hoin6EfugHhSoBf8+G6U9rF+uDIIl0idZq+6Bifzwg==} + cpu: [x64] + os: [win32] + '@effect/vitest@4.0.0-beta.102': resolution: {integrity: sha512-4dipFAYG6imOzrY3zy3BgzCJkbb9xESyzUef0WSx8bsK0/SpITqbJpdwKeOyDWLZ+rimjua8IbTFMAde865pIQ==} peerDependencies: @@ -386,6 +470,10 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + dprint@0.55.2: + resolution: {integrity: sha512-1d4D4SB9KiD2qFnBWbl3aoYjLvPVpZoth28yxTT00xJv2yXugdz0Xoyv7sGG0w0hzE6hQZMgd6B333GnySDpGQ==} + hasBin: true + effect@4.0.0-beta.102: resolution: {integrity: sha512-z8Y+Q76Hh/kjLFZrXu8tGn6e+tDsg45R+UHhxd190pXxD53OGwf/G/zDxXTkse4HJ5mobNZfitLfUCp4fMvu6w==} @@ -703,11 +791,6 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.8.1: - resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} - engines: {node: '>=14'} - hasBin: true - pure-rand@8.4.2: resolution: {integrity: sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng==} @@ -1090,6 +1173,51 @@ snapshots: human-id: 4.2.0 prettier: 2.8.8 + '@dprint/android-arm64@0.55.2': + optional: true + + '@dprint/android-x64@0.55.2': + optional: true + + '@dprint/darwin-arm64@0.55.2': + optional: true + + '@dprint/darwin-x64@0.55.2': + optional: true + + '@dprint/linux-arm64-glibc@0.55.2': + optional: true + + '@dprint/linux-arm64-musl@0.55.2': + optional: true + + '@dprint/linux-loong64-glibc@0.55.2': + optional: true + + '@dprint/linux-loong64-musl@0.55.2': + optional: true + + '@dprint/linux-ppc64-glibc@0.55.2': + optional: true + + '@dprint/linux-ppc64-musl@0.55.2': + optional: true + + '@dprint/linux-riscv64-glibc@0.55.2': + optional: true + + '@dprint/linux-x64-glibc@0.55.2': + optional: true + + '@dprint/linux-x64-musl@0.55.2': + optional: true + + '@dprint/win32-arm64@0.55.2': + optional: true + + '@dprint/win32-x64@0.55.2': + optional: true + '@effect/vitest@4.0.0-beta.102(effect@4.0.0-beta.102)(vitest@4.1.10(@types/node@25.7.0)(vite@8.1.5(@types/node@25.7.0)(yaml@2.9.0)))': dependencies: effect: 4.0.0-beta.102 @@ -1331,6 +1459,24 @@ snapshots: dependencies: path-type: 4.0.0 + dprint@0.55.2: + optionalDependencies: + '@dprint/android-arm64': 0.55.2 + '@dprint/android-x64': 0.55.2 + '@dprint/darwin-arm64': 0.55.2 + '@dprint/darwin-x64': 0.55.2 + '@dprint/linux-arm64-glibc': 0.55.2 + '@dprint/linux-arm64-musl': 0.55.2 + '@dprint/linux-loong64-glibc': 0.55.2 + '@dprint/linux-loong64-musl': 0.55.2 + '@dprint/linux-ppc64-glibc': 0.55.2 + '@dprint/linux-ppc64-musl': 0.55.2 + '@dprint/linux-riscv64-glibc': 0.55.2 + '@dprint/linux-x64-glibc': 0.55.2 + '@dprint/linux-x64-musl': 0.55.2 + '@dprint/win32-arm64': 0.55.2 + '@dprint/win32-x64': 0.55.2 + effect@4.0.0-beta.102: dependencies: '@standard-schema/spec': 1.1.0 @@ -1604,8 +1750,6 @@ snapshots: prettier@2.8.8: {} - prettier@3.8.1: {} - pure-rand@8.4.2: {} quansync@0.2.11: {} diff --git a/scripts/fixtures/consumer/consumer.ts b/scripts/fixtures/consumer/consumer.ts index 96998e8..b40339d 100644 --- a/scripts/fixtures/consumer/consumer.ts +++ b/scripts/fixtures/consumer/consumer.ts @@ -1,7 +1,7 @@ -import { Effect, Schema } from "effect" import { Machine } from "@typeonce/effect-machine" -import { AtomMachine } from "@typeonce/effect-machine/reactivity" import { ClusterMachine } from "@typeonce/effect-machine/cluster" +import { AtomMachine } from "@typeonce/effect-machine/reactivity" +import { Effect, Schema } from "effect" const State = Schema.TaggedUnion({ Idle: {}, diff --git a/scripts/fixtures/consumer/deep-bound.ts b/scripts/fixtures/consumer/deep-bound.ts index 9866201..696eda4 100644 --- a/scripts/fixtures/consumer/deep-bound.ts +++ b/scripts/fixtures/consumer/deep-bound.ts @@ -1,10 +1,10 @@ -import { Context, Effect, Layer, Schema } from "effect" -import { Atom } from "effect/unstable/reactivity" import { Machine } from "@typeonce/effect-machine" import { AtomMachine } from "@typeonce/effect-machine/reactivity" +import { Context, Effect, Layer, Schema } from "effect" +import { Atom } from "effect/unstable/reactivity" -type Equal = - (() => Type extends Left ? 1 : 2) extends () => Type extends Right ? 1 : 2 ? true : false +type Equal = (() => Type extends Left ? 1 : 2) extends () => Type extends Right ? 1 : 2 ? true + : false type Expect = Type class ExternalService extends Context.Service()("consumer/ExternalService") {} @@ -64,7 +64,7 @@ const childMachine = Machine.make({ Done: { entry: ({ state }) => Machine.action( - Effect.gen(function* () { + Effect.gen(function*() { const runtime = yield* Machine.runtime<{ readonly emits: typeof Internal.cases.ChildNotice.Type }>() yield* runtime.sendParent(Internal.cases.ChildNotice.make({ value: state.value })) }) @@ -104,7 +104,7 @@ const machine = Machine.make({ emits: [Emitted.cases.Notice], input: Schema.Struct({ seed: Schema.String }), initial: ({ seed }) => - Effect.gen(function* () { + Effect.gen(function*() { yield* InitialService if (seed.length < 0) return yield* Effect.fail(new InitialFailure()) return States.initial.Idle(State.cases.Idle.make({})) @@ -117,10 +117,11 @@ const machine = Machine.make({ }), on: { Begin: ({ target }) => - target.full.Ready(State.cases.Ready.make({}), (ready) => - ready.Editor(State.cases.Editor.make({}), (editor) => - editor.Editing(State.cases.Editing.make({ value: "ready" })) - ) + target.full.Ready( + State.cases.Ready.make({}), + (ready) => + ready.Editor(State.cases.Editor.make({}), (editor) => + editor.Editing(State.cases.Editing.make({ value: "ready" }))) ) } }, @@ -132,7 +133,7 @@ const machine = Machine.make({ on: { Save: ({ event, target }) => Machine.action( - Effect.gen(function* () { + Effect.gen(function*() { yield* ExternalService return yield* Effect.fail(new ActionFailure()) }), @@ -151,7 +152,7 @@ const machine = Machine.make({ on: { ChildNotice: ({ event, target }) => Machine.action( - Effect.gen(function* () { + Effect.gen(function*() { const runtime = yield* Machine.runtime<{ readonly emits: typeof Emitted.cases.Notice.Type }>() yield* runtime.sendParent(Emitted.cases.Notice.make({ value: event.value })) }), diff --git a/src/AtomMachine.ts b/src/AtomMachine.ts index b8ef94f..5f741ce 100644 --- a/src/AtomMachine.ts +++ b/src/AtomMachine.ts @@ -12,8 +12,8 @@ import type * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import * as Stream from "effect/Stream" import { AsyncResult, Atom, type AtomRegistry } from "effect/unstable/reactivity" -import * as Machine from "./Machine.js" import * as Model from "./internal/machineModel.js" +import * as Machine from "./Machine.js" /** * Error returned when a machine command is issued before startup completes. @@ -110,10 +110,10 @@ const startMachineAtomEffect = < & Machine.Machine.EnsureOutputImplementations, args: [...Machine.Machine.InputArgs] ): Effect.Effect< - Machine.MachineRef< - Machine.Machine.Snapshot, - Machine.Machine.EventOf, - MachineRuntimeError, + Machine.MachineRef< + Machine.Machine.Snapshot, + Machine.Machine.EventOf, + MachineRuntimeError, Output >, MachineStartError, @@ -499,11 +499,11 @@ const makeChildFromRefAtom = ( nested: Nested - ): ChildMachineAtom => - childFamily(nested) as ChildMachineAtom + ): ChildMachineAtom => childFamily(nested) as ChildMachineAtom return { ref, @@ -595,11 +595,11 @@ const makeFromRefAtom = ( makeChildFromRefAtom( makeChildRefAtom(optionalRef as any, descriptor), descriptor - )) + ) + ) const child = ( descriptor: Child - ): ChildMachineAtom => - childFamily(descriptor) as ChildMachineAtom + ): ChildMachineAtom => childFamily(descriptor) as ChildMachineAtom return { ref, @@ -613,10 +613,10 @@ const makeFromRefAtom = ( } type SnapshotNode = State extends Machine.Machine.AtomicSnapshot ? - | State - | (State extends { readonly state: infer Child } ? SnapshotNode - : State extends { readonly states: infer Regions } ? SnapshotNode - : never) + | State + | (State extends { readonly state: infer Child } ? SnapshotNode + : State extends { readonly states: infer Regions } ? SnapshotNode + : never) : never type SnapshotIdentifier = SnapshotNode extends infer Node ? @@ -773,19 +773,18 @@ type MissingBoundRequirements = Exclude Services > -type EnsureBoundRequirements = - IsAny> extends true ? { - readonly [BoundRequirementsTypeId]: MachineRequirementsOf - } - : [MissingBoundRequirements] extends [never] ? unknown - : { - readonly [BoundRequirementsTypeId]: MissingBoundRequirements - } +type EnsureBoundRequirements = IsAny> extends true ? { + readonly [BoundRequirementsTypeId]: MachineRequirementsOf + } + : [MissingBoundRequirements] extends [never] ? unknown + : { + readonly [BoundRequirementsTypeId]: MissingBoundRequirements + } -type EnsureMachineOutputImplementations = - IsAny> extends true ? { - readonly "~effect/reactivity/AtomMachine/ConcreteMachineRequired": M - } +type EnsureMachineOutputImplementations = IsAny> extends true ? + { + readonly "~effect/reactivity/AtomMachine/ConcreteMachineRequired": M + } : Machine.Machine.EnsureOutputImplementations, Machine.Machine.OutputStates> type MachineInputArgsOf = [ @@ -793,18 +792,18 @@ type MachineInputArgsOf = [ ] type MachineAtomOf = MachineAtom< - Machine.Machine.Snapshot>, - Machine.Machine.InputEvent, - MachineRuntimeError, Machine.Machine.Services>, - Machine.Machine.Output, - MachineStartError< - Machine.Machine.InitialError, - Machine.Machine.Error, - Machine.Machine.InitialServices, - Machine.Machine.Services, - RuntimeError - > + Machine.Machine.Snapshot>, + Machine.Machine.InputEvent, + MachineRuntimeError, Machine.Machine.Services>, + Machine.Machine.Output, + MachineStartError< + Machine.Machine.InitialError, + Machine.Machine.Error, + Machine.Machine.InitialServices, + Machine.Machine.Services, + RuntimeError > +> /** * An `AtomMachine` factory with one owned Effect runtime. @@ -915,9 +914,10 @@ const makeWithRuntime = ( export const bind = ( runtime: Atom.AtomRuntime ): Bound => ({ - make: ((machine: Machine.Machine.Any, ...args: ReadonlyArray) => - makeWithRuntime(runtime, machine, args)) as Bound< - Services, - RuntimeError - >["make"] + make: + ((machine: Machine.Machine.Any, ...args: ReadonlyArray) => + makeWithRuntime(runtime, machine, args)) as Bound< + Services, + RuntimeError + >["make"] }) diff --git a/src/ClusterMachine.ts b/src/ClusterMachine.ts index 0a6da01..3481468 100644 --- a/src/ClusterMachine.ts +++ b/src/ClusterMachine.ts @@ -9,8 +9,6 @@ import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" import * as Option from "effect/Option" import * as Schema from "effect/Schema" -import * as Machine from "./Machine.js" -import { Rpc } from "effect/unstable/rpc" import { ClusterError, ClusterSchema, @@ -20,6 +18,8 @@ import { type Sharding, Snowflake } from "effect/unstable/cluster" +import { Rpc } from "effect/unstable/rpc" +import * as Machine from "./Machine.js" type EntityAddress = EntityAddress.EntityAddress type PersistenceError = ClusterError.PersistenceError @@ -262,13 +262,13 @@ export interface ClusterMachine< } type MachineServices = - | ExcludeCompatibleRuntime< - Machine.ExecutionServices | Machine.Machine.InitialServices>, - Machine.Machine.Event, - Machine.Machine.Emit - > - | Machine.Machine.SnapshotDecodingServices> - | Machine.Machine.SnapshotEncodingServices> + | ExcludeCompatibleRuntime< + Machine.ExecutionServices | Machine.Machine.InitialServices>, + Machine.Machine.Event, + Machine.Machine.Emit + > + | Machine.Machine.SnapshotDecodingServices> + | Machine.Machine.SnapshotEncodingServices> type IsAny = 0 extends (1 & A) ? true : false diff --git a/src/Machine.ts b/src/Machine.ts index 18dc225..99c0ee7 100644 --- a/src/Machine.ts +++ b/src/Machine.ts @@ -510,8 +510,8 @@ type DuplicateEventTag< infer Head extends Machine.TaggedSchema, ...infer Tail extends ReadonlyArray ] ? Machine.TagOf extends infer Tag extends PropertyKey ? Tag extends Seen ? Tag | DuplicateEventTag - : DuplicateEventTag - : never + : DuplicateEventTag + : never : never type ValidateEventProtocol< @@ -1390,15 +1390,15 @@ export declare namespace ChildMachine { * @since 4.0.0 */ export type Ref = Child extends ChildMachine ? MachineRef< - Machine.Snapshot>, - Machine.InputEvent, - | Machine.Error - | ActionError> - | InfiniteTransitionError - | MachineSchemaDecodeError - | StoppedError, - Machine.Output - > + Machine.Snapshot>, + Machine.InputEvent, + | Machine.Error + | ActionError> + | InfiniteTransitionError + | MachineSchemaDecodeError + | StoppedError, + Machine.Output + > : never /** @@ -2064,8 +2064,8 @@ export declare namespace Machine { * @category utility types * @since 4.0.0 */ - export type ImmediateParentStateIdentifier = StateId extends - `${infer Head}.${infer Tail}` ? Tail extends `${string}.${string}` ? `${Head}.${ImmediateParentStateIdentifier}` + export type ImmediateParentStateIdentifier = StateId extends `${infer Head}.${infer Tail}` ? + Tail extends `${string}.${string}` ? `${Head}.${ImmediateParentStateIdentifier}` : Head : never @@ -2096,11 +2096,11 @@ export declare namespace Machine { States extends StateSchemas, StateId extends StateIdentifier > = StateId extends StateIdentifier ? - Extract, StateIdentifier> extends infer Parent - ? [Parent] extends [never] ? undefined - : Parent extends StateIdentifier ? StateByIdentifier - : undefined + Extract, StateIdentifier> extends infer Parent + ? [Parent] extends [never] ? undefined + : Parent extends StateIdentifier ? StateByIdentifier : undefined + : undefined : never /** @@ -2194,8 +2194,9 @@ export declare namespace Machine { * @since 4.0.0 */ export type TerminalOutput = { - readonly [Key in Extract]: Extract> extends infer StateId - extends StateIdentifier ? NodeByIdentifier extends infer Node + readonly [Key in Extract]: Extract> extends + infer StateId extends StateIdentifier ? + NodeByIdentifier extends infer Node ? Node extends { readonly type: "parallel" | "final" } ? OutputByIdentifier : Node extends { readonly states: infer Children extends StateSchemas } ? CompoundCompletionOutputRaw< States, @@ -2203,7 +2204,7 @@ export declare namespace Machine { StateId > : never - : never + : never : never }[Extract] @@ -4838,25 +4839,28 @@ type InvokeEffectResult = Machine.InvokeConfig< never > -type InvokeEffectIsInfallible> = - IsAny> extends true ? false : [Effect.Error] extends [never] ? true : false +type InvokeEffectIsInfallible> = IsAny> extends true ? false + : [Effect.Error] extends [never] ? true + : false type InvokeEffectConfig< Fx extends Effect.Effect, SuccessEvent, FailureEvent -> = { - readonly id: InvokeLifecycleId - readonly effect: Fx - readonly onSuccess: (value: NoInfer>) => SuccessEvent | void -} & ( - InvokeEffectIsInfallible extends true ? { - readonly onFailure?: never - } - : { - readonly onFailure: (error: NoInfer>) => FailureEvent | void +> = + & { + readonly id: InvokeLifecycleId + readonly effect: Fx + readonly onSuccess: (value: NoInfer>) => SuccessEvent | void } -) + & ( + InvokeEffectIsInfallible extends true ? { + readonly onFailure?: never + } + : { + readonly onFailure: (error: NoInfer>) => FailureEvent | void + } + ) /** * Invokes one Effect and maps its typed outcome into machine-local events. @@ -4885,24 +4889,25 @@ export const invokeEffect = < ): InvokeEffectResult< Effect.Services, SuccessEvent | (InvokeEffectIsInfallible extends true ? never : FailureEvent) -> => ((config: { - readonly id: string - readonly effect: Effect.Effect - readonly onSuccess: (value: unknown) => unknown - readonly onFailure?: (error: unknown) => unknown -}) => - invoke({ - id: config.id, - src: () => - effect( - config.onFailure === undefined - ? Effect.map(config.effect, config.onSuccess) - : Effect.matchEffect(config.effect, { - onFailure: (error) => Effect.succeed(config.onFailure!(error)), - onSuccess: (value) => Effect.succeed(config.onSuccess(value)) - }) - ) - }))(config as any) as any +> => + ((config: { + readonly id: string + readonly effect: Effect.Effect + readonly onSuccess: (value: unknown) => unknown + readonly onFailure?: (error: unknown) => unknown + }) => + invoke({ + id: config.id, + src: () => + effect( + config.onFailure === undefined + ? Effect.map(config.effect, config.onSuccess) + : Effect.matchEffect(config.effect, { + onFailure: (error) => Effect.succeed(config.onFailure!(error)), + onSuccess: (value) => Effect.succeed(config.onSuccess(value)) + }) + ) + }))(config as any) as any /** * Creates a cancellable state-scoped delayed event. @@ -4928,8 +4933,7 @@ type RetagFields = Omit = Target extends { readonly fields: Schema.Struct.Fields -} ? "_tag" extends keyof Target["~type.make.in"] ? - {} extends Pick ? unknown : { +} ? "_tag" extends keyof Target["~type.make.in"] ? {} extends Pick ? unknown : { readonly "~effect/Machine/RetagTargetError": "Target schema must supply its discriminator when make is called" } : unknown @@ -5243,13 +5247,14 @@ export const planInitial: < & Machine.EnsureOutputImplementations, ...args: [...Machine.InputArgs] ) => Effect.Effect< - { + & { readonly state: Machine.Snapshot readonly actions: ReadonlyArray< Effect.Effect, ActionServices> > readonly emittedEvents: ReadonlyArray> - } & ( + } + & ( | { readonly done: true readonly output: Output @@ -5360,7 +5365,7 @@ export const plan: < state: Machine.Snapshot, event: Machine.EventOf ) => Effect.Effect< - { + & { readonly next: Machine.Snapshot readonly actions: ReadonlyArray, ActionServices>> readonly emittedEvents: ReadonlyArray> @@ -5374,7 +5379,8 @@ export const plan: < readonly entryPaths: ReadonlyArray readonly changed: boolean }> - } & ( + } + & ( | { readonly done: true readonly output: Output @@ -5644,12 +5650,11 @@ export const transition = ( export const child = ( id: Id, machine: M -): ChildMachine => - ({ - [ChildMachineTypeId]: ChildMachineTypeId, - id, - machine - }) +): ChildMachine => ({ + [ChildMachineTypeId]: ChildMachineTypeId, + id, + machine +}) /** * Creates a typed parent-local address for lower-level child process logic. @@ -5660,8 +5665,7 @@ export const child = ( * @category constructors * @since 4.0.0 */ -export const childAddress = (id: string): ChildAddress => - id as ChildAddress +export const childAddress = (id: string): ChildAddress => id as ChildAddress /** * Spawns a child process owned by the currently running machine. diff --git a/src/internal/machinePlanner.ts b/src/internal/machinePlanner.ts index 280c412..5342286 100644 --- a/src/internal/machinePlanner.ts +++ b/src/internal/machinePlanner.ts @@ -195,21 +195,23 @@ export type MicrostepPlan = { readonly changed: boolean } -export type MacrostepPlan = { - readonly next: State - readonly actions: ReadonlyArray> - readonly microsteps: ReadonlyArray> - readonly emittedEvents: ReadonlyArray -} & ( - | { - readonly done: true - readonly output: Output +export type MacrostepPlan = + & { + readonly next: State + readonly actions: ReadonlyArray> + readonly microsteps: ReadonlyArray> + readonly emittedEvents: ReadonlyArray } - | { - readonly done: false - readonly output: undefined - } -) + & ( + | { + readonly done: true + readonly output: Output + } + | { + readonly done: false + readonly output: undefined + } + ) type TransitionHandler = ( context: Context @@ -914,13 +916,14 @@ export const planInitial: < machine: Machine, ...args: [...Machine.InputArgs] ) => Effect.Effect< - { + & { readonly state: Machine.Snapshot readonly actions: ReadonlyArray< Effect.Effect > readonly emittedEvents: ReadonlyArray> - } & ( + } + & ( | { readonly done: true readonly output: Output diff --git a/src/internal/machineProcess.ts b/src/internal/machineProcess.ts index 6844c36..dd1e79c 100644 --- a/src/internal/machineProcess.ts +++ b/src/internal/machineProcess.ts @@ -245,8 +245,7 @@ export const toProcessLogic: < const reserved = yield* Ref.modify(invokeSessions, (sessions) => HashMap.has(sessions, key) ? [false, sessions] as const - : [true, HashMap.set(sessions, key, { token, scope, childId, path })] as const - ) + : [true, HashMap.set(sessions, key, { token, scope, childId, path })] as const) if (!reserved) { yield* Scope.close(scope, Exit.void) return yield* Effect.fail(new ChildAlreadyExistsError({ id: invokeId })) diff --git a/src/internal/machineRuntime.ts b/src/internal/machineRuntime.ts index d6576b0..1887cea 100644 --- a/src/internal/machineRuntime.ts +++ b/src/internal/machineRuntime.ts @@ -424,26 +424,26 @@ const startInternal: < const sendTo = (child: ChildSelector, event: unknown): Effect.Effect => { const id = typeof child === "string" ? child : child.id return ( - SubscriptionRef.get(childRegistry).pipe( - Effect.flatMap((registry) => { - const entry = HashMap.get(registry.children, id) - return Option.isSome(entry) && matchesChildSelector(entry.value, child) - ? entry.value.ref.send(event) - : Effect.void - }) - ) + SubscriptionRef.get(childRegistry).pipe( + Effect.flatMap((registry) => { + const entry = HashMap.get(registry.children, id) + return Option.isSome(entry) && matchesChildSelector(entry.value, child) + ? entry.value.ref.send(event) + : Effect.void + }) + ) ) } const stopChild = (child: ChildSelector): Effect.Effect => { const id = typeof child === "string" ? child : child.id return ( - SubscriptionRef.get(childRegistry).pipe( - Effect.flatMap((registry) => { - const entry = HashMap.get(registry.children, id) - return Option.isSome(entry) && matchesChildSelector(entry.value, child) ? entry.value.ref.stop : Effect.void - }) - ) + SubscriptionRef.get(childRegistry).pipe( + Effect.flatMap((registry) => { + const entry = HashMap.get(registry.children, id) + return Option.isSome(entry) && matchesChildSelector(entry.value, child) ? entry.value.ref.stop : Effect.void + }) + ) ) } diff --git a/test/AtomMachine.test.ts b/test/AtomMachine.test.ts index 36cda86..1109468 100644 --- a/test/AtomMachine.test.ts +++ b/test/AtomMachine.test.ts @@ -1,7 +1,7 @@ import { assert, describe, it } from "@effect/vitest" import { Cause, Context, Data, Deferred, Effect, Fiber, Layer, Option, Schema, Stream } from "effect" -import { Machine } from "../src/index.js" import { AsyncResult, Atom, AtomRegistry } from "effect/unstable/reactivity" +import { Machine } from "../src/index.js" import { AtomMachine } from "../src/reactivity.js" class Count extends Schema.TaggedClass("Count")("Count", { @@ -92,8 +92,7 @@ const makeCounterMachine = () => Finish: ({ state, event }) => MachineInitial.Count(new Count({ value: state.value + event.by })) } }, - Done: { - } + Done: {} }) const makeFailingCounterMachine = () => @@ -107,8 +106,7 @@ const makeFailingCounterMachine = () => Finish: () => Effect.fail(new RuntimeError({ reason: "transition" })) } }, - Done: { - } + Done: {} }) const makeDelayedCounterMachine = (release: Deferred.Deferred) => @@ -125,8 +123,7 @@ const makeDelayedCounterMachine = (release: Deferred.Deferred) => Finish: ({ state, event }) => MachineInitial.Count(new Count({ value: state.value + event.by })) } }, - Done: { - } + Done: {} }) describe("AtomMachine", () => { @@ -650,8 +647,7 @@ describe("AtomMachine", () => { }) } }, - ValueRead: { - } + ValueRead: {} }) const bridge = AtomMachine.make(machine) yield* mount(registry, bridge.snapshot) diff --git a/test/ClusterMachine.test.ts b/test/ClusterMachine.test.ts index 987edec..044eccd 100644 --- a/test/ClusterMachine.test.ts +++ b/test/ClusterMachine.test.ts @@ -98,8 +98,7 @@ const makeCounter = (state: { }) } }, - Done: { - } + Done: {} }) const storageKey = (entityType: string, entityId: string): string => `${entityType}\u0000${entityId}` diff --git a/test/Machine.test.ts b/test/Machine.test.ts index 0846c89..e89caaa 100644 --- a/test/Machine.test.ts +++ b/test/Machine.test.ts @@ -1472,8 +1472,7 @@ describe("Machine", () => { }).handle({ all: { states: { - left: { - } + left: {} } } }) @@ -2284,8 +2283,7 @@ describe("Machine", () => { fulfillment .inventory( new Inventory({ warehouse: "warehouse-1" }), - (inventory) => - inventory.reserved(new InventoryReserved({ reservationId: event.value })) + (inventory) => inventory.reserved(new InventoryReserved({ reservationId: event.value })) ) .shipping( new Shipping({ address: "Main Street" }), @@ -4788,8 +4786,7 @@ describe("Machine", () => { Submit: () => FlatInitial.Success(new Success({ requestId: "request-1" })) } }, - Success: { - } + Success: {} }) assert.deepStrictEqual( @@ -4976,8 +4973,7 @@ describe("Machine", () => { Submit: () => FlatInitial.Success(new Success({ requestId: "request-1" })) } }, - Success: { - } + Success: {} }) const actor = yield* Machine.start(machine, { userId: "user-1" }) @@ -5012,8 +5008,7 @@ describe("Machine", () => { Reset: () => FlatInitial.Idle(new Idle({ userId: "user-2" })) } }, - Success: { - } + Success: {} }) const actor = yield* Machine.start(machine, { userId: "user-1" }) @@ -5098,8 +5093,7 @@ describe("Machine", () => { input: Input, initial: (input) => FlatInitial.Idle(new Idle({ userId: input.userId })) }).handle({ - Success: { - } + Success: {} }) const state = FlatInitial.Success(new Success({ requestId: "request-1" })) @@ -6411,8 +6405,7 @@ describe("Machine", () => { src: () => Machine.effect(Effect.succeed(new RequestSucceeded({ value: "loaded" }))) }), on: { - RequestSucceeded: ({ event }) => - FlatInitial.Success(new Success({ requestId: event.value })) + RequestSucceeded: ({ event }) => FlatInitial.Success(new Success({ requestId: event.value })) } }, Success: { @@ -6443,10 +6436,8 @@ describe("Machine", () => { onFailure: (error) => new RequestFailed({ error, cause: Cause.fail(error) }) }), on: { - RequestSucceeded: ({ event }) => - FlatInitial.Failed(new Failed({ message: event.value })), - RequestFailed: ({ event }) => - FlatInitial.Failed(new Failed({ message: event.error.message })) + RequestSucceeded: ({ event }) => FlatInitial.Failed(new Failed({ message: event.value })), + RequestFailed: ({ event }) => FlatInitial.Failed(new Failed({ message: event.error.message })) } }, Failed: { @@ -6470,8 +6461,7 @@ describe("Machine", () => { Loading: { invoke: Machine.after("1 hour", new RequestSucceeded({ value: "timeout" })), on: { - RequestSucceeded: ({ event }) => - FlatInitial.Success(new Success({ requestId: event.value })) + RequestSucceeded: ({ event }) => FlatInitial.Success(new Success({ requestId: event.value })) } }, Success: { @@ -6712,8 +6702,7 @@ describe("Machine", () => { RequestProgress: ({ event }) => FlatInitial.Success(new Success({ requestId: event.childState })) } }, - Success: { - } + Success: {} }) const actor = yield* Machine.start(machine, { userId: "user-1" }) @@ -6774,8 +6763,7 @@ describe("Machine", () => { RequestSucceeded: ({ event }) => FlatInitial.Success(new Success({ requestId: event.value })) } }, - Success: { - } + Success: {} }) const actor = yield* Machine.start(machine, { userId: "user-1" }) @@ -6841,8 +6829,7 @@ describe("Machine", () => { RequestSucceeded: ({ event }) => FlatInitial.Success(new Success({ requestId: event.value })) } }, - Success: { - } + Success: {} }) const actor = yield* Machine.start(machine, { userId: "user-1" }) diff --git a/test/PublicPrototype.test.ts b/test/PublicPrototype.test.ts index 2803b92..c8b9cad 100644 --- a/test/PublicPrototype.test.ts +++ b/test/PublicPrototype.test.ts @@ -19,7 +19,7 @@ it("uses the public pipeable and inspectable prototypes", () => { [key: symbol]: () => unknown } assert.deepStrictEqual(inspectable.toJSON(), { _id: "Machine" }) - assert.strictEqual(JSON.stringify(machine), '{"_id":"Machine"}') - assert.strictEqual(String(machine), '{"_id":"Machine"}') + assert.strictEqual(JSON.stringify(machine), "{\"_id\":\"Machine\"}") + assert.strictEqual(String(machine), "{\"_id\":\"Machine\"}") assert.deepStrictEqual(inspectable[Symbol.for("nodejs.util.inspect.custom")](), { _id: "Machine" }) }) diff --git a/typetest/AtomMachine.tst.ts b/typetest/AtomMachine.tst.ts index bda4f80..d138827 100644 --- a/typetest/AtomMachine.tst.ts +++ b/typetest/AtomMachine.tst.ts @@ -1,8 +1,8 @@ import { Context, Effect, Layer, type Option, Schema } from "effect" -import { Machine } from "../src/index.js" import { AsyncResult, Atom } from "effect/unstable/reactivity" -import { AtomMachine } from "../src/reactivity.js" import { describe, expect, it } from "tstyche" +import { Machine } from "../src/index.js" +import { AtomMachine } from "../src/reactivity.js" class Idle extends Schema.TaggedClass("Idle")("Idle", {}) {} @@ -347,10 +347,11 @@ describe("AtomMachine", () => { }), on: { Begin: ({ target }) => - target.full.Ready(DeepState.cases.Ready.make({}), (ready) => - ready.Editor(DeepState.cases.Editor.make({}), (editor) => - editor.Editing(DeepState.cases.Editing.make({ value: "ready" })) - ) + target.full.Ready( + DeepState.cases.Ready.make({}), + (ready) => + ready.Editor(DeepState.cases.Editor.make({}), (editor) => + editor.Editing(DeepState.cases.Editing.make({ value: "ready" }))) ) } }, diff --git a/typetest/ClusterMachine.tst.ts b/typetest/ClusterMachine.tst.ts index f876f18..7a53958 100644 --- a/typetest/ClusterMachine.tst.ts +++ b/typetest/ClusterMachine.tst.ts @@ -1,9 +1,9 @@ import { Context, Effect, type Layer, Option, Schema, SchemaGetter } from "effect" import { type MessageStorage, type Sharding } from "effect/unstable/cluster" -import { ClusterMachine } from "../src/cluster.js" -import { Machine } from "../src/index.js" import type { Rpc, RpcGroup } from "effect/unstable/rpc" import { describe, expect, it } from "tstyche" +import { ClusterMachine } from "../src/cluster.js" +import { Machine } from "../src/index.js" describe("ClusterMachine", () => { class Count extends Schema.TaggedClass("Count")("Count", { diff --git a/typetest/Machine.tst.ts b/typetest/Machine.tst.ts index 0628090..a3f534b 100644 --- a/typetest/Machine.tst.ts +++ b/typetest/Machine.tst.ts @@ -1,6 +1,6 @@ import { Context, Effect, Option, Schema } from "effect" -import { Machine } from "../src/index.js" import { describe, expect, it } from "tstyche" +import { Machine } from "../src/index.js" describe("Machine", () => { class Up extends Schema.TaggedClass("Up")("Up", { @@ -1096,8 +1096,7 @@ describe("Machine", () => { return Effect.as(DoneRequirement, target.full.down(new Down({}))) }, states: { - signedIn: { - } + signedIn: {} } } }