MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / makeFumaClient

Function makeFumaClient

packages/core/sdk/src/fuma-runtime.ts:355–401  ·  view source on GitHub ↗
(db: FumaDb, options: MakeFumaClientOptions = {})

Source from the content-addressed store, hash-verified

353};
354
355export const makeFumaClient = (db: FumaDb, options: MakeFumaClientOptions = {}): IFumaClient => {
356 const rebind = (handle: FumaDb): FumaDb =>
357 options.context === undefined ? handle : withQueryContext(handle, options.context);
358 const use: IFumaClient["use"] = (label, fn) =>
359 Effect.flatMap(Effect.service(activeFumaDbRef), (active) =>
360 fumaEffect(label, () => fn(makeSafeFumaQuery(rebind(active ?? db), options))),
361 ).pipe(Effect.withSpan(`fumadb.${label}`));
362
363 const transaction = <A, E>(effect: Effect.Effect<A, E>): Effect.Effect<A, E | StorageFailure> =>
364 Effect.flatMap(Effect.service(activeFumaDbRef), (active) => {
365 if (active) return effect as Effect.Effect<unknown, unknown>;
366
367 // The outermost transaction owns the post-commit hook queue; hooks
368 // queued anywhere inside (including nested pass-through transactions)
369 // run only after THIS commit, and are discarded on rollback.
370 const commitHooks: PendingCommitHook[] = [];
371 return Effect.contextWith((context) =>
372 Effect.tryPromise({
373 try: () =>
374 db.transaction(async (transactionDb) => {
375 const exit = await Effect.runPromiseExitWith(context)(
376 effect.pipe(
377 Effect.provideService(activeFumaDbRef, transactionDb),
378 Effect.provideService(pendingCommitHooksRef, commitHooks),
379 ),
380 );
381 if (Exit.isSuccess(exit)) return exit.value;
382
383 const failure = exit.cause.reasons.find(Cause.isFailReason);
384 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: FumaDB transactions roll back when the callback rejects
385 if (failure) throw new TransactionEffectFailure(failure.error);
386 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: FumaDB transactions roll back when the callback rejects
387 throw new TransactionEffectDefect(exit.cause);
388 }),
389 catch: (cause): E | StorageFailure => {
390 if (cause instanceof TransactionEffectFailure) return cause.error as E;
391 if (cause instanceof TransactionEffectDefect) {
392 return fumaFailureFromCause("transaction", cause.cause);
393 }
394 return fumaFailureFromCause("transaction", cause);
395 },
396 }).pipe(Effect.tap(() => runCommitHooks(commitHooks))),
397 );
398 }).pipe(Effect.withSpan("fumadb.transaction")) as Effect.Effect<A, E | StorageFailure>;
399
400 return { use, transaction };
401};
402
403export class FumaClient extends Context.Service<FumaClient, IFumaClient>()("executor/FumaClient") {
404 static layer = (db: FumaDb) => Layer.succeed(this)(makeFumaClient(db));

Callers 4

touchSubjectFunction · 0.90
createExecutorFunction · 0.90
makeAdminFunction · 0.90
FumaClientClass · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected