Skip to content

Resource

Resource: object

Defined in: Core/Resource.ts:35

all: <R>(resources) => Resource<InferError<R>, InferValue<R>>

Sequentially acquires an array/tuple or named record of resources.

All resources are released in strict reverse (LIFO) order upon completion. If the K-th resource fails to acquire or throws, all already-acquired resources (K-1 … 0) are immediately released in reverse order before propagating the error.

R extends Readonly<Record<string, Resource<any, any>>> | readonly Resource<any, any>[]

R

Resource<InferError<R>, InferValue<R>>

Resource.combine for binary resource pairing.

// Tuple acquisition:
const infraTuple = Resource.all([dbResource, redisResource, lockResource]);

// Named record acquisition:
const appInfra = Resource.all({
  db: connectDb(dbConfig),
  redis: connectRedis(redisConfig),
  s3: createTempBucket(s3Config),
});

const result = await pipe(
  appInfra,
  Resource.use(({ db, redis, s3 }) => runMigration(db, redis, s3)),
)();

chain: <A, E2, B>(transform) => <E1>(resource) => Resource<E2 | E1, B>

Sequentially acquires a second resource that depends on the value of the first.

If acquiring the second resource fails or throws, the first resource is released immediately before propagating the error. When Resource.use completes, both resources are released in reverse (LIFO) order: the second is released before the first.

A

E2

B

(value) => Resource<E2, B>

<E1>(resource) => Resource<E2 | E1, B>

Resource.map for transforming acquired values without opening a new resource.

const dbWithLock = pipe(
  connectPostgres(dbConfig),
  Resource.chain((db) =>
    pipe(
      acquireAdvisoryLock(db, "migrations"),
      Resource.map((lock) => ({ db, lock })),
    ),
  ),
);

combine: <E1, A, E2, B>(resourceA, resourceB) => Resource<E1 | E2, readonly [A, B]>

Acquires two resources in sequence and presents them as a tuple.

Resources are released in reverse order: the second is released before the first. If the second resource fails to acquire or throws, the first is released immediately before propagating the error.

E1

A

E2

B

Resource<E1, A>

Resource<E2, B>

Resource<E1 | E2, readonly [A, B]>

Resource.all for acquiring arbitrary tuples or named records of resources.

const combined = Resource.combine(dbResource, cacheResource);

const result = await pipe(
  combined,
  Resource.use(([conn, cache]) => lookupWithFallback(conn, cache, userId)),
)();

from: object

Task: <A, E>(acquire, release) => Resource<E, A> = makeTask

Creates a Resource from an acquire operation that cannot fail. Use this when opening the resource is guaranteed to succeed, such as in-memory locks, counters, or timers.

A

E = never

Task<A>

(value) => Task<unknown>

Resource<E, A>

Resource.make for creating resources with fallible acquisition.

const timerResource = Resource.from.Task(
  Task.tryCatch(() => Promise.resolve(startTimer()), { onError: () => defaultTimer }),
  (timer) => Task.tryCatch(() => Promise.resolve(timer.stop()), { onError: () => {} }),
);

make: <E, A>(acquire, release) => Resource<E, A> = makeResource

Creates a Resource from an acquire operation that may fail and a release finalizer.

E

A

Result<E, A>

(value) => Task<unknown>

Resource<E, A>

Resource.from.Task for creating resources with infallible acquisition.

const fileResource = Resource.make(
  Task.Result.tryCatch(() => fs.promises.open("data.csv", "r"), { onError: toFileError }),
  (handle) => Task.tryCatch(() => handle.close(), { onError: () => {} }),
);

map: <A, B>(transform) => <E>(resource) => Resource<E, B>

Transforms the value of an acquired resource while retaining guaranteed cleanup of the original asset.

If transform throws an exception, the acquired resource is released immediately before propagating the error.

A

B

(value) => B

<E>(resource) => Resource<E, B>

Resource.chain for sequencing dependent resource acquisitions.

const clientResource = pipe(
  connectCluster(clusterConfig),
  Resource.map((cluster) => cluster.getClient("analytics")),
);

use: <A, E2, B>(consume) => <E1>(resource) => Result<E2 | E1, B>

Acquires the resource, runs consume with it, then releases it.

Release always runs, even when consume returns an error or throws. If acquire fails, consume and release are both skipped and the error is returned.

A

E2

B

(value) => Result<E2, B>

<E1>(resource) => Result<E2 | E1, B>

const rows = await pipe(
  dbResource,
  Resource.use((conn) => runQuery(conn, "SELECT * FROM users")),
)();
// conn is closed whether the query succeeds, fails, or throws