Skip to content

Resource

Resource: object

Defined in: Core/Resource.ts:34

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, all already-acquired resources (K-1 … 0) are released in reverse order before Resource.use returns 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 Resource.use({
  run: ({ db, redis, s3 }: AppInfra) => runMigration(db, redis, s3),
})(appInfra);

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 returns an error, Resource.use releases the first resource before returning 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, the first is released before Resource.use returns 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 Resource.use({
  run: ([conn, cache]: readonly [DbClient, CacheClient]) => lookupWithFallback(conn, cache, userId),
})(combined);

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

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

Convert an infallible acquisition with Task.Result.from.Task before passing it here.

E

A

Result<E, A>

(value) => Task<unknown>

Resource<E, A>

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.

The transform must not throw.

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>(options) => <E1>(resource) => Deferred<Result<E2 | E1, B>>

Acquires the resource, runs the supplied work, then releases it.

Successfully acquired resources are released in reverse order when acquisition or work returns an error. If acquisition returns an error, work and its release are skipped. Release tasks and callbacks must not throw or reject.

The run callback parameter must be annotated: the resource arrives after the options, so TypeScript cannot infer its value type from the resource.

A

E2

B

(value) => Result<E2, B>

AbortSignal

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

const rows = await Resource.use({
  run: (conn: DbClient) => runQuery(conn, "SELECT * FROM users"),
})(dbResource);
// conn is closed whether the query succeeds or returns an error