@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
JavaScript
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