sca-tool
Version:
Universal static code analysis tool for calculating API operation costs across multiple frameworks (NestJS, Express, Fastify)
376 lines • 12.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_CONFIG = exports.FRAMEWORK_PRESETS = void 0;
exports.getFrameworkConfig = getFrameworkConfig;
exports.normalizePatterns = normalizePatterns;
exports.mergeConfigs = mergeConfigs;
exports.createConfig = createConfig;
/** Default framework presets */
exports.FRAMEWORK_PRESETS = {
nestjs: {
name: 'NestJS',
description: 'Configuration for NestJS applications with common ORMs',
config: {
operations: {
// Prisma operations
'findMany': 1,
'findUnique': 1,
'findFirst': 1,
'create': 1,
'createMany': 2,
'update': 1,
'updateMany': 2,
'upsert': 2,
'delete': 1,
'deleteMany': 2,
'count': 1,
'aggregate': 2,
'groupBy': 2,
'findRaw': 1,
'queryRaw': 1,
'executeRaw': 1,
// TypeORM operations
'find': 1,
'findOne': 1,
'findOneBy': 1,
'findAndCount': 2,
'save': 1,
'typeormInsert': 1,
'typeormUpdate': 1,
'typeormDelete': 1,
'remove': 1,
'createQueryBuilder': 1,
'getMany': 1,
'getOne': 1,
'getRawMany': 1,
'getRawOne': 1,
// Mongoose operations
'findById': 1,
'findByIdAndUpdate': 1,
'findByIdAndDelete': 1,
'findOneAndUpdate': 1,
'findOneAndDelete': 1,
'insertMany': 2,
'bulkWrite': 3,
'populate': 1,
// Supabase operations
'from': 1,
'supabaseSelect': 0, // Part of query chain, no additional cost
'supabaseInsert': 1,
'supabaseUpdate': 1,
'supabaseUpsert': 1,
'supabaseDelete': 1,
'single': 0, // Query modifier, no additional cost
'eq': 0, // Filter, no additional cost
'neq': 0,
'gt': 0,
'gte': 0,
'lt': 0,
'lte': 0,
'like': 0,
'ilike': 0,
'is': 0,
'not': 0,
'or': 0,
'and': 0,
'limit': 0,
'order': 0,
'signInWithPassword': 1,
'signUp': 1,
'signOut': 1,
'refreshSession': 1,
'updateUserById': 1,
// Generic HTTP/API calls
'httpGet': 1,
'httpPost': 1,
'httpPut': 1,
'httpPatch': 1,
'httpDelete': 1,
'request': 1,
'fetch': 1,
'axios': 1,
// Cache operations
'cacheGet': 0.5,
'cacheSet': 0.5,
'cacheDel': 0.5,
'mget': 1,
'mset': 1,
// Custom method costs (can be overridden)
'sendEmail': 0,
'sendOTPEmailFor2FA': 0,
'sendOTPEmailForResettingPassword': 0,
'generateToken': 0,
'validateToken': 1,
'hashPassword': 0,
'comparePassword': 0,
'fetchSpecificUserWithRole': 1,
'fetchUsers': 1
},
patterns: {
prisma: {
pattern: /\.(findMany|findUnique|findFirst|create|createMany|update|updateMany|upsert|delete|deleteMany|count|aggregate|groupBy|findRaw|queryRaw|executeRaw)\(/,
description: 'Prisma ORM operations'
},
typeorm: {
pattern: /\.(find|findOne|findOneBy|findAndCount|save|insert|update|delete|remove|createQueryBuilder)\(/,
description: 'TypeORM operations'
},
mongoose: {
pattern: /\.(find|findById|findOne|findOneAndUpdate|findOneAndDelete|findByIdAndUpdate|findByIdAndDelete|save|create|insertMany|updateOne|updateMany|deleteOne|deleteMany|bulkWrite|populate)\(/,
description: 'Mongoose ODM operations'
},
supabase: {
pattern: /(SupabaseService\.supabase|supabase)\.(from\(|auth\.|storage\.)/,
description: 'Supabase operations'
},
supabase_query: {
pattern: /\.(select|insert|update|upsert|delete)\(/,
description: 'Supabase query operations'
},
supabase_auth: {
pattern: /\.(signInWithPassword|signUp|signOut|refreshSession|updateUserById)\(/,
description: 'Supabase auth operations'
},
supabase_filters: {
pattern: /\.(eq|neq|gt|gte|lt|lte|like|ilike|in|is|not|or|and|single|limit|order)\(/,
description: 'Supabase filter operations',
defaultCost: 0
},
http_client: {
pattern: /\.(get|post|put|patch|delete|request)\(|fetch\(|axios\./,
description: 'HTTP client operations'
},
cache: {
pattern: /\.(get|set|del|mget|mset|hget|hset|zadd|zrem)\(/,
description: 'Cache operations (Redis, etc.)'
},
custom_service: {
pattern: /(await )?this\.([\w]+Service|[\w]+Repository)\./,
description: 'Custom service method calls'
},
email_service: {
pattern: /EmailService\.(send|sendOTP)/,
description: 'Email service operations'
}
},
parallelExecutionPatterns: [
'Promise.all',
'Promise.allSettled',
'Promise.race',
'await Promise.all',
'await Promise.allSettled'
],
ignorePatterns: [
'console.log',
'console.error',
'console.warn',
'JSON.stringify',
'JSON.parse',
'Math.',
'Date.',
'new Date',
'crypto.',
'bcrypt.',
'jwt.',
'uuid.',
'randomBytes',
'throw new',
'return {',
'return new',
'const ',
'let ',
'var ',
'if (',
'for (',
'while (',
'switch (',
'try {',
'catch ('
],
costMultipliers: {
loop: 2,
recursion: 3,
nested: 1.5,
conditional: 1
}
}
},
express: {
name: 'Express.js',
description: 'Configuration for Express.js applications',
config: {
operations: {
// Database operations (generic)
'query': 1,
'execute': 1,
'find': 1,
'findOne': 1,
'save': 1,
'create': 1,
'update': 1,
'delete': 1,
'insert': 1,
// HTTP operations
'httpGet': 1,
'httpPost': 1,
'httpPut': 1,
'httpDelete': 1,
'request': 1,
'fetch': 1
},
patterns: {
database: {
pattern: /\.(query|execute|find|findOne|save|create|update|delete|insert)\(/,
description: 'Database operations'
},
http: {
pattern: /\.(get|post|put|delete|request)\(|fetch\(/,
description: 'HTTP operations'
}
},
parallelExecutionPatterns: ['Promise.all', 'Promise.allSettled'],
ignorePatterns: ['console.', 'JSON.', 'Math.', 'Date.'],
costMultipliers: {
loop: 2,
recursion: 3,
nested: 1.5,
conditional: 1
}
}
},
fastify: {
name: 'Fastify',
description: 'Configuration for Fastify applications',
config: {
operations: {
// Similar to Express but with Fastify-specific patterns
'query': 1,
'find': 1,
'save': 1,
'create': 1,
'update': 1,
'delete': 1
},
patterns: {
database: {
pattern: /\.(query|find|save|create|update|delete)\(/,
description: 'Database operations'
}
},
parallelExecutionPatterns: ['Promise.all'],
ignorePatterns: ['console.', 'JSON.'],
costMultipliers: {
loop: 2,
recursion: 3,
nested: 1.5,
conditional: 1
}
}
}
};
/** Default configuration that works across frameworks */
exports.DEFAULT_CONFIG = {
operations: {
// Generic database operations
'select': 1,
'insert': 1,
'update': 1,
'delete': 1,
'find': 1,
'save': 1,
'create': 1,
// HTTP operations
'httpGet': 1,
'httpPost': 1,
'httpPut': 1,
'httpPatch': 1,
'httpDelete': 1,
'request': 1,
'fetch': 1
},
patterns: {
database: {
pattern: /\.(select|insert|update|delete|find|save|create)\(/,
description: 'Generic database operations'
},
http: {
pattern: /\.(get|post|put|patch|delete|request)\(|fetch\(/,
description: 'HTTP operations'
},
async_method: {
pattern: /await\s+\w+\./,
description: 'Async method calls'
}
},
parallelExecutionPatterns: [
'Promise.all',
'Promise.allSettled',
'Promise.race'
],
ignorePatterns: [
'console.',
'JSON.',
'Math.',
'Date.',
'crypto.',
'throw new',
'return',
'const ',
'let ',
'var '
],
costMultipliers: {
loop: 2,
recursion: 3,
nested: 1.5,
conditional: 1
}
};
/**
* Get configuration for a specific framework
*/
function getFrameworkConfig(framework) {
const preset = exports.FRAMEWORK_PRESETS[framework];
if (!preset) {
return exports.DEFAULT_CONFIG;
}
return mergeConfigs(exports.DEFAULT_CONFIG, preset.config);
}
/**
* Convert string patterns back to RegExp objects
*/
function normalizePatterns(config) {
if (!config.patterns)
return config;
const normalizedPatterns = Object.fromEntries(Object.entries(config.patterns).map(([key, value]) => [
key,
{
...value,
pattern: typeof value.pattern === 'string' ? new RegExp(value.pattern) : value.pattern
}
]));
return {
...config,
patterns: normalizedPatterns
};
}
/**
* Merge two configurations, with the second taking precedence
*/
function mergeConfigs(base, override) {
return {
operations: { ...base.operations, ...override.operations },
patterns: { ...base.patterns, ...override.patterns },
parallelExecutionPatterns: override.parallelExecutionPatterns || base.parallelExecutionPatterns,
ignorePatterns: override.ignorePatterns || base.ignorePatterns,
costMultipliers: { ...base.costMultipliers, ...override.costMultipliers },
methodCosts: { ...base.methodCosts, ...override.methodCosts }
};
}
/**
* Create a custom configuration
*/
function createConfig(options = {}) {
return mergeConfigs(exports.DEFAULT_CONFIG, options);
}
//# sourceMappingURL=config.js.map