@mondaydotcomorg/atp-compiler
Version:
Production-ready compiler for transforming async iteration patterns into resumable operations with checkpoint-based state management
106 lines • 3.69 kB
JavaScript
/**
* Example Plugin: Async Timeout Wrapper
*
* Automatically wraps await expressions with timeout protection
*
* @example
* // Before:
* const result = await fetch('https://api.example.com');
*
* // After:
* const result = await Promise.race([
* fetch('https://api.example.com'),
* new Promise((_, reject) =>
* setTimeout(() => reject(new Error('Timeout')), 5000)
* )
* ]);
*/
import * as t from '@babel/types';
export class AsyncTimeoutPlugin {
name = 'async-timeout';
version = '1.0.0';
priority = 40; // Run after main transformations
options;
transformCount = 0;
constructor(options = {}) {
this.options = {
timeout: options.timeout || 5000,
patterns: options.patterns || ['fetch', 'axios.*', 'http.*'],
wrapAll: options.wrapAll || false,
};
}
getVisitor(config) {
return {
AwaitExpression: (path) => {
// Check if should wrap this await
if (!this.shouldWrap(path.node.argument)) {
return;
}
// Create timeout promise
const timeoutPromise = t.newExpression(t.identifier('Promise'), [
t.arrowFunctionExpression([t.identifier('_'), t.identifier('reject')], t.blockStatement([
t.expressionStatement(t.callExpression(t.identifier('setTimeout'), [
t.arrowFunctionExpression([], t.callExpression(t.identifier('reject'), [
t.newExpression(t.identifier('Error'), [
t.stringLiteral(`Timeout after ${this.options.timeout}ms`),
]),
])),
t.numericLiteral(this.options.timeout),
])),
])),
]);
// Wrap in Promise.race
const raceCall = t.callExpression(t.memberExpression(t.identifier('Promise'), t.identifier('race')), [t.arrayExpression([path.node.argument, timeoutPromise])]);
// Replace await expression
path.node.argument = raceCall;
this.transformCount++;
},
};
}
getMetadata() {
return {
// Custom metadata
loopCount: 0,
arrayMethodCount: 0,
parallelCallCount: this.transformCount,
batchableCount: 0,
};
}
reset() {
this.transformCount = 0;
}
/**
* Check if this await should be wrapped with timeout
*/
shouldWrap(node) {
if (this.options.wrapAll) {
return true;
}
// Check if matches patterns
if (t.isCallExpression(node)) {
const funcName = this.getFunctionName(node);
if (funcName) {
return this.options.patterns.some((pattern) => {
const regex = new RegExp(pattern.replace('*', '.*'));
return regex.test(funcName);
});
}
}
return false;
}
/**
* Get function name from call expression
*/
getFunctionName(node) {
if (t.isIdentifier(node.callee)) {
return node.callee.name;
}
if (t.isMemberExpression(node.callee)) {
const obj = t.isIdentifier(node.callee.object) ? node.callee.object.name : '';
const prop = t.isIdentifier(node.callee.property) ? node.callee.property.name : '';
return `${obj}.${prop}`;
}
return null;
}
}
//# sourceMappingURL=timeout-plugin.js.map