@cgtk/std 0.0.196 → 0.0.197

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/async.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import type { Fn, Lazy, Maybe, Dispose, MaybePromise } from "./types.js";
2
- export declare const timeout: (ms: number, signal?: AbortSignal) => Promise<unknown>;
1
+ import type { Lazy, Maybe, Dispose, MaybePromise, Promisified, AsyncDispose } from "./types.js";
2
+ export declare const RESOLVED: Promise<void>;
3
+ export declare const timeout: (ms: number, signal?: AbortSignal) => Promise<void>;
3
4
  export declare const delay: (ms: number, signal?: AbortSignal) => <T>(x: T) => Promise<T>;
4
5
  export declare const probing: <T>(p: Promise<T>) => Lazy<Maybe<T>>;
5
- export declare const resolved: <T>(p: Promise<T>) => (f: Fn<T>) => () => void;
6
- export declare const promise: <T>(x: MaybePromise<T>) => Promise<any>;
7
- export declare const then: <T>(p: Promise<T>) => <R>(f: Fn<T, R>) => Promise<R>;
8
- export declare const dispose: (p: Promise<Dispose>) => () => void;
6
+ export declare const promisify: <T>(x: MaybePromise<T>) => Promisified<T>;
7
+ export declare const dispose: (p: Promise<Dispose>) => AsyncDispose;
package/async.js CHANGED
@@ -1,5 +1,6 @@
1
- import { filterT, noop } from "./fn.js";
2
- import { isDefined } from "./checks.js";
1
+ import { noop, then } from "./fn.js";
2
+ import { isPromise } from "./checks.js";
3
+ export const RESOLVED = Promise.resolve();
3
4
  export const timeout = (ms, signal) => new Promise((resolve, reject) => {
4
5
  if (signal?.aborted)
5
6
  reject(signal.reason);
@@ -8,7 +9,7 @@ export const timeout = (ms, signal) => new Promise((resolve, reject) => {
8
9
  if (signal?.aborted)
9
10
  reject(signal.reason);
10
11
  else
11
- resolve(undefined);
12
+ resolve();
12
13
  }, ms);
13
14
  signal?.addEventListener("abort", () => (clearTimeout(t), reject(signal.reason)), { once: true });
14
15
  }
@@ -19,26 +20,10 @@ export const probing = (p) => {
19
20
  p.then(x => value = x);
20
21
  return () => value;
21
22
  };
22
- export const resolved = (p) => {
23
- const val = probing(p);
24
- return (f) => {
25
- const g = (filterT((isDefined), f));
26
- return () => g(val());
27
- };
28
- };
29
- export const promise = (x) => (x instanceof Promise) ? x : Promise.resolve(x);
30
- export const then = (p) => (f) => p.then(f);
23
+ export const promisify = (x) => (isPromise(x) ? x : Promise.resolve(x));
31
24
  export const dispose = (p) => {
32
- let dispose = noop;
33
- let disposed = false;
34
- p.then(d => {
35
- if (disposed)
36
- d();
37
- else
38
- dispose = d;
39
- });
40
- return () => {
41
- disposed = true;
42
- dispose();
43
- };
25
+ const { promise, resolve } = Promise.withResolvers();
26
+ let dispose = noop, disposed = false;
27
+ p.then(d => (dispose = then(d, resolve), disposed && dispose()));
28
+ return () => (disposed = true, dispose(), promise);
44
29
  };
package/checks.d.ts CHANGED
@@ -28,3 +28,6 @@ export declare const isEmpty: (x: {
28
28
  length: number;
29
29
  }) => boolean;
30
30
  export declare const counted: (n: number) => () => boolean;
31
+ export declare const isBitSet: (x: number, n: number) => boolean;
32
+ export declare const isPromise: <T = any>(x: any) => x is Promise<T>;
33
+ export declare const isPromiseLike: <T = any>(x: any) => x is PromiseLike<T>;
package/checks.js CHANGED
@@ -43,3 +43,6 @@ export const counted = (n) => {
43
43
  let m = 0;
44
44
  return () => m++ < n;
45
45
  };
46
+ export const isBitSet = (x, n) => (x & (1 << n)) !== 0;
47
+ export const isPromise = (x) => x instanceof Promise;
48
+ export const isPromiseLike = (x) => x instanceof Promise;
package/fn.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Fn, FnV, FnF, Pred, TPred, Last, Lazy, Dispose, Reactive } from "./types.js";
1
+ import type { Fn, FnV, FnF, Pred, Last, Lazy, Dispose, Reactive, Promisified, MaybePromise } from "./types.js";
2
2
  export declare const tee: <T>(f: Fn<T, void>) => Fn<T, T>;
