import "dotenv/config"
import { Effect } from "effect"
class HttpError {
readonly _tag = "HttpError"
}
class ValidationErrors {
readonly _tag = "ValidationErrors"
public constructor(public readonly fields: { [x: string]: string[] }) {}
}
class ValidationError extends ValidationErrors {
public constructor(property: string, message: string) {
super({ [property]: [message] })
}
}
class GeneralError {
readonly _tag = "GeneralError"
}
const generateResponse = <
A,
R,
T extends Effect.Effect<A, ValidationErrors | GeneralError, R extends unknown ? never : R>,
>(
effect: T
) => {
return effect
.pipe(Effect.map((value) => ({ type: "success" as const, value: value as A })))
.pipe(
Effect.catchTag("ValidationErrors", (e) =>
Effect.succeed({
type: "failure" as const,
fields: e.fields,
})
)
)
.pipe(
Effect.catchAll(() =>
Effect.succeed({
type: "failure" as const,
fields: {} as { [x: string]: string[] },
})
)
)
}
function validationErrors(fields: { [x: string]: string[] }) {
return Effect.fail(new ValidationErrors(fields))
}
function validationError(property: string, message: string) {
return validationErrors({ [property]: [message] })
}
const program = Effect.gen(function* (_) {
yield* _(Effect.succeed("hola"))
yield* _(Math.random() > 0.5 ? Effect.fail(new HttpError()) : Effect.succeed("1"))
yield* _(validationError("Email", "Ya existe un usuario con este email"))
return yield* _(Math.random() > 0.5 ? Effect.fail(new GeneralError()) : Effect.succeed("2"))
}).pipe(
Effect.catchTag("HttpError", () => validationError("email", "Hola")),
generateResponse
)
const someServerAction = async () => await Effect.runPromise(program)
import "dotenv/config"
import { Effect } from "effect"
class HttpError {
readonly _tag = "HttpError"
}
class ValidationErrors {
readonly _tag = "ValidationErrors"
public constructor(public readonly fields: { [x: string]: string[] }) {}
}
class ValidationError extends ValidationErrors {
public constructor(property: string, message: string) {
super({ [property]: [message] })
}
}
class GeneralError {
readonly _tag = "GeneralError"
}
const generateResponse = <
A,
R,
T extends Effect.Effect<A, ValidationErrors | GeneralError, R extends unknown ? never : R>,
>(
effect: T
) => {
return effect
.pipe(Effect.map((value) => ({ type: "success" as const, value: value as A })))
.pipe(
Effect.catchTag("ValidationErrors", (e) =>
Effect.succeed({
type: "failure" as const,
fields: e.fields,
})
)
)
.pipe(
Effect.catchAll(() =>
Effect.succeed({
type: "failure" as const,
fields: {} as { [x: string]: string[] },
})
)
)
}
function validationErrors(fields: { [x: string]: string[] }) {
return Effect.fail(new ValidationErrors(fields))
}
function validationError(property: string, message: string) {
return validationErrors({ [property]: [message] })
}
const program = Effect.gen(function* (_) {
yield* _(Effect.succeed("hola"))
yield* _(Math.random() > 0.5 ? Effect.fail(new HttpError()) : Effect.succeed("1"))
yield* _(validationError("Email", "Ya existe un usuario con este email"))
return yield* _(Math.random() > 0.5 ? Effect.fail(new GeneralError()) : Effect.succeed("2"))
}).pipe(
Effect.catchTag("HttpError", () => validationError("email", "Hola")),
generateResponse
)
const someServerAction = async () => await Effect.runPromise(program)