Ir al contenido
GitHub

Primeros pasos con Paquetes Universales

Los paquetes universales de Effectify son la base para construir aplicaciones consistentes y seguras por tipos en React, SolidJS y Node.js. Esta guía explica los conceptos y patrones clave.

  • Componibilidad
  • Seguridad de tipos
  • Testeabilidad
  • Fiabilidad
import { Effect } from "effect"

const greetUser = (name: string) => Effect.succeed(`Hola, ${name}!`)

const processUser = (userId: string) =>
  Effect.gen(function*() {
    const user = yield* fetchUser(userId)
    const greeting = yield* greetUser(user.name)
    const result = yield* saveGreeting(greeting)
    return result
  })
interface User {
  readonly id: UserId
  readonly email: Email
  readonly name: UserName
  readonly createdAt: Date
}

const UserDomain = {
  create: (data: CreateUserData) => Effect<User, ValidationError>,
  validate: (user: User) => Effect<User, ValidationError>,
  updateProfile: (user: User, updates: UserUpdates) => Effect<User, ValidationError>,
}

class UserCreatedEvent {
  readonly _tag = "UserCreatedEvent"
  constructor(readonly user: User, readonly timestamp: Date) {}
}
export interface UserRepository {
  readonly save: (user: User) => Effect<User, RepositoryError>
  readonly findById: (id: UserId) => Effect<User | null, RepositoryError>
  readonly findByEmail: (email: Email) => Effect<User | null, RepositoryError>
}
export type UserId = string & { readonly _brand: "UserId" }
export type Email = string & { readonly _brand: "Email" }
export type UserName = string & { readonly _brand: "UserName" }

Constructores:

export const UserId = {
  make: (value: string): Effect<UserId, ValidationError> =>
    value.length > 0 && value.length <= 50
      ? Effect.succeed(value as UserId)
      : Effect.fail(new ValidationError("Invalid user ID", { field: "userId" })),
}

export const Email = {
  make: (value: string): Effect<Email, ValidationError> =>
    /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
      ? Effect.succeed(value as Email)
      : Effect.fail(new ValidationError("Invalid email format", { field: "email" })),
}
import { Schema } from "@effect/schema"

export const UserSchema = Schema.struct({
  id: Schema.string,
  email: Schema.string.pipe(Schema.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)),
  name: Schema.string.pipe(Schema.minLength(1), Schema.maxLength(100)),
  createdAt: Schema.Date,
})
import { Data } from "effect"

export class DomainError
  extends Data.TaggedError("DomainError")<{ readonly message: string; readonly cause?: unknown }>
{}
export class ValidationError
  extends Data.TaggedError("ValidationError")<{ readonly field: string; readonly message: string }>
{}
export class BusinessRuleViolationError
  extends Data.TaggedError("BusinessRuleViolationError")<{ readonly rule: string; readonly message: string }>
{}
export class ResourceNotFoundError
  extends Data.TaggedError("ResourceNotFoundError")<{ readonly resource: string; readonly id: string }>
{}