Zero Intermediate Awaits
Build deep chains without awaiting at every step — the full chain resolves in one await.
@farbenmeer/lacy wraps any Promise in a Proxy, letting you chain property access and method calls lazily. Nothing evaluates until you await the final result.
npm install @farbenmeer/lacyZero Intermediate Awaits
Build deep chains without awaiting at every step — the full chain resolves in one await.
Proxy-Based
Uses native JavaScript Proxy. No code generation, no decorators, no compilation required.
Standard Promise Protocol
LacyPromise implements .then(), .catch(), and .finally(), so it works anywhere a Promise does.
Escape Hatch
Access the raw underlying Promise at any point via the .$ property.
Without Lacy, fetching nested data requires multiple awaits:
const response = await fetch("/api/users");const data = await response.json();const name = data[0].name;With Lacy, the same thing as a single lazy chain:
import { lacy } from "@farbenmeer/lacy";
const name = await lacy(fetch("/api/users")).json()[0].name;import { lacy } from "@farbenmeer/lacy";
const users = lacy(Promise.resolve([ { name: "Alice", age: 30 }, { name: "Bob", age: 25 },]));
await users[0].name; // "Alice"await users.map((u) => u.name); // ["Alice", "Bob"]
// Deeply nested valuesconst data = lacy(Promise.resolve({ deeply: { nested: { value: 42 } } }));await data.deeply.nested.value; // 42
// Raw promise escape hatchconst raw = await users.$; // [{ name: "Alice", ... }, ...]obj.key) — returns a new LacyPromise resolving to the property valueobj.method(args)) — invokes the method on the resolved value and wraps the resultawait — resolves the full deferred chain.$ — unwraps to the raw underlying Promise