@mondaydotcomorg/atp-compiler 0.17.14
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/README.md +382 -0
- package/__tests__/integration/all-array-methods-native.test.ts +321 -0
- package/__tests__/integration/all-callback-types.test.ts +406 -0
- package/__tests__/integration/comprehensive-edge-cases.test.ts +701 -0
- package/__tests__/integration/native-behavior-verification.test.ts +340 -0
- package/__tests__/integration/semantic-correctness.test.ts +354 -0
- package/__tests__/integration/threshold-tests.test.ts +529 -0
- package/__tests__/unit/batch-optimizer.test.ts +253 -0
- package/__tests__/unit/checkpoint-manager.test.ts +145 -0
- package/__tests__/unit/detector.test.ts +346 -0
- package/dist/atp-compiler/src/index.d.ts +6 -0
- package/dist/atp-compiler/src/index.d.ts.map +1 -0
- package/dist/atp-compiler/src/index.js +6 -0
- package/dist/atp-compiler/src/index.js.map +1 -0
- package/dist/atp-compiler/src/runtime/batch-parallel.d.ts +3 -0
- package/dist/atp-compiler/src/runtime/batch-parallel.d.ts.map +1 -0
- package/dist/atp-compiler/src/runtime/batch-parallel.js +13 -0
- package/dist/atp-compiler/src/runtime/batch-parallel.js.map +1 -0
- package/dist/atp-compiler/src/runtime/checkpoint-manager.d.ts +19 -0
- package/dist/atp-compiler/src/runtime/checkpoint-manager.d.ts.map +1 -0
- package/dist/atp-compiler/src/runtime/checkpoint-manager.js +81 -0
- package/dist/atp-compiler/src/runtime/checkpoint-manager.js.map +1 -0
- package/dist/atp-compiler/src/runtime/context.d.ts +8 -0
- package/dist/atp-compiler/src/runtime/context.d.ts.map +1 -0
- package/dist/atp-compiler/src/runtime/context.js +25 -0
- package/dist/atp-compiler/src/runtime/context.js.map +1 -0
- package/dist/atp-compiler/src/runtime/errors.d.ts +38 -0
- package/dist/atp-compiler/src/runtime/errors.d.ts.map +1 -0
- package/dist/atp-compiler/src/runtime/errors.js +61 -0
- package/dist/atp-compiler/src/runtime/errors.js.map +1 -0
- package/dist/atp-compiler/src/runtime/index.d.ts +16 -0
- package/dist/atp-compiler/src/runtime/index.d.ts.map +1 -0
- package/dist/atp-compiler/src/runtime/index.js +20 -0
- package/dist/atp-compiler/src/runtime/index.js.map +1 -0
- package/dist/atp-compiler/src/runtime/resumable-arrays.d.ts +9 -0
- package/dist/atp-compiler/src/runtime/resumable-arrays.d.ts.map +1 -0
- package/dist/atp-compiler/src/runtime/resumable-arrays.js +179 -0
- package/dist/atp-compiler/src/runtime/resumable-arrays.js.map +1 -0
- package/dist/atp-compiler/src/runtime/resumable-loops.d.ts +4 -0
- package/dist/atp-compiler/src/runtime/resumable-loops.d.ts.map +1 -0
- package/dist/atp-compiler/src/runtime/resumable-loops.js +61 -0
- package/dist/atp-compiler/src/runtime/resumable-loops.js.map +1 -0
- package/dist/atp-compiler/src/runtime/resumable-parallel.d.ts +3 -0
- package/dist/atp-compiler/src/runtime/resumable-parallel.d.ts.map +1 -0
- package/dist/atp-compiler/src/runtime/resumable-parallel.js +44 -0
- package/dist/atp-compiler/src/runtime/resumable-parallel.js.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-batch.d.ts +13 -0
- package/dist/atp-compiler/src/transformer/array-transformer-batch.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-batch.js +55 -0
- package/dist/atp-compiler/src/transformer/array-transformer-batch.js.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-sequential.d.ts +6 -0
- package/dist/atp-compiler/src/transformer/array-transformer-sequential.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-sequential.js +23 -0
- package/dist/atp-compiler/src/transformer/array-transformer-sequential.js.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-utils.d.ts +18 -0
- package/dist/atp-compiler/src/transformer/array-transformer-utils.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-utils.js +69 -0
- package/dist/atp-compiler/src/transformer/array-transformer-utils.js.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-wrappers.d.ts +26 -0
- package/dist/atp-compiler/src/transformer/array-transformer-wrappers.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer-wrappers.js +88 -0
- package/dist/atp-compiler/src/transformer/array-transformer-wrappers.js.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer.d.ts +12 -0
- package/dist/atp-compiler/src/transformer/array-transformer.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/array-transformer.js +47 -0
- package/dist/atp-compiler/src/transformer/array-transformer.js.map +1 -0
- package/dist/atp-compiler/src/transformer/batch-detector.d.ts +16 -0
- package/dist/atp-compiler/src/transformer/batch-detector.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/batch-detector.js +131 -0
- package/dist/atp-compiler/src/transformer/batch-detector.js.map +1 -0
- package/dist/atp-compiler/src/transformer/batch-optimizer.d.ts +27 -0
- package/dist/atp-compiler/src/transformer/batch-optimizer.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/batch-optimizer.js +244 -0
- package/dist/atp-compiler/src/transformer/batch-optimizer.js.map +1 -0
- package/dist/atp-compiler/src/transformer/detector.d.ts +9 -0
- package/dist/atp-compiler/src/transformer/detector.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/detector.js +141 -0
- package/dist/atp-compiler/src/transformer/detector.js.map +1 -0
- package/dist/atp-compiler/src/transformer/index.d.ts +22 -0
- package/dist/atp-compiler/src/transformer/index.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/index.js +132 -0
- package/dist/atp-compiler/src/transformer/index.js.map +1 -0
- package/dist/atp-compiler/src/transformer/loop-transformer.d.ts +25 -0
- package/dist/atp-compiler/src/transformer/loop-transformer.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/loop-transformer.js +193 -0
- package/dist/atp-compiler/src/transformer/loop-transformer.js.map +1 -0
- package/dist/atp-compiler/src/transformer/promise-transformer.d.ts +17 -0
- package/dist/atp-compiler/src/transformer/promise-transformer.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/promise-transformer.js +132 -0
- package/dist/atp-compiler/src/transformer/promise-transformer.js.map +1 -0
- package/dist/atp-compiler/src/transformer/utils.d.ts +15 -0
- package/dist/atp-compiler/src/transformer/utils.d.ts.map +1 -0
- package/dist/atp-compiler/src/transformer/utils.js +118 -0
- package/dist/atp-compiler/src/transformer/utils.js.map +1 -0
- package/dist/atp-compiler/src/types.d.ts +57 -0
- package/dist/atp-compiler/src/types.d.ts.map +1 -0
- package/dist/atp-compiler/src/types.js +23 -0
- package/dist/atp-compiler/src/types.js.map +1 -0
- package/dist/protocol/src/auth.d.ts +173 -0
- package/dist/protocol/src/auth.d.ts.map +1 -0
- package/dist/protocol/src/auth.js +202 -0
- package/dist/protocol/src/auth.js.map +1 -0
- package/dist/protocol/src/index.d.ts +7 -0
- package/dist/protocol/src/index.d.ts.map +1 -0
- package/dist/protocol/src/index.js +7 -0
- package/dist/protocol/src/index.js.map +1 -0
- package/dist/protocol/src/oauth.d.ts +63 -0
- package/dist/protocol/src/oauth.d.ts.map +1 -0
- package/dist/protocol/src/oauth.js +5 -0
- package/dist/protocol/src/oauth.js.map +1 -0
- package/dist/protocol/src/providers.d.ts +167 -0
- package/dist/protocol/src/providers.d.ts.map +1 -0
- package/dist/protocol/src/providers.js +33 -0
- package/dist/protocol/src/providers.js.map +1 -0
- package/dist/protocol/src/schemas.d.ts +6 -0
- package/dist/protocol/src/schemas.d.ts.map +1 -0
- package/dist/protocol/src/schemas.js +51 -0
- package/dist/protocol/src/schemas.js.map +1 -0
- package/dist/protocol/src/types.d.ts +489 -0
- package/dist/protocol/src/types.d.ts.map +1 -0
- package/dist/protocol/src/types.js +88 -0
- package/dist/protocol/src/types.js.map +1 -0
- package/dist/protocol/src/validation.d.ts +76 -0
- package/dist/protocol/src/validation.d.ts.map +1 -0
- package/dist/protocol/src/validation.js +129 -0
- package/dist/protocol/src/validation.js.map +1 -0
- package/dist/provenance/src/ast/instrumentor.d.ts +37 -0
- package/dist/provenance/src/ast/instrumentor.d.ts.map +1 -0
- package/dist/provenance/src/ast/instrumentor.js +299 -0
- package/dist/provenance/src/ast/instrumentor.js.map +1 -0
- package/dist/provenance/src/index.d.ts +7 -0
- package/dist/provenance/src/index.d.ts.map +1 -0
- package/dist/provenance/src/index.js +7 -0
- package/dist/provenance/src/index.js.map +1 -0
- package/dist/provenance/src/policies/engine.d.ts +71 -0
- package/dist/provenance/src/policies/engine.d.ts.map +1 -0
- package/dist/provenance/src/policies/engine.js +433 -0
- package/dist/provenance/src/policies/engine.js.map +1 -0
- package/dist/provenance/src/registry.d.ts +94 -0
- package/dist/provenance/src/registry.d.ts.map +1 -0
- package/dist/provenance/src/registry.js +445 -0
- package/dist/provenance/src/registry.js.map +1 -0
- package/dist/provenance/src/tokens.d.ts +49 -0
- package/dist/provenance/src/tokens.d.ts.map +1 -0
- package/dist/provenance/src/tokens.js +239 -0
- package/dist/provenance/src/tokens.js.map +1 -0
- package/dist/provenance/src/types.d.ts +150 -0
- package/dist/provenance/src/types.d.ts.map +1 -0
- package/dist/provenance/src/types.js +47 -0
- package/dist/provenance/src/types.js.map +1 -0
- package/dist/runtime/src/approval/handler.d.ts +12 -0
- package/dist/runtime/src/approval/handler.d.ts.map +1 -0
- package/dist/runtime/src/approval/handler.js +17 -0
- package/dist/runtime/src/approval/handler.js.map +1 -0
- package/dist/runtime/src/approval/index.d.ts +17 -0
- package/dist/runtime/src/approval/index.d.ts.map +1 -0
- package/dist/runtime/src/approval/index.js +94 -0
- package/dist/runtime/src/approval/index.js.map +1 -0
- package/dist/runtime/src/approval/types.d.ts +21 -0
- package/dist/runtime/src/approval/types.d.ts.map +1 -0
- package/dist/runtime/src/approval/types.js +5 -0
- package/dist/runtime/src/approval/types.js.map +1 -0
- package/dist/runtime/src/cache/backends.d.ts +39 -0
- package/dist/runtime/src/cache/backends.d.ts.map +1 -0
- package/dist/runtime/src/cache/backends.js +167 -0
- package/dist/runtime/src/cache/backends.js.map +1 -0
- package/dist/runtime/src/cache/index.d.ts +32 -0
- package/dist/runtime/src/cache/index.d.ts.map +1 -0
- package/dist/runtime/src/cache/index.js +103 -0
- package/dist/runtime/src/cache/index.js.map +1 -0
- package/dist/runtime/src/cache/types.d.ts +20 -0
- package/dist/runtime/src/cache/types.d.ts.map +1 -0
- package/dist/runtime/src/cache/types.js +2 -0
- package/dist/runtime/src/cache/types.js.map +1 -0
- package/dist/runtime/src/embedding/index.d.ts +39 -0
- package/dist/runtime/src/embedding/index.d.ts.map +1 -0
- package/dist/runtime/src/embedding/index.js +162 -0
- package/dist/runtime/src/embedding/index.js.map +1 -0
- package/dist/runtime/src/embedding/types.d.ts +28 -0
- package/dist/runtime/src/embedding/types.d.ts.map +1 -0
- package/dist/runtime/src/embedding/types.js +5 -0
- package/dist/runtime/src/embedding/types.js.map +1 -0
- package/dist/runtime/src/embedding/utils.d.ts +11 -0
- package/dist/runtime/src/embedding/utils.d.ts.map +1 -0
- package/dist/runtime/src/embedding/utils.js +30 -0
- package/dist/runtime/src/embedding/utils.js.map +1 -0
- package/dist/runtime/src/embedding/vector-store.d.ts +64 -0
- package/dist/runtime/src/embedding/vector-store.d.ts.map +1 -0
- package/dist/runtime/src/embedding/vector-store.js +142 -0
- package/dist/runtime/src/embedding/vector-store.js.map +1 -0
- package/dist/runtime/src/index.d.ts +18 -0
- package/dist/runtime/src/index.d.ts.map +1 -0
- package/dist/runtime/src/index.js +17 -0
- package/dist/runtime/src/index.js.map +1 -0
- package/dist/runtime/src/llm/callback.d.ts +13 -0
- package/dist/runtime/src/llm/callback.d.ts.map +1 -0
- package/dist/runtime/src/llm/callback.js +19 -0
- package/dist/runtime/src/llm/callback.js.map +1 -0
- package/dist/runtime/src/llm/index.d.ts +29 -0
- package/dist/runtime/src/llm/index.d.ts.map +1 -0
- package/dist/runtime/src/llm/index.js +118 -0
- package/dist/runtime/src/llm/index.js.map +1 -0
- package/dist/runtime/src/llm/replay.d.ts +47 -0
- package/dist/runtime/src/llm/replay.d.ts.map +1 -0
- package/dist/runtime/src/llm/replay.js +114 -0
- package/dist/runtime/src/llm/replay.js.map +1 -0
- package/dist/runtime/src/llm/types.d.ts +24 -0
- package/dist/runtime/src/llm/types.d.ts.map +1 -0
- package/dist/runtime/src/llm/types.js +2 -0
- package/dist/runtime/src/llm/types.js.map +1 -0
- package/dist/runtime/src/log/index.d.ts +12 -0
- package/dist/runtime/src/log/index.d.ts.map +1 -0
- package/dist/runtime/src/log/index.js +166 -0
- package/dist/runtime/src/log/index.js.map +1 -0
- package/dist/runtime/src/log/types.d.ts +19 -0
- package/dist/runtime/src/log/types.d.ts.map +1 -0
- package/dist/runtime/src/log/types.js +5 -0
- package/dist/runtime/src/log/types.js.map +1 -0
- package/dist/runtime/src/metadata/decorators.d.ts +27 -0
- package/dist/runtime/src/metadata/decorators.d.ts.map +1 -0
- package/dist/runtime/src/metadata/decorators.js +38 -0
- package/dist/runtime/src/metadata/decorators.js.map +1 -0
- package/dist/runtime/src/metadata/generated.d.ts +18 -0
- package/dist/runtime/src/metadata/generated.d.ts.map +1 -0
- package/dist/runtime/src/metadata/generated.js +290 -0
- package/dist/runtime/src/metadata/generated.js.map +1 -0
- package/dist/runtime/src/metadata/index.d.ts +11 -0
- package/dist/runtime/src/metadata/index.d.ts.map +1 -0
- package/dist/runtime/src/metadata/index.js +45 -0
- package/dist/runtime/src/metadata/index.js.map +1 -0
- package/dist/runtime/src/metadata/types.d.ts +22 -0
- package/dist/runtime/src/metadata/types.d.ts.map +1 -0
- package/dist/runtime/src/metadata/types.js +6 -0
- package/dist/runtime/src/metadata/types.js.map +1 -0
- package/dist/runtime/src/pause/index.d.ts +11 -0
- package/dist/runtime/src/pause/index.d.ts.map +1 -0
- package/dist/runtime/src/pause/index.js +15 -0
- package/dist/runtime/src/pause/index.js.map +1 -0
- package/dist/runtime/src/pause/types.d.ts +46 -0
- package/dist/runtime/src/pause/types.d.ts.map +1 -0
- package/dist/runtime/src/pause/types.js +57 -0
- package/dist/runtime/src/pause/types.js.map +1 -0
- package/dist/runtime/src/progress/index.d.ts +19 -0
- package/dist/runtime/src/progress/index.d.ts.map +1 -0
- package/dist/runtime/src/progress/index.js +61 -0
- package/dist/runtime/src/progress/index.js.map +1 -0
- package/dist/runtime/src/progress/types.d.ts +7 -0
- package/dist/runtime/src/progress/types.d.ts.map +1 -0
- package/dist/runtime/src/progress/types.js +2 -0
- package/dist/runtime/src/progress/types.js.map +1 -0
- package/dist/runtime/src/registry.d.ts +16 -0
- package/dist/runtime/src/registry.d.ts.map +1 -0
- package/dist/runtime/src/registry.js +16 -0
- package/dist/runtime/src/registry.js.map +1 -0
- package/dist/runtime/src/utils.d.ts +11 -0
- package/dist/runtime/src/utils.d.ts.map +1 -0
- package/dist/runtime/src/utils.js +31 -0
- package/dist/runtime/src/utils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/jest.config.js +29 -0
- package/package.json +56 -0
- package/project.json +31 -0
- package/src/index.ts +6 -0
- package/src/runtime/batch-parallel.ts +22 -0
- package/src/runtime/checkpoint-manager.ts +105 -0
- package/src/runtime/context.ts +33 -0
- package/src/runtime/errors.ts +79 -0
- package/src/runtime/index.ts +35 -0
- package/src/runtime/resumable-arrays.ts +253 -0
- package/src/runtime/resumable-loops.ts +93 -0
- package/src/runtime/resumable-parallel.ts +57 -0
- package/src/transformer/array-transformer-batch.ts +86 -0
- package/src/transformer/array-transformer-sequential.ts +38 -0
- package/src/transformer/array-transformer-utils.ts +80 -0
- package/src/transformer/array-transformer-wrappers.ts +165 -0
- package/src/transformer/array-transformer.ts +76 -0
- package/src/transformer/batch-detector.ts +166 -0
- package/src/transformer/batch-optimizer.ts +320 -0
- package/src/transformer/detector.ts +171 -0
- package/src/transformer/index.ts +155 -0
- package/src/transformer/loop-transformer.ts +285 -0
- package/src/transformer/promise-transformer.ts +194 -0
- package/src/transformer/utils.ts +147 -0
- package/src/types.ts +101 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { getCheckpointManager } from './checkpoint-manager.js';
|
|
2
|
+
import type { LoopCheckpoint } from '../types.js';
|
|
3
|
+
import { InfiniteLoopDetectionError } from './errors.js';
|
|
4
|
+
|
|
5
|
+
const MAX_ITERATIONS = 1000000;
|
|
6
|
+
|
|
7
|
+
export async function resumableMap<T, R>(
|
|
8
|
+
items: T[],
|
|
9
|
+
callback: (item: T, index: number, array: T[]) => Promise<R>,
|
|
10
|
+
mapId: string
|
|
11
|
+
): Promise<R[]> {
|
|
12
|
+
const checkpointManager = getCheckpointManager();
|
|
13
|
+
const checkpoint = await checkpointManager.load(mapId);
|
|
14
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
15
|
+
const results = (checkpoint?.results as R[]) || [];
|
|
16
|
+
|
|
17
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
18
|
+
if (i > MAX_ITERATIONS) {
|
|
19
|
+
throw new InfiniteLoopDetectionError(mapId, i);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
results[i] = await callback(items[i]!, i, items);
|
|
23
|
+
|
|
24
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
25
|
+
loopId: mapId,
|
|
26
|
+
currentIndex: i + 1,
|
|
27
|
+
results: results,
|
|
28
|
+
timestamp: Date.now(),
|
|
29
|
+
};
|
|
30
|
+
await checkpointManager.save(newCheckpoint);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await checkpointManager.clear(mapId);
|
|
34
|
+
return results;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function resumableForEach<T>(
|
|
38
|
+
items: T[],
|
|
39
|
+
callback: (item: T, index: number, array: T[]) => Promise<void>,
|
|
40
|
+
forEachId: string
|
|
41
|
+
): Promise<void> {
|
|
42
|
+
const checkpointManager = getCheckpointManager();
|
|
43
|
+
const checkpoint = await checkpointManager.load(forEachId);
|
|
44
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
45
|
+
|
|
46
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
47
|
+
if (i > MAX_ITERATIONS) {
|
|
48
|
+
throw new InfiniteLoopDetectionError(forEachId, i);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
await callback(items[i]!, i, items);
|
|
52
|
+
|
|
53
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
54
|
+
loopId: forEachId,
|
|
55
|
+
currentIndex: i + 1,
|
|
56
|
+
timestamp: Date.now(),
|
|
57
|
+
};
|
|
58
|
+
await checkpointManager.save(newCheckpoint);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
await checkpointManager.clear(forEachId);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function resumableFilter<T>(
|
|
65
|
+
items: T[],
|
|
66
|
+
callback: (item: T, index: number, array: T[]) => Promise<boolean>,
|
|
67
|
+
filterId: string
|
|
68
|
+
): Promise<T[]> {
|
|
69
|
+
const checkpointManager = getCheckpointManager();
|
|
70
|
+
const checkpoint = await checkpointManager.load(filterId);
|
|
71
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
72
|
+
const results = (checkpoint?.results as T[]) || [];
|
|
73
|
+
|
|
74
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
75
|
+
if (i > MAX_ITERATIONS) {
|
|
76
|
+
throw new InfiniteLoopDetectionError(filterId, i);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const passed = await callback(items[i]!, i, items);
|
|
80
|
+
if (passed) {
|
|
81
|
+
results.push(items[i]!);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
85
|
+
loopId: filterId,
|
|
86
|
+
currentIndex: i + 1,
|
|
87
|
+
results: results,
|
|
88
|
+
timestamp: Date.now(),
|
|
89
|
+
};
|
|
90
|
+
await checkpointManager.save(newCheckpoint);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
await checkpointManager.clear(filterId);
|
|
94
|
+
return results;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function resumableReduce<T, R>(
|
|
98
|
+
items: T[],
|
|
99
|
+
callback: (accumulator: R, item: T, index: number, array: T[]) => Promise<R>,
|
|
100
|
+
initialValue: R,
|
|
101
|
+
reduceId: string
|
|
102
|
+
): Promise<R> {
|
|
103
|
+
const checkpointManager = getCheckpointManager();
|
|
104
|
+
const checkpoint = await checkpointManager.load(reduceId);
|
|
105
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
106
|
+
let accumulator = (checkpoint?.accumulator as R) ?? initialValue;
|
|
107
|
+
|
|
108
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
109
|
+
if (i > MAX_ITERATIONS) {
|
|
110
|
+
throw new InfiniteLoopDetectionError(reduceId, i);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
accumulator = await callback(accumulator, items[i]!, i, items);
|
|
114
|
+
|
|
115
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
116
|
+
loopId: reduceId,
|
|
117
|
+
currentIndex: i + 1,
|
|
118
|
+
accumulator: accumulator,
|
|
119
|
+
timestamp: Date.now(),
|
|
120
|
+
};
|
|
121
|
+
await checkpointManager.save(newCheckpoint);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
await checkpointManager.clear(reduceId);
|
|
125
|
+
return accumulator;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export async function resumableFind<T>(
|
|
129
|
+
items: T[],
|
|
130
|
+
callback: (item: T, index: number, array: T[]) => Promise<boolean>,
|
|
131
|
+
findId: string
|
|
132
|
+
): Promise<T | undefined> {
|
|
133
|
+
const checkpointManager = getCheckpointManager();
|
|
134
|
+
const checkpoint = await checkpointManager.load(findId);
|
|
135
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
136
|
+
|
|
137
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
138
|
+
if (i > MAX_ITERATIONS) {
|
|
139
|
+
throw new InfiniteLoopDetectionError(findId, i);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const found = await callback(items[i]!, i, items);
|
|
143
|
+
if (found) {
|
|
144
|
+
await checkpointManager.clear(findId);
|
|
145
|
+
return items[i];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
149
|
+
loopId: findId,
|
|
150
|
+
currentIndex: i + 1,
|
|
151
|
+
timestamp: Date.now(),
|
|
152
|
+
};
|
|
153
|
+
await checkpointManager.save(newCheckpoint);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
await checkpointManager.clear(findId);
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export async function resumableSome<T>(
|
|
161
|
+
items: T[],
|
|
162
|
+
callback: (item: T, index: number, array: T[]) => Promise<boolean>,
|
|
163
|
+
someId: string
|
|
164
|
+
): Promise<boolean> {
|
|
165
|
+
const checkpointManager = getCheckpointManager();
|
|
166
|
+
const checkpoint = await checkpointManager.load(someId);
|
|
167
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
168
|
+
|
|
169
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
170
|
+
if (i > MAX_ITERATIONS) {
|
|
171
|
+
throw new InfiniteLoopDetectionError(someId, i);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const result = await callback(items[i]!, i, items);
|
|
175
|
+
if (result) {
|
|
176
|
+
await checkpointManager.clear(someId);
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
181
|
+
loopId: someId,
|
|
182
|
+
currentIndex: i + 1,
|
|
183
|
+
timestamp: Date.now(),
|
|
184
|
+
};
|
|
185
|
+
await checkpointManager.save(newCheckpoint);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
await checkpointManager.clear(someId);
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export async function resumableEvery<T>(
|
|
193
|
+
items: T[],
|
|
194
|
+
callback: (item: T, index: number, array: T[]) => Promise<boolean>,
|
|
195
|
+
everyId: string
|
|
196
|
+
): Promise<boolean> {
|
|
197
|
+
const checkpointManager = getCheckpointManager();
|
|
198
|
+
const checkpoint = await checkpointManager.load(everyId);
|
|
199
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
200
|
+
|
|
201
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
202
|
+
if (i > MAX_ITERATIONS) {
|
|
203
|
+
throw new InfiniteLoopDetectionError(everyId, i);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const result = await callback(items[i]!, i, items);
|
|
207
|
+
if (!result) {
|
|
208
|
+
await checkpointManager.clear(everyId);
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
213
|
+
loopId: everyId,
|
|
214
|
+
currentIndex: i + 1,
|
|
215
|
+
timestamp: Date.now(),
|
|
216
|
+
};
|
|
217
|
+
await checkpointManager.save(newCheckpoint);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
await checkpointManager.clear(everyId);
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export async function resumableFlatMap<T, R>(
|
|
225
|
+
items: T[],
|
|
226
|
+
callback: (item: T, index: number, array: T[]) => Promise<R[]>,
|
|
227
|
+
flatMapId: string
|
|
228
|
+
): Promise<R[]> {
|
|
229
|
+
const checkpointManager = getCheckpointManager();
|
|
230
|
+
const checkpoint = await checkpointManager.load(flatMapId);
|
|
231
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
232
|
+
const results = (checkpoint?.results as R[]) || [];
|
|
233
|
+
|
|
234
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
235
|
+
if (i > MAX_ITERATIONS) {
|
|
236
|
+
throw new InfiniteLoopDetectionError(flatMapId, i);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const mapped = await callback(items[i]!, i, items);
|
|
240
|
+
results.push(...mapped);
|
|
241
|
+
|
|
242
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
243
|
+
loopId: flatMapId,
|
|
244
|
+
currentIndex: i + 1,
|
|
245
|
+
results: results,
|
|
246
|
+
timestamp: Date.now(),
|
|
247
|
+
};
|
|
248
|
+
await checkpointManager.save(newCheckpoint);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
await checkpointManager.clear(flatMapId);
|
|
252
|
+
return results;
|
|
253
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { getCheckpointManager } from './checkpoint-manager.js';
|
|
2
|
+
import type { LoopCheckpoint } from '../types.js';
|
|
3
|
+
import { InfiniteLoopDetectionError } from './errors.js';
|
|
4
|
+
|
|
5
|
+
const MAX_ITERATIONS = 1000000;
|
|
6
|
+
|
|
7
|
+
export async function resumableForOf<T>(
|
|
8
|
+
items: T[],
|
|
9
|
+
callback: (item: T, index: number) => Promise<void>,
|
|
10
|
+
loopId: string
|
|
11
|
+
): Promise<void> {
|
|
12
|
+
const checkpointManager = getCheckpointManager();
|
|
13
|
+
const checkpoint = await checkpointManager.load(loopId);
|
|
14
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
15
|
+
|
|
16
|
+
for (let i = startIndex; i < items.length; i++) {
|
|
17
|
+
if (i > MAX_ITERATIONS) {
|
|
18
|
+
throw new InfiniteLoopDetectionError(loopId, i);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
await callback(items[i]!, i);
|
|
22
|
+
|
|
23
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
24
|
+
loopId,
|
|
25
|
+
currentIndex: i + 1,
|
|
26
|
+
timestamp: Date.now(),
|
|
27
|
+
};
|
|
28
|
+
await checkpointManager.save(newCheckpoint);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
await checkpointManager.clear(loopId);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function resumableWhile(
|
|
35
|
+
conditionFn: () => boolean | Promise<boolean>,
|
|
36
|
+
bodyFn: (iteration: number) => Promise<void>,
|
|
37
|
+
loopId: string
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
const checkpointManager = getCheckpointManager();
|
|
40
|
+
const checkpoint = await checkpointManager.load(loopId);
|
|
41
|
+
let iteration = checkpoint?.currentIndex || 0;
|
|
42
|
+
|
|
43
|
+
while (await Promise.resolve(conditionFn())) {
|
|
44
|
+
if (iteration > MAX_ITERATIONS) {
|
|
45
|
+
throw new InfiniteLoopDetectionError(loopId, iteration);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await bodyFn(iteration);
|
|
49
|
+
|
|
50
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
51
|
+
loopId,
|
|
52
|
+
currentIndex: iteration + 1,
|
|
53
|
+
timestamp: Date.now(),
|
|
54
|
+
};
|
|
55
|
+
await checkpointManager.save(newCheckpoint);
|
|
56
|
+
|
|
57
|
+
iteration++;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
await checkpointManager.clear(loopId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function resumableForLoop(
|
|
64
|
+
initValue: number,
|
|
65
|
+
conditionFn: (i: number) => boolean,
|
|
66
|
+
incrementFn: (i: number) => number,
|
|
67
|
+
bodyFn: (i: number) => Promise<void>,
|
|
68
|
+
loopId: string
|
|
69
|
+
): Promise<void> {
|
|
70
|
+
const checkpointManager = getCheckpointManager();
|
|
71
|
+
const checkpoint = await checkpointManager.load(loopId);
|
|
72
|
+
let i = checkpoint?.currentIndex !== undefined ? checkpoint.currentIndex : initValue;
|
|
73
|
+
|
|
74
|
+
let iterations = 0;
|
|
75
|
+
while (conditionFn(i)) {
|
|
76
|
+
if (iterations++ > MAX_ITERATIONS) {
|
|
77
|
+
throw new InfiniteLoopDetectionError(loopId, iterations);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await bodyFn(i);
|
|
81
|
+
|
|
82
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
83
|
+
loopId,
|
|
84
|
+
currentIndex: incrementFn(i),
|
|
85
|
+
timestamp: Date.now(),
|
|
86
|
+
};
|
|
87
|
+
await checkpointManager.save(newCheckpoint);
|
|
88
|
+
|
|
89
|
+
i = incrementFn(i);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
await checkpointManager.clear(loopId);
|
|
93
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { getCheckpointManager } from './checkpoint-manager.js';
|
|
2
|
+
import type { LoopCheckpoint } from '../types.js';
|
|
3
|
+
|
|
4
|
+
export async function resumablePromiseAll<T>(
|
|
5
|
+
promises: Promise<T>[],
|
|
6
|
+
parallelId: string
|
|
7
|
+
): Promise<T[]> {
|
|
8
|
+
const checkpointManager = getCheckpointManager();
|
|
9
|
+
const checkpoint = await checkpointManager.load(parallelId);
|
|
10
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
11
|
+
const results = (checkpoint?.results as T[]) || [];
|
|
12
|
+
|
|
13
|
+
for (let i = startIndex; i < promises.length; i++) {
|
|
14
|
+
results[i] = (await promises[i]) as T;
|
|
15
|
+
|
|
16
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
17
|
+
loopId: parallelId,
|
|
18
|
+
currentIndex: i + 1,
|
|
19
|
+
results: results,
|
|
20
|
+
timestamp: Date.now(),
|
|
21
|
+
};
|
|
22
|
+
await checkpointManager.save(newCheckpoint);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
await checkpointManager.clear(parallelId);
|
|
26
|
+
return results;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function resumablePromiseAllSettled<T>(
|
|
30
|
+
promises: Promise<T>[],
|
|
31
|
+
parallelId: string
|
|
32
|
+
): Promise<PromiseSettledResult<T>[]> {
|
|
33
|
+
const checkpointManager = getCheckpointManager();
|
|
34
|
+
const checkpoint = await checkpointManager.load(parallelId);
|
|
35
|
+
const startIndex = checkpoint?.currentIndex || 0;
|
|
36
|
+
const results = (checkpoint?.results as PromiseSettledResult<T>[]) || [];
|
|
37
|
+
|
|
38
|
+
for (let i = startIndex; i < promises.length; i++) {
|
|
39
|
+
try {
|
|
40
|
+
const value = (await promises[i]) as T;
|
|
41
|
+
results[i] = { status: 'fulfilled', value };
|
|
42
|
+
} catch (reason) {
|
|
43
|
+
results[i] = { status: 'rejected', reason };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const newCheckpoint: LoopCheckpoint = {
|
|
47
|
+
loopId: parallelId,
|
|
48
|
+
currentIndex: i + 1,
|
|
49
|
+
results: results,
|
|
50
|
+
timestamp: Date.now(),
|
|
51
|
+
};
|
|
52
|
+
await checkpointManager.save(newCheckpoint);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
await checkpointManager.clear(parallelId);
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import { generateUniqueId } from '../runtime/context.js';
|
|
3
|
+
import { BatchParallelDetector } from './batch-detector.js';
|
|
4
|
+
import { findLLMCallExpression } from './array-transformer-utils.js';
|
|
5
|
+
import { wrapBatchResultIfNeeded } from './array-transformer-wrappers.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Extract batch call info from callback
|
|
9
|
+
*/
|
|
10
|
+
export function extractBatchCallInfo(
|
|
11
|
+
callback: t.Function,
|
|
12
|
+
batchDetector: BatchParallelDetector
|
|
13
|
+
): {
|
|
14
|
+
mapperFunction: t.ArrowFunctionExpression;
|
|
15
|
+
} | null {
|
|
16
|
+
const paramName = callback.params[0];
|
|
17
|
+
if (!t.isIdentifier(paramName)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const param = paramName.name;
|
|
22
|
+
|
|
23
|
+
const llmCall = findLLMCallExpression(callback.body);
|
|
24
|
+
if (!llmCall) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const callInfo = batchDetector.extractCallInfo(llmCall);
|
|
29
|
+
if (!callInfo) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const payloadNode = batchDetector.extractPayloadNode(llmCall);
|
|
34
|
+
if (!payloadNode) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const mapperFunction = t.arrowFunctionExpression(
|
|
39
|
+
[t.identifier(param)],
|
|
40
|
+
t.objectExpression([
|
|
41
|
+
t.objectProperty(t.identifier('type'), t.stringLiteral(callInfo.type)),
|
|
42
|
+
t.objectProperty(t.identifier('operation'), t.stringLiteral(callInfo.operation)),
|
|
43
|
+
t.objectProperty(t.identifier('payload'), payloadNode),
|
|
44
|
+
])
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return { mapperFunction };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Transform simple array method to batch parallel execution
|
|
52
|
+
*/
|
|
53
|
+
export function transformToBatchParallel(
|
|
54
|
+
path: any,
|
|
55
|
+
node: t.CallExpression,
|
|
56
|
+
methodName: string,
|
|
57
|
+
callback: t.Function,
|
|
58
|
+
batchDetector: BatchParallelDetector,
|
|
59
|
+
onTransform: () => void,
|
|
60
|
+
fallbackTransform: () => boolean
|
|
61
|
+
): boolean {
|
|
62
|
+
const methodId = generateUniqueId(`${methodName}_batch`);
|
|
63
|
+
const array = (node.callee as t.MemberExpression).object;
|
|
64
|
+
|
|
65
|
+
const callInfo = extractBatchCallInfo(callback, batchDetector);
|
|
66
|
+
if (!callInfo) {
|
|
67
|
+
return fallbackTransform();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const batchCallsArray = t.callExpression(t.memberExpression(array, t.identifier('map')), [
|
|
71
|
+
callInfo.mapperFunction,
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
const batchCall = t.awaitExpression(
|
|
75
|
+
t.callExpression(t.memberExpression(t.identifier('__runtime'), t.identifier('batchParallel')), [
|
|
76
|
+
batchCallsArray,
|
|
77
|
+
t.stringLiteral(methodId),
|
|
78
|
+
])
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const finalCall = wrapBatchResultIfNeeded(batchCall, methodName, array, methodId);
|
|
82
|
+
|
|
83
|
+
path.replaceWith(finalCall);
|
|
84
|
+
onTransform();
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import { generateUniqueId } from '../runtime/context.js';
|
|
3
|
+
import { getRuntimeMethodName } from './array-transformer-utils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Transform to sequential execution with checkpoints (fallback)
|
|
7
|
+
*/
|
|
8
|
+
export function transformToSequential(
|
|
9
|
+
path: any,
|
|
10
|
+
node: t.CallExpression,
|
|
11
|
+
methodName: string,
|
|
12
|
+
callback: t.Function,
|
|
13
|
+
onTransform: () => void
|
|
14
|
+
): boolean {
|
|
15
|
+
const runtimeMethod = getRuntimeMethodName(methodName);
|
|
16
|
+
if (!runtimeMethod) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const methodId = generateUniqueId(methodName);
|
|
21
|
+
const array = (node.callee as t.MemberExpression).object;
|
|
22
|
+
const args: t.Expression[] = [array, callback as t.Expression, t.stringLiteral(methodId)];
|
|
23
|
+
|
|
24
|
+
if (methodName === 'reduce' && node.arguments[1]) {
|
|
25
|
+
args.push(node.arguments[1] as t.Expression);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const runtimeCall = t.awaitExpression(
|
|
29
|
+
t.callExpression(
|
|
30
|
+
t.memberExpression(t.identifier('__runtime'), t.identifier(runtimeMethod)),
|
|
31
|
+
args
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
path.replaceWith(runtimeCall);
|
|
36
|
+
onTransform();
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Find LLM call expression in callback body
|
|
5
|
+
*/
|
|
6
|
+
export function findLLMCallExpression(
|
|
7
|
+
body: t.BlockStatement | t.Expression
|
|
8
|
+
): t.CallExpression | null {
|
|
9
|
+
let found: t.CallExpression | null = null;
|
|
10
|
+
|
|
11
|
+
const visit = (node: t.Node) => {
|
|
12
|
+
if (found) return;
|
|
13
|
+
|
|
14
|
+
if (t.isAwaitExpression(node) && t.isCallExpression(node.argument)) {
|
|
15
|
+
const call = node.argument;
|
|
16
|
+
if (t.isMemberExpression(call.callee)) {
|
|
17
|
+
found = call;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Object.keys(node).forEach((key) => {
|
|
23
|
+
const value = (node as any)[key];
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
value.forEach((item) => {
|
|
26
|
+
if (item && typeof item === 'object' && item.type) {
|
|
27
|
+
visit(item);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
} else if (value && typeof value === 'object' && value.type) {
|
|
31
|
+
visit(value);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
visit(body);
|
|
37
|
+
return found;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get array method name from call expression
|
|
42
|
+
*/
|
|
43
|
+
export function getArrayMethodName(node: t.CallExpression): string | null {
|
|
44
|
+
const arrayMethods = ['map', 'forEach', 'filter', 'reduce', 'find', 'some', 'every', 'flatMap'];
|
|
45
|
+
|
|
46
|
+
const { isArrayMethod } = require('./utils.js');
|
|
47
|
+
|
|
48
|
+
for (const method of arrayMethods) {
|
|
49
|
+
if (isArrayMethod(node, method)) {
|
|
50
|
+
return method;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get runtime method name for array method
|
|
59
|
+
*/
|
|
60
|
+
export function getRuntimeMethodName(arrayMethod: string): string | null {
|
|
61
|
+
const mapping: Record<string, string> = {
|
|
62
|
+
map: 'resumableMap',
|
|
63
|
+
forEach: 'resumableForEach',
|
|
64
|
+
filter: 'resumableFilter',
|
|
65
|
+
reduce: 'resumableReduce',
|
|
66
|
+
find: 'resumableFind',
|
|
67
|
+
some: 'resumableSome',
|
|
68
|
+
every: 'resumableEvery',
|
|
69
|
+
flatMap: 'resumableFlatMap',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return mapping[arrayMethod] || null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Check if method can use batch parallel optimization
|
|
77
|
+
*/
|
|
78
|
+
export function canUseBatchParallel(methodName: string): boolean {
|
|
79
|
+
return ['map', 'forEach', 'filter', 'find', 'some', 'every'].includes(methodName);
|
|
80
|
+
}
|