3
3
  export declare const comp: <Fs extends Fn[]>(...fs: Fs) => (x: Fs[0] extends Fn<infer T> ? T : never) => Last<Fs> extends Fn<any, infer R> ? R : never;
4
4
  export declare const pipe: <T, Fs extends [Fn<T>, ...Fn[]]>(x: T, ...fs: Fs) => Last<Fs> extends Fn<any, infer R> ? R : never;
@@ -17,7 +17,6 @@ export declare const where: <T, U, V>(p: Pred<T>, f: Fn<T, U>, g: Fn<T, V>) => (
17
17
  export declare const before: <F extends Fn<void>>(f: F) => FnF;
18
18
  export declare const after: <F extends Fn<void>>(f: F) => FnF;
19
19
  export declare const filter: <T>(p: Pred<T>, f: Fn<T>) => (x: T) => void;
20
- export declare const filterT: <T>(p: TPred<T>, f: Fn<T>) => <S>(x: S) => void;
21
20
  export declare const scan: <T, S>(f: FnV<[S, T], S>, a: S) => Fn<T, S>;
22
21
  export declare const memoize: <T extends any[], K, V>(f: FnV<T, V>, key?: FnV<T, K>, cache?: Map<K, V>) => (...xs: T) => NonNullable<V>;
23
22
  export declare const abortable: <T = any>(f: Fn<AbortSignal>) => (reason?: T) => void;
@@ -27,3 +26,5 @@ export declare const idemp: <F extends FnV<any[], Dispose | void>>(d: Fn<Dispose
27
26
  export declare const toggler: (f: Fn<void, Dispose>) => Fn<boolean, Dispose>;
28
27
  export declare const voidify: <F extends FnV>(f: F) => (...xs: Parameters<F>) => void;
29
28
  export declare const effectual: <T>(f: Reactive<T>, g: Fn<T>) => Dispose;
29
+ export declare const promisify: <F extends FnV>(f: F) => (...xs: Parameters<F>) => Promisified<ReturnType<F>>;
30
+ export declare const then: <T, F extends FnV<any, MaybePromise<any>>>(f: F, g?: Fn<Awaited<ReturnType<F>>, T>) => (...xs: Parameters<F>) => Promise<T>;
package/fn.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { add } from "./set.js";
2
+ import * as Async from "./async.js";
3
+ import { isPromise } from "./checks.js";
2
4
  export const tee = f => x => (f(x), x);
3
5
  export const comp = (...fs) => (x) => fs.reduce((x, f) => f(x), x);
4
6
  export const pipe = (x, ...fs) => fs.reduce((x, f) => f(x), x);
@@ -22,8 +24,6 @@ export const after = (f) => g => (...xs) => {
22
24
  };
23
25
  export const filter = (p, f) => (x) => { if (p(x))
24
26
  f(x); };
25
- export const filterT = (p, f) => (x) => { if (p(x))
26
- f(x); };
27
27
  export const scan = (f, a) => (x) => a = f(a, x);
28
28
  export const memoize = (f, key = (...xs) => xs[0], cache = new Map()) => (...xs) => {
29
29
  const k = key(...xs);
@@ -56,3 +56,8 @@ export const toggler = (f) => {
56
56
  };
57
57
  export const voidify = (f) => (...xs) => { f(...xs); };
58
58
  export const effectual = (f, g) => disposable(d => d(f(idemp(d, g))));
59
+ export const promisify = (f) => (...xs) => Async.promisify(f(...xs));
60
+ export const then = (f, g = identity) => (...xs) => {
61
+ const r = f(...xs);
62
+ return isPromise(r) ? r.then(g) : Promise.resolve(g(r));
63
+ };
package/iterable.d.ts CHANGED
@@ -5,23 +5,13 @@ export declare const just: <T>(x: T) => IteratorObject<T>;
5
5
  export declare const enumerate: (n?: number) => <T>(x: T) => Indexed<T>;
6
6
  export declare function empty(): Generator<never, void, unknown>;
7
7
  export declare function concat<T>(...xxs: ReadonlyArray<IteratorObject<T>>): Generator<T, void, unknown>;
8
- export declare const toArray: <T>(xs: IteratorObject<T>) => T[];
9
8
  export declare const map: <T, U = T>(f: Fn<T, U>) => (xs: IteratorObject<T>) => IteratorObject<U, undefined, unknown>;
10
- export declare const filter: <T>(f: Pred<T>) => (xs: IteratorObject<T>) => IteratorObject<T, undefined, unknown>;
11
- export declare const drop: (n: number) => <T>(xs: IteratorObject<T>) => IteratorObject<T, undefined, unknown>;
12
- export declare const flatMap: <T, U = Iterable<T>>(f: Fn<T, Iterator<U> | Iterable<U>>) => (xs: IteratorObject<T>) => IteratorObject<U, undefined, unknown>;
13
- export declare const forEach: <T>(f?: Fn<T>) => (xs: IteratorObject<T>) => void;
14
- export declare const some: <T>(f: Pred<T>) => (xs: IteratorObject<T>) => boolean;
15
- export declare const every: <T>(f: Pred<T>) => (xs: IteratorObject<T>) => boolean;
16
- export declare const find: <T>(f: Pred<T>) => (xs: IteratorObject<T>) => T | undefined;
17
- export declare const flat: <T>(xs: IteratorObject<IteratorObject<T>>) => IteratorObject<T, undefined, unknown>;
18
9
  export declare const prepend: <A>(ys: IteratorObject<A>) => (xs: IteratorObject<A>) => Generator<A, void, unknown>;
19
10
  export declare const append: <A>(ys: IteratorObject<A>) => (xs: IteratorObject<A>) => Generator<A, void, unknown>;
20
11
  export declare const first: <T>(xs: IteratorObject<T>) => T | undefined;
21
12
  export declare const reduce: <T, S>(f: FnV<[S, T, number], S>, a: S) => (xs: IteratorObject<T>) => S;
22
13
  export declare const reduceRec: <T, A, R>(xs: IteratorObject<T>, f: FnV<[A, T, Fn<A>], R>, o: A, result: Fn<A, R>) => R;
23
- export declare const traverse: <T>(children: Fn<T, Iterable<T>>, f: Fn<T>) => Fn<T>;
24
- export declare const take: (n: number) => <T>(xs: IteratorObject<T>) => Generator<T>;
14
+ export declare const take: <T>(n: number, xs: IteratorObject<T>) => Generator<T, void, unknown>;
25
15
  export declare function arange(a: number, b?: number, s?: number): Generator<number, void, unknown>;
26
16
  export declare const linspace: (a: number, b: number, n: number) => Generator<number, void, unknown>;
27
17
  export declare const steps: (a: number, b: number, s?: number, o?: number, eps?: number) => Generator<number, void, unknown>;
package/iterable.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { assert, isDefined } from "./checks.js";
2
- import { pipe, comp, scan, apply, noop, identity, constantly } from "./fn.js";
2
+ import { bind, pipe, comp, scan, apply, noop, constantly } from "./fn.js";
3
3
  import { set } from "./map.js";
4
4
  export const next = (xs) => {
5
5
  const { done, value } = xs.next();
@@ -15,16 +15,7 @@ export function* empty() { }
15
15
  export function* concat(...xxs) { for (const xs of xxs)
16
16
  yield* xs; }
17
17
  ;
18
- export const toArray = (xs) => xs.toArray();
19
18
  export const map = (f) => (xs) => xs.map(f);
20
- export const filter = (f) => (xs) => xs.filter(f);
21
- export const drop = (n) => (xs) => xs.drop(n);
22
- export const flatMap = (f) => (xs) => xs.flatMap(f);
23
- export const forEach = (f = noop) => (xs) => xs.forEach(f);
24
- export const some = (f) => (xs) => xs.some(f);
25
- export const every = (f) => (xs) => xs.every(f);
26
- export const find = (f) => (xs) => xs.find(f);
27
- export const flat = (xs) => xs.flatMap(identity);
28
19
  export const prepend = (ys) => (xs) => concat(ys, xs);
29
20
  export const append = (ys) => (xs) => concat(xs, ys);
30
21
  export const first = (xs) => xs.find(constantly(true));
@@ -39,8 +30,7 @@ export const reduceRec = (xs, f, o, result) => {
39
30
  };
40
31
  return next(o);
41
32
  };
42
- export const traverse = (children, f) => (x) => (f(x), forEach(traverse(children, f))(Iterator.from(children(x))));
43
- export const take = n => function* (xs) {
33
+ export const take = function* (n, xs) {
44
34
  for (let i = 0; i < n; i++) {
45
35
  const { done, value } = xs.next();
46
36
  if (done)
@@ -146,8 +136,8 @@ export const reduceA = (f, a) => async (xs) => {
146
136
  export const race = (n) => async function* (xs) {
147
137
  const it = pipe(xs, map(enumerate()), map(([i, x]) => [i, x.then(y => [i, y])]));
148
138
  const accum = reduce((set), new Map());
149
- const tasks = pipe(it, (take(n)), accum);
150
- const next = comp((take(1)), accum);
139
+ const tasks = pipe(it, bind((take), n), accum);
140
+ const next = comp(bind((take), 1), accum);
151
141
  while (tasks.size > 0) {
152
142
  const [i, x] = await Promise.race(tasks.values());
153
143
  tasks.delete(i);
@@ -155,4 +145,4 @@ export const race = (n) => async function* (xs) {
155
145
  next(it);
156
146
  }
157
147
  };
158
- export const zmap = (f) => (...xs) => forEach(apply(f))(zip(...xs));
148
+ export const zmap = (f) => (...xs) => zip(...xs).forEach(apply(f));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cgtk/std",
3
- "version": "0.0.196",
3
+ "version": "0.0.197",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "exports": {
@@ -37,7 +37,7 @@
37
37
  "./npy": "./npy.js",
38
38
  "./port": "./port.js",
39
39
  "./rect": "./rect.js",
40
- "./resource": "./resource.js",
40
+ "./scope": "./scope.js",
41
41
  "./utils": "./utils.js"
42
42
  },
43
43
  "publishConfig": {
package/port.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Dispose, Fn, Fns, FnV, RecordOf, MaybePromise, Reactive } from "./types.js";
1
+ import type { Dispose, Fn, Fns, FnV, RecordOf, MaybePromise, Reactive, AsyncDispose } from "./types.js";
2
2
  export interface Message<K, V> {
3
3
  type: K;
4
4
  payload: V;
@@ -25,6 +25,6 @@ interface TransferableFnV<T extends any[], R> {
25
25
  }
26
26
  export declare const client: <S extends RecordOf<any>, T = Worker>(target: Port & MessageEventTarget<T>) => { [k in keyof S]: TransferableFnV<Parameters<S[k]>, Promise<ReturnType<S[k]>>>; };
27
27
  export declare const server: <S extends RecordOf<any>, T = Worker>(target: Port & MessageEventTarget<T>) => { [k in keyof S]: Fn<FnV<Parameters<S[k]>, MaybePromise<ReturnType<S[k]>>>, Dispose>; };
28
- export declare const startClient: (worker: Worker, f: Fn<Worker, Dispose | void>) => Promise<Dispose>;
28
+ export declare const startClient: (worker: Worker, f: Fn<Worker, Dispose | void>) => Promise<AsyncDispose>;
29
29
  export declare const startServer: (worker: Worker, f: Fn<Worker, MaybePromise<Dispose>>) => Promise<Dispose>;
30
30
  export {};
package/port.js CHANGED
@@ -1,7 +1,7 @@
1
- import { forEach, noop, bind } from "./fn.js";
1
+ import { noop, bind, then } from "./fn.js";
2
2
  import { isDefined } from "./checks.js";
3
3
  import { on } from "./dom.js";
4
- import { promise } from "./async.js";
4
+ import { promisify } from "./async.js";
5
5
  ;
6
6
  export const onMessages = (target, fs) => on(target, "message", ({ data: { type, payload } }) => (type in fs) && fs[type](payload));
7
7
  export const onMessage = (target, name, f) => on(target, "message", ({ data: { type, payload } }) => type == name && f(payload));
@@ -39,18 +39,18 @@ export const server = (target) => {
39
39
  onMessage(target, "rpc", async ({ id, name, args }) => {
40
40
  const f = fns.get(name);
41
41
  if (isDefined(f))
42
- rpc({ id, result: await promise(f(...args)) });
42
+ rpc({ id, result: await promisify(f(...args)) });
43
43
  });
44
44
  return new Proxy({}, {
45
45
  get: (_, k) => (f) => (fns.set(k, f), () => fns.delete(k))
46
46
  });
47
47
  };
48
48
  export const startClient = async (worker, f) => {
49
- const cli = client(worker);
50
- await cli.start();
51
- return forEach(f(worker) ?? noop, () => cli.stop().then(() => worker.terminate()));
49
+ const { start, stop } = client(worker);
50
+ await start();
51
+ return then(stop, f(worker) ?? noop);
52
52
  };
53
53
  export const startServer = async (worker, f) => {
54
- const ser = server(worker);
55
- return ser.start(async () => { ser.stop(await promise(f(worker))); });
54
+ const { start, stop } = server(worker);
55
+ return start(async () => { stop(await promisify(f(worker))); });
56
56
  };
package/scope.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import type { Fn, FnV, Dispose, AsyncDispose, MaybePromise, Structure } from "./types.js";
2
+ type Result = Dispose | AsyncDispose | void;
3
+ export type Scope<T> = Dispose & {
4
+ value: T;
5
+ dispose: Dispose;
6
+ map<S>(f: Fn<T, S>): Scope<S>;
7
+ use(f: Fn<T, MaybePromise<Result>>): Scope<T>;
8
+ };
9
+ export declare const scope: <T>(value: T, dispose?: Dispose) => Scope<T>;
10
+ type Unwrapped<T> = T extends Scope<infer U> ? U : {
11
+ [K in keyof T]: Unwrapped<T[K]>;
12
+ };
13
+ export declare const compose: <R extends Structure<Scope<any>>>(rs: R) => Scope<Unwrapped<R>>;
14
+ export declare const of: <T>(x: T, f: Fn<T, Dispose>) => Scope<T>;
15
+ type Use = <T>(r: Scope<T>) => T;
16
+ export declare const gen: <R>(f: FnV<[Use, Fn<Dispose, Dispose>], R>) => Scope<R>;
17
+ export declare const consume: (f: Fn<Use, Dispose | void>) => Dispose;
18
+ export declare const worker: (w: Worker) => Scope<Worker>;
19
+ export {};
package/scope.js ADDED
@@ -0,0 +1,41 @@
1
+ import * as F from "./fn.js";
2
+ import * as Async from "./async.js";
3
+ import { isPromise, isFunction } from "./checks.js";
4
+ import { add } from "./set.js";
5
+ export const scope = (value, dispose = F.noop) => {
6
+ const s = (() => dispose());
7
+ s.value = value;
8
+ s.dispose = dispose;
9
+ s.map = f => scope(f(value), dispose);
10
+ s.use = f => {
11
+ const r = f(value);
12
+ const d = isPromise(r) ?
13
+ Async.dispose(r.then(d => F.then(d ?? F.noop, dispose))) :
14
+ F.then(r ?? F.noop, dispose);
15
+ return scope(value, d);
16
+ };
17
+ return s;
18
+ };
19
+ const iLeaf = (r) => Object.hasOwn(r, "value") && Object.hasOwn(r, "dispose") && isFunction(r["dispose"]);
20
+ export const compose = (rs) => {
21
+ const disposes = [];
22
+ const rec = (rs) => {
23
+ if (iLeaf(rs)) {
24
+ disposes.push(rs.dispose);
25
+ return rs.value;
26
+ }
27
+ else if (Array.isArray(rs)) {
28
+ return rs.map(rec);
29
+ }
30
+ return Object.fromEntries(Object.entries(rs).map(([k, v]) => [k, rec(v)]));
31
+ };
32
+ const value = rec(rs);
33
+ return scope(value, F.forEach(...disposes));
34
+ };
35
+ export const of = (x, f) => scope(x, f(x));
36
+ export const gen = (f) => {
37
+ const res = new Set();
38
+ return scope(f(r => (res.add(r.dispose), r.value), F.bind(add, res)), () => res.forEach(f => f()));
39
+ };
40
+ export const consume = (f) => F.disposable(use => use(f(r => (use(r.dispose), r.value)) ?? F.noop));
41
+ export const worker = (w) => of(w, x => x.terminate.bind(x));
package/types.d.ts CHANGED
@@ -14,9 +14,11 @@ export type Fns<T> = {
14
14
  };
15
15
  export type FnF = <F extends FnV>(f: F) => (...xs: Parameters<F>) => ReturnType<F>;
16
16
  export type Dispose = Fn<void>;
17
+ export type AsyncDispose = Fn<void, Promise<void>>;
17
18
  export type Reactive<T = unknown, R = any> = Fn<Fn<T, R>, Dispose>;
18
19
  export type Lazy<T> = () => T;
19
- export type MaybePromise<T = unknown> = T | PromiseLike<T>;
20
+ export type MaybePromise<T = unknown> = T | Promise<T>;
21
+ export type Promisified<T> = T extends Promise<any> ? T : Promise<T>;
20
22
  export type Last<T extends any[]> = T extends [...any, infer Rest] ? Rest : never;
21
23
  export type Tail<T extends any[]> = T extends [any, ...(infer Rest)] ? Rest : never;
22
24
  export type Push<T extends any[], V> = [...T, V];
package/resource.d.ts DELETED
@@ -1,19 +0,0 @@
1
- import type { Fn, FnV, Dispose, Structure, Reactive, RecordOf } from "./types.js";
2
- export type Resource<T> = Reactive<T, Dispose | void> & {
3
- value: T;
4
- dispose: Dispose;
5
- map<S>(f: Fn<T, S>): Resource<S>;
6
- flatMap<S>(f: Fn<T, Resource<S>>): Resource<S>;
7
- promise(f: Fn<T, Promise<Dispose | void>>): Promise<Dispose>;
8
- };
9
- export declare const resource: <T>(value: T, dispose?: Dispose) => Resource<T>;
10
- export declare const awaited: <T>({ value, dispose }: Resource<Promise<T>>) => Promise<Resource<Awaited<T>>>;
11
- type Unwrapped<T> = T extends Resource<infer U> ? U : {
12
- [K in keyof T]: Unwrapped<T[K]>;
13
- };
14
- export declare const compose: <R extends Structure<Resource<any>>>(rs: R) => Resource<Unwrapped<R>>;
15
- export declare const of: <T>(x: T, f: Fn<T, Dispose>) => Resource<T>;
16
- export declare const gen: <R>(f: FnV<[<T>(r: Resource<T>) => T, Fn<Dispose, Dispose>], R>) => Resource<R>;
17
- export declare const consume: (f: Fn<(<T>(r: Resource<T>) => T), Dispose | void>) => Dispose;
18
- export declare const swapping: <F extends RecordOf<FnV<any, Dispose | void>>>(fs: F) => Resource<{ [K in import("./types.js").Entry<keyof F, FnV<Parameters<import("./types.js").ValueOf<F>>, Dispose>> as K[0]]: K[1]; }>;
19
- export {};
package/resource.js DELETED
@@ -1,46 +0,0 @@
1
- import * as F from "./fn.js";
2
- import { isFunction } from "./checks.js";
3
- import { add } from "./set.js";
4
- import { mapValues } from "./object.js";
5
- export const resource = (value, dispose = F.noop) => {
6
- const res = ((f) => F.forEach(f(value) ?? F.noop, dispose));
7
- res.value = value;
8
- res.dispose = dispose;
9
- res.map = (f) => resource(f(value), dispose);
10
- res.flatMap = (f) => {
11
- const res = f(value);
12
- return resource(res.value, F.forEach(res.dispose, dispose));
13
- };
14
- res.promise = async (f) => F.forEach((await f(value)) ?? F.noop, dispose);
15
- return res;
16
- };
17
- export const awaited = async ({ value, dispose }) => resource(await value, dispose);
18
- const isResource = (r) => isFunction(r) &&
19
- Object.hasOwn(r, "value") &&
20
- Object.hasOwn(r, "dispose") &&
21
- isFunction(r["dispose"]);
22
- export const compose = (rs) => {
23
- const disposes = [];
24
- const rec = (rs) => {
25
- if (isResource(rs)) {
26
- disposes.push(rs.dispose);
27
- return rs.value;
28
- }
29
- else if (Array.isArray(rs)) {
30
- return rs.map(rec);
31
- }
32
- return Object.fromEntries(Object.entries(rs).map(([k, v]) => [k, rec(v)]));
33
- };
34
- const value = rec(rs);
35
- return resource(value, F.forEach(...disposes));
36
- };
37
- export const of = (x, f) => resource(x, f(x));
38
- export const gen = (f) => {
39
- const res = new Set();
40
- return resource(f((r) => (res.add(r.dispose), r.value), F.bind(add, res)), () => res.forEach((f) => f()));
41
- };
42
- export const consume = (f) => F.disposable((use) => use(f((r) => (use(r.dispose), r.value)) ?? F.noop));
43
- export const swapping = (fs) => {
44
- const swap = F.swapping();
45
- return resource(mapValues(fs, swap), swap(F.noop));
46
- };