@thi.ng/transducers-async 0.2.4 → 0.2.6

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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2024-04-26T13:32:20Z
3
+ - **Last updated**: 2024-06-21T19:34:38Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,15 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ### [0.2.6](https://github.com/thi-ng/umbrella/tree/@thi.ng/transducers-async@0.2.6) (2024-06-21)
13
+
14
+ #### ♻️ Refactoring
15
+
16
+ - rename various rest args to be more semantically meaningful ([8088a56](https://github.com/thi-ng/umbrella/commit/8088a56))
17
+ - update merge()/sync() ([ef82528](https://github.com/thi-ng/umbrella/commit/ef82528))
18
+ - dedupe internal shared functionality
19
+ - dedupe iter removal in merge()/sync() ([abc6a46](https://github.com/thi-ng/umbrella/commit/abc6a46))
20
+
12
21
  ## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/transducers-async@0.2.0) (2024-04-20)
13
22
 
14
23
  #### 🚀 Features
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Mastodon Follow](https://img.shields.io/mastodon/follow/109331703950160316?domain=https%3A%2F%2Fmastodon.thi.ng&style=social)](https://mastodon.thi.ng/@toxi)
8
8
 
9
9
  > [!NOTE]
10
- > This is one of 192 standalone projects, maintained as part
10
+ > This is one of 193 standalone projects, maintained as part
11
11
  > of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
12
12
  > and anti-framework.
13
13
  >
@@ -116,7 +116,7 @@ For Node.js REPL:
116
116
  const txa = await import("@thi.ng/transducers-async");
117
117
  ```
118
118
 
119
- Package sizes (brotli'd, pre-treeshake): ESM: 3.10 KB
119
+ Package sizes (brotli'd, pre-treeshake): ESM: 3.11 KB
120
120
 
121
121
  ## Dependencies
122
122
 
package/as-async.js CHANGED
@@ -2,8 +2,7 @@ import { wait } from "./delayed.js";
2
2
  async function* asAsyncIterable(src, delay = 0) {
3
3
  for (let x of src) {
4
4
  yield x;
5
- if (delay > 0)
6
- await wait(delay);
5
+ if (delay > 0) await wait(delay);
7
6
  }
8
7
  }
9
8
  export {
package/cat.js CHANGED
@@ -6,8 +6,7 @@ const cat = () => (rfn) => {
6
6
  if (x != null) {
7
7
  for await (let y of x) {
8
8
  acc = await r(acc, y);
9
- if (isReduced(acc))
10
- return acc.deref();
9
+ if (isReduced(acc)) return acc.deref();
11
10
  }
12
11
  }
13
12
  return acc;
package/concat.d.ts CHANGED
@@ -27,7 +27,7 @@ import type { MaybeAsyncIterable, Nullable } from "@thi.ng/api";
27
27
  * // [ 1, 2, 3, undefined, 4, 5 ]
28
28
  * ```
29
29
  *
30
- * @param xs -
30
+ * @param sources -
31
31
  */
32
- export declare function concat<T>(...xs: Nullable<MaybeAsyncIterable<T>>[]): AsyncIterableIterator<T>;
32
+ export declare function concat<T>(...sources: Nullable<MaybeAsyncIterable<T>>[]): AsyncIterableIterator<T>;
33
33
  //# sourceMappingURL=concat.d.ts.map
package/concat.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ensureIterable } from "./ensure.js";
2
- async function* concat(...xs) {
3
- for (let x of xs) {
4
- x != null && (yield* ensureIterable(x));
2
+ async function* concat(...sources) {
3
+ for (let src of sources) {
4
+ src != null && (yield* ensureIterable(src));
5
5
  }
6
6
  }
7
7
  export {
@@ -0,0 +1,21 @@
1
+ /** @internal */
2
+ export declare const __inflightIters: <T extends {
3
+ iter: AsyncIterator<any>;
4
+ }>(iters: T[]) => Promise<{
5
+ iter: T;
6
+ res: IteratorResult<any, any>;
7
+ }>[];
8
+ /** @internal */
9
+ export declare const __iterNext: <T extends {
10
+ id: number;
11
+ iter: AsyncIterator<any>;
12
+ }>(promises: Promise<{
13
+ iter: T;
14
+ res: IteratorResult<any, any>;
15
+ }>[], iter: T) => void;
16
+ /** @internal */
17
+ export declare const __iterRemove: <T extends {
18
+ id: number;
19
+ iter: AsyncIterator<any>;
20
+ }>(iters: T[], id: number) => true | undefined;
21
+ //# sourceMappingURL=iter.d.ts.map
@@ -0,0 +1,15 @@
1
+ const __inflightIters = (iters) => iters.map((iter) => iter.iter.next().then((res) => ({ iter, res })));
2
+ const __iterNext = (promises, iter) => {
3
+ promises[iter.id] = iter.iter.next().then((res) => ({ res, iter }));
4
+ };
5
+ const __iterRemove = (iters, id) => {
6
+ iters.splice(id, 1);
7
+ const n = iters.length;
8
+ if (!n) return true;
9
+ for (let i = id; i < n; i++) iters[i].id--;
10
+ };
11
+ export {
12
+ __inflightIters,
13
+ __iterNext,
14
+ __iterRemove
15
+ };
package/iterator.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { FnAny, MaybeAsyncIterable } from "@thi.ng/api";
2
2
  import type { AsyncTransducer, AsyncTxLike } from "./api.js";
3
- export declare function iterator1<A, B>(xform: AsyncTxLike<A, B>, xs: MaybeAsyncIterable<A>): AsyncIterableIterator<B>;
4
- export declare function iterator<A, B>(xform: AsyncTxLike<A, B>, xs: MaybeAsyncIterable<A>): AsyncIterableIterator<B>;
3
+ export declare function iterator1<A, B>(xform: AsyncTxLike<A, B>, src: MaybeAsyncIterable<A>): AsyncIterableIterator<B>;
4
+ export declare function iterator<A, B>(xform: AsyncTxLike<A, B>, src: MaybeAsyncIterable<A>): AsyncIterableIterator<B>;
5
5
  export declare const __iter: (xform: FnAny<AsyncTransducer<any, any>>, args: any[], impl?: typeof iterator1) => AsyncIterableIterator<any> | undefined;
6
6
  //# sourceMappingURL=iterator.d.ts.map
package/iterator.js CHANGED
@@ -4,9 +4,9 @@ import { isIterable } from "@thi.ng/checks/is-iterable";
4
4
  import { isReduced } from "@thi.ng/transducers/reduced";
5
5
  import { ensureAsyncTransducer } from "./ensure.js";
6
6
  import { push } from "./push.js";
7
- async function* iterator1(xform, xs) {
7
+ async function* iterator1(xform, src) {
8
8
  const [_, complete, reduce] = ensureAsyncTransducer(xform)([NO_OP, NO_OP, (_2, x) => x]);
9
- for await (let x of xs) {
9
+ for await (let x of src) {
10
10
  let y = await reduce(SEMAPHORE, x);
11
11
  if (isReduced(y)) {
12
12
  const res = await complete(y.deref());
@@ -20,11 +20,11 @@ async function* iterator1(xform, xs) {
20
20
  }
21
21
  }
22
22
  }
23
- async function* iterator(xform, xs) {
23
+ async function* iterator(xform, src) {
24
24
  const [_, complete, reduce] = ensureAsyncTransducer(
25
25
  xform
26
26
  )(push());
27
- for await (let x of xs) {
27
+ for await (let x of src) {
28
28
  const y = await reduce([], x);
29
29
  if (isReduced(y)) {
30
30
  yield* await complete(y.deref());
package/merge.js CHANGED
@@ -1,25 +1,15 @@
1
+ import { __inflightIters, __iterNext, __iterRemove } from "./internal/iter.js";
1
2
  async function* merge(src) {
2
3
  const iters = src.map((v, id) => ({ id, iter: v[Symbol.asyncIterator]() }));
3
- let n = iters.length;
4
- const $remove = (id) => {
5
- iters.splice(id, 1);
6
- if (!--n)
7
- return true;
8
- for (let i = id; i < n; i++)
9
- iters[i].id--;
10
- };
11
- const promises = iters.map(
12
- (iter) => iter.iter.next().then((res) => ({ iter, res }))
13
- );
4
+ const promises = __inflightIters(iters);
14
5
  while (true) {
15
6
  const { iter, res } = await Promise.race(promises);
16
7
  if (res.done) {
17
8
  promises.splice(iter.id, 1);
18
- if ($remove(iter.id))
19
- return;
9
+ if (__iterRemove(iters, iter.id)) return;
20
10
  } else {
21
11
  yield res.value;
22
- promises[iter.id] = iter.iter.next().then((res2) => ({ res: res2, iter }));
12
+ __iterNext(promises, iter);
23
13
  }
24
14
  }
25
15
  }
package/mult.js CHANGED
@@ -18,16 +18,12 @@ class Mult {
18
18
  this.isActive = true;
19
19
  (async () => {
20
20
  for await (let val of this.src) {
21
- for (let s of this.subs)
22
- s.resolve(val);
23
- if (val === void 0)
24
- this.subs.length = 0;
25
- if (!this.subs.length)
26
- break;
21
+ for (let s of this.subs) s.resolve(val);
22
+ if (val === void 0) this.subs.length = 0;
23
+ if (!this.subs.length) break;
27
24
  await Promise.all(this.subs.map((x) => x.notifyP));
28
25
  }
29
- for (let s of this.subs)
30
- s.resolve(void 0);
26
+ for (let s of this.subs) s.resolve(void 0);
31
27
  this.subs.length = 0;
32
28
  this.isActive = false;
33
29
  })();
@@ -60,13 +56,11 @@ class MSub {
60
56
  this.$await();
61
57
  }
62
58
  async *[Symbol.asyncIterator]() {
63
- if (this.active)
64
- illegalState("multiple consumers unsupported");
59
+ if (this.active) illegalState("multiple consumers unsupported");
65
60
  this.active = true;
66
61
  while (true) {
67
62
  const res = await this.valueP;
68
- if (res === void 0)
69
- break;
63
+ if (res === void 0) break;
70
64
  yield res;
71
65
  this.notify();
72
66
  this.$await();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/transducers-async",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Async versions of various highly composable transducers, reducers and iterators",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -10,7 +10,7 @@
10
10
  "type": "git",
11
11
  "url": "https://github.com/thi-ng/umbrella.git"
12
12
  },
13
- "homepage": "https://github.com/thi-ng/umbrella/tree/develop/packages/transducers-async#readme",
13
+ "homepage": "https://thi.ng/transducers-async",
14
14
  "funding": [
15
15
  {
16
16
  "type": "github",
@@ -36,18 +36,18 @@
36
36
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
37
37
  },
38
38
  "dependencies": {
39
- "@thi.ng/api": "^8.11.1",
40
- "@thi.ng/buffers": "^0.1.2",
41
- "@thi.ng/checks": "^3.6.3",
42
- "@thi.ng/compose": "^3.0.3",
43
- "@thi.ng/errors": "^2.5.6",
44
- "@thi.ng/transducers": "^9.0.4"
39
+ "@thi.ng/api": "^8.11.3",
40
+ "@thi.ng/buffers": "^0.1.4",
41
+ "@thi.ng/checks": "^3.6.5",
42
+ "@thi.ng/compose": "^3.0.5",
43
+ "@thi.ng/errors": "^2.5.8",
44
+ "@thi.ng/transducers": "^9.0.6"
45
45
  },
46
46
  "devDependencies": {
47
- "@microsoft/api-extractor": "^7.43.0",
48
- "esbuild": "^0.20.2",
49
- "typedoc": "^0.25.12",
50
- "typescript": "^5.4.3"
47
+ "@microsoft/api-extractor": "^7.47.0",
48
+ "esbuild": "^0.21.5",
49
+ "typedoc": "^0.25.13",
50
+ "typescript": "^5.5.2"
51
51
  },
52
52
  "keywords": [
53
53
  "async",
@@ -81,7 +81,8 @@
81
81
  },
82
82
  "files": [
83
83
  "./*.js",
84
- "./*.d.ts"
84
+ "./*.d.ts",
85
+ "internal"
85
86
  ],
86
87
  "exports": {
87
88
  ".": {
@@ -204,5 +205,5 @@
204
205
  "status": "alpha",
205
206
  "year": 2018
206
207
  },
207
- "gitHead": "0bec55821066c18eb977a7eabd42c0bb2b096d98\n"
208
+ "gitHead": "154c95cf9d6bab32174498ec3b5b5d87e42be7f9\n"
208
209
  }
package/partition.js CHANGED
@@ -3,8 +3,7 @@ import { unreduced } from "@thi.ng/transducers/reduced";
3
3
  import { __iter, iterator } from "./iterator.js";
4
4
  function partition(...args) {
5
5
  const iter = __iter(partition, args, iterator);
6
- if (iter)
7
- return iter;
6
+ if (iter) return iter;
8
7
  let size = args[0], all, step;
9
8
  if (isNumber(args[1])) {
10
9
  step = args[1];
package/pubsub.js CHANGED
@@ -34,8 +34,7 @@ class PubSub {
34
34
  */
35
35
  unsubscribeTopic(id, sub) {
36
36
  const subs = this.topics.get(id);
37
- if (!subs)
38
- return false;
37
+ if (!subs) return false;
39
38
  const idx = subs.findIndex((x) => x === sub) ?? -1;
40
39
  if (idx >= 0) {
41
40
  subs.splice(idx, 1);
@@ -48,15 +47,12 @@ class PubSub {
48
47
  for await (let val of this.src) {
49
48
  const topic = this.topicFn(val);
50
49
  const subs = this.topics.get(topic);
51
- if (!(subs && subs.length))
52
- continue;
53
- for (let s of subs)
54
- s.resolve(val);
50
+ if (!(subs && subs.length)) continue;
51
+ for (let s of subs) s.resolve(val);
55
52
  await Promise.all(subs.map((x) => x.notifyP));
56
53
  }
57
54
  for (let subs of this.topics.values()) {
58
- for (let s of subs)
59
- s.resolve(void 0);
55
+ for (let s of subs) s.resolve(void 0);
60
56
  }
61
57
  this.topics.clear();
62
58
  this.isActive = false;
package/push.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { MaybeAsyncIterable } from "@thi.ng/api";
2
2
  import type { AsyncReducer } from "./api.js";
3
3
  export declare function push<T>(): AsyncReducer<T, T[]>;
4
- export declare function push<T>(xs: MaybeAsyncIterable<T>): Promise<T[]>;
4
+ export declare function push<T>(src: MaybeAsyncIterable<T>): Promise<T[]>;
5
5
  //# sourceMappingURL=push.d.ts.map
package/push.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import { reducer } from "./reduce.js";
2
- function push(xs) {
3
- return xs ? (async () => {
2
+ function push(src) {
3
+ return src ? (async () => {
4
4
  let res = [];
5
- for await (let x of xs)
6
- res.push(x);
5
+ for await (let x of src) res.push(x);
7
6
  return res;
8
7
  })() : reducer(
9
8
  () => [],
package/raf.js CHANGED
@@ -9,13 +9,10 @@ const raf = (opts) => {
9
9
  gen.write(void 0);
10
10
  };
11
11
  const update = (t) => {
12
- if (isClosed)
13
- return;
12
+ if (isClosed) return;
14
13
  if (opts?.timestamp) {
15
- if (t0 === true)
16
- t0 = t;
17
- if (t0)
18
- t -= t0;
14
+ if (t0 === true) t0 = t;
15
+ if (t0) t -= t0;
19
16
  } else {
20
17
  t = frame++;
21
18
  }
package/reduce.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { asyncIdentity } from "@thi.ng/api/async";
2
2
  import { isReduced } from "@thi.ng/transducers/reduced";
3
- async function reduce([init, complete, $reduce], ...xs) {
4
- let acc = xs.length < 2 ? await init() : xs.shift();
5
- for await (let x of xs[0]) {
3
+ async function reduce([init, complete, $reduce], ...args) {
4
+ let acc = args.length < 2 ? await init() : args.shift();
5
+ for await (let x of args[0]) {
6
6
  const y = await $reduce(acc, x);
7
7
  if (isReduced(y)) {
8
8
  acc = y.deref();
package/sidechain.js CHANGED
@@ -9,12 +9,10 @@ async function* sidechain(src, side, opts) {
9
9
  let buf = [];
10
10
  while (true) {
11
11
  const [res, side2] = await Promise.race(promises);
12
- if (res.done)
13
- return;
12
+ if (res.done) return;
14
13
  if (side2) {
15
14
  promises[1] = $side.next().then((res2) => [res2, true]);
16
- if (!buf.length)
17
- continue;
15
+ if (!buf.length) continue;
18
16
  if (lastOnly) {
19
17
  yield buf[0];
20
18
  buf.length = 0;
@@ -24,10 +22,8 @@ async function* sidechain(src, side, opts) {
24
22
  }
25
23
  } else {
26
24
  promises[0] = $iter.next().then((res2) => [res2]);
27
- if (lastOnly)
28
- buf[0] = res.value;
29
- else
30
- buf.push(res.value);
25
+ if (lastOnly) buf[0] = res.value;
26
+ else buf.push(res.value);
31
27
  }
32
28
  }
33
29
  }
package/source.js CHANGED
@@ -17,33 +17,27 @@ const source = (initial, buffer = 1) => {
17
17
  while (true) {
18
18
  const val = await promise;
19
19
  last = val;
20
- if (val === void 0)
21
- break;
20
+ if (val === void 0) break;
22
21
  yield val;
23
22
  newPromise();
24
- if (queue.readable())
25
- resolve(queue.read());
23
+ if (queue.readable()) resolve(queue.read());
26
24
  }
27
25
  state = 2;
28
26
  }();
29
27
  gen.write = (x) => {
30
- if (state > 0)
31
- return;
28
+ if (state > 0) return;
32
29
  if (resolve) {
33
30
  resolve(x);
34
31
  resolve = void 0;
35
32
  } else if (queue.writable()) {
36
33
  queue.write(x);
37
- if (x === void 0)
38
- state = 1;
39
- } else
40
- illegalState("buffer overflow");
34
+ if (x === void 0) state = 1;
35
+ } else illegalState("buffer overflow");
41
36
  };
42
37
  gen.update = (fn, ...args) => gen.write(fn(last, ...args));
43
38
  gen.close = () => gen.write(void 0);
44
39
  gen.deref = () => last;
45
- if (initial !== void 0)
46
- gen.write(initial);
40
+ if (initial !== void 0) gen.write(initial);
47
41
  return gen;
48
42
  };
49
43
  export {
package/sync.js CHANGED
@@ -1,26 +1,18 @@
1
+ import { __inflightIters, __iterNext, __iterRemove } from "./internal/iter.js";
1
2
  async function* sync(src, opts) {
2
3
  let iters = Object.entries(src).map(([key, v], id) => ({
3
4
  key,
4
5
  id,
5
6
  iter: v[Symbol.asyncIterator]()
6
7
  }));
7
- let n = iters.length;
8
- const $remove = (id) => {
9
- iters.splice(id, 1);
10
- if (!--n)
11
- return true;
12
- for (let i = id; i < n; i++)
13
- iters[i].id--;
14
- };
15
8
  const $initial = async () => {
16
9
  const res = await Promise.all(iters.map(({ iter }) => iter.next()));
17
- for (let i = 0; i < n; ) {
10
+ for (let i = 0, n = iters.length; i < n; ) {
18
11
  if (res[i].done) {
19
12
  res.splice(i, 1);
20
- if ($remove(i))
21
- return;
22
- } else
23
- i++;
13
+ if (__iterRemove(iters, i)) return;
14
+ n--;
15
+ } else i++;
24
16
  }
25
17
  return res.reduce(
26
18
  (acc, x, i) => (acc[iters[i].key] = x.value, acc),
@@ -40,23 +32,19 @@ async function* sync(src, opts) {
40
32
  tuple = {};
41
33
  } else {
42
34
  tuple = await $initial();
43
- if (!tuple)
44
- return;
35
+ if (!tuple) return;
45
36
  yield { ...tuple };
46
37
  }
47
- const promises = iters.map(
48
- (iter) => iter.iter.next().then((res) => ({ iter, res }))
49
- );
38
+ const promises = __inflightIters(iters);
50
39
  while (true) {
51
40
  const { iter, res } = await Promise.race(promises);
52
41
  if (res.done) {
53
42
  promises.splice(iter.id, 1);
54
- if ($remove(iter.id))
55
- return;
43
+ if (__iterRemove(iters, iter.id)) return;
56
44
  } else {
57
45
  tuple[iter.key] = res.value;
58
46
  yield { ...tuple };
59
- promises[iter.id] = iter.iter.next().then((res2) => ({ res: res2, iter }));
47
+ __iterNext(promises, iter);
60
48
  }
61
49
  }
62
50
  }
package/transduce.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ensureAsyncTransducer } from "./ensure.js";
2
2
  import { reduce } from "./reduce.js";
3
- function transduce(xform, reducer, ...xs) {
4
- return reduce(ensureAsyncTransducer(xform)(reducer), ...xs);
3
+ function transduce(xform, reducer, ...args) {
4
+ return reduce(ensureAsyncTransducer(xform)(reducer), ...args);
5
5
  }
6
6
  export {
7
7
  transduce
package/zip.js CHANGED
@@ -6,8 +6,7 @@ async function* zip(...src) {
6
6
  const tuple = [];
7
7
  for (let i of iters) {
8
8
  let v = await i.next();
9
- if (v.done)
10
- return;
9
+ if (v.done) return;
11
10
  tuple.push(v.value);
12
11
  }
13
12
  yield tuple;