@mantiq/helpers 0.5.21 → 0.5.23
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/package.json +1 -1
- package/src/Collection.ts +15 -1
- package/src/async/Parallel.ts +69 -0
- package/src/index.ts +3 -0
package/package.json
CHANGED
package/src/Collection.ts
CHANGED
|
@@ -547,9 +547,23 @@ export class LazyCollection<T> implements Iterable<T> {
|
|
|
547
547
|
})
|
|
548
548
|
}
|
|
549
549
|
|
|
550
|
-
/** Take the first N items */
|
|
550
|
+
/** Take the first N items (positive) or last N items (negative) */
|
|
551
551
|
take(count: number): LazyCollection<T> {
|
|
552
552
|
const source = this.source
|
|
553
|
+
if (count < 0) {
|
|
554
|
+
// Negative: take the last |count| items — requires buffering
|
|
555
|
+
const absCount = -count
|
|
556
|
+
return new LazyCollection({
|
|
557
|
+
*[Symbol.iterator]() {
|
|
558
|
+
const buffer: T[] = []
|
|
559
|
+
for (const item of source) {
|
|
560
|
+
buffer.push(item)
|
|
561
|
+
if (buffer.length > absCount) buffer.shift()
|
|
562
|
+
}
|
|
563
|
+
yield* buffer
|
|
564
|
+
},
|
|
565
|
+
})
|
|
566
|
+
}
|
|
553
567
|
return new LazyCollection({
|
|
554
568
|
*[Symbol.iterator]() {
|
|
555
569
|
let taken = 0
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named parallel task runner.
|
|
3
|
+
*
|
|
4
|
+
* Unlike the `parallel()` function (which takes an array of thunks),
|
|
5
|
+
* `Parallel.run()` accepts a named record so results are strongly typed
|
|
6
|
+
* by key — no index juggling.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const { users, posts } = await Parallel.run({
|
|
11
|
+
* users: () => db.query('SELECT * FROM users'),
|
|
12
|
+
* posts: () => db.query('SELECT * FROM posts'),
|
|
13
|
+
* })
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* `Parallel.map()` provides a concurrent-limited map over arrays:
|
|
17
|
+
* ```ts
|
|
18
|
+
* const thumbnails = await Parallel.map(images, (img) => resize(img), 5)
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export class Parallel {
|
|
22
|
+
/**
|
|
23
|
+
* Run named async tasks concurrently, returning a typed record of results.
|
|
24
|
+
*/
|
|
25
|
+
static async run<T extends Record<string, () => Promise<any>>>(
|
|
26
|
+
tasks: T,
|
|
27
|
+
): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>> }> {
|
|
28
|
+
const entries = Object.entries(tasks)
|
|
29
|
+
const results = await Promise.all(entries.map(([, fn]) => fn()))
|
|
30
|
+
return Object.fromEntries(entries.map(([key], i) => [key, results[i]])) as any
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Map over items concurrently with an optional concurrency limit.
|
|
35
|
+
*
|
|
36
|
+
* @param items - Array of items to process
|
|
37
|
+
* @param fn - Async function to apply to each item
|
|
38
|
+
* @param concurrency - Maximum number of concurrent tasks (default: Infinity)
|
|
39
|
+
*/
|
|
40
|
+
static async map<T, R>(
|
|
41
|
+
items: T[],
|
|
42
|
+
fn: (item: T, index: number) => Promise<R>,
|
|
43
|
+
concurrency = Infinity,
|
|
44
|
+
): Promise<R[]> {
|
|
45
|
+
if (items.length === 0) return []
|
|
46
|
+
|
|
47
|
+
if (concurrency >= items.length) {
|
|
48
|
+
return Promise.all(items.map((item, index) => fn(item, index)))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const results: R[] = new Array(items.length)
|
|
52
|
+
let nextIndex = 0
|
|
53
|
+
|
|
54
|
+
async function runNext(): Promise<void> {
|
|
55
|
+
while (nextIndex < items.length) {
|
|
56
|
+
const idx = nextIndex++
|
|
57
|
+
results[idx] = await fn(items[idx]!, idx)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const workers = Array.from(
|
|
62
|
+
{ length: Math.min(concurrency, items.length) },
|
|
63
|
+
() => runNext(),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
await Promise.all(workers)
|
|
67
|
+
return results
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,9 @@ export type { HttpResponse, HttpError, HttpMiddleware, RetryConfig } from './Htt
|
|
|
19
19
|
export { HttpFake } from './HttpFake.ts'
|
|
20
20
|
export type { StubResponse, StubHandler } from './HttpFake.ts'
|
|
21
21
|
|
|
22
|
+
// ── Async (class-based) ─────────────────────────────────────────
|
|
23
|
+
export { Parallel } from './async/Parallel.ts'
|
|
24
|
+
|
|
22
25
|
// ── Async utilities ──────────────────────────────────────────────
|
|
23
26
|
export {
|
|
24
27
|
parseDuration,
|