UNPKG

@mondaydotcomorg/atp-compiler

Version:

Production-ready compiler for transforming async iteration patterns into resumable operations with checkpoint-based state management

131 lines 4.01 kB
import * as t from '@babel/types'; import { isPausableCallExpression, getMemberExpressionPath } from './utils.js'; export class BatchParallelDetector { canBatch(promiseAllNode) { const arrayArg = promiseAllNode.arguments[0]; if (!t.isArrayExpression(arrayArg)) { return false; } if (arrayArg.elements.length === 0) { return false; } return arrayArg.elements.every((el) => { if (!el || t.isSpreadElement(el)) { return false; } return this.isDirectPausableCall(el); }); } isDirectPausableCall(node) { if (t.isAwaitExpression(node)) { node = node.argument; } if (!t.isCallExpression(node)) { return false; } return isPausableCallExpression(node); } extractBatchCalls(arrayNode) { const calls = []; for (const el of arrayNode.elements) { if (!el || t.isSpreadElement(el)) { continue; } let callNode = el; if (t.isAwaitExpression(callNode)) { callNode = callNode.argument; } if (!t.isCallExpression(callNode)) { continue; } const callInfo = this.extractCallInfo(callNode); if (callInfo) { calls.push(callInfo); } } return calls; } extractCallInfo(callNode) { if (!t.isMemberExpression(callNode.callee)) { return null; } const path = getMemberExpressionPath(callNode.callee); const parts = path.split('.'); if (parts.length < 3) { return null; } const [namespace, service, method] = parts; if (namespace !== 'atp' || !method) { return null; } const type = service; const payload = this.extractPayload(callNode.arguments); return { type, operation: method, payload, }; } /** * Extract payload AST node directly */ extractPayloadNode(callNode) { if (callNode.arguments.length === 0) { return t.objectExpression([]); } const firstArg = callNode.arguments[0]; if (!firstArg || t.isSpreadElement(firstArg) || !t.isExpression(firstArg)) { return null; } return firstArg; } extractPayload(args) { if (args.length === 0) { return {}; } const firstArg = args[0]; if (t.isSpreadElement(firstArg)) { return {}; } if (t.isObjectExpression(firstArg)) { return this.objectExpressionToRecord(firstArg); } if (t.isStringLiteral(firstArg)) { return { message: firstArg.value }; } return {}; } objectExpressionToRecord(obj) { const record = {}; for (const prop of obj.properties) { if (t.isObjectProperty(prop) && !prop.computed) { const key = t.isIdentifier(prop.key) ? prop.key.name : String(prop.key); const value = this.extractValue(prop.value); record[key] = value; } } return record; } extractValue(node) { if (t.isStringLiteral(node)) { return node.value; } if (t.isNumericLiteral(node)) { return node.value; } if (t.isBooleanLiteral(node)) { return node.value; } if (t.isNullLiteral(node)) { return null; } if (t.isArrayExpression(node)) { return node.elements.map((el) => el && !t.isSpreadElement(el) ? this.extractValue(el) : null); } if (t.isObjectExpression(node)) { return this.objectExpressionToRecord(node); } return undefined; } } //# sourceMappingURL=batch-detector.js.map