Skip to content

Effect v4 across the SDKs: @misofm/effect foundation, typed errors, Effect in public signatures - #28

Merged
tamashi095 merged 5 commits into
mainfrom
feat/effect-v4
Sep 8, 2026
Merged

Effect v4 across the SDKs: @misofm/effect foundation, typed errors, Effect in public signatures#28
tamashi095 merged 5 commits into
mainfrom
feat/effect-v4

Conversation

@tamashi095

@tamashi095 tamashi095 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Stacked on #27 (base is feat/split-musicos-platform); rebase onto main once that merges.

What changes

  • New @misofm/effect (0.1.0): one SuiClient / SuiGraphQL Context.Service, one tagged-error vocabulary (Schema.TaggedError), the object-read primitives (getObjectContent, getOptionalObjectContent, getObjectsContent, listDynamicFields as a Stream, decodeBcs through Schema, assertObjectType) and the execute helpers. Every SDK depends on it so a consumer provides exactly one layer.
  • @misofm/musicos 0.3.0, @misofm/partyos 0.3.0, @misofm/platform 0.26.0: every read that performs I/O returns Effect<A, E, SuiClient>; client extensions keep their names and provide the service internally (R = never); PTB builders stay synchronous; domain types are Schema.Class and no generated BCS shape crosses the public boundary; optional reads return Option. isNotFound is gone in favour of Effect.catchTag("ObjectNotFoundError", …), and platform adds the domain not-found errors the api read service hand-rolled.
  • @misofm/streaming 0.3.0: warmTrack is an Effect (interruption aborts in-flight fetches; per-item tolerance unchanged); acquirePlayer is a Scope-managed player; play() stays a synchronous gesture-safe call.
  • @misofm/transcoding 0.4.0: already Effect; gains the ./errors subpath and pins streaming 0.3.0.
  • effect is an exact peer (4.0.0-rc.112) everywhere; the effect-v* publish tag arm is added; root README and CLAUDE.md document the conventions.

Verification

  • bun run typecheck, bun run build, bun run codegen:check: clean across all six workspaces.
  • bun test: 352 pass; the 2 failures are transcoding's FFmpeg-binary tests (no FFmpeg on the dev box; green in CI).
  • bun run test:consumer: six tarballs install into the fixture; every ./errors subpath resolves; single instance of effect and each @misofm/*.

Notes

  • Downstream (api, app, cli) will need a second migration pass for the Effect signatures after this publishes; the split PRs (misofm/api#28, misofm/app#130, misofm/cli#23) target the Promise-based 0.25.0/0.2.0 line and stay valid until then.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QGmuA3eMr4iaRTdz3J8JZJ

Deliberate choices surfaced by review

  • The JSON-safe read/* projections keep null for absent values (they feed the HTTP read service); library-level optional reads elsewhere return Option.
  • The raw generated-binding namespaces stay reachable through the bcs/call getters and ./contracts/* as the documented escape hatch; no read or query returns a generated type.

tamashi095 and others added 5 commits September 8, 2026 16:43
… the SDKs

One SuiClient/SuiGraphQL service tag and one error vocabulary
(Schema.TaggedError: ObjectNotFoundError, ObjectTypeMismatchError,
SuiRpcError, BcsDecodeError, TransactionFailedError,
GraphQLUnavailableError, DeploymentError), the shared object-read and
dynamic-field primitives (getObjectContent, getOptionalObjectContent,
getObjectsContent, listDynamicFields as a Stream, decodeBcs through
Schema, assertObjectType), and the execute helpers (buildTx,
signAndExecute, execThunks) with the pure effect extractors. Every SDK
migrates onto this package next so consumers provide exactly one layer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGmuA3eMr4iaRTdz3J8JZJ
… API

Every read that performs I/O now returns an Effect that requires the
shared SuiClient service from @misofm/effect and fails with the tagged
error vocabulary (ObjectNotFoundError, ObjectTypeMismatchError,
SuiRpcError, BcsDecodeError); the client extensions keep their names and
provide the service internally so their methods have no requirements.
Domain types are Schema classes decoded from the generated BCS output, so
no generated shape crosses the public boundary. PTB builders stay
synchronous.

- musicos 0.3.0: queries, view, and the miso() client; execute re-exports
  the foundation; optional extension reads return Option.
- partyos 0.3.0: queries built on the foundation reads and the
  dynamic-field Stream; Party is a Schema class.
- streaming 0.3.0: warmTrack is an Effect with interruption-driven abort
  and the same per-item tolerance; acquirePlayer is a Scope-managed player;
  play() stays a synchronous gesture-safe call.
- transcoding 0.4.0: ./errors subpath and error-handling docs; already
  Effect-based.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGmuA3eMr4iaRTdz3J8JZJ
…ventions

platform 0.26.0 depends on @misofm/effect and the migrated musicos,
partyos, and streaming packages. Every read that performs I/O returns an
Effect requiring the shared SuiClient (and SuiGraphQL where needed) and
fails with the tagged errors in ./errors, which now also carry the
domain not-found cases the api read service had to hand-roll
(ReleaseNotFoundError, ReceiptNotFoundError, RecordPurchaseNotFoundError).
Domain values (Pressing, Listing, PressingRecord, RoyaltyPool,
RoyaltyStake, RoutedStake, Profile, Media, Cta, PlatformLink, Genre) are
Schema classes; Genre is the pilot value object derived through the new
PlatformDeployment service. The client extensions keep their names and
provide the services internally; PTB builders stay synchronous.

The isolated-consumer fixture installs all six tarballs, imports every
package's ./errors subpath, and asserts a single copy of effect.
transcoding pins streaming 0.3.0 so a consumer gets one copy.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGmuA3eMr4iaRTdz3J8JZJ
- share.initializeShareCurrencies: a rejecting onBatch callback is that
  batch's typed failure (SuiRpcError) instead of a defect, so it no longer
  interrupts sibling batches whose transactions are already submitted.
- musicos.getWorksByIds: an id requested under two work kinds fails with
  ConflictingWorkKindError instead of a thrown defect.
- platform README: the protocol accessor is optional until ready().

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGmuA3eMr4iaRTdz3J8JZJ
@tamashi095
tamashi095 changed the base branch from feat/split-musicos-platform to main September 8, 2026 22:09
@tamashi095
tamashi095 merged commit 66706b5 into main Sep 8, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant