UNPKG

@proofkit/fmodata

Version:

FileMaker OData API client

90 lines (89 loc) 2.77 kB
import { Effect, Schedule } from "effect"; import { BuilderInvariantError, isFMODataError, isTransientError } from "./errors.js"; import { HttpClient, ODataConfig } from "./services.js"; function requestFromService(url, options) { return Effect.gen(function* () { const client = yield* HttpClient; const config = yield* ODataConfig; return yield* client.request(url, { ...options, normalizeDatabaseName: (options == null ? void 0 : options.normalizeDatabaseName) ?? config.normalizeDatabaseName }); }); } function runAsResult(effect) { return Effect.runPromise( effect.pipe( Effect.map((data) => ({ data, error: void 0 })), Effect.catchAll((error) => Effect.succeed({ data: void 0, error })) ) ).catch((defect) => ({ data: void 0, error: isFMODataError(defect) ? defect : new BuilderInvariantError("runAsResult", String(defect)) })); } function withOptionalSpan(effect, spanName, attributes) { if (!spanName) { return effect; } return withSpan(effect, spanName, attributes); } function runLayerResult(layer, effect, spanName, attributes) { const provided = Effect.provide(withOptionalSpan(effect, spanName, attributes), layer); return runAsResult(provided); } async function runLayerOrThrow(layer, effect, spanName, attributes) { const result = await runLayerResult(layer, effect, spanName, attributes); if (result.error) { throw result.error; } return result.data; } function tryEffect(fn, mapError) { return Effect.tryPromise({ try: () => Promise.resolve(fn()), catch: mapError }); } function fromValidation(fn) { return Effect.tryPromise({ try: fn, catch: (e) => e }).pipe(Effect.flatMap((result) => result.valid ? Effect.succeed(result.data) : Effect.fail(result.error))); } function buildRetrySchedule(policy) { const maxRetries = policy.maxRetries ?? 3; const baseDelay = `${policy.baseDelay ?? 500} millis`; const useJitter = policy.jitter !== false; const base = Schedule.exponential(baseDelay); const withJitter = useJitter ? Schedule.jittered(base) : base; return withJitter.pipe( Schedule.intersect(Schedule.recurs(maxRetries)), Schedule.whileInput((error) => isTransientError(error)) ); } function withRetryPolicy(effect, retryPolicy) { if (!retryPolicy) { return effect; } return effect.pipe(Effect.retry(buildRetrySchedule(retryPolicy))); } function withSpan(effect, name, attributes) { return effect.pipe( Effect.withSpan(name, { attributes: attributes ? attributes : void 0 }) ); } export { buildRetrySchedule, fromValidation, requestFromService, runAsResult, runLayerOrThrow, runLayerResult, tryEffect, withRetryPolicy, withSpan }; //# sourceMappingURL=effect.js.map