0.3.0 • Published 7 months ago
@ortense/attempt v0.3.0

@ortense/attempt
Uma biblioteca TypeScript minimalista para tratamento seguro de erros usando o padrão Result Type.
Instalação
npm install @ortense/attempt # npm
yarn add @ortense/attempt # yarn
pnpm add @ortense/attempt # pnpm
bun add @ortense/attempt # bunPor que usar?
- 🎯 Type-safe: Tratamento de erros com segurança de tipos
- 🎨 Elegante: API simples e expressiva
- 🔒 Seguro: Sem exceções não tratadas
- 🪶 Leve: Zero dependências
- 📦 Pequeno: Bundle size mínimo
- 💪 Robusto: 100% testado
Uso Básico
import { attempt, attemptAsync } from '@ortense/attempt'
// Código síncrono
const result = attempt(() => {
const number = parseInt("123")
if (isNaN(number)) throw new Error("Número inválido")
return number
})
if (result.success) {
console.log(result.value) // 123
} else {
console.error(result.error) // Error
}
// Código assíncrono
const result = await attemptAsync(
fetch("https://api.example.com/data")
.then(response => response.json())
)
if (result.success) {
console.log(result.value) // dados da API
} else {
console.error(result.error.message) // "Falha na API"
}API
Tipos
type Success<T> = {
success: true
value: T
}
type Failure<E extends Error> = {
success: false
error: E
}
type Result<T, E extends Error> = Success<T> | Failure<E>
type Match<T, E extends Error> = {
success: (value: T) => void;
failure: (error: E) => void;
}Funções
success<T>(value: T): Success<T>
Cria um resultado de sucesso contendo um valor.
const result = success(42)
// { success: true, value: 42 }match<T, E extends Error>(result: Result<T, E>, match: Match<T, E>): void
Executa diferentes callbacks baseados no estado do resultado.
match(result, {
success: (value) => {
console.log("Sucesso:", value)
},
failure: (error) => {
console.error("Falha:", error)
}
})failure<E extends Error>(error: unknown): Failure<E>
Cria um resultado de falha contendo um erro.
const result = failure(new Error("Algo deu errado"))
// { success: false, error: Error("Algo deu errado") }
// Strings são convertidas para Error
const result = failure("Algo deu errado")
// { success: false, error: Error("Algo deu errado") }attempt<T, E extends Error>(fn: () => T): Result<T, E>
Executa uma função e captura qualquer erro lançado.
const result = attempt(() => {
if (Math.random() > 0.5) throw new Error("Azar!")
return "Sorte!"
})
if (result.success) {
console.log(result.value) // "Sorte!"
} else {
console.error(result.error) // Error("Azar!")
}attemptAsync<T, E extends Error>(Promise<T>): Promise<Result<T, E>>
Resolve uma promise e captura qualquer erro lançado.
const result = await attemptAsync(
fetch("https://api.example.com/data")
.then(response.json())
)
if (result.success) {
console.log(result.value) // dados da API
} else {
console.error(result.error) // "Falha na API"
}Exemplos Avançados
Erros Customizados
class ApiError extends Error {
constructor(
message: string,
public statusCode: number
) {
super(message)
this.name = "ApiError"
}
}
const result = attempt(() => {
throw new ApiError("Não autorizado", 401)
})
if (!result.success) {
console.log(result.error.statusCode) // 401
}Type Narrowing
function processResult(result: Result<number, Error>) {
if (result.success) {
// TypeScript sabe que result.value é number
return result.value * 2
} else {
// TypeScript sabe que result.error é Error
return result.error.message
}
}Composição de Operações
const getUser = async (id: string) => {
const result = await attemptAsync(
fetch(`/api/users/${id}`)
.then(response => {
if (!response.ok) throw new Error("Usuário não encontrado")
return response
})
.then(response => response.json())
)
if (!result.success) {
return result // early return com o erro
}
// Processa apenas em caso de sucesso
return attempt(() => {
const user = result.value
if (!user.active) throw new Error("Usuário inativo")
return user
})
}
// Usando map para uma composição mais limpa
const getUserName = async (id: string) => {
const result = await attemptAsync(
fetch(`/api/users/${id}`)
.then(response => {
if (!response.ok) throw new Error("Usuário não encontrado")
return response
})
.then(response => response.json())
)
return result.map(user => user.name)
}Licença
MIT © Marcus Ortense