UNPKG

@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
/** * 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