skills/fp-async/SKILL.md
Practical async patterns using TaskEither - clean pipelines instead of try/catch hell, with real API examples
npx skillsauth add ranbot-ai/awesome-skills fp-asyncInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Stop writing nested try/catch blocks. Stop losing error context. Start building clean async pipelines that handle errors properly.
TaskEither is simply an async operation that tracks success or failure. That's it. No fancy terminology needed.
TaskEither.try/catch flows.// TaskEither<Error, User> means:
// "An async operation that either fails with Error or succeeds with User"
// BEFORE: Try/catch hell
async function getUserData(userId: string) {
try {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
const user = await response.json()
try {
const posts = await fetch(`/api/users/${userId}/posts`)
if (!posts.ok) {
throw new Error(`HTTP ${posts.status}`)
}
const postsData = await posts.json()
return { user, posts: postsData }
} catch (postsError) {
// Now what? Return partial data? Rethrow? Log?
console.error('Failed to fetch posts:', postsError)
return { user, posts: [] }
}
} catch (error) {
// Lost all context about what failed
console.error('Something failed:', error)
throw error
}
}
import * as TE from 'fp-ts/TaskEither'
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
// One wrapper function - reuse everywhere
const fetchJson = <T>(url: string): TE.TaskEither<Error, T> =>
TE.tryCatch(
async () => {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
return response.json()
},
(error) => error instanceof Error ? error : new Error(String(error))
)
// AFTER: Clean and composable
const getUser = (userId: string) => fetchJson<User>(`/api/users/${userId}`)
const getPosts = (userId: string) => fetchJson<Post[]>(`/api/users/${userId}/posts`)
TE.tryCatch takes two things:
TE.tryCatch(
() => somePromise, // The async work
(thrown) => toError(thrown) // Convert failures to your error type
)
// Wrap a value as success
const success = TE.right<Error, number>(42)
// Wrap a value as failure
const failure = TE.left<Error, number>(new Error('Nope'))
// From a nullable value (null/undefined becomes error)
const fromNullable = TE.fromNullable(new Error('Value was null'))
const result = fromNullable(maybeUser) // TaskEither<Error, User>
// From a condition
const mustBePositive = TE.fromPredicate(
(n: number) => n > 0,
(n) => new Error(`Expected positive, got ${n}`)
)
// BEFORE: Deeply nested, hard to follow
async function processOrder(orderId: string) {
try {
const order = await fetchOrder(orderId)
if (!order) throw new Error('Order not found')
try {
const user = await fetchUser(order.userId)
if (!user) throw new Error('User not found')
try {
const inventory = await checkInventory(order.items)
if (!inventory.available) throw new Error('Out of stock')
try {
const payment = await chargePayment(user, order.total)
if (!payment.success) throw new Error('Payment failed')
try {
const shipment = await createShipment(order, user)
return { order, shipment, payment }
} catch (e) {
// Refund payment? Log? What's the state now?
await refundPayment(payment.id)
throw e
}
} catch (e) {
throw e
}
} catch (e) {
throw e
}
} catch (e) {
throw e
}
} catch (e) {
console.error('Order processing failed', e)
throw e
}
}
// AFTER: Flat, readable pipeline
const processOrder = (orderId: string) =>
pipe(
fetchOrder(orderId),
TE.chain(order => fetchUser(order.userId)),
TE.chain(user =>
pipe(
checkInventory(order.items),
TE.chain(inventory => chargePayment(user, order.total))
)
),
TE.chain(payment => createShipment(order, user, payment))
)
Use map when your transformation is synchronous and can't fail:
pipe(
fetchUser(userId),
TE.map(user => user.name.toUpperCase()) // Just tran
testing
Fix SEO indexing issues, crawl budget problems, and Search Console coverage errors for Next.js apps. Covers canonical tags, noindex audits, sitemap health, static rendering, and internal linking.
data-ai
Analyze AI disruption pressure across a business, map competitive exposure, and produce a 90-day defensive action plan.
tools
--- name: longbridge description: 125+ agent skills for Longbridge Securities — real-time quotes, charts, fundamentals, portfolio analysis, options, and more for HK/US/A-share/SG markets. Trilingual: Simplified Chinese, Traditional category: AI & Agents source: antigravity tags: [api, mcp, claude, ai, agent, security, cro] url: https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/longbridge --- # Longbridge ## Overview Longbridge is the official skill collection for Longbr
tools
Design, debug, and harden GitHub Actions CI/CD workflows, including reusable workflows, matrix builds, self-hosted runners, OIDC authentication, caching, environments, secrets, and release automation.