import { Effect, Result, Schema } from "effect"; type SyncDecodingSchema = Schema.Top & { readonly DecodingServices: never; }; export const parseJsonStringEffect = (value: string) => Effect.try({ try: () => JSON.parse(value) as unknown, catch: (cause) => new Error("Invalid JSON payload", { cause }), }); export const parseJsonStringEither = (value: string) => Result.try({ try: () => Effect.runSync(parseJsonStringEffect(value)), catch: (cause) => cause instanceof Error ? cause : new Error("Failed to parse JSON payload", { cause }), }); export const parseJsonStringOrThrow = (value: string): T => Result.getOrThrow(parseJsonStringEither(value)) as T; export const parseJsonStringOrDefault = (value: string, fallback: T): T => { const parsed = parseJsonStringEither(value); return Result.match(parsed, { onSuccess: (decoded) => decoded as T, onFailure: () => fallback, }); }; export const parseJsonStringWithSchemaOrDefault = < S extends SyncDecodingSchema, >( value: string, schema: S, fallback: S["Type"], ): S["Type"] => { const parsed = parseJsonStringEither(value); return Result.match(parsed, { onSuccess: (decoded) => { const decodedWithSchema = Result.try({ try: () => Schema.decodeUnknownSync(schema)(decoded), catch: () => fallback, }); return Result.match(decodedWithSchema, { onSuccess: (value) => value, onFailure: () => fallback, }); }, onFailure: () => fallback, }); };