UNPKG

@mondaydotcomorg/atp-compiler

Version:

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

149 lines 5.74 kB
import { parse } from '@babel/parser'; import _traverse from '@babel/traverse'; const traverse = _traverse.default || _traverse; import _generate from '@babel/generator'; const generate = _generate.default || _generate; import * as t from '@babel/types'; import { AsyncIterationDetector } from './detector.js'; import { LoopTransformer } from './loop-transformer.js'; import { ArrayTransformer } from './array-transformer.js'; import { PromiseTransformer } from './promise-transformer.js'; import { DEFAULT_COMPILER_CONFIG } from '../types.js'; import { TransformationError } from '../runtime/errors.js'; import { resetIdCounter } from '../runtime/context.js'; /** * ATP Compiler - Standard compiler for transforming code to support resumability * Implements ICompiler interface for consistency and dependency injection support */ export class ATPCompiler { config; detector; loopTransformer; arrayTransformer; promiseTransformer; constructor(config = {}) { this.config = { ...DEFAULT_COMPILER_CONFIG, ...config }; this.detector = new AsyncIterationDetector(); this.loopTransformer = new LoopTransformer(this.config.batchSizeThreshold); this.arrayTransformer = new ArrayTransformer(this.config.batchSizeThreshold); this.promiseTransformer = new PromiseTransformer(this.config.enableBatchParallel); } detect(code) { return this.detector.detect(code); } transform(code) { resetIdCounter(); const detection = this.detector.detect(code); if (!detection.needsTransform) { return { code, transformed: false, patterns: [], metadata: { loopCount: 0, arrayMethodCount: 0, parallelCallCount: 0, batchableCount: 0, }, }; } try { const ast = parse(code, { sourceType: 'module', plugins: ['typescript'], allowAwaitOutsideFunction: true, allowReturnOutsideFunction: true, }); this.loopTransformer.resetTransformCount(); this.arrayTransformer.resetTransformCount(); this.promiseTransformer.resetTransformCount(); traverse(ast, { ForOfStatement: (path) => { this.loopTransformer.transformForOfLoop(path); }, WhileStatement: (path) => { this.loopTransformer.transformWhileLoop(path); }, ForStatement: (path) => { this.loopTransformer.transformForLoop(path); }, CallExpression: (path) => { if (this.isArrayMethodCall(path.node)) { this.arrayTransformer.transformArrayMethod(path); } else if (this.isPromiseAllCall(path.node)) { this.promiseTransformer.transformPromiseAll(path); } else if (this.isPromiseAllSettledCall(path.node)) { this.promiseTransformer.transformPromiseAllSettled(path); } }, }); const output = generate(ast, { sourceMaps: false, retainLines: true, comments: true, }); const metadata = { loopCount: this.loopTransformer.getTransformCount(), arrayMethodCount: this.arrayTransformer.getTransformCount(), parallelCallCount: this.promiseTransformer.getTransformCount(), batchableCount: detection.batchableParallel ? 1 : 0, }; return { code: output.code, transformed: true, patterns: detection.patterns, metadata, }; } catch (error) { const message = error instanceof Error ? error.message : String(error); throw new TransformationError(message, code, 'unknown'); } } isArrayMethodCall(node) { if (!t.isMemberExpression(node.callee)) { return false; } const property = node.callee.property; if (!t.isIdentifier(property)) { return false; } const arrayMethods = ['map', 'forEach', 'filter', 'reduce', 'find', 'some', 'every', 'flatMap']; return arrayMethods.includes(property.name); } isPromiseAllCall(node) { const callee = node.callee; return (t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: 'Promise' }) && t.isIdentifier(callee.property, { name: 'all' })); } isPromiseAllSettledCall(node) { const callee = node.callee; return (t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: 'Promise' }) && t.isIdentifier(callee.property, { name: 'allSettled' })); } /** * Get the compiler type identifier (ICompiler interface requirement) */ getType() { return 'ATPCompiler'; } /** * Get cache statistics (ICompiler interface requirement) * ATPCompiler doesn't cache ASTs, so returns null */ getCacheStats() { return null; } } export * from './detector.js'; export * from './batch-detector.js'; export * from './batch-optimizer.js'; export * from './loop-transformer.js'; export * from './array-transformer.js'; export * from './promise-transformer.js'; export * from './utils.js'; //# sourceMappingURL=index.js.map