@proofkit/fmodata
Version:
FileMaker OData API client
90 lines (89 loc) • 2.77 kB
JavaScript
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